Page MenuHomePhabricator (Chris)

No OneTemporary

Size
6 MB
Referenced Files
None
Subscribers
None
This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/mongodb-1.12.0/CONTRIBUTING.md b/mongodb-1.12.0/CONTRIBUTING.md
deleted file mode 100644
index 825f4234..00000000
--- a/mongodb-1.12.0/CONTRIBUTING.md
+++ /dev/null
@@ -1,463 +0,0 @@
-# Contributing to the PHP Driver for MongoDB
-
-## Building from Source
-
-Developers who would like to contribute to the driver will need to build it from
-source. The repository may be initialized with:
-
-```
-$ git clone https://github.com/mongodb/mongo-php-driver.git
-$ cd mongo-php-driver
-$ git submodule update --init
-```
-
-The following script may be used to build the driver:
-
-```
-#!/bin/sh
-
-phpize > /dev/null && \
-./configure --enable-mongodb-developer-flags > /dev/null && \
-make clean > /dev/null && make all > /dev/null && make install
-```
-
-## Testing
-
-The extension's test use the PHPT format from PHP internals. This format is
-documented in the following links:
-
- * [Introduction to PHPT Files](https://qa.php.net/write-test.php)
- * [PHPT - Test File Layout](https://qa.php.net/phpt_details.php)
-
-Generally, most tests will be based on the following template:
-
-```
---TEST--
-Description of API or JIRA issue being tested
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php /* One or more skip functions */ ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-// Test code
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-===DONE===
-```
-
-The `basic-skipif.inc` and `basic.inc` files contain utility functions for the
-`SKIPIF` and `FILE` sections, respectively. If those functions are not needed
-(e.g. skip logic only depends on checking the `PHP_INT_SIZE` constant), the test
-should not include the file. When it doubt, keep it simple.
-
-### Best Practices for `SKIPIF`
-
-The [`skipif.php`](tests/utils/skipif.php) file defines various helper functions
-for use within a test's [`SKIPIF`](https://qa.php.net/phpt_details.php#skipif_section)
-section. When multiple functions are used in a single `SKIPIF` section, they
-should be logically ordered:
-
- * Any PHP environment requirements should be checked first. For example, if a
- test requires a 64-bit architecture, start by checking `PHP_INT_SIZE` before
- anything else.
- * Any extension build requirements (e.g. `skip_if_not_libmongoc_crypto()`) or
- test environment requirements (e.g. `skip_if_auth()`) should then be checked.
- These functions only examine local information, such as `phpinfo()` output or
- the structure of the `URI` constant, and do not interact with a remote
- MongoDB server.
- * Any remote server requirements should then be checked. A general integration
- test that requires any type of remote server to be accessible might use
- `skip_if_not_live()` while a test requiring a replica set would prefer
- `skip_if_not_replica_set()`.
- * After requiring a remote server to be accessible (optionally with a specific
- type), you can enforce requirements about that server. This includes checking
- its server version, storage engine, availability of test commands, etc.
- * Finally, use `skip_if_not_clean()` if needed to ensure that the collection(s)
- under test are dropped before the test runs.
-
-As a rule of thumb, your `SKIPIF` logic should be written to allow the test to
-run in as many environments as possible. To paraphrase the
-[robustness principal](https://en.wikipedia.org/wiki/Robustness_principle):
-
-> Be conservative in what/how you test, and liberal in what environment you require
-
-Consider that a well-crafted `EXPECTF` section may allow a `SKIPIF` section to
-be less restrictive.
-
-### Local Mongo Orchestration (and CI platforms)
-
-The test suite depends on [Mongo Orchestration](https://github.com/10gen/mongo-orchestration).
-Mongo Orchestration is an HTTP server that provides a REST API for maintaining
-MongoDB configurations. These configurations are provided by the
-[drivers-evergreen-tools](https://github.com/mongodb-labs/drivers-evergreen-tools)
-repository. These configurations can be run locally. Alternatively, you can use
-the GitHub Actions workflow if you don't want to set up a local development
-environment.
-
-Mongo Orchestration expects that the ``mongod`` (and ``mongos``) binaries are
-available in the ``PATH``.
-
-Once installed, Mongo Orchestration can be started with
-
-```
-~/.local/bin/mongo-orchestration start --no-fork --enable-majority-read-concern
-```
-
-The test suite uses the ``MONGODB_URI`` environment variable as connection
-string to run all tests. If not set, tests assume MongoDB is listening on the
-default MongoDB port (27017) on localhost.
-
-With this set-up, the tests can be run with `make test`.
-
-If Mongo Orchestration is running on non-default settings, the
-``MONGO_ORCHESTRATION_URI`` environment variable can be used to specify where
-mongo-orchestration is listening:
-
-```
-MONGO_ORCHESTRATION_URI=http://localhost:1234/v1 make test
-```
-
-## Updating libmongoc, libbson, and libmongocrypt
-
-The PHP driver can use either system libraries or bundled versions of
-libmongoc, libbson, and libmongocrypt. If a new version of either library is
-available, the submodule and build configuration will need to be updated to
-reflect the new sources and/or package version.
-
-### Updating libmongoc and libbson
-
-#### Update libmongoc submodule
-
-```
-$ cd src/libmongoc
-$ git fetch
-$ git checkout 1.20.0
-```
-
-During development, it may be necessary to temporarily point the libmongoc
-submodule to a commit on the developer's fork of libmongoc. For instance, the
-developer may be working on a PHP driver feature that depends on an unmerged
-pull request to libmongoc. In this case, `git remote add` can be used to add
-the fork before fetching and checking out the target commit. Additionally, the
-submodule path in
-[`.gitmodules`](https://github.com/mongodb/mongo-php-driver/blob/master/.gitmodules)
-must also be updated to refer to the fork.
-
-#### Ensure libmongoc version information is correct
-
-The build process for Autotools and Windows rely on
-`src/LIBMONGOC_VERSION_CURRENT` to infer version information for libmongoc and
-libbson. This file can be regenerated using the following Makefile target:
-
-```
-$ make libmongoc-version-current
-```
-
-Alternatively, the `build/calc_release_version.py` script in libmongoc can be
-executed directly.
-
-Note: If the libmongoc submodule points to a non-release, non-master branch, the
-script may fail to correctly detect the version. This issue is being tracked in
-[CDRIVER-3315](https://jira.mongodb.org/browse/CDRIVER-3315) and can be safely
-ignored since this should only happen during development (any PHP driver release
-should point to a tagged libmongoc release).
-
-#### Update sources in build configurations
-
-The Autotools and Windows build configurations (`config.m4` and `config.w32`,
-respectively) define several variables (e.g. `PHP_MONGODB_MONGOC_SOURCES`) that
-collectively enumerate all of the the sources within the libmongoc submodule to
-include in a bundled build.
-
-These variables should each have a shell command in a preceding comment, which
-should be run to regenerate that particular list of source files. Each command
-may be run manually or `scripts/update-submodule-sources.php` may be used to
-update all variables. In the event that either libmongoc or libbson introduce a
-new source directory, that will need to be manually added (follow prior art).
-
-#### Update package dependencies
-
-The Autotools configuration additionally includes some `pkg-config` commands for
-using libmongoc and libbson as system libraries (in lieu of a bundled build).
-When bumping the libmongoc version, be sure to update the version check _and_
-error message in the `pkg-config` blocks for both libmongoc and libbson.
-
-For example, the following lines might be updated for libmongoc:
-
-```
-if $PKG_CONFIG libmongoc-1.0 --atleast-version 1.20.0; then
-
-...
-
-AC_MSG_ERROR(system libmongoc must be upgraded to version >= 1.20.0)
-```
-
-#### Update tested versions in Evergreen configuration
-
-Evergreen tests against multiple versions of libmongoc. When updating to a newer
-libmongoc version, make sure to update the `libmongoc-version` build axis in
-`.evergreen/config.yml`. In general, we test against two additional versions of
-libmongoc:
-
-- The upcoming patch release of the current libmongoc minor version (e.g. the
- `r1.x` branch)
-- The upcoming minor release of libmongoc (e.g. the `master` branch)
-
-#### Update sources in PECL package generation script
-
-If either libmongoc or libbson introduce a new source directory, that may also
-require updating the glob patterns in the `bin/prep-release.php` script to
-ensure new source files will be included in any generated PECL package.
-
-#### Test and commit your changes
-
-Verify that the upgrade was successful by ensuring that the driver can compile
-using both the bundled sources and system libraries for libmongoc and libbson,
-and by ensuring that the test suite passes. Once done, commit the changes to all
-of the above files/paths. For example:
-
-```
-$ git commit -m "Bump libmongoc to 1.20.0" config.m4 config.w32 src/libmongoc src/LIBMONGOC_VERSION_CURRENT
-```
-
-### Updating libmongocrypt
-
-To update libmongocrypt, the steps are similar to the above:
-
-```
-$ cd src/libmongocrypt
-$ git fetch
-$ git checkout 1.3.0
-$ make libmongocrypt-version-current
-```
-
-Package dependencies in `config.m4` must also be updated (either manually or
-with `scripts/update-submodule-sources.php`), as do the sources in the PECL
-generation script.
-
-## Releasing
-
-The follow steps outline the release process for a maintenance branch (e.g.
-releasing the `vX.Y` branch as X.Y.Z).
-
-### Ensure PHP version compatibility
-
-Ensure that the library test suite completes on supported versions of PHP.
-
-### Ensure Windows compatibility
-
-PECL will create Windows DLLs for new releases; however, you must ensure that
-the extension successfully builds on Windows before releasing. Windows builds
-are tested by [AppVeyor](.appveyor.yml).
-
-See the [internals wiki](https://wiki.php.net/internals/windows/stepbystepbuild)
-for more information.
-
-### Transition JIRA issues and version
-
-All issues associated with the release version should be in the "Closed" state
-and have a resolution of "Fixed". Issues with other resolutions (e.g.
-"Duplicate", "Works as Designed") should be removed from the release version so
-that they do not appear in the release notes.
-
-Check the corresponding ".x" fix version to see if it contains any issues that
-are resolved as "Fixed" and should be included in this release version.
-
-Update the version's release date and status from the
-[Manage Versions](https://jira.mongodb.org/plugins/servlet/project-config/PHPC/versions)
-page.
-
-### Update version info
-
-The PHP driver uses [semantic versioning](http://semver.org/). Do not break
-backwards compatibility in a non-major release or your users will kill you.
-
-Before proceeding, ensure that the `master` branch is up-to-date with all code
-changes in this maintenance branch. This is important because we will later
-merge the ensuing release commits up to master with `--strategy=ours`, which
-will ignore changes from the merged commits.
-
-Update the version and stability constants in `phongo_version.h`. This should
-entail removing the version's "-dev" suffix, changing the stability to
-"stable", and increasing the last digit for `PHP_MONGO_VERSION_DESC`:
-
-```
-#define PHP_MONGODB_VERSION "1.1.8-dev"
-#define PHP_MONGODB_STABILITY "devel"
-#define PHP_MONGODB_VERSION_DESC 1,1,8,0
-```
-
-The above would be changed to:
-
-```
-#define PHP_MONGODB_VERSION "1.1.8"
-#define PHP_MONGODB_STABILITY "stable"
-#define PHP_MONGODB_VERSION_DESC 1,1,8,1
-```
-
-The Makefile targets for creating the PECL package depend on these constants, so
-you must rebuild the extension after updating `phongo_version.h`.
-
-> **Note:** If this is an alpha or beta release, the version string should
-> include the X.Y.Z version followed by the stability and an increment. For
-> instance, the first beta release in the 1.4.0 series would be "1.4.0beta1".
-> Alpha and beta releases use "alpha" and "beta" stability strings,
-> respectively. Release candidates (e.g. "1.4.0RC1") also use "beta" stability.
-> See [Documenting release stability and API stability](https://pear.php.net/manual/en/guide.developers.package2.stability.php)
-> for more information. For each change to the suffixes of
-> `PHP_MONGODB_VERSION`, increment the last digit of
-> `PHP_MONGODB_VERSION_DESC`.
-
-### Build PECL package
-
-Create the PECL package description file with `make package.xml`. This creates
-a `package.xml` file from a template. Version, author, and file information will
-be filled in, but release notes must be copied manually from JIRA.
-
-After copying release notes, use `make package` to create the package file (e.g.
-`mongodb-X.Y.Z.tgz`) and ensure that it can be successfully installed:
-
-```
-$ pecl install -f mongodb-X.Y.Z.tgz
-```
-
-### Commit version update and release notes
-
-Commit the modified `phongo_version.h` file as "Package X.Y.Z"
-
-```
-$ git add phongo_version.h
-$ git commit -m "Package X.Y.Z"
-```
-
-### Tag release
-
-The previous commit will be the target for our release tag:
-
-```
-$ git tag -a -m "Release X.Y.Z" X.Y.Z
-```
-
-### Update version info back to dev
-
-After tagging, the version and stability constants in `phongo_version.h` should be
-updated back to development status.
-
-```
-#define PHP_MONGODB_VERSION "1.1.8"
-#define PHP_MONGODB_STABILITY "stable"
-#define PHP_MONGODB_VERSION_DESC 1,1,8,1
-```
-
-The above would be changed to:
-
-```
-#define PHP_MONGODB_VERSION "1.1.9-dev"
-#define PHP_MONGODB_STABILITY "devel"
-#define PHP_MONGODB_VERSION_DESC 1,1,9,0
-```
-
-Commit this change:
-
-```
-$ git commit -m "Back to -dev" phongo_version.h
-```
-
-> **Note:** If this is an alpha, beta, or RC release, the version string should
-> increment the stability sequence instead of the patch version. For example,
-> if the constants were originally "1.4.0-dev" and "devel" and then changed to
-> "1.4.0beta1" and "beta" for the first beta release, this step would see them
-> ultimately changed to "1.4.0beta2-dev" and "devel".
-
-### Push commits and tags
-
-```
-$ git push
-$ git push --tags
-```
-
-### Release PECL package
-
-The PECL package may be published via the
-[Release Upload](https://pecl.php.net/release-upload.php) form. You will have
-one chance to confirm the package information after uploading.
-
-### Merge the maintenance branch up to master
-
-```
-$ git checkout master
-$ git merge vX.Y --strategy=ours
-$ git push
-```
-
-The `--strategy=ours` option ensures that all changes from the merged commits
-will be ignored.
-
-### Publish release notes
-
-The following template should be used for creating GitHub release notes via
-[this form](https://github.com/mongodb/mongo-php-driver/releases/new). The PECL
-package may also be attached to the release notes.
-
-```
-The PHP team is happy to announce that version X.Y.Z of the [mongodb](https://pecl.php.net/package/mongodb) PHP extension is now available on PECL.
-
-**Release Highlights**
-
-<one or more paragraphs describing important changes in this release>
-
-A complete list of resolved issues in this release may be found at:
-$JIRA_URL
-
-**Documentation**
-
-Documentation is available on PHP.net:
-https://www.php.net/set.mongodb
-
-**Installation**
-
-You can either download and install the source manually, or you can install the extension with:
-
- pecl install mongodb-X.Y.Z
-
-or update with:
-
- pecl upgrade mongodb-X.Y.Z
-
-Windows binaries are available on PECL:
-https://pecl.php.net/package/mongodb
-```
-
-> **Note:** If this is an alpha or beta release, the installation examples
-> should refer to the exact version (e.g. "mongodb-1.8.0beta2"). This is necessary
-> because PECL prioritizes recent, stable releases over any stability preferences
-> (e.g. "mongodb-beta").
-
-The URL for the list of resolved JIRA issues will need to be updated with each
-release. You may obtain the list from
-[this form](https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=12484).
-
-If commits from community contributors were included in this release, append the
-following section:
-
-```
-**Thanks**
-
-Thanks for our community contributors for X.Y.Z:
-
- * [$CONTRIBUTOR_NAME](https://github.com/$GITHUB_USERNAME)
-```
-
-Release announcements should also be posted in the [MongoDB Product & Driver Announcements: Driver Releases](https://www.mongodb.com/community/forums/tags/c/announcements/driver-releases/110/php) forum and shared on Twitter.
-
-### Update compatibility tables in MongoDB docs
-
-For minor releases, create a DOCSP ticket indicating whether there are changes to MongoDB Server or PHP version
-compatibility. The [compatibility tables](https://docs.mongodb.com/drivers/driver-compatibility-reference#php-driver-compatibility)
-in the MongoDB documentation must be updated to account for new releases. Make sure to update both MongoDB and Language
-compatibility tables, as shown in [this pull request](https://github.com/mongodb/docs-ecosystem/pull/642).
diff --git a/mongodb-1.12.0/config.m4 b/mongodb-1.12.0/config.m4
deleted file mode 100644
index 8fa2d102..00000000
--- a/mongodb-1.12.0/config.m4
+++ /dev/null
@@ -1,540 +0,0 @@
-dnl config.m4 for extension mongodb
-PHP_ARG_ENABLE([mongodb],
- [whether to enable MongoDB support],
- [AS_HELP_STRING([--enable-mongodb],
- [Enable MongoDB support])])
-
-if test "$PHP_MONGODB" != "no"; then
- dnl Check PHP version is compatible with this extension
- AC_MSG_CHECKING([PHP version])
-
- PHP_MONGODB_PHP_VERSION=$PHP_VERSION
- PHP_MONGODB_PHP_VERSION_ID=$PHP_VERSION_ID
-
- if test -z "$PHP_MONGODB_PHP_VERSION"; then
- if test -z "$PHP_CONFIG"; then
- AC_MSG_ERROR([php-config not found])
- fi
- PHP_MONGODB_PHP_VERSION=`${PHP_CONFIG} --version`
- PHP_MONGODB_PHP_VERSION_ID=`echo "${PHP_MONGODB_PHP_VERSION}" | $AWK 'BEGIN { FS = "."; } { printf "%d", ([$]1 * 100 + [$]2) * 100 + [$]3;}'`
- fi
-
- AC_MSG_RESULT($PHP_MONGODB_PHP_VERSION)
- if test "$PHP_MONGODB_PHP_VERSION_ID" -lt "70200"; then
- AC_MSG_ERROR([not supported. Need a PHP version >= 7.2.0 (found $PHP_MONGODB_PHP_VERSION)])
- fi
-
- PHP_ARG_ENABLE([mongodb-developer-flags],
- [whether to enable developer build flags],
- [AS_HELP_STRING([--enable-mongodb-developer-flags],
- [MongoDB: Enable developer flags [default=no]])],
- [no],
- [no])
-
- if test "$PHP_MONGODB_DEVELOPER_FLAGS" = "yes"; then
- dnl Warn about functions which might be candidates for format attributes
- AX_CHECK_COMPILE_FLAG(-Wmissing-format-attribute, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wmissing-format-attribute" ,, -Werror)
- dnl Avoid duplicating values for an enum
- AX_CHECK_COMPILE_FLAG(-Wduplicate-enum, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wduplicate-enum" ,, -Werror)
- dnl Warns on mismatches between #ifndef and #define header guards
- AX_CHECK_COMPILE_FLAG(-Wheader-guard, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wheader-guard" ,, -Werror)
- dnl logical not of a non-boolean expression
- AX_CHECK_COMPILE_FLAG(-Wlogical-not-parentheses, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wlogical-not-parentheses" ,, -Werror)
- dnl Warn about suspicious uses of logical operators in expressions
- AX_CHECK_COMPILE_FLAG(-Wlogical-op, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wlogical-op",, -Werror ,, -Werror)
- dnl memory error detector.
- dnl FIXME: -fsanitize=address,undefined for clang. The AX_CHECK_COMPILE_FLAG macro isn't happy about that string :(
- AX_CHECK_COMPILE_FLAG(-fsanitize-address, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -fsanitize-address" ,, -Werror)
- dnl Enable frame debugging
- AX_CHECK_COMPILE_FLAG(-fno-omit-frame-pointer, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -fno-omit-frame-pointer" ,, -Werror)
- dnl Make sure we don't optimize calls
- AX_CHECK_COMPILE_FLAG(-fno-optimize-sibling-calls, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -fno-optimize-sibling-calls" ,, -Werror)
- AX_CHECK_COMPILE_FLAG(-Wlogical-op-parentheses, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wlogical-op-parentheses" ,, -Werror)
- AX_CHECK_COMPILE_FLAG(-Wpointer-bool-conversion, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wpointer-bool-conversion" ,, -Werror)
- AX_CHECK_COMPILE_FLAG(-Wbool-conversion, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wbool-conversion" ,, -Werror)
- AX_CHECK_COMPILE_FLAG(-Wloop-analysis, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wloop-analysis" ,, -Werror)
- AX_CHECK_COMPILE_FLAG(-Wsizeof-array-argument, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wsizeof-array-argument" ,, -Werror)
- AX_CHECK_COMPILE_FLAG(-Wstring-conversion, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wstring-conversion" ,, -Werror)
- AX_CHECK_COMPILE_FLAG(-Wno-variadic-macros, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wno-variadic-macros" ,, -Werror)
- AX_CHECK_COMPILE_FLAG(-Wno-sign-compare, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wno-sign-compare" ,, -Werror)
- AX_CHECK_COMPILE_FLAG(-fstack-protector, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -fstack-protector" ,, -Werror)
- AX_CHECK_COMPILE_FLAG(-fno-exceptions, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -fno-exceptions" ,, -Werror)
- AX_CHECK_COMPILE_FLAG(-Wformat-security, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wformat-security" ,, -Werror)
- AX_CHECK_COMPILE_FLAG(-Wformat-nonliteral, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wformat-nonliteral" ,, -Werror)
- AX_CHECK_COMPILE_FLAG(-Winit-self, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Winit-self" ,, -Werror)
- AX_CHECK_COMPILE_FLAG(-Wwrite-strings, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wwrite-strings" ,, -Werror)
- AX_CHECK_COMPILE_FLAG(-Wenum-compare, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wenum-compare" ,, -Werror)
- AX_CHECK_COMPILE_FLAG(-Wempty-body, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wempty-body" ,, -Werror)
- AX_CHECK_COMPILE_FLAG(-Wparentheses, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wparentheses" ,, -Werror)
- AX_CHECK_COMPILE_FLAG(-Wdeclaration-after-statement, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wdeclaration-after-statement" ,, -Werror)
- AX_CHECK_COMPILE_FLAG(-Wmaybe-uninitialized, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wmaybe-uninitialized" ,, -Werror)
- AX_CHECK_COMPILE_FLAG(-Wimplicit-fallthrough, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wimplicit-fallthrough" ,, -Werror)
- AX_CHECK_COMPILE_FLAG(-Werror, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Werror" ,, -Werror)
- AX_CHECK_COMPILE_FLAG(-Wextra, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wextra" ,, -Werror)
- AX_CHECK_COMPILE_FLAG(-Wno-unused-parameter, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wno-unused-parameter" ,, -Werror)
- AX_CHECK_COMPILE_FLAG(-Wno-unused-but-set-variable, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wno-unused-but-set-variable" ,, -Werror)
- AX_CHECK_COMPILE_FLAG(-Wno-missing-field-initializers, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wno-missing-field-initializers",, -Werror)
-
- MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS"
- STD_CFLAGS="-g -O0 -Wall"
- fi
-
-
- PHP_ARG_ENABLE([mongodb-coverage],
- [whether to enable code coverage],
- [AS_HELP_STRING([--enable-mongodb-coverage],
- [MongoDB: Enable developer code coverage information [default=no]])],
- [no],
- [no])
-
- if test "$PHP_MONGODB_COVERAGE" = "yes"; then
- if test "$ext_shared" != "yes"; then
- AC_MSG_ERROR(code coverage is not supported for static builds)
- fi
-
- COVERAGE_CFLAGS="--coverage -g"
- COVERAGE_LDFLAGS="--coverage"
-
- MONGODB_SHARED_LIBADD="$MONGODB_SHARED_LIBADD $COVERAGE_LDFLAGS"
- fi
-
- PHP_MONGODB_CFLAGS="$STD_CFLAGS $MAINTAINER_CFLAGS $COVERAGE_CFLAGS"
-
- PHP_MONGODB_SOURCES="\
- php_phongo.c \
- phongo_compat.c \
- src/bson.c \
- src/bson-encode.c \
- src/phongo_apm.c \
- src/phongo_ini.c \
- src/BSON/Binary.c \
- src/BSON/BinaryInterface.c \
- src/BSON/DBPointer.c \
- src/BSON/Decimal128.c \
- src/BSON/Decimal128Interface.c \
- src/BSON/Int64.c \
- src/BSON/Javascript.c \
- src/BSON/JavascriptInterface.c \
- src/BSON/MaxKey.c \
- src/BSON/MaxKeyInterface.c \
- src/BSON/MinKey.c \
- src/BSON/MinKeyInterface.c \
- src/BSON/ObjectId.c \
- src/BSON/ObjectIdInterface.c \
- src/BSON/Persistable.c \
- src/BSON/Regex.c \
- src/BSON/RegexInterface.c \
- src/BSON/Serializable.c \
- src/BSON/Symbol.c \
- src/BSON/Timestamp.c \
- src/BSON/TimestampInterface.c \
- src/BSON/Type.c \
- src/BSON/Undefined.c \
- src/BSON/Unserializable.c \
- src/BSON/UTCDateTime.c \
- src/BSON/UTCDateTimeInterface.c \
- src/BSON/functions.c \
- src/MongoDB/BulkWrite.c \
- src/MongoDB/ClientEncryption.c \
- src/MongoDB/Command.c \
- src/MongoDB/Cursor.c \
- src/MongoDB/CursorId.c \
- src/MongoDB/CursorInterface.c \
- src/MongoDB/Manager.c \
- src/MongoDB/Query.c \
- src/MongoDB/ReadConcern.c \
- src/MongoDB/ReadPreference.c \
- src/MongoDB/Server.c \
- src/MongoDB/ServerApi.c \
- src/MongoDB/Session.c \
- src/MongoDB/WriteConcern.c \
- src/MongoDB/WriteConcernError.c \
- src/MongoDB/WriteError.c \
- src/MongoDB/WriteResult.c \
- src/MongoDB/Exception/AuthenticationException.c \
- src/MongoDB/Exception/BulkWriteException.c \
- src/MongoDB/Exception/CommandException.c \
- src/MongoDB/Exception/ConnectionException.c \
- src/MongoDB/Exception/ConnectionTimeoutException.c \
- src/MongoDB/Exception/EncryptionException.c \
- src/MongoDB/Exception/Exception.c \
- src/MongoDB/Exception/ExecutionTimeoutException.c \
- src/MongoDB/Exception/InvalidArgumentException.c \
- src/MongoDB/Exception/LogicException.c \
- src/MongoDB/Exception/RuntimeException.c \
- src/MongoDB/Exception/ServerException.c \
- src/MongoDB/Exception/SSLConnectionException.c \
- src/MongoDB/Exception/UnexpectedValueException.c \
- src/MongoDB/Exception/WriteException.c \
- src/MongoDB/Monitoring/CommandFailedEvent.c \
- src/MongoDB/Monitoring/CommandStartedEvent.c \
- src/MongoDB/Monitoring/CommandSubscriber.c \
- src/MongoDB/Monitoring/CommandSucceededEvent.c \
- src/MongoDB/Monitoring/Subscriber.c \
- src/MongoDB/Monitoring/functions.c \
- "
-
- PHP_ARG_WITH([mongodb-system-libs],
- [whether to compile against system libraries instead of bundled],
- [AS_HELP_STRING([--with-mongodb-system-libs=@<:@yes/no@:>@],
- [MongoDB: Use system libraries for libbson, libmongoc, and libmongocrypt [default=no]])],
- [no],
- [no])
- PHP_ARG_WITH([libbson],
- [whether to use system libbson],
- [AS_HELP_STRING([--with-libbson=@<:@yes/no@:>@],
- [MongoDB: Use system libbson [default=no]])],
- [no],
- [no])
- PHP_ARG_WITH([libmongoc],
- [whether to use system libmongoc],
- [AS_HELP_STRING([--with-libmongoc=@<:@yes/no@:>@],
- [MongoDB: Use system libmongoc [default=no]])],
- [no],
- [no])
- PHP_ARG_WITH([mongodb-client-side-encryption],
- [whether to enable client-side encryption],
- [AS_HELP_STRING([--with-mongodb-client-side-encryption=@<:@auto/yes/no@:>@],
- [MongoDB: Enable client-side encryption [default=auto]])],
- [auto],
- [no])
-
- if test "$PHP_LIBBSON" != "no"; then
- AC_MSG_WARN(Using --with-libbson is deprecated and will be removed in a future version. Please use --with-system-libs instead)
-
- if test "$PHP_LIBMONGOC" = "no"; then
- AC_MSG_ERROR(Cannot use system libbson and bundled libmongoc)
- fi
-
- PHP_MONGODB_SYSTEM_LIBS="yes"
- fi
-
- if test "$PHP_LIBMONGOC" != "no"; then
- AC_MSG_WARN(Using --with-libmongoc is deprecated and will be removed in a future version. Please use --with-system-libs instead)
-
- if test "$PHP_LIBBSON" = "no"; then
- AC_MSG_ERROR(Cannot use system libmongoc and bundled libbson)
- fi
-
- PHP_MONGODB_SYSTEM_LIBS="yes"
- fi
-
- PHP_MONGODB_BSON_VERSION_STRING="None"
- PHP_MONGODB_MONGOC_VERSION_STRING="None"
- PHP_MONGODB_MONGOCRYPT_VERSION_STRING="None"
-
- if test "$PHP_MONGODB_SYSTEM_LIBS" != "no"; then
- AC_PATH_PROG(PKG_CONFIG, pkg-config, no)
- AC_MSG_CHECKING(for libbson)
- if test -x "$PKG_CONFIG" && $PKG_CONFIG --exists libbson-1.0; then
- if $PKG_CONFIG libbson-1.0 --atleast-version 1.20.0; then
- PHP_MONGODB_BSON_CFLAGS=`$PKG_CONFIG libbson-1.0 --cflags`
- PHP_MONGODB_BSON_LIBS=`$PKG_CONFIG libbson-1.0 --libs`
- PHP_MONGODB_BSON_VERSION=`$PKG_CONFIG libbson-1.0 --modversion`
- PHP_MONGODB_BSON_VERSION_STRING="System ($PHP_MONGODB_BSON_VERSION)"
- AC_MSG_RESULT(version $PHP_MONGODB_BSON_VERSION found)
- else
- AC_MSG_ERROR(system libbson must be upgraded to version >= 1.19.1)
- fi
- else
- AC_MSG_ERROR(pkgconfig and libbson must be installed)
- fi
- PHP_MONGODB_CFLAGS="$PHP_MONGODB_CFLAGS $PHP_MONGODB_BSON_CFLAGS"
- PHP_EVAL_LIBLINE($PHP_MONGODB_BSON_LIBS, MONGODB_SHARED_LIBADD)
- AC_DEFINE(HAVE_SYSTEM_LIBBSON, 1, [Use system libbson])
-
- AC_MSG_CHECKING(for libmongoc)
- if test -x "$PKG_CONFIG" && $PKG_CONFIG --exists libmongoc-1.0; then
- if $PKG_CONFIG libmongoc-1.0 --atleast-version 1.20.0; then
- PHP_MONGODB_MONGOC_CFLAGS=`$PKG_CONFIG libmongoc-1.0 --cflags`
- PHP_MONGODB_MONGOC_LIBS=`$PKG_CONFIG libmongoc-1.0 --libs`
- PHP_MONGODB_MONGOC_VERSION=`$PKG_CONFIG libmongoc-1.0 --modversion`
- PHP_MONGODB_MONGOC_VERSION_STRING="System ($PHP_MONGODB_MONGOC_VERSION)"
- AC_MSG_RESULT(version $PHP_MONGODB_MONGOC_VERSION found)
- else
- AC_MSG_ERROR(system libmongoc must be upgraded to version >= 1.19.1)
- fi
- else
- AC_MSG_ERROR(pkgconfig and libmongoc must be installed)
- fi
- PHP_MONGODB_CFLAGS="$PHP_MONGODB_CFLAGS $PHP_MONGODB_MONGOC_CFLAGS"
- PHP_EVAL_LIBLINE($PHP_MONGODB_MONGOC_LIBS, MONGODB_SHARED_LIBADD)
- AC_DEFINE(HAVE_SYSTEM_LIBMONGOC, 1, [Use system libmongoc])
-
- if test "$PHP_MONGODB_CLIENT_SIDE_ENCRYPTION" != "no"; then
- AC_MSG_CHECKING(for libmongocrypt)
-
- if test -x "$PKG_CONFIG" && $PKG_CONFIG --exists libmongocrypt; then
- if $PKG_CONFIG libmongocrypt --atleast-version 1.3.0; then
- PHP_MONGODB_MONGOCRYPT_CFLAGS=`$PKG_CONFIG libmongocrypt --cflags`
- PHP_MONGODB_MONGOCRYPT_LIBS=`$PKG_CONFIG libmongocrypt --libs`
- PHP_MONGODB_MONGOCRYPT_VERSION=`$PKG_CONFIG libmongocrypt --modversion`
- PHP_MONGODB_MONGOCRYPT_VERSION_STRING="System ($PHP_MONGODB_MONGOCRYPT_VERSION)"
- AC_MSG_RESULT(version $PHP_MONGODB_MONGOCRYPT_VERSION found)
-
- PHP_MONGODB_CFLAGS="$PHP_MONGODB_CFLAGS $PHP_MONGODB_MONGOCRYPT_CFLAGS"
- PHP_EVAL_LIBLINE($PHP_MONGODB_MONGOCRYPT_LIBS, MONGODB_SHARED_LIBADD)
- AC_DEFINE(HAVE_SYSTEM_LIBMONGOCRYPT, 1, [Use system libmongocrypt])
- elif test "$PHP_MONGODB_CLIENT_SIDE_ENCRYPTION" = "yes"; then
- AC_MSG_ERROR(system libmongocrypt must be upgraded to version >= 1.2.1)
- else
- AC_MSG_RESULT(found an older version, compiling without client-side encryption)
- fi
- else
- if test "$PHP_MONGODB_CLIENT_SIDE_ENCRYPTION" = "yes"; then
- AC_MSG_ERROR(pkgconfig and libmongocrypt must be installed)
- else
- AC_MSG_RESULT(not found, compiling without client-side encryption)
- fi
- fi
- fi
- fi
-
- if test "$PHP_MONGODB_SYSTEM_LIBS" = "no"; then
- PHP_MONGODB_BUNDLED_CFLAGS="$STD_CFLAGS -DBSON_COMPILATION -DMONGOC_COMPILATION"
- dnl TODO: MONGOCRYPT-219 makes the -std argument obsolete
- PHP_MONGODB_LIBMONGOCRYPT_CFLAGS="-DKMS_MSG_STATIC -std=gnu99"
-
- dnl M4 doesn't know if we're building statically or as a shared module, so
- dnl attempt to include both paths while ignoring errors. If neither path
- dnl exists, report an error during configure (this is later than M4 parsing
- dnl during phpize but better than nothing).
- m4_pushdef([_include],[
- dnl TODO: Fix this for PECL install (PHPC-1218)
- dnl if test ! \( -f "$1" -o -f "ext/mongodb/$1" \); then
- dnl AC_MSG_ERROR([m4 could not include $1: No such file or directory])
- dnl fi
- m4_builtin([sinclude],[$1])
- m4_builtin([sinclude],[ext/mongodb/][$1])
- ])
-
- dnl Avoid using AC_CONFIG_MACRO_DIR, which might conflict with PHP
- _include([scripts/autotools/m4/as_var_copy.m4])
- _include([scripts/autotools/m4/ax_check_compile_flag.m4])
- _include([scripts/autotools/m4/ax_prototype.m4])
- _include([scripts/autotools/m4/ax_pthread.m4])
- _include([scripts/autotools/m4/php_mongodb.m4])
- _include([scripts/autotools/m4/pkg.m4])
-
- _include([scripts/autotools/CheckCompiler.m4])
- _include([scripts/autotools/CheckHost.m4])
-
- _include([scripts/autotools/libbson/CheckAtomics.m4])
- _include([scripts/autotools/libbson/CheckHeaders.m4])
- _include([scripts/autotools/libbson/Endian.m4])
- _include([scripts/autotools/libbson/FindDependencies.m4])
- _include([scripts/autotools/libbson/Versions.m4])
-
- _include([scripts/autotools/libmongoc/CheckCompression.m4])
- _include([scripts/autotools/libmongoc/CheckResolv.m4])
- _include([scripts/autotools/libmongoc/CheckSasl.m4])
- _include([scripts/autotools/libmongoc/CheckSSL.m4])
- _include([scripts/autotools/libmongoc/CheckICU.m4])
- _include([scripts/autotools/libmongoc/FindDependencies.m4])
- _include([scripts/autotools/libmongoc/PlatformFlags.m4])
- _include([scripts/autotools/libmongoc/Versions.m4])
- _include([scripts/autotools/libmongoc/WeakSymbols.m4])
-
- dnl This include modifies the value of $PHP_MONGODB_CLIENT_SIDE_ENCRYPTION to "yes"
- dnl or "no" depending on whether dependencies for libmongocrypt are fulfilled
- _include([scripts/autotools/libmongocrypt/CheckSSL.m4])
- _include([scripts/autotools/libmongocrypt/Endian.m4])
- _include([scripts/autotools/libmongocrypt/Version.m4])
-
- PHP_MONGODB_BSON_VERSION_STRING="Bundled ($BSON_VERSION)"
- PHP_MONGODB_MONGOC_VERSION_STRING="Bundled ($MONGOC_VERSION)"
- PHP_MONGODB_MONGOCRYPT_VERSION_STRING="Bundled ($MONGOCRYPT_BUILD_VERSION)"
-
- m4_popdef([_include])
-
- AC_SUBST(BSON_EXTRA_ALIGN, 0)
- AC_SUBST(BSON_OS, 1)
-
- AC_SUBST(MONGOC_NO_AUTOMATIC_GLOBALS, 1)
- AC_SUBST(MONGOC_ENABLE_MONGODB_AWS_AUTH, 0)
- AC_SUBST(MONGOC_ENABLE_RDTSCP, 0)
- AC_SUBST(MONGOC_ENABLE_SHM_COUNTERS, 0)
- AC_SUBST(MONGOC_TRACE, 1)
-
- dnl Assignments for metadata handshake. Leave CFLAGS/LDFLAGS empty as they
- dnl would likely cause platform info (PHP version) to be truncated. We can
- dnl consider restoring CFLAGS/LDFLAGS once CDRIVER-3134 is resolved.
- AC_SUBST(MONGOC_CC, [$CC])
- AC_SUBST(MONGOC_USER_SET_CFLAGS, [])
- AC_SUBST(MONGOC_USER_SET_LDFLAGS, [])
-
- if test "$PHP_MONGODB_CLIENT_SIDE_ENCRYPTION" = "yes"; then
- AC_SUBST(MONGOC_ENABLE_CLIENT_SIDE_ENCRYPTION, 1)
- else
- AC_SUBST(MONGOC_ENABLE_CLIENT_SIDE_ENCRYPTION, 0)
- fi
-
- if test "$PHP_MONGODB_DEVELOPER_FLAGS" = "yes"; then
- AC_SUBST(MONGOC_ENABLE_DEBUG_ASSERTIONS, 1)
- else
- AC_SUBST(MONGOC_ENABLE_DEBUG_ASSERTIONS, 0)
- fi
-
- dnl On MacOS, use gcut from the coreutils brew package instead of cut
- dnl Generated with: find src/libmongoc/src/common -name '*.c' -print0 | cut -sz -d / -f 5- | sort -dz | tr '\000' ' '
- PHP_MONGODB_COMMON_SOURCES="common-b64.c common-md5.c common-thread.c"
-
- dnl Generated with: find src/libmongoc/src/kms-message/src -maxdepth 1 -name '*.c' -print0 | cut -sz -d / -f 6- | sort -dz | tr '\000' ' '
- PHP_MONGODB_KMS_MESSAGE_SOURCES="hexlify.c kms_b64.c kms_caller_identity_request.c kms_crypto_apple.c kms_crypto_libcrypto.c kms_crypto_none.c kms_crypto_windows.c kms_decrypt_request.c kms_encrypt_request.c kms_kv_list.c kms_message.c kms_port.c kms_request.c kms_request_opt.c kms_request_str.c kms_response.c kms_response_parser.c sort.c"
-
- dnl Generated with: find src/libmongoc/src/libbson/src/bson -name '*.c' -print0 | cut -sz -d / -f 7- | sort -dz | tr '\000' ' '
- PHP_MONGODB_BSON_SOURCES="bcon.c bson-atomic.c bson.c bson-clock.c bson-context.c bson-decimal128.c bson-error.c bson-iso8601.c bson-iter.c bson-json.c bson-keys.c bson-md5.c bson-memory.c bson-oid.c bson-reader.c bson-string.c bson-timegm.c bson-utf8.c bson-value.c bson-version-functions.c bson-writer.c"
-
- dnl Generated with: find src/libmongoc/src/libbson/src/jsonsl -name '*.c' -print0 | cut -sz -d / -f 7- | sort -dz | tr '\000' ' '
- PHP_MONGODB_JSONSL_SOURCES="jsonsl.c"
-
- dnl Generated with: find src/libmongoc/src/libmongoc/src/mongoc -name '*.c' -print0 | cut -sz -d / -f 7- | sort -dz | tr '\000' ' '
- PHP_MONGODB_MONGOC_SOURCES="mongoc-aggregate.c mongoc-apm.c mongoc-array.c mongoc-async.c mongoc-async-cmd.c mongoc-buffer.c mongoc-bulk-operation.c mongoc-change-stream.c mongoc-client.c mongoc-client-pool.c mongoc-client-session.c mongoc-client-side-encryption.c mongoc-cluster-aws.c mongoc-cluster.c mongoc-cluster-cyrus.c mongoc-cluster-sasl.c mongoc-cluster-sspi.c mongoc-cmd.c mongoc-collection.c mongoc-compression.c mongoc-counters.c mongoc-crypt.c mongoc-crypto.c mongoc-crypto-cng.c mongoc-crypto-common-crypto.c mongoc-crypto-openssl.c mongoc-cursor-array.c mongoc-cursor.c mongoc-cursor-change-stream.c mongoc-cursor-cmd.c mongoc-cursor-cmd-deprecated.c mongoc-cursor-find.c mongoc-cursor-find-cmd.c mongoc-cursor-find-opquery.c mongoc-cursor-legacy.c mongoc-cyrus.c mongoc-database.c mongoc-error.c mongoc-find-and-modify.c mongoc-generation-map.c mongoc-gridfs-bucket.c mongoc-gridfs-bucket-file.c mongoc-gridfs.c mongoc-gridfs-file.c mongoc-gridfs-file-list.c mongoc-gridfs-file-page.c mongoc-handshake.c mongoc-host-list.c mongoc-http.c mongoc-index.c mongoc-init.c mongoc-interrupt.c mongoc-libressl.c mongoc-linux-distro-scanner.c mongoc-list.c mongoc-log.c mongoc-matcher.c mongoc-matcher-op.c mongoc-memcmp.c mongoc-ocsp-cache.c mongoc-openssl.c mongoc-optional.c mongoc-opts.c mongoc-opts-helpers.c mongoc-queue.c mongoc-rand-cng.c mongoc-rand-common-crypto.c mongoc-rand-openssl.c mongoc-read-concern.c mongoc-read-prefs.c mongoc-rpc.c mongoc-sasl.c mongoc-scram.c mongoc-secure-channel.c mongoc-secure-transport.c mongoc-server-api.c mongoc-server-description.c mongoc-server-monitor.c mongoc-server-stream.c mongoc-set.c mongoc-shared.c mongoc-socket.c mongoc-ssl.c mongoc-sspi.c mongoc-stream-buffered.c mongoc-stream.c mongoc-stream-file.c mongoc-stream-gridfs.c mongoc-stream-gridfs-download.c mongoc-stream-gridfs-upload.c mongoc-stream-socket.c mongoc-stream-tls.c mongoc-stream-tls-libressl.c mongoc-stream-tls-openssl-bio.c mongoc-stream-tls-openssl.c mongoc-stream-tls-secure-channel.c mongoc-stream-tls-secure-transport.c mongoc-timeout.c mongoc-topology-background-monitoring.c mongoc-topology.c mongoc-topology-description-apm.c mongoc-topology-description.c mongoc-topology-scanner.c mongoc-ts-pool.c mongoc-uri.c mongoc-util.c mongoc-version-functions.c mongoc-write-command.c mongoc-write-command-legacy.c mongoc-write-concern.c"
-
- dnl Generated with: find src/libmongoc/src/zlib-1.2.11 -maxdepth 1 -name '*.c' -print0 | cut -sz -d / -f 5- | sort -dz | tr '\000' ' '
- PHP_MONGODB_ZLIB_SOURCES="adler32.c compress.c crc32.c deflate.c gzclose.c gzlib.c gzread.c gzwrite.c infback.c inffast.c inflate.c inftrees.c trees.c uncompr.c zutil.c"
-
- PHP_MONGODB_ADD_SOURCES([src/libmongoc/src/common/], $PHP_MONGODB_COMMON_SOURCES, $PHP_MONGODB_BUNDLED_CFLAGS)
- PHP_MONGODB_ADD_SOURCES([src/libmongoc/src/libbson/src/bson/], $PHP_MONGODB_BSON_SOURCES, $PHP_MONGODB_BUNDLED_CFLAGS)
- PHP_MONGODB_ADD_SOURCES([src/libmongoc/src/libbson/src/jsonsl/], $PHP_MONGODB_JSONSL_SOURCES, $PHP_MONGODB_BUNDLED_CFLAGS)
- PHP_MONGODB_ADD_SOURCES([src/libmongoc/src/libmongoc/src/mongoc/], $PHP_MONGODB_MONGOC_SOURCES, $PHP_MONGODB_BUNDLED_CFLAGS)
-
- PHP_MONGODB_ADD_INCLUDE([src/libmongoc/src/common/])
- PHP_MONGODB_ADD_INCLUDE([src/libmongoc/src/libbson/src/])
- PHP_MONGODB_ADD_INCLUDE([src/libmongoc/src/libbson/src/jsonsl/])
- PHP_MONGODB_ADD_INCLUDE([src/libmongoc/src/libmongoc/src/])
-
- PHP_MONGODB_ADD_BUILD_DIR([src/libmongoc/src/common/])
- PHP_MONGODB_ADD_BUILD_DIR([src/libmongoc/src/libbson/src/bson/])
- PHP_MONGODB_ADD_BUILD_DIR([src/libmongoc/src/libbson/src/jsonsl/])
- PHP_MONGODB_ADD_BUILD_DIR([src/libmongoc/src/libmongoc/src/mongoc/])
-
- dnl If compiling without libmongocrypt, use kms_message sources bundled with libmongoc.
- dnl If compiling with libmongocrypt, kms_message bundled with libmongocrypt is used as it is most likely newer.
- if test "$PHP_MONGODB_CLIENT_SIDE_ENCRYPTION" != "yes" && test "$PHP_MONGODB_SSL" != "no"; then
- AC_SUBST(MONGOC_ENABLE_MONGODB_AWS_AUTH, 1)
- PHP_MONGODB_ADD_SOURCES([src/libmongoc/src/kms-message/src/], $PHP_MONGODB_KMS_MESSAGE_SOURCES, $PHP_MONGODB_BUNDLED_CFLAGS)
- PHP_MONGODB_ADD_INCLUDE([src/libmongoc/src/kms-message/src/])
- PHP_MONGODB_ADD_BUILD_DIR([src/libmongoc/src/kms-message/src/])
- fi
-
- dnl TODO: Use $ext_srcdir if we can move this after PHP_NEW_EXTENSION
- ac_config_dir=PHP_EXT_SRCDIR(mongodb)
-
- AC_CONFIG_FILES([
- ${ac_config_dir}/src/libmongoc/src/common/common-config.h
- ${ac_config_dir}/src/libmongoc/src/libbson/src/bson/bson-config.h
- ${ac_config_dir}/src/libmongoc/src/libbson/src/bson/bson-version.h
- ${ac_config_dir}/src/libmongoc/src/libmongoc/src/mongoc/mongoc-config.h
- ${ac_config_dir}/src/libmongoc/src/libmongoc/src/mongoc/mongoc-version.h
- ])
-
- if test "x$bundled_zlib" = "xyes"; then
- PHP_MONGODB_ZLIB_CFLAGS="$PHP_MONGODB_BUNDLED_CFLAGS"
- AC_CHECK_HEADER([unistd.h], [PHP_MONGODB_ZLIB_CFLAGS="$PHP_MONGODB_ZLIB_CFLAGS -DHAVE_UNISTD_H=1"], [])
- PHP_MONGODB_ADD_SOURCES([src/libmongoc/src/zlib-1.2.11/], $PHP_MONGODB_ZLIB_SOURCES, $PHP_MONGODB_ZLIB_CFLAGS)
- PHP_MONGODB_ADD_INCLUDE([src/libmongoc/src/zlib-1.2.11/])
- PHP_MONGODB_ADD_BUILD_DIR([src/libmongoc/src/zlib-1.2.11/])
- AC_CONFIG_FILES([${ac_config_dir}/src/libmongoc/src/zlib-1.2.11/zconf.h])
- fi
-
- if test "$PHP_MONGODB_CLIENT_SIDE_ENCRYPTION" = "yes"; then
- dnl Since libmongocrypt adds kms-message, we can enable AWS auth in this case
- AC_SUBST(MONGOC_ENABLE_MONGODB_AWS_AUTH, 1)
- AC_SUBST(MONGOCRYPT_ENABLE_TRACE, 1)
-
- dnl Generated with: find src/libmongocrypt/src -maxdepth 1 -name '*.c' -print0 | cut -sz -d / -f 4- | sort -dz | tr '\000' ' '
- PHP_MONGODB_MONGOCRYPT_SOURCES="mongocrypt-binary.c mongocrypt-buffer.c mongocrypt.c mongocrypt-cache.c mongocrypt-cache-collinfo.c mongocrypt-cache-key.c mongocrypt-cache-oauth.c mongocrypt-ciphertext.c mongocrypt-crypto.c mongocrypt-ctx.c mongocrypt-ctx-datakey.c mongocrypt-ctx-decrypt.c mongocrypt-ctx-encrypt.c mongocrypt-endpoint.c mongocrypt-kek.c mongocrypt-key-broker.c mongocrypt-key.c mongocrypt-kms-ctx.c mongocrypt-log.c mongocrypt-marking.c mongocrypt-opts.c mongocrypt-status.c mongocrypt-traverse-util.c mongocrypt-util.c"
-
- dnl Generated with: find src/libmongocrypt/src/crypto -name '*.c' -print0 | cut -sz -d / -f 5- | sort -dz | tr '\000' ' '
- PHP_MONGODB_MONGOCRYPT_CRYPTO_SOURCES="cng.c commoncrypto.c libcrypto.c none.c"
-
- dnl Generated with: find src/libmongocrypt/src/os_posix -name '*.c' -print0 | cut -sz -d / -f 5- | sort -dz | tr '\000' ' '
- PHP_MONGODB_MONGOCRYPT_OS_POSIX_SOURCES="os_mutex.c os_once.c"
-
- dnl Generated with: find src/libmongocrypt/src/os_win -name '*.c' -print0 | cut -sz -d / -f 5- | sort -dz | tr '\000' ' '
- PHP_MONGODB_MONGOCRYPT_OS_WIN_SOURCES="os_mutex.c os_once.c"
-
- dnl Generated with: find src/libmongocrypt/kms-message/src -maxdepth 1 -name '*.c' -print0 | cut -sz -d / -f 5- | sort -dz | tr '\000' ' '
- PHP_MONGODB_MONGOCRYPT_KMS_MESSAGE_SOURCES="hexlify.c kms_azure_request.c kms_b64.c kms_caller_identity_request.c kms_crypto_apple.c kms_crypto_libcrypto.c kms_crypto_none.c kms_crypto_windows.c kms_decrypt_request.c kms_encrypt_request.c kms_gcp_request.c kms_kmip_reader_writer.c kms_kmip_request.c kms_kmip_response.c kms_kmip_response_parser.c kms_kv_list.c kms_message.c kms_port.c kms_request.c kms_request_opt.c kms_request_str.c kms_response.c kms_response_parser.c sort.c"
-
- PHP_MONGODB_LIBMONGOCRYPT_CFLAGS="$PHP_MONGODB_BUNDLED_CFLAGS $PHP_MONGODB_LIBMONGOCRYPT_CFLAGS"
- PHP_MONGODB_ADD_SOURCES([src/libmongocrypt/src/], $PHP_MONGODB_MONGOCRYPT_SOURCES, $PHP_MONGODB_LIBMONGOCRYPT_CFLAGS)
- PHP_MONGODB_ADD_SOURCES([src/libmongocrypt/src/crypto/], $PHP_MONGODB_MONGOCRYPT_CRYPTO_SOURCES, $PHP_MONGODB_LIBMONGOCRYPT_CFLAGS)
- PHP_MONGODB_ADD_SOURCES([src/libmongocrypt/src/os_posix/], $PHP_MONGODB_MONGOCRYPT_OS_POSIX_SOURCES, $PHP_MONGODB_LIBMONGOCRYPT_CFLAGS)
- PHP_MONGODB_ADD_SOURCES([src/libmongocrypt/src/os_win/], $PHP_MONGODB_MONGOCRYPT_OS_WIN_SOURCES, $PHP_MONGODB_LIBMONGOCRYPT_CFLAGS)
- PHP_MONGODB_ADD_SOURCES([src/libmongocrypt/kms-message/src/], $PHP_MONGODB_MONGOCRYPT_KMS_MESSAGE_SOURCES, $PHP_MONGODB_LIBMONGOCRYPT_CFLAGS)
-
- PHP_MONGODB_ADD_INCLUDE([src/libmongocrypt/src/])
- PHP_MONGODB_ADD_INCLUDE([src/libmongocrypt/kms-message/src/])
- PHP_MONGODB_ADD_INCLUDE([src/libmongocrypt-compat/])
-
- PHP_MONGODB_ADD_BUILD_DIR([src/libmongocrypt/src/])
- PHP_MONGODB_ADD_BUILD_DIR([src/libmongocrypt/src/crypto/])
- PHP_MONGODB_ADD_BUILD_DIR([src/libmongocrypt/src/os_posix/])
- PHP_MONGODB_ADD_BUILD_DIR([src/libmongocrypt/src/os_win/])
- PHP_MONGODB_ADD_BUILD_DIR([src/libmongocrypt/kms-message/src/])
-
- AC_CONFIG_FILES([
- ${ac_config_dir}/src/libmongocrypt/src/mongocrypt-config.h
- ${ac_config_dir}/src/libmongocrypt/src/mongocrypt.h
- ])
- fi
- fi
-
- PHP_NEW_EXTENSION(mongodb, $PHP_MONGODB_SOURCES, $ext_shared,, $PHP_MONGODB_CFLAGS)
-
- PHP_SUBST(MONGODB_SHARED_LIBADD)
-
- PHP_ADD_EXTENSION_DEP(mongodb, date)
- PHP_ADD_EXTENSION_DEP(mongodb, json)
- PHP_ADD_EXTENSION_DEP(mongodb, spl)
- PHP_ADD_EXTENSION_DEP(mongodb, standard)
-
- PHP_ADD_INCLUDE(PHP_EXT_SRCDIR(mongodb)[/src/BSON/])
- PHP_ADD_INCLUDE(PHP_EXT_SRCDIR(mongodb)[/src/MongoDB/])
- PHP_ADD_INCLUDE(PHP_EXT_SRCDIR(mongodb)[/src/MongoDB/Exception/])
- PHP_ADD_INCLUDE(PHP_EXT_SRCDIR(mongodb)[/src/MongoDB/Monitoring/])
- PHP_ADD_INCLUDE(PHP_EXT_SRCDIR(mongodb)[/src/contrib/])
-
- PHP_ADD_BUILD_DIR(PHP_EXT_BUILDDIR(mongodb)[/src/BSON/])
- PHP_ADD_BUILD_DIR(PHP_EXT_BUILDDIR(mongodb)[/src/MongoDB/])
- PHP_ADD_BUILD_DIR(PHP_EXT_BUILDDIR(mongodb)[/src/MongoDB/Exception/])
- PHP_ADD_BUILD_DIR(PHP_EXT_BUILDDIR(mongodb)[/src/MongoDB/Monitoring/])
- PHP_ADD_BUILD_DIR(PHP_EXT_BUILDDIR(mongodb)[/src/contrib/])
-
- dnl Necessary to ensure that static builds include "-pthread" when linking
- if test "$ext_shared" != "yes"; then
- EXTRA_LDFLAGS_PROGRAM="$EXTRA_LDFLAGS_PROGRAM $EXTRA_LDFLAGS"
- fi
-
- dnl This must come after PHP_NEW_EXTENSION, otherwise the srcdir won't be set
- PHP_ADD_MAKEFILE_FRAGMENT
-
- dnl The libmongocrypt line intentionally uses the PHP_LIBBSON flag as that decides whether to build against bundled or system libraries.
- AC_CONFIG_COMMANDS_POST([
- if test "$enable_static" = "no"; then
- echo "
-mongodb was configured with the following options:
-
-Build configuration:
- CFLAGS : $CFLAGS
- Extra CFLAGS : $STD_CFLAGS $EXTRA_CFLAGS
- Developers flags (slow) : $MAINTAINER_CFLAGS
- Code Coverage flags (extra slow) : $COVERAGE_CFLAGS
- libmongoc : $PHP_MONGODB_BSON_VERSION_STRING
- libbson : $PHP_MONGODB_MONGOC_VERSION_STRING
- libmongocrypt : $PHP_MONGODB_MONGOCRYPT_VERSION_STRING
- LDFLAGS : $LDFLAGS
- EXTRA_LDFLAGS : $EXTRA_LDFLAGS
- MONGODB_SHARED_LIBADD : $MONGODB_SHARED_LIBADD
-
-Please submit bugreports at:
- https://jira.mongodb.org/browse/PHPC
-
-"
- fi
- ])
-fi
-
-dnl: vim: et sw=2
diff --git a/mongodb-1.12.0/config.w32 b/mongodb-1.12.0/config.w32
deleted file mode 100644
index 82492909..00000000
--- a/mongodb-1.12.0/config.w32
+++ /dev/null
@@ -1,378 +0,0 @@
-// vim:ft=javascript
-
-function mongodb_generate_header(inpath, outpath, replacements)
-{
- STDOUT.WriteLine("Generating " + outpath);
-
- var infile = FSO.OpenTextFile(inpath, 1);
- var outdata = infile.ReadAll();
- infile.Close();
-
- for (var key in replacements) {
- var replacement = replacements[key];
-
- if (typeof replacement === 'string') {
- replacement = replacement.replace(/"/g, '\\"');
- }
-
- outdata = outdata.replace(new RegExp('@' + key + '@', 'g'), replacement);
- }
-
- var outfile = FSO.CreateTextFile(outpath, true);
- outfile.Write(outdata);
- outfile.Close();
-}
-
-function mongodb_parse_version_file(inpath, prefix)
-{
- var infile = FSO.OpenTextFile(inpath, 1);
- var version = infile.ReadLine();
- infile.Close();
-
- var xyz_pre = version.split("-");
- var xyz = xyz_pre[0].split(".");
- var pre = xyz_pre.length > 1 ? xyz_pre[1] : "";
-
- var replacements = {};
- replacements[prefix + "VERSION"] = version;
- replacements[prefix + "MAJOR_VERSION"] = xyz[0];
- replacements[prefix + "MINOR_VERSION"] = xyz[1];
- replacements[prefix + "MICRO_VERSION"] = xyz[2];
- replacements[prefix + "PRERELEASE_VERSION"] = pre;
-
- return replacements;
-}
-
-function create_folder_recursive(path)
-{
- if (FSO.FolderExists(path)) {
- return;
- }
-
- create_folder_recursive(FSO.GetParentFolderName(path));
- FSO.CreateFolder(path);
-}
-
-function MONGODB_ADD_SOURCES(dir, file_list)
-{
- // Ensure obj_dir and all parent directories exist
- create_folder_recursive(FSO.BuildPath(get_define('BUILD_DIR'), dir));
- ADD_SOURCES(configure_module_dirname + dir, file_list, "mongodb", dir);
-}
-
-ARG_ENABLE("mongodb", "MongoDB support", "no");
-ARG_WITH("mongodb-sasl", "MongoDB: Build against Cyrus-SASL", "yes");
-ARG_WITH("mongodb-client-side-encryption", "MongoDB: Enable client-side encryption", "yes");
-
-if (PHP_MONGODB != "no") {
- /* Note: ADD_EXTENSION_DEP() only reports the date and standard extensions as
- * installed in PHP 7.3.25+, 7.4.13+, and 8.0.0+). On other versions, assume
- * that they're always enabled. */
- if (
- PHP_VERSION >= 8 ||
- (PHP_VERSION == 7 && PHP_MINOR_VERSION == 3 && PHP_RELEASE_VERSION >= 25) ||
- (PHP_VERSION == 7 && PHP_MINOR_VERSION == 4 && PHP_RELEASE_VERSION >= 13)
- ) {
- ADD_EXTENSION_DEP("mongodb", "date", false);
- ADD_EXTENSION_DEP("mongodb", "standard", false);
- }
-
- ADD_EXTENSION_DEP("mongodb", "json", false);
- ADD_EXTENSION_DEP("mongodb", "spl", false);
-
- /* MongoDB does not actually depend on PHP's OpenSSL extension, but this is in
- * place to ensure that later SSL library checks succeed. This can be removed
- * once we support building with Secure Channel. */
- ADD_EXTENSION_DEP("mongodb", "openssl", false);
-
- var PHP_MONGODB_CFLAGS="\
- /D BSON_COMPILATION /D MONGOC_COMPILATION \
- /I" + configure_module_dirname + " \
- /I" + configure_module_dirname + "/src/BSON \
- /I" + configure_module_dirname + "/src/MongoDB \
- /I" + configure_module_dirname + "/src/MongoDB/Exception \
- /I" + configure_module_dirname + "/src/contrib \
- /I" + configure_module_dirname + "/src/libmongoc/src/common \
- /I" + configure_module_dirname + "/src/libmongoc/src/libbson/src \
- /I" + configure_module_dirname + "/src/libmongoc/src/libbson/src/jsonsl \
- /I" + configure_module_dirname + "/src/libmongoc/src/libmongoc/src \
- ";
-
- // Condense whitespace in CFLAGS
- PHP_MONGODB_CFLAGS = PHP_MONGODB_CFLAGS.replace(/\s+/g, ' ');
-
- // On MacOS, use gcut from the coreutils brew package instead of cut
- // Generated with: find src/libmongoc/src/common -name '*.c' -print0 | cut -sz -d / -f 5- | sort -dz | tr '\000' ' '
- var PHP_MONGODB_COMMON_SOURCES="common-b64.c common-md5.c common-thread.c"
-
- // Generated with: find src/libmongoc/src/kms-message/src -maxdepth 1 -name '*.c' -print0 | cut -sz -d / -f 6- | sort -dz | tr '\000' ' '
- var PHP_MONGODB_KMS_MESSAGE_SOURCES="hexlify.c kms_b64.c kms_caller_identity_request.c kms_crypto_apple.c kms_crypto_libcrypto.c kms_crypto_none.c kms_crypto_windows.c kms_decrypt_request.c kms_encrypt_request.c kms_kv_list.c kms_message.c kms_port.c kms_request.c kms_request_opt.c kms_request_str.c kms_response.c kms_response_parser.c sort.c";
-
- // Generated with: find src/libmongoc/src/libbson/src/bson -name '*.c' -print0 | cut -sz -d / -f 7- | sort -dz | tr '\000' ' '
- var PHP_MONGODB_BSON_SOURCES="bcon.c bson-atomic.c bson.c bson-clock.c bson-context.c bson-decimal128.c bson-error.c bson-iso8601.c bson-iter.c bson-json.c bson-keys.c bson-md5.c bson-memory.c bson-oid.c bson-reader.c bson-string.c bson-timegm.c bson-utf8.c bson-value.c bson-version-functions.c bson-writer.c";
-
- // Generated with: find src/libmongoc/src/libbson/src/jsonsl -name '*.c' -print0 | cut -sz -d / -f 7- | sort -dz | tr '\000' ' '
- var PHP_MONGODB_JSONSL_SOURCES="jsonsl.c";
-
- // Generated with: find src/libmongoc/src/libmongoc/src/mongoc -name '*.c' -print0 | cut -sz -d / -f 7- | sort -dz | tr '\000' ' '
- var PHP_MONGODB_MONGOC_SOURCES="mongoc-aggregate.c mongoc-apm.c mongoc-array.c mongoc-async.c mongoc-async-cmd.c mongoc-buffer.c mongoc-bulk-operation.c mongoc-change-stream.c mongoc-client.c mongoc-client-pool.c mongoc-client-session.c mongoc-client-side-encryption.c mongoc-cluster-aws.c mongoc-cluster.c mongoc-cluster-cyrus.c mongoc-cluster-sasl.c mongoc-cluster-sspi.c mongoc-cmd.c mongoc-collection.c mongoc-compression.c mongoc-counters.c mongoc-crypt.c mongoc-crypto.c mongoc-crypto-cng.c mongoc-crypto-common-crypto.c mongoc-crypto-openssl.c mongoc-cursor-array.c mongoc-cursor.c mongoc-cursor-change-stream.c mongoc-cursor-cmd.c mongoc-cursor-cmd-deprecated.c mongoc-cursor-find.c mongoc-cursor-find-cmd.c mongoc-cursor-find-opquery.c mongoc-cursor-legacy.c mongoc-cyrus.c mongoc-database.c mongoc-error.c mongoc-find-and-modify.c mongoc-generation-map.c mongoc-gridfs-bucket.c mongoc-gridfs-bucket-file.c mongoc-gridfs.c mongoc-gridfs-file.c mongoc-gridfs-file-list.c mongoc-gridfs-file-page.c mongoc-handshake.c mongoc-host-list.c mongoc-http.c mongoc-index.c mongoc-init.c mongoc-interrupt.c mongoc-libressl.c mongoc-linux-distro-scanner.c mongoc-list.c mongoc-log.c mongoc-matcher.c mongoc-matcher-op.c mongoc-memcmp.c mongoc-ocsp-cache.c mongoc-openssl.c mongoc-optional.c mongoc-opts.c mongoc-opts-helpers.c mongoc-queue.c mongoc-rand-cng.c mongoc-rand-common-crypto.c mongoc-rand-openssl.c mongoc-read-concern.c mongoc-read-prefs.c mongoc-rpc.c mongoc-sasl.c mongoc-scram.c mongoc-secure-channel.c mongoc-secure-transport.c mongoc-server-api.c mongoc-server-description.c mongoc-server-monitor.c mongoc-server-stream.c mongoc-set.c mongoc-shared.c mongoc-socket.c mongoc-ssl.c mongoc-sspi.c mongoc-stream-buffered.c mongoc-stream.c mongoc-stream-file.c mongoc-stream-gridfs.c mongoc-stream-gridfs-download.c mongoc-stream-gridfs-upload.c mongoc-stream-socket.c mongoc-stream-tls.c mongoc-stream-tls-libressl.c mongoc-stream-tls-openssl-bio.c mongoc-stream-tls-openssl.c mongoc-stream-tls-secure-channel.c mongoc-stream-tls-secure-transport.c mongoc-timeout.c mongoc-topology-background-monitoring.c mongoc-topology.c mongoc-topology-description-apm.c mongoc-topology-description.c mongoc-topology-scanner.c mongoc-ts-pool.c mongoc-uri.c mongoc-util.c mongoc-version-functions.c mongoc-write-command.c mongoc-write-command-legacy.c mongoc-write-concern.c";
-
- EXTENSION("mongodb", "php_phongo.c phongo_compat.c", null, PHP_MONGODB_CFLAGS);
- MONGODB_ADD_SOURCES("/src", "bson.c bson-encode.c phongo_apm.c phongo_ini.c");
- MONGODB_ADD_SOURCES("/src/BSON", "Binary.c BinaryInterface.c DBPointer.c Decimal128.c Decimal128Interface.c Int64.c Javascript.c JavascriptInterface.c MaxKey.c MaxKeyInterface.c MinKey.c MinKeyInterface.c ObjectId.c ObjectIdInterface.c Persistable.c Regex.c RegexInterface.c Serializable.c Symbol.c Timestamp.c TimestampInterface.c Type.c Undefined.c Unserializable.c UTCDateTime.c UTCDateTimeInterface.c functions.c");
- MONGODB_ADD_SOURCES("/src/MongoDB", "BulkWrite.c ClientEncryption.c Command.c Cursor.c CursorId.c CursorInterface.c Manager.c Query.c ReadConcern.c ReadPreference.c Server.c ServerApi.c Session.c WriteConcern.c WriteConcernError.c WriteError.c WriteResult.c");
- MONGODB_ADD_SOURCES("/src/MongoDB/Exception", "AuthenticationException.c BulkWriteException.c CommandException.c ConnectionException.c ConnectionTimeoutException.c EncryptionException.c Exception.c ExecutionTimeoutException.c InvalidArgumentException.c LogicException.c RuntimeException.c ServerException.c SSLConnectionException.c UnexpectedValueException.c WriteException.c");
- MONGODB_ADD_SOURCES("/src/MongoDB/Monitoring", "CommandFailedEvent.c CommandStartedEvent.c CommandSubscriber.c CommandSucceededEvent.c Subscriber.c functions.c");
- MONGODB_ADD_SOURCES("/src/libmongoc/src/common", PHP_MONGODB_COMMON_SOURCES);
- MONGODB_ADD_SOURCES("/src/libmongoc/src/libbson/src/bson", PHP_MONGODB_BSON_SOURCES);
- MONGODB_ADD_SOURCES("/src/libmongoc/src/libbson/src/jsonsl", PHP_MONGODB_JSONSL_SOURCES);
- MONGODB_ADD_SOURCES("/src/libmongoc/src/libmongoc/src/mongoc", PHP_MONGODB_MONGOC_SOURCES);
-
- var bson_opts = {
- BSON_BYTE_ORDER: 1234,
- BSON_OS: 2,
- BSON_HAVE_STDBOOL_H: 0,
- BSON_HAVE_STRINGS_H: 0,
- BSON_HAVE_ATOMIC_32_ADD_AND_FETCH: 0,
- BSON_HAVE_ATOMIC_64_ADD_AND_FETCH: 0,
- BSON_PTHREAD_ONCE_INIT_NEEDS_BRACES: 0,
- BSON_HAVE_CLOCK_GETTIME: 0,
- BSON_HAVE_STRNLEN: 0,
- BSON_HAVE_SNPRINTF: 0,
- BSON_HAVE_STRLCPY: 0,
- BSON_HAVE_REALLOCF: 0,
- BSON_NEEDS_SET_OUTPUT_FORMAT: 0,
- BSON_HAVE_TIMESPEC: 0,
- BSON_EXTRA_ALIGN: 0,
- BSON_HAVE_SYSCALL_TID: 0,
- BSON_HAVE_DECIMAL128: 0,
- BSON_HAVE_GMTIME_R: 0,
- BSON_HAVE_RAND_R: 0
- };
-
- if (CHECK_FUNC_IN_HEADER("stdio.h", "_set_output_format")) {
- bson_opts.BSON_NEEDS_SET_OUTPUT_FORMAT = 1;
- }
-
- mongodb_generate_header(
- configure_module_dirname + "/src/libmongoc/src/libbson/src/bson/bson-config.h.in",
- configure_module_dirname + "/src/libmongoc/src/libbson/src/bson/bson-config.h",
- bson_opts
- );
-
- mongodb_generate_header(
- configure_module_dirname + "/src/libmongoc/src/libbson/src/bson/bson-version.h.in",
- configure_module_dirname + "/src/libmongoc/src/libbson/src/bson/bson-version.h",
- mongodb_parse_version_file(configure_module_dirname + "/src/LIBMONGOC_VERSION_CURRENT", "BSON_")
- );
-
- var mongoc_opts = {
- // TODO: Support building with Secure Channel on Windows
- MONGOC_ENABLE_SSL_SECURE_CHANNEL: 0,
- MONGOC_ENABLE_CRYPTO_CNG: 0,
- // Secure Transport does not apply to Windows
- MONGOC_ENABLE_SSL_SECURE_TRANSPORT: 0,
- MONGOC_ENABLE_CRYPTO_COMMON_CRYPTO: 0,
- MONGOC_ENABLE_SSL_LIBRESSL: 0,
- MONGOC_ENABLE_SSL_OPENSSL: 0,
- MONGOC_ENABLE_CRYPTO_LIBCRYPTO: 0,
- MONGOC_ENABLE_SSL: 0,
- MONGOC_ENABLE_CRYPTO: 0,
- MONGOC_ENABLE_CRYPTO_SYSTEM_PROFILE: 0,
- MONGOC_ENABLE_CLIENT_SIDE_ENCRYPTION: 0,
- MONGOC_ENABLE_COMPRESSION_SNAPPY: 0,
- MONGOC_ENABLE_COMPRESSION_ZLIB: 0,
- MONGOC_ENABLE_COMPRESSION_ZSTD: 0,
- MONGOC_ENABLE_COMPRESSION: 0,
- MONGOC_ENABLE_DEBUG_ASSERTIONS: 0,
- MONGOC_ENABLE_MONGODB_AWS_AUTH: 0,
- MONGOC_ENABLE_SASL: 0,
- MONGOC_ENABLE_SASL_CYRUS: 0,
- MONGOC_ENABLE_SASL_GSSAPI: 0,
- MONGOC_ENABLE_SASL_SSPI: 0,
- MONGOC_ENABLE_ICU: 0,
- MONGOC_ENABLE_RDTSCP: 0,
- MONGOC_ENABLE_SHM_COUNTERS: 0,
- MONGOC_HAVE_ASN1_STRING_GET0_DATA: 0,
- MONGOC_HAVE_SASL_CLIENT_DONE: 0,
- MONGOC_HAVE_SCHED_GETCPU: 0,
- MONGOC_HAVE_SOCKLEN: 1,
- MONGOC_HAVE_WEAK_SYMBOLS: 0,
- MONGOC_NO_AUTOMATIC_GLOBALS: 1,
- MONGOC_SOCKET_ARG2: "struct sockaddr",
- MONGOC_SOCKET_ARG3: "socklen_t",
- MONGOC_TRACE: 1,
- MONGOC_HAVE_DNSAPI: 0,
- MONGOC_HAVE_RES_NSEARCH: 0,
- MONGOC_HAVE_RES_NDESTROY: 0,
- MONGOC_HAVE_RES_NCLOSE: 0,
- MONGOC_HAVE_RES_SEARCH: 0,
- MONGOC_HAVE_SS_FAMILY: 0,
- MONGOC_CC: "",
- MONGOC_USER_SET_CFLAGS: "",
- MONGOC_USER_SET_LDFLAGS: ""
- };
-
- var mongoc_ssl_path_to_check = PHP_MONGODB;
-
- if (typeof PHP_OPENSSL === 'string') {
- mongoc_ssl_path_to_check += ";" + PHP_OPENSSL;
- }
-
- var mongoc_ssl_found = false;
-
- /* PHP 7.1.2 introduced SETUP_OPENSSL(), which supports OpenSSL 1.1.x. Earlier
- * versions will use the legacy check for OpenSSL 1.0.x and lower. */
- if (typeof SETUP_OPENSSL === 'function') {
- openssl_type = SETUP_OPENSSL("mongodb", mongoc_ssl_path_to_check);
- mongoc_ssl_found = openssl_type > 0;
- if (openssl_type >= 2) {
- mongoc_opts.MONGOC_HAVE_ASN1_STRING_GET0_DATA = 1;
- }
- } else if (CHECK_LIB("ssleay32.lib", "mongodb", mongoc_ssl_path_to_check) &&
- CHECK_LIB("libeay32.lib", "mongodb", mongoc_ssl_path_to_check) &&
- CHECK_LIB("crypt32.lib", "mongodb", mongoc_ssl_path_to_check) &&
- CHECK_HEADER_ADD_INCLUDE("openssl/ssl.h", "CFLAGS_MONGODB")) {
- mongoc_ssl_found = true;
- }
-
- if (mongoc_ssl_found) {
- mongoc_opts.MONGOC_ENABLE_SSL_OPENSSL = 1;
- mongoc_opts.MONGOC_ENABLE_CRYPTO_LIBCRYPTO = 1;
- mongoc_opts.MONGOC_ENABLE_SSL = 1;
- mongoc_opts.MONGOC_ENABLE_CRYPTO = 1;
- mongoc_opts.MONGOC_ENABLE_MONGODB_AWS_AUTH = 1;
-
- ADD_FLAG("CFLAGS_MONGODB", "/D KMS_MSG_STATIC=1 /D KMS_MESSAGE_ENABLE_CRYPTO=1 /D KMS_MESSAGE_ENABLE_CRYPTO_LIBCRYPTO=1");
- } else {
- WARNING("mongodb libopenssl support not enabled, libs not found");
- }
-
- // TODO: Support building with native GSSAPI (SSPI) on Windows
- if (PHP_MONGODB_SASL != "no" &&
- CHECK_LIB("libsasl.lib", "mongodb", PHP_MONGODB) &&
- CHECK_HEADER_ADD_INCLUDE("sasl/sasl.h", "CFLAGS_MONGODB")) {
- mongoc_opts.MONGOC_ENABLE_SASL = 1;
- mongoc_opts.MONGOC_ENABLE_SASL_CYRUS = 1;
- if (CHECK_FUNC_IN_HEADER("sasl/sasl.h", "sasl_client_done")) {
- mongoc_opts.MONGOC_HAVE_SASL_CLIENT_DONE = 1;
- }
- } else if (PHP_MONGODB_SASL != "no") {
- WARNING("mongodb libsasl support not enabled, libs not found");
- }
-
- if (PHP_MONGODB_CLIENT_SIDE_ENCRYPTION != "no" && mongoc_ssl_found) {
- mongoc_opts.MONGOC_ENABLE_CLIENT_SIDE_ENCRYPTION = 1;
-
- ADD_FLAG("CFLAGS_MONGODB", "/D KMS_MESSAGE_LITTLE_ENDIAN=1");
- ADD_FLAG("CFLAGS_MONGODB", "/I" + configure_module_dirname + "/src/libmongocrypt/src");
- ADD_FLAG("CFLAGS_MONGODB", "/I" + configure_module_dirname + "/src/libmongocrypt/kms-message/src");
- ADD_FLAG("CFLAGS_MONGODB", "/I" + configure_module_dirname + "/src/libmongocrypt-compat");
-
- var mongocrypt_opts = {
- MONGOCRYPT_ENABLE_TRACE: 1,
- MONGOCRYPT_ENABLE_CRYPTO: 1,
- MONGOCRYPT_ENABLE_CRYPTO_LIBCRYPTO: 1,
- // TODO: Support building with Secure Channel on Windows
- MONGOCRYPT_ENABLE_CRYPTO_CNG: 0,
- // Secure Transport does not apply to Windows
- MONGOCRYPT_ENABLE_CRYPTO_COMMON_CRYPTO: 0
- };
-
- // Generated with: find src/libmongocrypt/src -maxdepth 1 -name '*.c' -print0 | cut -sz -d / -f 4- | sort -dz | tr '\000' ' '
- var PHP_MONGODB_MONGOCRYPT_SOURCES="mongocrypt-binary.c mongocrypt-buffer.c mongocrypt.c mongocrypt-cache.c mongocrypt-cache-collinfo.c mongocrypt-cache-key.c mongocrypt-cache-oauth.c mongocrypt-ciphertext.c mongocrypt-crypto.c mongocrypt-ctx.c mongocrypt-ctx-datakey.c mongocrypt-ctx-decrypt.c mongocrypt-ctx-encrypt.c mongocrypt-endpoint.c mongocrypt-kek.c mongocrypt-key-broker.c mongocrypt-key.c mongocrypt-kms-ctx.c mongocrypt-log.c mongocrypt-marking.c mongocrypt-opts.c mongocrypt-status.c mongocrypt-traverse-util.c mongocrypt-util.c";
-
- // Generated with: find src/libmongocrypt/src/crypto -name '*.c' -print0 | cut -sz -d / -f 5- | sort -dz | tr '\000' ' '
- var PHP_MONGODB_MONGOCRYPT_CRYPTO_SOURCES="cng.c commoncrypto.c libcrypto.c none.c";
-
- // Generated with: find src/libmongocrypt/src/os_posix -name '*.c' -print0 | cut -sz -d / -f 5- | sort -dz | tr '\000' ' '
- var PHP_MONGODB_MONGOCRYPT_OS_POSIX_SOURCES="os_mutex.c os_once.c";
-
- // Generated with: find src/libmongocrypt/src/os_win -name '*.c' -print0 | cut -sz -d / -f 5- | sort -dz | tr '\000' ' '
- var PHP_MONGODB_MONGOCRYPT_OS_WIN_SOURCES="os_mutex.c os_once.c";
-
- // Generated with: find src/libmongocrypt/kms-message/src -maxdepth 1 -name '*.c' -print0 | cut -sz -d / -f 5- | sort -dz | tr '\000' ' '
- var PHP_MONGODB_MONGOCRYPT_KMS_MESSAGE_SOURCES="hexlify.c kms_azure_request.c kms_b64.c kms_caller_identity_request.c kms_crypto_apple.c kms_crypto_libcrypto.c kms_crypto_none.c kms_crypto_windows.c kms_decrypt_request.c kms_encrypt_request.c kms_gcp_request.c kms_kmip_reader_writer.c kms_kmip_request.c kms_kmip_response.c kms_kmip_response_parser.c kms_kv_list.c kms_message.c kms_port.c kms_request.c kms_request_opt.c kms_request_str.c kms_response.c kms_response_parser.c sort.c";
-
- MONGODB_ADD_SOURCES("/src/libmongocrypt/src", PHP_MONGODB_MONGOCRYPT_SOURCES);
- MONGODB_ADD_SOURCES("/src/libmongocrypt/src/crypto", PHP_MONGODB_MONGOCRYPT_CRYPTO_SOURCES);
- MONGODB_ADD_SOURCES("/src/libmongocrypt/src/os_posix", PHP_MONGODB_MONGOCRYPT_OS_POSIX_SOURCES);
- MONGODB_ADD_SOURCES("/src/libmongocrypt/src/os_win", PHP_MONGODB_MONGOCRYPT_OS_WIN_SOURCES);
- MONGODB_ADD_SOURCES("/src/libmongocrypt/kms-message/src", PHP_MONGODB_MONGOCRYPT_KMS_MESSAGE_SOURCES);
-
- var mongocrypt_version = mongodb_parse_version_file(configure_module_dirname + "/src/LIBMONGOCRYPT_VERSION_CURRENT", "")
- mongocrypt_opts.MONGOCRYPT_BUILD_VERSION = mongocrypt_version.VERSION;
-
- mongodb_generate_header(
- configure_module_dirname + "/src/libmongocrypt/src/mongocrypt-config.h.in",
- configure_module_dirname + "/src/libmongocrypt/src/mongocrypt-config.h",
- mongocrypt_opts
- );
-
- mongodb_generate_header(
- configure_module_dirname + "/src/libmongocrypt/src/mongocrypt.h.in",
- configure_module_dirname + "/src/libmongocrypt/src/mongocrypt.h",
- mongocrypt_opts
- );
- } else if (PHP_MONGODB_CLIENT_SIDE_ENCRYPTION != "no") {
- // No SSL library found, we can't enable libmongocrypt
- WARNING("mongodb libmongocrypt support not enabled, crypto libs not found");
- }
-
- if (PHP_MONGODB_CLIENT_SIDE_ENCRYPTION == "no" && mongoc_ssl_found) {
- // Add kms-message sources bundled with libmongoc
- MONGODB_ADD_SOURCES("/src/libmongoc/src/kms-message/src", PHP_MONGODB_KMS_MESSAGE_SOURCES);
- ADD_FLAG("CFLAGS_MONGODB", "/I" + configure_module_dirname + "/src/libmongoc/src/kms-message/src");
- }
-
- if (CHECK_LIB("dnsapi.lib", "mongodb", PHP_MONGODB) &&
- CHECK_HEADER_ADD_INCLUDE("windns.h", "CFLAGS_MONGODB")) {
- mongoc_opts.MONGOC_HAVE_DNSAPI = 1;
- }
-
- if (CHECK_LIB("icuuc.lib", "mongodb", PHP_MONGODB) &&
- CHECK_HEADER_ADD_INCLUDE("unicode/utf.h", "CFLAGS_MONGODB")) {
- mongoc_opts.MONGODB_ENABLE_ICU = 1;
-
- ADD_FLAG("LIBS_MONGODB", "icudt.lib icuin.lib icuio.lib");
-
- /* Compat for ICU before 58.1.*/
- if (CHECK_LIB("icule.lib", "mongodb", PHP_MONGODB)) {
- ADD_FLAG("LIBS_MONGODB", "icule.lib");
- }
- if (CHECK_LIB("iculx.lib", "mongodb", PHP_MONGODB)) {
- ADD_FLAG("LIBS_MONGODB", "iculx.lib");
- }
-
- ADD_FLAG("CFLAGS_MONGODB", "/EHsc /D U_USING_ICU_NAMESPACE=1");
- }
-
- if (typeof COMPILER_NAME === 'string') {
- mongoc_opts.MONGOC_CC = COMPILER_NAME;
- } else if (typeof VC_VERSIONS === 'array' && typeof VC_VERSIONS[VCVERS] === 'string') {
- mongoc_opts.MONGOC_CC = VC_VERSIONS[VCVERS];
- } else if (typeof COMPILER_NAME_LONG === 'string') {
- mongoc_opts.MONGOC_CC = COMPILER_NAME_LONG;
- }
-
- /* MONGOC_USER_SET_CFLAGS and MONGOC_USER_SET_LDFLAGS can be left blank, as we
- * do not expect CFLAGS or LDFLAGS to be customized at build time. */
-
- mongodb_generate_header(
- configure_module_dirname + "/src/libmongoc/src/libmongoc/src/mongoc/mongoc-config.h.in",
- configure_module_dirname + "/src/libmongoc/src/libmongoc/src/mongoc/mongoc-config.h",
- mongoc_opts
- );
-
- mongodb_generate_header(
- configure_module_dirname + "/src/libmongoc/src/common/common-config.h.in",
- configure_module_dirname + "/src/libmongoc/src/common/common-config.h",
- mongoc_opts
- );
-
- mongodb_generate_header(
- configure_module_dirname + "/src/libmongoc/src/libmongoc/src/mongoc/mongoc-version.h.in",
- configure_module_dirname + "/src/libmongoc/src/libmongoc/src/mongoc/mongoc-version.h",
- mongodb_parse_version_file(configure_module_dirname + "/src/LIBMONGOC_VERSION_CURRENT", "MONGOC_")
- );
-}
diff --git a/mongodb-1.12.0/phongo_compat.c b/mongodb-1.12.0/phongo_compat.c
deleted file mode 100644
index cee43b86..00000000
--- a/mongodb-1.12.0/phongo_compat.c
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright 2015-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/* Our Compatability header */
-#include "phongo_compat.h"
-
-void phongo_add_exception_prop(const char* prop, int prop_len, zval* value)
-{
- if (EG(exception)) {
- zval ex;
- ZVAL_OBJ(&ex, EG(exception));
- zend_update_property(Z_OBJCE(ex), PHONGO_COMPAT_OBJ_P(&ex), prop, prop_len, value);
- }
-}
-
-#ifdef ZEND_HASH_GET_APPLY_COUNT /* PHP 7.2 or earlier recursion protection */
-zend_bool php_phongo_zend_hash_apply_protection_begin(HashTable* ht)
-{
- if (!ht) {
- return 1;
- }
- if (ZEND_HASH_GET_APPLY_COUNT(ht) > 0) {
- return 0;
- }
- if (ZEND_HASH_APPLY_PROTECTION(ht)) {
- ZEND_HASH_INC_APPLY_COUNT(ht);
- }
- return 1;
-}
-
-zend_bool php_phongo_zend_hash_apply_protection_end(HashTable* ht)
-{
- if (!ht) {
- return 1;
- }
- if (ZEND_HASH_GET_APPLY_COUNT(ht) == 0) {
- return 0;
- }
- if (ZEND_HASH_APPLY_PROTECTION(ht)) {
- ZEND_HASH_DEC_APPLY_COUNT(ht);
- }
- return 1;
-}
-#else /* PHP 7.3 or later */
-zend_bool php_phongo_zend_hash_apply_protection_begin(zend_array* ht)
-{
- if (GC_IS_RECURSIVE(ht)) {
- return 0;
- }
- if (!(GC_FLAGS(ht) & GC_IMMUTABLE)) {
- GC_PROTECT_RECURSION(ht);
- }
- return 1;
-}
-
-zend_bool php_phongo_zend_hash_apply_protection_end(zend_array* ht)
-{
- if (!GC_IS_RECURSIVE(ht)) {
- return 0;
- }
- if (!(GC_FLAGS(ht) & GC_IMMUTABLE)) {
- GC_UNPROTECT_RECURSION(ht);
- }
- return 1;
-}
-#endif
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/phongo_compat.h b/mongodb-1.12.0/phongo_compat.h
deleted file mode 100644
index 9b685453..00000000
--- a/mongodb-1.12.0/phongo_compat.h
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- * Copyright 2015-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef PHONGO_COMPAT_H
-#define PHONGO_COMPAT_H
-
-#include <php.h>
-#include <Zend/zend_string.h>
-#include <Zend/zend_portability.h>
-
-#ifdef PHP_WIN32
-#include "config.w32.h"
-#else
-#include <php_config.h>
-#endif
-
-#ifndef PHP_FE_END
-#define PHP_FE_END \
- { \
- NULL, NULL, NULL \
- }
-#endif
-
-#ifndef HASH_KEY_NON_EXISTENT
-#define HASH_KEY_NON_EXISTENT HASH_KEY_NON_EXISTANT
-#endif
-
-#if defined(__GNUC__)
-#define ARG_UNUSED __attribute__((unused))
-#else
-#define ARG_UNUSED
-#endif
-
-#if defined(__GNUC__)
-#define PHONGO_GNUC_CHECK_VERSION(major, minor) \
- ((__GNUC__ > (major)) || \
- ((__GNUC__ == (major)) && (__GNUC_MINOR__ >= (minor))))
-#else
-#define PHONGO_GNUC_CHECK_VERSION(major, minor) 0
-#endif
-
-#if PHONGO_GNUC_CHECK_VERSION(7, 0)
-#define PHONGO_BREAK_INTENTIONALLY_MISSING __attribute__((fallthrough));
-#elif defined(__clang__) && __clang_major__ >= 12
-#define PHONGO_BREAK_INTENTIONALLY_MISSING __attribute__((fallthrough));
-#else
-#define PHONGO_BREAK_INTENTIONALLY_MISSING
-#endif
-
-#if PHP_VERSION_ID >= 80000
-#define PHONGO_COMPAT_OBJ_P(val) Z_OBJ_P(val)
-#define phongo_compat_object_handler_type zend_object
-#define PHONGO_COMPAT_GET_OBJ(val) val
-#define PHONGO_COMPAT_SET_COMPARE_OBJECTS_HANDLER(type) php_phongo_handler_##type.compare = php_phongo_##type##_compare_objects;
-#else /* PHP_VERSION_ID < 80000 */
-#define PHONGO_COMPAT_OBJ_P(val) val
-#define phongo_compat_object_handler_type zval
-#define PHONGO_COMPAT_GET_OBJ(val) Z_OBJ_P(val)
-#define PHONGO_COMPAT_SET_COMPARE_OBJECTS_HANDLER(type) php_phongo_handler_##type.compare_objects = php_phongo_##type##_compare_objects;
-#define ZEND_COMPARE_OBJECTS_FALLBACK(o1, o2)
-#endif /* PHP_VERSION_ID >= 80000 */
-
-#if SIZEOF_ZEND_LONG == 8
-#define PHONGO_LONG_FORMAT PRId64
-#elif SIZEOF_ZEND_LONG == 4
-#define PHONGO_LONG_FORMAT PRId32
-#else
-#error Unsupported architecture (integers are neither 32-bit nor 64-bit)
-#endif
-#define PHONGO_ALLOC_OBJECT_T(_obj_t, _class_type) (_obj_t*) ecalloc(1, sizeof(_obj_t) + zend_object_properties_size(_class_type))
-#define ADD_ASSOC_STRING(_zv, _key, _value) add_assoc_string_ex(_zv, ZEND_STRL(_key), (char*) (_value));
-#define ADD_ASSOC_STRINGL(_zv, _key, _value, _len) add_assoc_stringl_ex(_zv, ZEND_STRL(_key), (char*) (_value), _len);
-#define ADD_ASSOC_STRING_EX(_zv, _key, _key_len, _value, _value_len) add_assoc_stringl_ex(_zv, _key, _key_len, (char*) (_value), _value_len);
-#define ADD_ASSOC_LONG_EX(_zv, _key, _value) add_assoc_long_ex(_zv, ZEND_STRL(_key), _value);
-#define ADD_ASSOC_ZVAL_EX(_zv, _key, _value) add_assoc_zval_ex(_zv, ZEND_STRL(_key), _value);
-#define ADD_ASSOC_ZVAL(_zv, _key, _value) add_assoc_zval(_zv, _key, _value);
-#define ADD_ASSOC_NULL_EX(_zv, _key) add_assoc_null_ex(_zv, ZEND_STRL(_key));
-#define ADD_ASSOC_BOOL_EX(_zv, _key, _value) add_assoc_bool_ex(_zv, ZEND_STRL(_key), _value);
-#define ZVAL_INT64_STRING(_zv, _value) \
- do { \
- char tmp[24]; \
- int tmp_len; \
- tmp_len = snprintf(tmp, sizeof(tmp), "%" PRId64, (_value)); \
- ZVAL_STRINGL((_zv), tmp, tmp_len); \
- } while (0)
-#define ADD_ASSOC_INT64_AS_STRING(_zv, _key, _value) \
- do { \
- zval z_int; \
- ZVAL_INT64_STRING(&z_int, (_value)); \
- ADD_ASSOC_ZVAL_EX((_zv), (_key), &z_int); \
- } while (0)
-#define ADD_NEXT_INDEX_STRINGL(_zv, _value, _len) add_next_index_stringl(_zv, _value, _len);
-#define PHONGO_RETVAL_SMART_STR(val) RETVAL_STRINGL(ZSTR_VAL((val).s), ZSTR_LEN((val).s));
-#define ZVAL_STATIC_INIT \
- { \
- { \
- 0 \
- } \
- }
-
-#if SIZEOF_ZEND_LONG == 8
-#define ADD_INDEX_INT64(_zv, _index, _value) add_index_long((_zv), (_index), (_value))
-#define ADD_NEXT_INDEX_INT64(_zv, _value) add_next_index_long((_zv), (_value))
-#define ADD_ASSOC_INT64(_zv, _key, _value) add_assoc_long((_zv), (_key), (_value))
-#define ZVAL_INT64(_zv, _value) ZVAL_LONG((_zv), (_value))
-#elif SIZEOF_ZEND_LONG == 4
-#define ADD_INDEX_INT64(_zv, _index, _value) \
- if ((_value) > INT32_MAX || (_value) < INT32_MIN) { \
- zval zchild; \
- php_phongo_bson_new_int64(&zchild, (_value)); \
- add_index_zval((_zv), (_index), &zchild); \
- } else { \
- add_index_long((_zv), (_index), (_value)); \
- }
-#define ADD_NEXT_INDEX_INT64(_zv, _value) \
- if ((_value) > INT32_MAX || (_value) < INT32_MIN) { \
- zval zchild; \
- php_phongo_bson_new_int64(&zchild, (_value)); \
- add_next_index_zval((_zv), &zchild); \
- } else { \
- add_next_index_long((_zv), (_value)); \
- }
-#define ADD_ASSOC_INT64(_zv, _key, _value) \
- if ((_value) > INT32_MAX || (_value) < INT32_MIN) { \
- zval zchild; \
- php_phongo_bson_new_int64(&zchild, (_value)); \
- add_assoc_zval((_zv), (_key), &zchild); \
- } else { \
- add_assoc_long((_zv), (_key), (_value)); \
- }
-#define ZVAL_INT64(_zv, _value) \
- if ((_value) > INT32_MAX || (_value) < INT32_MIN) { \
- php_phongo_bson_new_int64((_zv), (_value)); \
- } else { \
- ZVAL_LONG((_zv), (_value)); \
- }
-#else /* SIZEOF_ZEND_LONG != 8 && SIZEOF_ZEND_LONG != 4 */
-#error Unsupported architecture (integers are neither 32-bit nor 64-bit)
-#endif /* SIZEOF_ZEND_LONG */
-
-#if PHP_VERSION_ID < 70300
-#define ZVAL_COPY_DEREF(z, v) \
- do { \
- zval* _z3 = (v); \
- if (Z_OPT_REFCOUNTED_P(_z3)) { \
- if (UNEXPECTED(Z_OPT_ISREF_P(_z3))) { \
- _z3 = Z_REFVAL_P(_z3); \
- if (Z_OPT_REFCOUNTED_P(_z3)) { \
- Z_ADDREF_P(_z3); \
- } \
- } else { \
- Z_ADDREF_P(_z3); \
- } \
- } \
- ZVAL_COPY_VALUE(z, _z3); \
- } while (0)
-#endif /* PHP_VERSION_ID < 70300 */
-
-#if PHP_VERSION_ID < 70300
-static inline zend_bool zend_ini_parse_bool(zend_string* str)
-{
- if (zend_string_equals_literal_ci(str, "true") ||
- zend_string_equals_literal_ci(str, "yes") ||
- zend_string_equals_literal_ci(str, "on")) {
- return 1;
- } else {
- return atoi(ZSTR_VAL(str)) != 0;
- }
-}
-#endif /* PHP_VERSION_ID < 70300 */
-
-/* Compatibility macros to override error handling logic */
-#define PHONGO_PARSE_PARAMETERS_START(min_num_args, max_num_args) \
- do { \
- zend_error_handling error_handling; \
- zend_replace_error_handling( \
- EH_THROW, \
- phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), \
- &error_handling); \
- ZEND_PARSE_PARAMETERS_START(min_num_args, max_num_args)
-
-#define PHONGO_PARSE_PARAMETERS_END() \
- ZEND_PARSE_PARAMETERS_END_EX( \
- zend_restore_error_handling(&error_handling); \
- return ); \
- zend_restore_error_handling(&error_handling); \
- } \
- while (0)
-
-#ifndef ZEND_PARSE_PARAMETERS_NONE
-#define PHONGO_PARSE_PARAMETERS_NONE() \
- do { \
- zend_error_handling error_handling; \
- zend_replace_error_handling( \
- EH_THROW, \
- phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), \
- &error_handling); \
- if (zend_parse_parameters_none() == FAILURE) { \
- zend_restore_error_handling(&error_handling); \
- return; \
- } \
- zend_restore_error_handling(&error_handling); \
- } while (0)
-#else
-#define PHONGO_PARSE_PARAMETERS_NONE() \
- do { \
- zend_error_handling error_handling; \
- zend_replace_error_handling( \
- EH_THROW, \
- phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), \
- &error_handling); \
- if (UNEXPECTED(ZEND_NUM_ARGS() != 0)) { \
- zend_wrong_parameters_none_error(); \
- zend_restore_error_handling(&error_handling); \
- return; \
- } \
- zend_restore_error_handling(&error_handling); \
- } while (0)
-#endif
-
-/* Z_PARAM_OBJECT_OF_CLASS_OR_NULL was introduced in PHP 8.0.
- * See: https://github.com/php/php-src/commit/e93d20ad7ebc1075ef1248a663935ee5ea69f1cd */
-#ifndef Z_PARAM_OBJECT_OF_CLASS_OR_NULL
-#define Z_PARAM_OBJECT_OF_CLASS_OR_NULL(dest, _ce) \
- Z_PARAM_OBJECT_OF_CLASS_EX(dest, _ce, 1, 0)
-#endif
-
-/* Per https://wiki.php.net/rfc/internal_method_return_types, "Non-final
- * internal method return types - when possible - are declared tentatively in
- * PHP 8.1, and they will become enforced in PHP 9.0." This can be revisited
- * when more general typing improvements are made in PHPC-1709. */
-#ifndef ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX
-#define ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(name, return_reference, required_num_args, type, allow_null) \
- ZEND_BEGIN_ARG_INFO_EX(name, 0, return_reference, required_num_args)
-#endif
-
-void phongo_add_exception_prop(const char* prop, int prop_len, zval* value);
-zend_bool php_phongo_zend_hash_apply_protection_begin(HashTable* ht);
-zend_bool php_phongo_zend_hash_apply_protection_end(HashTable* ht);
-
-#endif /* PHONGO_COMPAT_H */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/phongo_version.h b/mongodb-1.12.0/phongo_version.h
deleted file mode 100644
index f6426f2a..00000000
--- a/mongodb-1.12.0/phongo_version.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright 2014-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef PHONGO_VERSION_H
-#define PHONGO_VERSION_H
-
-/* clang-format off */
-#define PHP_MONGODB_VERSION "1.12.0"
-#define PHP_MONGODB_STABILITY "stable"
-#define PHP_MONGODB_VERSION_DESC 1,12,0,1
-/* clang-format on */
-
-#endif /* PHONGO_VERSION_H */
diff --git a/mongodb-1.12.0/php_bson.h b/mongodb-1.12.0/php_bson.h
deleted file mode 100644
index a02a0451..00000000
--- a/mongodb-1.12.0/php_bson.h
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright 2014-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef PHONGO_BSON_H
-#define PHONGO_BSON_H
-
-#include <bson/bson.h>
-
-/* PHP Core stuff */
-#include <php.h>
-
-#define BSON_UNSERIALIZE_FUNC_NAME "bsonUnserialize"
-#define BSON_SERIALIZE_FUNC_NAME "bsonSerialize"
-
-#define PHONGO_ODM_FIELD_NAME "__pclass"
-
-typedef enum {
- PHONGO_BSON_NONE = 0x00,
- PHONGO_BSON_ADD_ID = 0x01,
- PHONGO_BSON_RETURN_ID = 0x02
-} php_phongo_bson_flags_t;
-
-typedef enum {
- PHONGO_TYPEMAP_NONE,
- PHONGO_TYPEMAP_NATIVE_ARRAY,
- PHONGO_TYPEMAP_NATIVE_OBJECT,
- PHONGO_TYPEMAP_CLASS
-} php_phongo_bson_typemap_types;
-
-typedef enum {
- PHONGO_FIELD_PATH_ITEM_NONE,
- PHONGO_FIELD_PATH_ITEM_ARRAY,
- PHONGO_FIELD_PATH_ITEM_DOCUMENT
-} php_phongo_bson_field_path_item_types;
-
-typedef struct {
- char** elements;
- php_phongo_bson_field_path_item_types* element_types;
- size_t allocated_size;
- size_t size;
- size_t ref_count;
- bool owns_elements;
-} php_phongo_field_path;
-
-typedef struct _php_phongo_field_path_map_element {
- php_phongo_field_path* entry;
- php_phongo_bson_typemap_types node_type;
- zend_class_entry* node_ce;
-} php_phongo_field_path_map_element;
-
-typedef struct {
- php_phongo_bson_typemap_types document_type;
- zend_class_entry* document;
- php_phongo_bson_typemap_types array_type;
- zend_class_entry* array;
- php_phongo_bson_typemap_types root_type;
- zend_class_entry* root;
- struct {
- php_phongo_field_path_map_element** map;
- size_t allocated_size;
- size_t size;
- } field_paths;
-} php_phongo_bson_typemap;
-
-typedef struct {
- zval zchild;
- php_phongo_bson_typemap map;
- zend_class_entry* odm;
- bool is_visiting_array;
- php_phongo_field_path* field_path;
-} php_phongo_bson_state;
-
-#define PHONGO_BSON_INIT_STATE(s) \
- do { \
- memset(&(s), 0, sizeof(php_phongo_bson_state)); \
- } while (0)
-#define PHONGO_BSON_INIT_DEBUG_STATE(s) \
- do { \
- memset(&(s), 0, sizeof(php_phongo_bson_state)); \
- s.map.root_type = PHONGO_TYPEMAP_NATIVE_ARRAY; \
- s.map.document_type = PHONGO_TYPEMAP_NATIVE_ARRAY; \
- } while (0)
-
-void php_phongo_zval_to_bson(zval* data, php_phongo_bson_flags_t flags, bson_t* bson, bson_t** bson_out);
-bool php_phongo_bson_to_zval_ex(const unsigned char* data, int data_len, php_phongo_bson_state* state);
-bool php_phongo_bson_to_zval(const unsigned char* data, int data_len, zval* out);
-bool php_phongo_bson_value_to_zval(const bson_value_t* value, zval* zv);
-void php_phongo_zval_to_bson_value(zval* data, php_phongo_bson_flags_t flags, bson_value_t* value);
-bool php_phongo_bson_typemap_to_state(zval* typemap, php_phongo_bson_typemap* map);
-void php_phongo_bson_state_ctor(php_phongo_bson_state* state);
-void php_phongo_bson_state_dtor(php_phongo_bson_state* state);
-void php_phongo_bson_state_copy_ctor(php_phongo_bson_state* dst, php_phongo_bson_state* src);
-void php_phongo_bson_typemap_dtor(php_phongo_bson_typemap* map);
-
-void php_phongo_bson_new_timestamp_from_increment_and_timestamp(zval* object, uint32_t increment, uint32_t timestamp);
-void php_phongo_bson_new_int64(zval* object, int64_t integer);
-
-php_phongo_field_path* php_phongo_field_path_alloc(bool owns_elements);
-void php_phongo_field_path_free(php_phongo_field_path* field_path);
-void php_phongo_field_path_write_item_at_current_level(php_phongo_field_path* field_path, const char* element);
-void php_phongo_field_path_write_type_at_current_level(php_phongo_field_path* field_path, php_phongo_bson_field_path_item_types element_type);
-bool php_phongo_field_path_push(php_phongo_field_path* field_path, const char* element, php_phongo_bson_field_path_item_types element_type);
-bool php_phongo_field_path_pop(php_phongo_field_path* field_path);
-
-char* php_phongo_field_path_as_string(php_phongo_field_path* field_path);
-
-#endif /* PHONGO_BSON_H */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/php_phongo.c b/mongodb-1.12.0/php_phongo.c
deleted file mode 100644
index 415acf95..00000000
--- a/mongodb-1.12.0/php_phongo.c
+++ /dev/null
@@ -1,4066 +0,0 @@
-/*
- * Copyright 2014-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/* External libs */
-#include "bson/bson.h"
-#include "mongoc/mongoc.h"
-
-/* PHP Core stuff */
-#include <php.h>
-#include <php_ini.h>
-#include <ext/standard/info.h>
-#include <ext/standard/file.h>
-#include <Zend/zend_hash.h>
-#include <Zend/zend_interfaces.h>
-#include <Zend/zend_exceptions.h>
-#include <ext/spl/spl_iterators.h>
-#include <ext/spl/spl_exceptions.h>
-#include <ext/standard/php_var.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <Zend/zend_smart_str.h>
-
-#ifdef MONGOC_ENABLE_CLIENT_SIDE_ENCRYPTION
-#include <mongocrypt/mongocrypt.h>
-#endif
-
-/* getpid() */
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef PHP_WIN32
-#include <process.h>
-#endif
-
-/* Stream wrapper */
-#include <main/php_streams.h>
-#include <main/php_network.h>
-/* String manipulation */
-#include <Zend/zend_string.h>
-/* PHP array helpers */
-#include "php_array_api.h"
-
-/* Our Compatability header */
-#include "phongo_compat.h"
-
-/* Our stuffz */
-#include "php_phongo.h"
-#include "php_bson.h"
-#include "src/phongo_apm.h"
-#include "src/phongo_ini.h"
-#include "src/BSON/functions.h"
-#include "src/MongoDB/Monitoring/functions.h"
-
-#undef MONGOC_LOG_DOMAIN
-#define MONGOC_LOG_DOMAIN "PHONGO"
-
-#define PHONGO_METADATA_SEPARATOR " / "
-#define PHONGO_METADATA_SEPARATOR_LEN (sizeof(PHONGO_METADATA_SEPARATOR) - 1)
-#define PHONGO_METADATA_PHP_VERSION_PREFIX "PHP "
-#define PHONGO_METADATA_PHP_VERSION_PREFIX_LEN (sizeof(PHONGO_METADATA_PHP_VERSION_PREFIX) - 1)
-
-ZEND_DECLARE_MODULE_GLOBALS(mongodb)
-#if defined(ZTS) && defined(COMPILE_DL_MONGODB)
-ZEND_TSRMLS_CACHE_DEFINE();
-#endif
-
-/* Initialize a thread counter, which will be atomically incremented in GINIT.
- * In turn, GSHUTDOWN will decrement the counter and call mongoc_cleanup() when
- * it reaches zero (i.e. last thread is shutdown). This is necessary because
- * mongoc_cleanup() must be called after all persistent clients have been
- * destroyed. */
-static int32_t phongo_num_threads = 0;
-
-/* Declare zend_class_entry dependencies, which are initialized in MINIT */
-zend_class_entry* php_phongo_date_immutable_ce;
-zend_class_entry* php_phongo_json_serializable_ce;
-
-php_phongo_server_description_type_map_t
- php_phongo_server_description_type_map[PHONGO_SERVER_DESCRIPTION_TYPES] = {
- { PHONGO_SERVER_UNKNOWN, "Unknown" },
- { PHONGO_SERVER_STANDALONE, "Standalone" },
- { PHONGO_SERVER_MONGOS, "Mongos" },
- { PHONGO_SERVER_POSSIBLE_PRIMARY, "PossiblePrimary" },
- { PHONGO_SERVER_RS_PRIMARY, "RSPrimary" },
- { PHONGO_SERVER_RS_SECONDARY, "RSSecondary" },
- { PHONGO_SERVER_RS_ARBITER, "RSArbiter" },
- { PHONGO_SERVER_RS_OTHER, "RSOther" },
- { PHONGO_SERVER_RS_GHOST, "RSGhost" },
- { PHONGO_SERVER_LOAD_BALANCER, "LoadBalancer" },
- };
-
-/* {{{ phongo_std_object_handlers */
-zend_object_handlers phongo_std_object_handlers;
-
-zend_object_handlers* phongo_get_std_object_handlers(void)
-{
- return &phongo_std_object_handlers;
-}
-/* }}} */
-
-/* Forward declarations */
-static bool phongo_split_namespace(const char* namespace, char** dbname, char** cname);
-
-/* {{{ Error reporting and logging */
-zend_class_entry* phongo_exception_from_phongo_domain(php_phongo_error_domain_t domain)
-{
- switch (domain) {
- case PHONGO_ERROR_INVALID_ARGUMENT:
- return php_phongo_invalidargumentexception_ce;
- case PHONGO_ERROR_LOGIC:
- return php_phongo_logicexception_ce;
- case PHONGO_ERROR_RUNTIME:
- return php_phongo_runtimeexception_ce;
- case PHONGO_ERROR_UNEXPECTED_VALUE:
- return php_phongo_unexpectedvalueexception_ce;
- case PHONGO_ERROR_MONGOC_FAILED:
- return php_phongo_runtimeexception_ce;
- case PHONGO_ERROR_CONNECTION_FAILED:
- return php_phongo_connectionexception_ce;
- }
-
- MONGOC_ERROR("Resolving unknown phongo error domain: %d", domain);
- return php_phongo_runtimeexception_ce;
-}
-zend_class_entry* phongo_exception_from_mongoc_domain(mongoc_error_domain_t domain, mongoc_error_code_t code)
-{
- if (domain == MONGOC_ERROR_CLIENT) {
- if (code == MONGOC_ERROR_CLIENT_AUTHENTICATE) {
- return php_phongo_authenticationexception_ce;
- }
-
- if (code == MONGOC_ERROR_CLIENT_INVALID_ENCRYPTION_ARG) {
- return php_phongo_invalidargumentexception_ce;
- }
- }
-
- if (domain == MONGOC_ERROR_COMMAND && code == MONGOC_ERROR_COMMAND_INVALID_ARG) {
- return php_phongo_invalidargumentexception_ce;
- }
-
- if (domain == MONGOC_ERROR_SERVER) {
- if (code == PHONGO_SERVER_ERROR_EXCEEDED_TIME_LIMIT) {
- return php_phongo_executiontimeoutexception_ce;
- }
-
- return php_phongo_serverexception_ce;
- }
-
- if (domain == MONGOC_ERROR_SERVER_SELECTION && code == MONGOC_ERROR_SERVER_SELECTION_FAILURE) {
- return php_phongo_connectiontimeoutexception_ce;
- }
-
- if (domain == MONGOC_ERROR_STREAM) {
- if (code == MONGOC_ERROR_STREAM_SOCKET) {
- return php_phongo_connectiontimeoutexception_ce;
- }
-
- return php_phongo_connectionexception_ce;
- }
-
- if (domain == MONGOC_ERROR_WRITE_CONCERN) {
- return php_phongo_serverexception_ce;
- }
-
- if (domain == MONGOC_ERROR_PROTOCOL && code == MONGOC_ERROR_PROTOCOL_BAD_WIRE_VERSION) {
- return php_phongo_connectionexception_ce;
- }
-
- if (domain == MONGOC_ERROR_CLIENT_SIDE_ENCRYPTION) {
- return php_phongo_encryptionexception_ce;
- }
-
- return php_phongo_runtimeexception_ce;
-}
-void phongo_throw_exception(php_phongo_error_domain_t domain, const char* format, ...)
-{
- va_list args;
- char* message;
- int message_len;
-
- va_start(args, format);
- message_len = vspprintf(&message, 0, format, args);
- zend_throw_exception(phongo_exception_from_phongo_domain(domain), message, 0);
- efree(message);
- va_end(args);
-}
-
-static int phongo_exception_append_error_labels(zval* labels, const bson_iter_t* iter)
-{
- bson_iter_t error_labels;
- uint32_t label_count = 0;
-
- if (!BSON_ITER_HOLDS_ARRAY(iter) || !bson_iter_recurse(iter, &error_labels)) {
- return label_count;
- }
-
- while (bson_iter_next(&error_labels)) {
- if (BSON_ITER_HOLDS_UTF8(&error_labels)) {
- const char* error_label;
- uint32_t error_label_len;
-
- error_label = bson_iter_utf8(&error_labels, &error_label_len);
- ADD_NEXT_INDEX_STRINGL(labels, error_label, error_label_len);
- label_count++;
- }
- }
-
- return label_count;
-}
-
-static void phongo_exception_add_error_labels(const bson_t* reply)
-{
- bson_iter_t iter, child;
- zval labels;
- uint32_t label_count = 0;
-
- if (!reply) {
- return;
- }
-
- array_init(&labels);
-
- if (bson_iter_init_find(&iter, reply, "errorLabels")) {
- label_count += phongo_exception_append_error_labels(&labels, &iter);
- }
-
- if (bson_iter_init_find(&iter, reply, "writeConcernError") && BSON_ITER_HOLDS_DOCUMENT(&iter) &&
- bson_iter_recurse(&iter, &child) && bson_iter_find(&child, "errorLabels")) {
- label_count += phongo_exception_append_error_labels(&labels, &child);
- }
-
- /* mongoc_write_result_t always reports writeConcernErrors in an array, so
- * we must iterate this to collect WCE labels for BulkWrite replies. */
- if (bson_iter_init_find(&iter, reply, "writeConcernErrors") && BSON_ITER_HOLDS_ARRAY(&iter) && bson_iter_recurse(&iter, &child)) {
- bson_iter_t wce;
-
- while (bson_iter_next(&child)) {
- if (BSON_ITER_HOLDS_DOCUMENT(&child) && bson_iter_recurse(&child, &wce) && bson_iter_find(&wce, "errorLabels")) {
- label_count += phongo_exception_append_error_labels(&labels, &wce);
- }
- }
- }
-
- if (label_count > 0) {
- phongo_add_exception_prop(ZEND_STRL("errorLabels"), &labels);
- }
-
- zval_ptr_dtor(&labels);
-}
-
-void phongo_throw_exception_from_bson_error_t_and_reply(bson_error_t* error, const bson_t* reply)
-{
- /* Server errors (other than ExceededTimeLimit) and write concern errors
- * may use CommandException and report the result document for the
- * failed command. For BC, ExceededTimeLimit errors will continue to use
- * ExcecutionTimeoutException and omit the result document. */
- if (reply && ((error->domain == MONGOC_ERROR_SERVER && error->code != PHONGO_SERVER_ERROR_EXCEEDED_TIME_LIMIT) || error->domain == MONGOC_ERROR_WRITE_CONCERN)) {
- zval zv;
-
- zend_throw_exception(php_phongo_commandexception_ce, error->message, error->code);
- if (php_phongo_bson_to_zval(bson_get_data(reply), reply->len, &zv)) {
- phongo_add_exception_prop(ZEND_STRL("resultDocument"), &zv);
- }
-
- zval_ptr_dtor(&zv);
- } else {
- zend_throw_exception(phongo_exception_from_mongoc_domain(error->domain, error->code), error->message, error->code);
- }
- phongo_exception_add_error_labels(reply);
-}
-
-void phongo_throw_exception_from_bson_error_t(bson_error_t* error)
-{
- phongo_throw_exception_from_bson_error_t_and_reply(error, NULL);
-}
-
-/* }}} */
-
-/* {{{ Init objects */
-static void phongo_cursor_init(zval* return_value, zval* manager, mongoc_cursor_t* cursor, zval* readPreference, zval* session) /* {{{ */
-{
- php_phongo_cursor_t* intern;
-
- object_init_ex(return_value, php_phongo_cursor_ce);
-
- intern = Z_CURSOR_OBJ_P(return_value);
- intern->cursor = cursor;
- intern->server_id = mongoc_cursor_get_hint(cursor);
- intern->advanced = false;
- intern->current = 0;
-
- ZVAL_ZVAL(&intern->manager, manager, 1, 0);
-
- if (readPreference) {
- ZVAL_ZVAL(&intern->read_preference, readPreference, 1, 0);
- }
-
- if (session) {
- ZVAL_ZVAL(&intern->session, session, 1, 0);
- }
-} /* }}} */
-
-static void phongo_cursor_init_for_command(zval* return_value, zval* manager, mongoc_cursor_t* cursor, const char* db, zval* command, zval* readPreference, zval* session) /* {{{ */
-{
- php_phongo_cursor_t* intern;
-
- phongo_cursor_init(return_value, manager, cursor, readPreference, session);
- intern = Z_CURSOR_OBJ_P(return_value);
-
- intern->database = estrdup(db);
-
- ZVAL_ZVAL(&intern->command, command, 1, 0);
-} /* }}} */
-
-static void phongo_cursor_init_for_query(zval* return_value, zval* manager, mongoc_cursor_t* cursor, const char* namespace, zval* query, zval* readPreference, zval* session) /* {{{ */
-{
- php_phongo_cursor_t* intern;
-
- phongo_cursor_init(return_value, manager, cursor, readPreference, session);
- intern = Z_CURSOR_OBJ_P(return_value);
-
- /* namespace has already been validated by phongo_execute_query() */
- phongo_split_namespace(namespace, &intern->database, &intern->collection);
-
- /* cursor has already been advanced by phongo_execute_query() calling
- * phongo_cursor_advance_and_check_for_error() */
- intern->advanced = true;
-
- ZVAL_ZVAL(&intern->query, query, 1, 0);
-} /* }}} */
-
-void phongo_server_init(zval* return_value, zval* manager, uint32_t server_id) /* {{{ */
-{
- php_phongo_server_t* server;
-
- object_init_ex(return_value, php_phongo_server_ce);
-
- server = Z_SERVER_OBJ_P(return_value);
- server->server_id = server_id;
-
- ZVAL_ZVAL(&server->manager, manager, 1, 0);
-}
-/* }}} */
-
-void phongo_session_init(zval* return_value, zval* manager, mongoc_client_session_t* client_session) /* {{{ */
-{
- php_phongo_session_t* session;
-
- object_init_ex(return_value, php_phongo_session_ce);
-
- session = Z_SESSION_OBJ_P(return_value);
- session->client_session = client_session;
-
- ZVAL_ZVAL(&session->manager, manager, 1, 0);
-}
-/* }}} */
-
-void phongo_objectid_init(zval* return_value, const bson_oid_t* oid) /* {{{ */
-{
- php_phongo_objectid_t* intern;
-
- object_init_ex(return_value, php_phongo_objectid_ce);
-
- intern = Z_OBJECTID_OBJ_P(return_value);
- bson_oid_to_string(oid, intern->oid);
- intern->initialized = true;
-}
-/* }}} */
-
-void phongo_readconcern_init(zval* return_value, const mongoc_read_concern_t* read_concern) /* {{{ */
-{
- php_phongo_readconcern_t* intern;
-
- object_init_ex(return_value, php_phongo_readconcern_ce);
-
- intern = Z_READCONCERN_OBJ_P(return_value);
- intern->read_concern = mongoc_read_concern_copy(read_concern);
-}
-/* }}} */
-
-void phongo_readpreference_init(zval* return_value, const mongoc_read_prefs_t* read_prefs) /* {{{ */
-{
- php_phongo_readpreference_t* intern;
-
- object_init_ex(return_value, php_phongo_readpreference_ce);
-
- intern = Z_READPREFERENCE_OBJ_P(return_value);
- intern->read_preference = mongoc_read_prefs_copy(read_prefs);
-}
-/* }}} */
-
-void phongo_writeconcern_init(zval* return_value, const mongoc_write_concern_t* write_concern) /* {{{ */
-{
- php_phongo_writeconcern_t* intern;
-
- object_init_ex(return_value, php_phongo_writeconcern_ce);
-
- intern = Z_WRITECONCERN_OBJ_P(return_value);
- intern->write_concern = mongoc_write_concern_copy(write_concern);
-}
-/* }}} */
-
-zend_bool phongo_writeconcernerror_init(zval* return_value, bson_t* bson) /* {{{ */
-{
- bson_iter_t iter;
- php_phongo_writeconcernerror_t* intern;
-
- object_init_ex(return_value, php_phongo_writeconcernerror_ce);
-
- intern = Z_WRITECONCERNERROR_OBJ_P(return_value);
- intern->code = 0;
-
- if (bson_iter_init_find(&iter, bson, "code") && BSON_ITER_HOLDS_INT32(&iter)) {
- intern->code = bson_iter_int32(&iter);
- }
-
- if (bson_iter_init_find(&iter, bson, "errmsg") && BSON_ITER_HOLDS_UTF8(&iter)) {
- uint32_t errmsg_len;
- const char* err_msg = bson_iter_utf8(&iter, &errmsg_len);
-
- intern->message = estrndup(err_msg, errmsg_len);
- }
-
- if (bson_iter_init_find(&iter, bson, "errInfo") && BSON_ITER_HOLDS_DOCUMENT(&iter)) {
- uint32_t len;
- const uint8_t* data = NULL;
-
- bson_iter_document(&iter, &len, &data);
-
- if (!php_phongo_bson_to_zval(data, len, &intern->info)) {
- zval_ptr_dtor(&intern->info);
- ZVAL_UNDEF(&intern->info);
-
- return false;
- }
- }
-
- return true;
-} /* }}} */
-
-zend_bool phongo_writeerror_init(zval* return_value, bson_t* bson) /* {{{ */
-{
- bson_iter_t iter;
- php_phongo_writeerror_t* intern;
-
- object_init_ex(return_value, php_phongo_writeerror_ce);
-
- intern = Z_WRITEERROR_OBJ_P(return_value);
- intern->code = 0;
- intern->index = 0;
-
- if (bson_iter_init_find(&iter, bson, "code") && BSON_ITER_HOLDS_INT32(&iter)) {
- intern->code = bson_iter_int32(&iter);
- }
-
- if (bson_iter_init_find(&iter, bson, "errmsg") && BSON_ITER_HOLDS_UTF8(&iter)) {
- uint32_t errmsg_len;
- const char* err_msg = bson_iter_utf8(&iter, &errmsg_len);
-
- intern->message = estrndup(err_msg, errmsg_len);
- }
-
- if (bson_iter_init_find(&iter, bson, "errInfo") && BSON_ITER_HOLDS_DOCUMENT(&iter)) {
- uint32_t len;
- const uint8_t* data = NULL;
-
- bson_iter_document(&iter, &len, &data);
-
- if (!php_phongo_bson_to_zval(data, len, &intern->info)) {
- zval_ptr_dtor(&intern->info);
- ZVAL_UNDEF(&intern->info);
-
- return false;
- }
- }
-
- if (bson_iter_init_find(&iter, bson, "index") && BSON_ITER_HOLDS_INT32(&iter)) {
- intern->index = bson_iter_int32(&iter);
- }
-
- return true;
-} /* }}} */
-
-static php_phongo_writeresult_t* phongo_writeresult_init(zval* return_value, bson_t* reply, zval* manager, uint32_t server_id) /* {{{ */
-{
- php_phongo_writeresult_t* writeresult;
-
- object_init_ex(return_value, php_phongo_writeresult_ce);
-
- writeresult = Z_WRITERESULT_OBJ_P(return_value);
- writeresult->reply = bson_copy(reply);
- writeresult->server_id = server_id;
-
- ZVAL_ZVAL(&writeresult->manager, manager, 1, 0);
-
- return writeresult;
-} /* }}} */
-/* }}} */
-
-/* {{{ CRUD */
-/* Splits a namespace name into the database and collection names, allocated with estrdup. */
-static bool phongo_split_namespace(const char* namespace, char** dbname, char** cname) /* {{{ */
-{
- char* dot = strchr(namespace, '.');
-
- if (!dot) {
- return false;
- }
-
- if (cname) {
- *cname = estrdup(namespace + (dot - namespace) + 1);
- }
- if (dbname) {
- *dbname = estrndup(namespace, dot - namespace);
- }
-
- return true;
-} /* }}} */
-
-/* Parses the "readConcern" option for an execute method. If mongoc_opts is not
- * NULL, the option will be appended. On error, false is returned and an
- * exception is thrown. */
-static bool phongo_parse_read_concern(zval* options, bson_t* mongoc_opts) /* {{{ */
-{
- zval* option = NULL;
- mongoc_read_concern_t* read_concern;
-
- if (!options) {
- return true;
- }
-
- if (Z_TYPE_P(options) != IS_ARRAY) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected options to be array, %s given", PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(options));
- return false;
- }
-
- option = php_array_fetchc(options, "readConcern");
-
- if (!option) {
- return true;
- }
-
- if (Z_TYPE_P(option) != IS_OBJECT || !instanceof_function(Z_OBJCE_P(option), php_phongo_readconcern_ce)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"readConcern\" option to be %s, %s given", ZSTR_VAL(php_phongo_readconcern_ce->name), PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(option));
- return false;
- }
-
- read_concern = Z_READCONCERN_OBJ_P(option)->read_concern;
-
- if (mongoc_opts && !mongoc_read_concern_append(read_concern, mongoc_opts)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Error appending \"readConcern\" option");
- return false;
- }
-
- return true;
-} /* }}} */
-
-/* Parses the "readPreference" option for an execute method. If zreadPreference
- * is not NULL, it will be assigned to the option. On error, false is returned
- * and an exception is thrown. */
-bool phongo_parse_read_preference(zval* options, zval** zreadPreference) /* {{{ */
-{
- zval* option = NULL;
-
- if (!options) {
- return true;
- }
-
- if (Z_TYPE_P(options) != IS_ARRAY) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected options to be array, %s given", PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(options));
- return false;
- }
-
- option = php_array_fetchc(options, "readPreference");
-
- if (!option) {
- return true;
- }
-
- if (Z_TYPE_P(option) != IS_OBJECT || !instanceof_function(Z_OBJCE_P(option), php_phongo_readpreference_ce)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"readPreference\" option to be %s, %s given", ZSTR_VAL(php_phongo_readpreference_ce->name), PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(option));
- return false;
- }
-
- if (zreadPreference) {
- *zreadPreference = option;
- }
-
- return true;
-} /* }}} */
-
-/* Parses the "session" option for an execute method. The client object should
- * correspond to the Manager executing the operation and will be used to ensure
- * that the session is correctly associated with that client. If mongoc_opts is
- * not NULL, the option will be appended. If zsession is not NULL, it will be
- * assigned to the option. On error, false is returned and an exception is
- * thrown. */
-bool phongo_parse_session(zval* options, mongoc_client_t* client, bson_t* mongoc_opts, zval** zsession) /* {{{ */
-{
- zval* option = NULL;
- const mongoc_client_session_t* client_session;
-
- if (!options) {
- return true;
- }
-
- if (Z_TYPE_P(options) != IS_ARRAY) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected options to be array, %s given", PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(options));
- return false;
- }
-
- option = php_array_fetchc(options, "session");
-
- if (!option) {
- return true;
- }
-
- if (Z_TYPE_P(option) != IS_OBJECT || !instanceof_function(Z_OBJCE_P(option), php_phongo_session_ce)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"session\" option to be %s, %s given", ZSTR_VAL(php_phongo_session_ce->name), PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(option));
- return false;
- }
-
- client_session = Z_SESSION_OBJ_P(option)->client_session;
-
- if (client != mongoc_client_session_get_client(client_session)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Cannot use Session started from a different Manager");
- return false;
- }
-
- if (mongoc_opts && !mongoc_client_session_append(client_session, mongoc_opts, NULL)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Error appending \"session\" option");
- return false;
- }
-
- if (zsession) {
- *zsession = option;
- }
-
- return true;
-} /* }}} */
-
-/* Parses the "writeConcern" option for an execute method. If mongoc_opts is not
- * NULL, the option will be appended. If zwriteConcern is not NULL, it will be
- * assigned to the option. On error, false is returned and an exception is
- * thrown. */
-static bool phongo_parse_write_concern(zval* options, bson_t* mongoc_opts, zval** zwriteConcern) /* {{{ */
-{
- zval* option = NULL;
- mongoc_write_concern_t* write_concern;
-
- if (!options) {
- return true;
- }
-
- if (Z_TYPE_P(options) != IS_ARRAY) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected options to be array, %s given", PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(options));
- return false;
- }
-
- option = php_array_fetchc(options, "writeConcern");
-
- if (!option) {
- return true;
- }
-
- if (Z_TYPE_P(option) != IS_OBJECT || !instanceof_function(Z_OBJCE_P(option), php_phongo_writeconcern_ce)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"writeConcern\" option to be %s, %s given", ZSTR_VAL(php_phongo_writeconcern_ce->name), PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(option));
- return false;
- }
-
- write_concern = Z_WRITECONCERN_OBJ_P(option)->write_concern;
-
- if (mongoc_opts && !mongoc_write_concern_append(write_concern, mongoc_opts)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Error appending \"writeConcern\" option");
- return false;
- }
-
- if (zwriteConcern) {
- *zwriteConcern = option;
- }
-
- return true;
-}
-
-bool phongo_execute_bulk_write(zval* manager, const char* namespace, php_phongo_bulkwrite_t* bulk_write, zval* options, uint32_t server_id, zval* return_value) /* {{{ */
-{
- mongoc_client_t* client = NULL;
- bson_error_t error = { 0 };
- int success;
- bson_t reply = BSON_INITIALIZER;
- mongoc_bulk_operation_t* bulk = bulk_write->bulk;
- php_phongo_writeresult_t* writeresult;
- zval* zwriteConcern = NULL;
- zval* zsession = NULL;
- const mongoc_write_concern_t* write_concern = NULL;
-
- client = Z_MANAGER_OBJ_P(manager)->client;
-
- if (bulk_write->executed) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "BulkWrite objects may only be executed once and this instance has already been executed");
- return false;
- }
-
- if (!phongo_split_namespace(namespace, &bulk_write->database, &bulk_write->collection)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s: %s", "Invalid namespace provided", namespace);
- return false;
- }
-
- if (!phongo_parse_session(options, client, NULL, &zsession)) {
- /* Exception should already have been thrown */
- return false;
- }
-
- if (!phongo_parse_write_concern(options, NULL, &zwriteConcern)) {
- /* Exception should already have been thrown */
- return false;
- }
-
- /* If a write concern was not specified, libmongoc will use the client's
- * write concern; however, we should still fetch it for the write result.
- * Additionally, we need to check if an unacknowledged write concern would
- * conflict with an explicit session. */
- write_concern = zwriteConcern ? Z_WRITECONCERN_OBJ_P(zwriteConcern)->write_concern : mongoc_client_get_write_concern(client);
-
- if (zsession && !mongoc_write_concern_is_acknowledged(write_concern)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Cannot combine \"session\" option with an unacknowledged write concern");
- return false;
- }
-
- mongoc_bulk_operation_set_database(bulk, bulk_write->database);
- mongoc_bulk_operation_set_collection(bulk, bulk_write->collection);
- mongoc_bulk_operation_set_client(bulk, client);
- mongoc_bulk_operation_set_hint(bulk, server_id);
-
- if (zsession) {
- ZVAL_ZVAL(&bulk_write->session, zsession, 1, 0);
- mongoc_bulk_operation_set_client_session(bulk, Z_SESSION_OBJ_P(zsession)->client_session);
- }
-
- if (zwriteConcern) {
- mongoc_bulk_operation_set_write_concern(bulk, Z_WRITECONCERN_OBJ_P(zwriteConcern)->write_concern);
- }
-
- success = mongoc_bulk_operation_execute(bulk, &reply, &error);
- bulk_write->executed = true;
-
- writeresult = phongo_writeresult_init(return_value, &reply, manager, mongoc_bulk_operation_get_hint(bulk));
- writeresult->write_concern = mongoc_write_concern_copy(write_concern);
-
- /* A BulkWriteException is always thrown if mongoc_bulk_operation_execute()
- * fails to ensure that the write result is accessible. If the error does
- * not originate from the server (e.g. socket error), throw the appropriate
- * exception first. It will be included in BulkWriteException's message and
- * will also be accessible via Exception::getPrevious(). */
- if (!success) {
- if (error.domain != MONGOC_ERROR_SERVER && error.domain != MONGOC_ERROR_WRITE_CONCERN) {
- phongo_throw_exception_from_bson_error_t_and_reply(&error, &reply);
- }
-
- /* Argument errors occur before command execution, so there is no need
- * to layer this InvalidArgumentException behind a BulkWriteException.
- * In practice, this will be a "Cannot do an empty bulk write" error. */
- if (error.domain == MONGOC_ERROR_COMMAND && error.code == MONGOC_ERROR_COMMAND_INVALID_ARG) {
- goto cleanup;
- }
-
- if (EG(exception)) {
- char* message;
-
- (void) spprintf(&message, 0, "Bulk write failed due to previous %s: %s", PHONGO_ZVAL_EXCEPTION_NAME(EG(exception)), error.message);
- zend_throw_exception(php_phongo_bulkwriteexception_ce, message, 0);
- efree(message);
- } else {
- zend_throw_exception(php_phongo_bulkwriteexception_ce, error.message, error.code);
- }
-
- /* Ensure error labels are added to the final BulkWriteException. If a
- * previous exception was also thrown, error labels will already have
- * been added by phongo_throw_exception_from_bson_error_t_and_reply. */
- phongo_exception_add_error_labels(&reply);
- phongo_add_exception_prop(ZEND_STRL("writeResult"), return_value);
- }
-
-cleanup:
- bson_destroy(&reply);
-
- return success;
-} /* }}} */
-
-/* Advance the cursor and return whether there is an error. On error, false is
- * returned and an exception is thrown. */
-bool phongo_cursor_advance_and_check_for_error(mongoc_cursor_t* cursor) /* {{{ */
-{
- const bson_t* doc = NULL;
-
- if (!mongoc_cursor_next(cursor, &doc)) {
- bson_error_t error = { 0 };
-
- /* Check for connection related exceptions */
- if (EG(exception)) {
- return false;
- }
-
- /* Could simply be no docs, which is not an error */
- if (mongoc_cursor_error_document(cursor, &error, &doc)) {
- phongo_throw_exception_from_bson_error_t_and_reply(&error, doc);
- return false;
- }
- }
-
- return true;
-} /* }}} */
-
-bool phongo_execute_query(zval* manager, const char* namespace, zval* zquery, zval* options, uint32_t server_id, zval* return_value) /* {{{ */
-{
- mongoc_client_t* client;
- const php_phongo_query_t* query;
- bson_t opts = BSON_INITIALIZER;
- mongoc_cursor_t* cursor;
- char* dbname;
- char* collname;
- mongoc_collection_t* collection;
- zval* zreadPreference = NULL;
- zval* zsession = NULL;
-
- client = Z_MANAGER_OBJ_P(manager)->client;
-
- if (!phongo_split_namespace(namespace, &dbname, &collname)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s: %s", "Invalid namespace provided", namespace);
- return false;
- }
- collection = mongoc_client_get_collection(client, dbname, collname);
- efree(dbname);
- efree(collname);
-
- query = Z_QUERY_OBJ_P(zquery);
-
- bson_copy_to(query->opts, &opts);
-
- if (query->read_concern) {
- mongoc_collection_set_read_concern(collection, query->read_concern);
- }
-
- if (!phongo_parse_read_preference(options, &zreadPreference)) {
- /* Exception should already have been thrown */
- mongoc_collection_destroy(collection);
- bson_destroy(&opts);
- return false;
- }
-
- if (!phongo_parse_session(options, client, &opts, &zsession)) {
- /* Exception should already have been thrown */
- mongoc_collection_destroy(collection);
- bson_destroy(&opts);
- return false;
- }
-
- if (!BSON_APPEND_INT32(&opts, "serverId", server_id)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Error appending \"serverId\" option");
- mongoc_collection_destroy(collection);
- bson_destroy(&opts);
- return false;
- }
-
- cursor = mongoc_collection_find_with_opts(collection, query->filter, &opts, phongo_read_preference_from_zval(zreadPreference));
- mongoc_collection_destroy(collection);
- bson_destroy(&opts);
-
- /* maxAwaitTimeMS must be set before the cursor is sent */
- if (query->max_await_time_ms) {
- mongoc_cursor_set_max_await_time_ms(cursor, query->max_await_time_ms);
- }
-
- if (!phongo_cursor_advance_and_check_for_error(cursor)) {
- mongoc_cursor_destroy(cursor);
- return false;
- }
-
- phongo_cursor_init_for_query(return_value, manager, cursor, namespace, zquery, zreadPreference, zsession);
-
- return true;
-} /* }}} */
-
-static bson_t* create_wrapped_command_envelope(const char* db, bson_t* reply)
-{
- bson_t* tmp;
- size_t max_ns_len = strlen(db) + 5 + 1; /* db + ".$cmd" + '\0' */
- char* ns = emalloc(max_ns_len);
-
- snprintf(ns, max_ns_len, "%s.$cmd", db);
- tmp = BCON_NEW("cursor", "{", "id", BCON_INT64(0), "ns", BCON_UTF8(ns), "firstBatch", "[", BCON_DOCUMENT(reply), "]", "}");
- efree(ns);
-
- return tmp;
-}
-
-static zval* phongo_create_implicit_session(zval* manager) /* {{{ */
-{
- mongoc_client_session_t* cs;
- zval* zsession;
-
- cs = mongoc_client_start_session(Z_MANAGER_OBJ_P(manager)->client, NULL, NULL);
-
- if (!cs) {
- return NULL;
- }
-
- zsession = ecalloc(1, sizeof(zval));
-
- phongo_session_init(zsession, manager, cs);
-
- return zsession;
-} /* }}} */
-
-bool phongo_execute_command(zval* manager, php_phongo_command_type_t type, const char* db, zval* zcommand, zval* options, uint32_t server_id, zval* return_value) /* {{{ */
-{
- mongoc_client_t* client;
- const php_phongo_command_t* command;
- bson_iter_t iter;
- bson_t reply;
- bson_error_t error = { 0 };
- bson_t opts = BSON_INITIALIZER;
- mongoc_cursor_t* cmd_cursor;
- zval* zreadPreference = NULL;
- zval* zsession = NULL;
- bool result = false;
- bool free_reply = false;
- bool free_zsession = false;
- bool is_unacknowledged_write_concern = false;
-
- client = Z_MANAGER_OBJ_P(manager)->client;
- command = Z_COMMAND_OBJ_P(zcommand);
-
- if ((type & PHONGO_OPTION_READ_CONCERN) && !phongo_parse_read_concern(options, &opts)) {
- /* Exception should already have been thrown */
- goto cleanup;
- }
-
- if ((type & PHONGO_OPTION_READ_PREFERENCE) && !phongo_parse_read_preference(options, &zreadPreference)) {
- /* Exception should already have been thrown */
- goto cleanup;
- }
-
- if (!phongo_parse_session(options, client, &opts, &zsession)) {
- /* Exception should already have been thrown */
- goto cleanup;
- }
-
- if (type & PHONGO_OPTION_WRITE_CONCERN) {
- zval* zwriteConcern = NULL;
-
- if (!phongo_parse_write_concern(options, &opts, &zwriteConcern)) {
- /* Exception should already have been thrown */
- goto cleanup;
- }
-
- /* Determine if the explicit or inherited write concern is
- * unacknowledged so that we can ensure it does not conflict with an
- * explicit or implicit session. */
- if (zwriteConcern) {
- is_unacknowledged_write_concern = !mongoc_write_concern_is_acknowledged(Z_WRITECONCERN_OBJ_P(zwriteConcern)->write_concern);
- } else if (type != PHONGO_COMMAND_RAW) {
- is_unacknowledged_write_concern = !mongoc_write_concern_is_acknowledged(mongoc_client_get_write_concern(client));
- }
- }
-
- if (zsession && is_unacknowledged_write_concern) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Cannot combine \"session\" option with an unacknowledged write concern");
- goto cleanup;
- }
-
- /* If an explicit session was not provided and the effective write concern
- * is not unacknowledged, attempt to create an implicit client session
- * (ignoring any errors). */
- if (!zsession && !is_unacknowledged_write_concern) {
- zsession = phongo_create_implicit_session(manager);
-
- if (zsession) {
- free_zsession = true;
-
- if (!mongoc_client_session_append(Z_SESSION_OBJ_P(zsession)->client_session, &opts, NULL)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Error appending implicit \"sessionId\" option");
- goto cleanup;
- }
- }
- }
-
- if (!BSON_APPEND_INT32(&opts, "serverId", server_id)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Error appending \"serverId\" option");
- goto cleanup;
- }
-
- /* Although "opts" already always includes the serverId option, the read
- * preference is added to the command parts, which is relevant for mongos
- * command construction. */
- switch (type) {
- case PHONGO_COMMAND_RAW:
- result = mongoc_client_command_with_opts(client, db, command->bson, phongo_read_preference_from_zval(zreadPreference), &opts, &reply, &error);
- break;
- case PHONGO_COMMAND_READ:
- result = mongoc_client_read_command_with_opts(client, db, command->bson, phongo_read_preference_from_zval(zreadPreference), &opts, &reply, &error);
- break;
- case PHONGO_COMMAND_WRITE:
- result = mongoc_client_write_command_with_opts(client, db, command->bson, &opts, &reply, &error);
- break;
- case PHONGO_COMMAND_READ_WRITE:
- /* We can pass NULL as readPreference, as this argument was added historically, but has no function */
- result = mongoc_client_read_write_command_with_opts(client, db, command->bson, NULL, &opts, &reply, &error);
- break;
- default:
- /* Should never happen, but if it does: exception */
- phongo_throw_exception(PHONGO_ERROR_LOGIC, "Type '%d' should never have been passed to phongo_execute_command, please file a bug report", type);
- goto cleanup;
- }
-
- free_reply = true;
-
- if (!result) {
- phongo_throw_exception_from_bson_error_t_and_reply(&error, &reply);
- goto cleanup;
- }
-
- /* According to mongoc_cursor_new_from_command_reply_with_opts(), the reply
- * bson_t is ultimately destroyed on both success and failure. */
- if (bson_iter_init_find(&iter, &reply, "cursor") && BSON_ITER_HOLDS_DOCUMENT(&iter)) {
- bson_t initial_reply = BSON_INITIALIZER;
- bson_t cursor_opts = BSON_INITIALIZER;
- bson_error_t error = { 0 };
-
- bson_copy_to(&reply, &initial_reply);
-
- bson_append_int32(&cursor_opts, "serverId", -1, server_id);
-
- if (command->max_await_time_ms) {
- bson_append_bool(&cursor_opts, "awaitData", -1, 1);
- bson_append_int64(&cursor_opts, "maxAwaitTimeMS", -1, command->max_await_time_ms);
- bson_append_bool(&cursor_opts, "tailable", -1, 1);
- }
-
- if (command->batch_size) {
- bson_append_int64(&cursor_opts, "batchSize", -1, command->batch_size);
- }
-
- if (zsession && !mongoc_client_session_append(Z_SESSION_OBJ_P(zsession)->client_session, &cursor_opts, &error)) {
- phongo_throw_exception_from_bson_error_t(&error);
- bson_destroy(&initial_reply);
- bson_destroy(&cursor_opts);
- result = false;
- goto cleanup;
- }
-
- cmd_cursor = mongoc_cursor_new_from_command_reply_with_opts(client, &initial_reply, &cursor_opts);
- bson_destroy(&cursor_opts);
- } else {
- bson_t cursor_opts = BSON_INITIALIZER;
- bson_t* wrapped_reply = create_wrapped_command_envelope(db, &reply);
-
- bson_append_int32(&cursor_opts, "serverId", -1, server_id);
- cmd_cursor = mongoc_cursor_new_from_command_reply_with_opts(client, wrapped_reply, &cursor_opts);
- bson_destroy(&cursor_opts);
- }
-
- phongo_cursor_init_for_command(return_value, manager, cmd_cursor, db, zcommand, zreadPreference, zsession);
-
-cleanup:
- bson_destroy(&opts);
-
- if (free_reply) {
- bson_destroy(&reply);
- }
-
- if (free_zsession) {
- zval_ptr_dtor(zsession);
- efree(zsession);
- }
-
- return result;
-} /* }}} */
-/* }}} */
-
-/* {{{ mongoc types from from_zval */
-const mongoc_write_concern_t* phongo_write_concern_from_zval(zval* zwrite_concern) /* {{{ */
-{
- if (zwrite_concern) {
- php_phongo_writeconcern_t* intern = Z_WRITECONCERN_OBJ_P(zwrite_concern);
-
- if (intern) {
- return intern->write_concern;
- }
- }
-
- return NULL;
-} /* }}} */
-
-const mongoc_read_concern_t* phongo_read_concern_from_zval(zval* zread_concern) /* {{{ */
-{
- if (zread_concern) {
- php_phongo_readconcern_t* intern = Z_READCONCERN_OBJ_P(zread_concern);
-
- if (intern) {
- return intern->read_concern;
- }
- }
-
- return NULL;
-} /* }}} */
-
-const mongoc_read_prefs_t* phongo_read_preference_from_zval(zval* zread_preference) /* {{{ */
-{
- if (zread_preference) {
- php_phongo_readpreference_t* intern = Z_READPREFERENCE_OBJ_P(zread_preference);
-
- if (intern) {
- return intern->read_preference;
- }
- }
-
- return NULL;
-} /* }}} */
-/* }}} */
-
-/* {{{ phongo zval from mongoc types */
-php_phongo_server_description_type_t php_phongo_server_description_type(mongoc_server_description_t* sd)
-{
- const char* name = mongoc_server_description_type(sd);
- int i;
-
- for (i = 0; i < PHONGO_SERVER_DESCRIPTION_TYPES; i++) {
- if (!strcmp(name, php_phongo_server_description_type_map[i].name)) {
- return php_phongo_server_description_type_map[i].type;
- }
- }
-
- return PHONGO_SERVER_UNKNOWN;
-}
-
-bool php_phongo_server_to_zval(zval* retval, mongoc_client_t* client, mongoc_server_description_t* sd) /* {{{ */
-{
- mongoc_host_list_t* host = mongoc_server_description_host(sd);
- const bson_t* hello_response = mongoc_server_description_hello_response(sd);
- bson_iter_t iter;
-
- array_init(retval);
-
- ADD_ASSOC_STRING(retval, "host", host->host);
- ADD_ASSOC_LONG_EX(retval, "port", host->port);
- ADD_ASSOC_LONG_EX(retval, "type", php_phongo_server_description_type(sd));
- ADD_ASSOC_BOOL_EX(retval, "is_primary", !strcmp(mongoc_server_description_type(sd), php_phongo_server_description_type_map[PHONGO_SERVER_RS_PRIMARY].name));
- ADD_ASSOC_BOOL_EX(retval, "is_secondary", !strcmp(mongoc_server_description_type(sd), php_phongo_server_description_type_map[PHONGO_SERVER_RS_SECONDARY].name));
- ADD_ASSOC_BOOL_EX(retval, "is_arbiter", !strcmp(mongoc_server_description_type(sd), php_phongo_server_description_type_map[PHONGO_SERVER_RS_ARBITER].name));
- ADD_ASSOC_BOOL_EX(retval, "is_hidden", bson_iter_init_find_case(&iter, hello_response, "hidden") && bson_iter_as_bool(&iter));
- ADD_ASSOC_BOOL_EX(retval, "is_passive", bson_iter_init_find_case(&iter, hello_response, "passive") && bson_iter_as_bool(&iter));
-
- if (bson_iter_init_find(&iter, hello_response, "tags") && BSON_ITER_HOLDS_DOCUMENT(&iter)) {
- const uint8_t* bytes;
- uint32_t len;
- php_phongo_bson_state state;
-
- PHONGO_BSON_INIT_DEBUG_STATE(state);
- bson_iter_document(&iter, &len, &bytes);
- if (!php_phongo_bson_to_zval_ex(bytes, len, &state)) {
- /* Exception already thrown */
- zval_ptr_dtor(&state.zchild);
- return false;
- }
-
- ADD_ASSOC_ZVAL_EX(retval, "tags", &state.zchild);
- }
-
- /* If the server description is a load balancer, its hello_response will be
- * empty. Instead, report the hello_response from the handshake description
- * (i.e. backing server). */
- if (!strcmp(mongoc_server_description_type(sd), php_phongo_server_description_type_map[PHONGO_SERVER_LOAD_BALANCER].name)) {
- const bson_t* handshake_response;
- mongoc_server_description_t* handshake_sd;
- bson_error_t error = { 0 };
- php_phongo_bson_state state;
-
- if (!(handshake_sd = mongoc_client_get_handshake_description(client, mongoc_server_description_id(sd), NULL, &error))) {
- phongo_throw_exception(PHONGO_ERROR_RUNTIME, "Failed to get handshake server description: %s", error.message);
- return false;
- }
-
- PHONGO_BSON_INIT_DEBUG_STATE(state);
- handshake_response = mongoc_server_description_hello_response(handshake_sd);
-
- if (!php_phongo_bson_to_zval_ex(bson_get_data(handshake_response), handshake_response->len, &state)) {
- /* Exception already thrown */
- mongoc_server_description_destroy(handshake_sd);
- zval_ptr_dtor(&state.zchild);
- return false;
- }
-
- ADD_ASSOC_ZVAL_EX(retval, "last_hello_response", &state.zchild);
- mongoc_server_description_destroy(handshake_sd);
- } else {
- php_phongo_bson_state state;
-
- PHONGO_BSON_INIT_DEBUG_STATE(state);
-
- if (!php_phongo_bson_to_zval_ex(bson_get_data(hello_response), hello_response->len, &state)) {
- /* Exception already thrown */
- zval_ptr_dtor(&state.zchild);
- return false;
- }
-
- ADD_ASSOC_ZVAL_EX(retval, "last_hello_response", &state.zchild);
- }
-
- /* TODO: Use MONGOC_RTT_UNSET once it is added to libmongoc's public API (CDRIVER-4176) */
- if (mongoc_server_description_round_trip_time(sd) == -1) {
- ADD_ASSOC_NULL_EX(retval, "round_trip_time");
- } else {
- ADD_ASSOC_LONG_EX(retval, "round_trip_time", (zend_long) mongoc_server_description_round_trip_time(sd));
- }
-
- return true;
-} /* }}} */
-
-void php_phongo_read_concern_to_zval(zval* retval, const mongoc_read_concern_t* read_concern) /* {{{ */
-{
- const char* level = mongoc_read_concern_get_level(read_concern);
-
- array_init_size(retval, 1);
-
- if (level) {
- ADD_ASSOC_STRING(retval, "level", level);
- }
-} /* }}} */
-
-/* If options is not an array, insert it as a field in a newly allocated array.
- * This may be used to convert legacy options (e.g. ReadPreference option for
- * an executeQuery method) into an options array.
- *
- * A pointer to the array zval will always be returned. If allocated is set to
- * true, php_phongo_prep_legacy_option_free() should be used to free the array
- * zval later. */
-zval* php_phongo_prep_legacy_option(zval* options, const char* key, bool* allocated) /* {{{ */
-{
- *allocated = false;
-
- if (options && Z_TYPE_P(options) != IS_ARRAY) {
- zval* new_options = ecalloc(1, sizeof(zval));
-
- array_init_size(new_options, 1);
- add_assoc_zval(new_options, key, options);
- Z_ADDREF_P(options);
- *allocated = true;
-
- return new_options;
- }
-
- return options;
-} /* }}} */
-
-void php_phongo_prep_legacy_option_free(zval* options) /* {{{ */
-{
- zval_ptr_dtor(options);
- efree(options);
-} /* }}} */
-
-/* Prepare tagSets for BSON encoding by converting each array in the set to an
- * object. This ensures that empty arrays will serialize as empty documents.
- *
- * php_phongo_read_preference_tags_are_valid() handles actual validation of the
- * tag set structure. */
-void php_phongo_read_preference_prep_tagsets(zval* tagSets) /* {{{ */
-{
- HashTable* ht_data;
- zval* tagSet;
-
- if (Z_TYPE_P(tagSets) != IS_ARRAY) {
- return;
- }
-
- ht_data = HASH_OF(tagSets);
-
- ZEND_HASH_FOREACH_VAL_IND(ht_data, tagSet)
- {
- ZVAL_DEREF(tagSet);
- if (Z_TYPE_P(tagSet) == IS_ARRAY) {
- SEPARATE_ZVAL_NOREF(tagSet);
- convert_to_object(tagSet);
- }
- }
- ZEND_HASH_FOREACH_END();
-} /* }}} */
-
-/* Checks if tags is valid to set on a mongoc_read_prefs_t. It may be null or an
- * array of one or more documents. */
-bool php_phongo_read_preference_tags_are_valid(const bson_t* tags) /* {{{ */
-{
- bson_iter_t iter;
-
- if (bson_empty0(tags)) {
- return true;
- }
-
- if (!bson_iter_init(&iter, tags)) {
- return false;
- }
-
- while (bson_iter_next(&iter)) {
- if (!BSON_ITER_HOLDS_DOCUMENT(&iter)) {
- return false;
- }
- }
-
- return true;
-} /* }}} */
-
-void php_phongo_write_concern_to_zval(zval* retval, const mongoc_write_concern_t* write_concern) /* {{{ */
-{
- const char* wtag = mongoc_write_concern_get_wtag(write_concern);
- const int32_t w = mongoc_write_concern_get_w(write_concern);
- const int64_t wtimeout = mongoc_write_concern_get_wtimeout_int64(write_concern);
-
- array_init_size(retval, 4);
-
- if (wtag) {
- ADD_ASSOC_STRING(retval, "w", wtag);
- } else if (mongoc_write_concern_get_wmajority(write_concern)) {
- ADD_ASSOC_STRING(retval, "w", PHONGO_WRITE_CONCERN_W_MAJORITY);
- } else if (w != MONGOC_WRITE_CONCERN_W_DEFAULT) {
- ADD_ASSOC_LONG_EX(retval, "w", w);
- }
-
- if (mongoc_write_concern_journal_is_set(write_concern)) {
- ADD_ASSOC_BOOL_EX(retval, "j", mongoc_write_concern_get_journal(write_concern));
- }
-
- if (wtimeout != 0) {
-#if SIZEOF_ZEND_LONG == 4
- if (wtimeout > INT32_MAX || wtimeout < INT32_MIN) {
- ADD_ASSOC_INT64_AS_STRING(retval, "wtimeout", wtimeout);
- } else {
- ADD_ASSOC_LONG_EX(retval, "wtimeout", wtimeout);
- }
-#else
- ADD_ASSOC_LONG_EX(retval, "wtimeout", wtimeout);
-#endif
- }
-} /* }}} */
-/* }}} */
-
-static mongoc_uri_t* php_phongo_make_uri(const char* uri_string) /* {{{ */
-{
- mongoc_uri_t* uri;
- bson_error_t error = { 0 };
-
- uri = mongoc_uri_new_with_error(uri_string, &error);
- MONGOC_DEBUG("Connection string: '%s'", uri_string);
-
- if (!uri) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Failed to parse MongoDB URI: '%s'. %s.", uri_string, error.message);
- return NULL;
- }
-
- return uri;
-} /* }}} */
-
-static const char* php_phongo_bson_type_to_string(bson_type_t type) /* {{{ */
-{
- switch (type) {
- case BSON_TYPE_EOD:
- return "EOD";
- case BSON_TYPE_DOUBLE:
- return "double";
- case BSON_TYPE_UTF8:
- return "string";
- case BSON_TYPE_DOCUMENT:
- return "document";
- case BSON_TYPE_ARRAY:
- return "array";
- case BSON_TYPE_BINARY:
- return "Binary";
- case BSON_TYPE_UNDEFINED:
- return "undefined";
- case BSON_TYPE_OID:
- return "ObjectId";
- case BSON_TYPE_BOOL:
- return "boolean";
- case BSON_TYPE_DATE_TIME:
- return "UTCDateTime";
- case BSON_TYPE_NULL:
- return "null";
- case BSON_TYPE_REGEX:
- return "Regex";
- case BSON_TYPE_DBPOINTER:
- return "DBPointer";
- case BSON_TYPE_CODE:
- return "Javascript";
- case BSON_TYPE_SYMBOL:
- return "symbol";
- case BSON_TYPE_CODEWSCOPE:
- return "Javascript with scope";
- case BSON_TYPE_INT32:
- return "32-bit integer";
- case BSON_TYPE_TIMESTAMP:
- return "Timestamp";
- case BSON_TYPE_INT64:
- return "64-bit integer";
- case BSON_TYPE_DECIMAL128:
- return "Decimal128";
- case BSON_TYPE_MAXKEY:
- return "MaxKey";
- case BSON_TYPE_MINKEY:
- return "MinKey";
- default:
- return "unknown";
- }
-} /* }}} */
-
-#define PHONGO_URI_INVALID_TYPE(iter, expected) \
- phongo_throw_exception( \
- PHONGO_ERROR_INVALID_ARGUMENT, \
- "Expected %s for \"%s\" URI option, %s given", \
- (expected), \
- bson_iter_key(&(iter)), \
- php_phongo_bson_type_to_string(bson_iter_type(&(iter))))
-
-static bool php_phongo_uri_finalize_auth(mongoc_uri_t* uri) /* {{{ */
-{
- const bson_t* credentials = mongoc_uri_get_credentials(uri);
- bson_iter_t iter;
- const char* source = NULL;
- const char* username = mongoc_uri_get_username(uri);
- bool require_auth = username != NULL;
-
- if (bson_iter_init_find_case(&iter, credentials, MONGOC_URI_AUTHSOURCE)) {
- source = bson_iter_utf8(&iter, NULL);
- require_auth = true;
- }
-
- /* authSource with GSSAPI or X509 should always be external */
- if (mongoc_uri_get_auth_mechanism(uri)) {
- if (!strcasecmp(mongoc_uri_get_auth_mechanism(uri), "GSSAPI") ||
- !strcasecmp(mongoc_uri_get_auth_mechanism(uri), "MONGODB-X509")) {
-
- if (source) {
- if (strcasecmp(source, "$external")) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Failed to parse URI options: GSSAPI and X509 require \"$external\" authSource.");
- return false;
- }
- } else {
- mongoc_uri_set_auth_source(uri, "$external");
- }
- }
-
- /* Mechanisms other than MONGODB-X509 and MONGODB-AWS require a username */
- if (strcasecmp(mongoc_uri_get_auth_mechanism(uri), "MONGODB-X509") &&
- strcasecmp(mongoc_uri_get_auth_mechanism(uri), "MONGODB-AWS")) {
- if (!mongoc_uri_get_username(uri) ||
- !strcmp(mongoc_uri_get_username(uri), "")) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Failed to parse URI options: '%s' authentication mechanism requires username.", mongoc_uri_get_auth_mechanism(uri));
- return false;
- }
- }
-
- /* MONGODB-X509 errors if a password is supplied. */
- if (!strcasecmp(mongoc_uri_get_auth_mechanism(uri), "MONGODB-X509")) {
- if (mongoc_uri_get_password(uri)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Failed to parse URI options: X509 authentication mechanism does not accept a password.");
- return false;
- }
- }
- } else if (require_auth) {
- if (source && strcmp(source, "$external") != 0 && (!username || strcmp(username, "") == 0)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Failed to parse URI options: Default authentication mechanism requires username.");
- return false;
- }
- }
-
- return true;
-} /* }}} */
-
-static bool php_phongo_uri_finalize_directconnection(mongoc_uri_t* uri) /* {{{ */
-{
- const mongoc_host_list_t* hosts;
-
- if (!mongoc_uri_get_option_as_bool(uri, MONGOC_URI_DIRECTCONNECTION, false)) {
- return true;
- }
-
- /* Per the URI options spec, directConnection conflicts with multiple hosts
- * and SRV URIs, which may resolve to multiple hosts. */
- if (!strncmp(mongoc_uri_get_string(uri), "mongodb+srv://", 14)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Failed to parse URI options: SRV URI not allowed with directConnection option.");
- return false;
- }
-
- hosts = mongoc_uri_get_hosts(uri);
-
- if (hosts && hosts->next) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Failed to parse URI options: Multiple seeds not allowed with directConnection option.");
- return false;
- }
-
- return true;
-} /* }}} */
-
-static bool php_phongo_uri_finalize_tls(mongoc_uri_t* uri) /* {{{ */
-{
- const bson_t* options;
- bson_iter_t iter;
-
- if (!(options = mongoc_uri_get_options(uri))) {
- return true;
- }
-
- if (bson_iter_init_find_case(&iter, options, MONGOC_URI_TLSINSECURE) &&
- (bson_iter_init_find_case(&iter, options, MONGOC_URI_TLSALLOWINVALIDCERTIFICATES) ||
- bson_iter_init_find_case(&iter, options, MONGOC_URI_TLSALLOWINVALIDHOSTNAMES) ||
- bson_iter_init_find_case(&iter, options, MONGOC_URI_TLSDISABLEOCSPENDPOINTCHECK) ||
- bson_iter_init_find_case(&iter, options, MONGOC_URI_TLSDISABLECERTIFICATEREVOCATIONCHECK))) {
- phongo_throw_exception(
- PHONGO_ERROR_INVALID_ARGUMENT,
- "Failed to parse URI options: %s may not be combined with %s, %s, %s, or %s.",
- MONGOC_URI_TLSINSECURE,
- MONGOC_URI_TLSALLOWINVALIDCERTIFICATES,
- MONGOC_URI_TLSALLOWINVALIDHOSTNAMES,
- MONGOC_URI_TLSDISABLEOCSPENDPOINTCHECK,
- MONGOC_URI_TLSDISABLECERTIFICATEREVOCATIONCHECK);
- return false;
- }
-
- if (bson_iter_init_find_case(&iter, options, MONGOC_URI_TLSALLOWINVALIDCERTIFICATES) &&
- (bson_iter_init_find_case(&iter, options, MONGOC_URI_TLSDISABLEOCSPENDPOINTCHECK) ||
- bson_iter_init_find_case(&iter, options, MONGOC_URI_TLSDISABLECERTIFICATEREVOCATIONCHECK))) {
- phongo_throw_exception(
- PHONGO_ERROR_INVALID_ARGUMENT,
- "Failed to parse URI options: %s may not be combined with %s or %s.",
- MONGOC_URI_TLSALLOWINVALIDCERTIFICATES,
- MONGOC_URI_TLSDISABLEOCSPENDPOINTCHECK,
- MONGOC_URI_TLSDISABLECERTIFICATEREVOCATIONCHECK);
- return false;
- }
-
- return true;
-} /* }}} */
-
-static bool php_phongo_apply_options_to_uri(mongoc_uri_t* uri, bson_t* options) /* {{{ */
-{
- bson_iter_t iter;
-
- /* Return early if there are no options to apply */
- if (bson_empty0(options) || !bson_iter_init(&iter, options)) {
- return true;
- }
-
- while (bson_iter_next(&iter)) {
- const char* key = bson_iter_key(&iter);
-
- /* Skip read preference, read concern, and write concern options, as
- * those will be processed by other functions. */
- if (!strcasecmp(key, MONGOC_URI_JOURNAL) ||
- !strcasecmp(key, MONGOC_URI_MAXSTALENESSSECONDS) ||
- !strcasecmp(key, MONGOC_URI_READCONCERNLEVEL) ||
- !strcasecmp(key, MONGOC_URI_READPREFERENCE) ||
- !strcasecmp(key, MONGOC_URI_READPREFERENCETAGS) ||
- !strcasecmp(key, MONGOC_URI_SAFE) ||
- !strcasecmp(key, MONGOC_URI_W) ||
- !strcasecmp(key, MONGOC_URI_WTIMEOUTMS)) {
-
- continue;
- }
-
- if (mongoc_uri_option_is_bool(key)) {
- /* The option's type is not validated because bson_iter_as_bool() is
- * used to cast the value to a boolean. Validation may be introduced
- * in PHPC-990. */
- if (!mongoc_uri_set_option_as_bool(uri, key, bson_iter_as_bool(&iter))) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Failed to parse \"%s\" URI option", key);
- return false;
- }
-
- continue;
- }
-
- if (mongoc_uri_option_is_int32(key)) {
- if (!BSON_ITER_HOLDS_INT32(&iter)) {
- PHONGO_URI_INVALID_TYPE(iter, "32-bit integer");
- return false;
- }
-
- if (!mongoc_uri_set_option_as_int32(uri, key, bson_iter_int32(&iter))) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Failed to parse \"%s\" URI option", key);
- return false;
- }
-
- continue;
- }
-
- if (mongoc_uri_option_is_utf8(key)) {
- if (!BSON_ITER_HOLDS_UTF8(&iter)) {
- PHONGO_URI_INVALID_TYPE(iter, "string");
- return false;
- }
-
- if (!strcasecmp(key, MONGOC_URI_REPLICASET) && !strcmp("", bson_iter_utf8(&iter, NULL))) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Value for URI option \"%s\" cannot be empty string.", key);
- return false;
- }
-
- if (!mongoc_uri_set_option_as_utf8(uri, key, bson_iter_utf8(&iter, NULL))) {
- /* Assignment uses mongoc_uri_set_appname() for the "appname"
- * option, which validates length in addition to UTF-8 encoding.
- * For BC, we report the invalid string to the user. */
- if (!strcasecmp(key, MONGOC_URI_APPNAME)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Invalid appname value: '%s'", bson_iter_utf8(&iter, NULL));
- } else {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Failed to parse \"%s\" URI option", key);
- }
- return false;
- }
-
- continue;
- }
-
- if (!strcasecmp(key, "username")) {
- if (!BSON_ITER_HOLDS_UTF8(&iter)) {
- PHONGO_URI_INVALID_TYPE(iter, "string");
- return false;
- }
-
- if (!mongoc_uri_set_username(uri, bson_iter_utf8(&iter, NULL))) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Failed to parse \"%s\" URI option", key);
- return false;
- }
-
- continue;
- }
-
- if (!strcasecmp(key, "password")) {
- if (!BSON_ITER_HOLDS_UTF8(&iter)) {
- PHONGO_URI_INVALID_TYPE(iter, "string");
- return false;
- }
-
- if (!mongoc_uri_set_password(uri, bson_iter_utf8(&iter, NULL))) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Failed to parse \"%s\" URI option", key);
- return false;
- }
-
- continue;
- }
-
- if (!strcasecmp(key, MONGOC_URI_AUTHMECHANISM)) {
- if (!BSON_ITER_HOLDS_UTF8(&iter)) {
- PHONGO_URI_INVALID_TYPE(iter, "string");
- return false;
- }
-
- if (!mongoc_uri_set_auth_mechanism(uri, bson_iter_utf8(&iter, NULL))) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Failed to parse \"%s\" URI option", key);
- return false;
- }
-
- continue;
- }
-
- if (!strcasecmp(key, MONGOC_URI_AUTHSOURCE)) {
- if (!BSON_ITER_HOLDS_UTF8(&iter)) {
- PHONGO_URI_INVALID_TYPE(iter, "string");
- return false;
- }
-
- if (!mongoc_uri_set_auth_source(uri, bson_iter_utf8(&iter, NULL))) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Failed to parse \"%s\" URI option", key);
- return false;
- }
-
- continue;
- }
-
- if (!strcasecmp(key, MONGOC_URI_AUTHMECHANISMPROPERTIES)) {
- bson_t properties;
- uint32_t len;
- const uint8_t* data;
-
- if (!BSON_ITER_HOLDS_DOCUMENT(&iter)) {
- PHONGO_URI_INVALID_TYPE(iter, "array or object");
- return false;
- }
-
- bson_iter_document(&iter, &len, &data);
-
- if (!bson_init_static(&properties, data, len)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Could not initialize BSON structure for auth mechanism properties");
- return false;
- }
-
- if (!mongoc_uri_set_mechanism_properties(uri, &properties)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Failed to parse \"%s\" URI option", key);
- return false;
- }
-
- continue;
- }
-
- if (!strcasecmp(key, MONGOC_URI_GSSAPISERVICENAME)) {
- bson_t unused, properties = BSON_INITIALIZER;
-
- if (mongoc_uri_get_mechanism_properties(uri, &unused)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "authMechanismProperties SERVICE_NAME already set, ignoring \"%s\"", key);
- return false;
- }
-
- if (!BSON_ITER_HOLDS_UTF8(&iter)) {
- PHONGO_URI_INVALID_TYPE(iter, "string");
- return false;
- }
-
- bson_append_utf8(&properties, "SERVICE_NAME", -1, bson_iter_utf8(&iter, NULL), -1);
-
- if (!mongoc_uri_set_mechanism_properties(uri, &properties)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Failed to parse \"%s\" URI option", key);
- bson_destroy(&properties);
- return false;
- }
-
- bson_destroy(&properties);
-
- continue;
- }
-
- if (!strcasecmp(key, MONGOC_URI_COMPRESSORS)) {
- if (!BSON_ITER_HOLDS_UTF8(&iter)) {
- PHONGO_URI_INVALID_TYPE(iter, "string");
- return false;
- }
-
- if (!mongoc_uri_set_compressors(uri, bson_iter_utf8(&iter, NULL))) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Failed to parse \"%s\" URI option", key);
- return false;
- }
-
- continue;
- }
- }
-
- /* Validate any interactions between URI options */
- if (!php_phongo_uri_finalize_auth(uri)) {
- /* Exception should already have been thrown */
- return false;
- }
-
- if (!php_phongo_uri_finalize_directconnection(uri)) {
- /* Exception should already have been thrown */
- return false;
- }
-
- return true;
-} /* }}} */
-
-static bool php_phongo_apply_rc_options_to_uri(mongoc_uri_t* uri, bson_t* options) /* {{{ */
-{
- bson_iter_t iter;
- mongoc_read_concern_t* new_rc;
- const mongoc_read_concern_t* old_rc;
-
- if (!(old_rc = mongoc_uri_get_read_concern(uri))) {
- phongo_throw_exception(PHONGO_ERROR_MONGOC_FAILED, "mongoc_uri_t does not have a read concern");
-
- return false;
- }
-
- /* Return early if there are no options to apply */
- if (bson_empty0(options) || !bson_iter_init(&iter, options)) {
- return true;
- }
-
- new_rc = mongoc_read_concern_copy(old_rc);
-
- while (bson_iter_next(&iter)) {
- const char* key = bson_iter_key(&iter);
-
- if (!strcasecmp(key, MONGOC_URI_READCONCERNLEVEL)) {
- if (!BSON_ITER_HOLDS_UTF8(&iter)) {
- PHONGO_URI_INVALID_TYPE(iter, "string");
- mongoc_read_concern_destroy(new_rc);
-
- return false;
- }
-
- mongoc_read_concern_set_level(new_rc, bson_iter_utf8(&iter, NULL));
- }
- }
-
- mongoc_uri_set_read_concern(uri, new_rc);
- mongoc_read_concern_destroy(new_rc);
-
- return true;
-} /* }}} */
-
-static bool php_phongo_apply_rp_options_to_uri(mongoc_uri_t* uri, bson_t* options) /* {{{ */
-{
- bson_iter_t iter;
- mongoc_read_prefs_t* new_rp;
- const mongoc_read_prefs_t* old_rp;
-
- if (!(old_rp = mongoc_uri_get_read_prefs_t(uri))) {
- phongo_throw_exception(PHONGO_ERROR_MONGOC_FAILED, "mongoc_uri_t does not have a read preference");
-
- return false;
- }
-
- /* Return early if there are no options to apply */
- if (bson_empty0(options) || !bson_iter_init(&iter, options)) {
- return true;
- }
-
- new_rp = mongoc_read_prefs_copy(old_rp);
-
- while (bson_iter_next(&iter)) {
- const char* key = bson_iter_key(&iter);
-
- if (!strcasecmp(key, MONGOC_URI_READPREFERENCE)) {
- const char* str;
-
- if (!BSON_ITER_HOLDS_UTF8(&iter)) {
- PHONGO_URI_INVALID_TYPE(iter, "string");
- mongoc_read_prefs_destroy(new_rp);
-
- return false;
- }
-
- str = bson_iter_utf8(&iter, NULL);
-
- if (0 == strcasecmp("primary", str)) {
- mongoc_read_prefs_set_mode(new_rp, MONGOC_READ_PRIMARY);
- } else if (0 == strcasecmp("primarypreferred", str)) {
- mongoc_read_prefs_set_mode(new_rp, MONGOC_READ_PRIMARY_PREFERRED);
- } else if (0 == strcasecmp("secondary", str)) {
- mongoc_read_prefs_set_mode(new_rp, MONGOC_READ_SECONDARY);
- } else if (0 == strcasecmp("secondarypreferred", str)) {
- mongoc_read_prefs_set_mode(new_rp, MONGOC_READ_SECONDARY_PREFERRED);
- } else if (0 == strcasecmp("nearest", str)) {
- mongoc_read_prefs_set_mode(new_rp, MONGOC_READ_NEAREST);
- } else {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Unsupported %s value: '%s'", bson_iter_key(&iter), str);
- mongoc_read_prefs_destroy(new_rp);
-
- return false;
- }
- }
-
- if (!strcasecmp(key, MONGOC_URI_READPREFERENCETAGS)) {
- bson_t tags;
- uint32_t len;
- const uint8_t* data;
-
- if (!BSON_ITER_HOLDS_ARRAY(&iter)) {
- PHONGO_URI_INVALID_TYPE(iter, "array");
- mongoc_read_prefs_destroy(new_rp);
-
- return false;
- }
-
- bson_iter_array(&iter, &len, &data);
-
- if (!bson_init_static(&tags, data, len)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Could not initialize BSON structure for read preference tags");
- mongoc_read_prefs_destroy(new_rp);
-
- return false;
- }
-
- if (!php_phongo_read_preference_tags_are_valid(&tags)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Read preference tags must be an array of zero or more documents");
- mongoc_read_prefs_destroy(new_rp);
-
- return false;
- }
-
- mongoc_read_prefs_set_tags(new_rp, &tags);
- }
-
- if (!strcasecmp(key, MONGOC_URI_MAXSTALENESSSECONDS)) {
- int64_t max_staleness_seconds;
-
- if (!BSON_ITER_HOLDS_INT(&iter)) {
- PHONGO_URI_INVALID_TYPE(iter, "integer");
- mongoc_read_prefs_destroy(new_rp);
-
- return false;
- }
-
- max_staleness_seconds = bson_iter_as_int64(&iter);
-
- if (max_staleness_seconds != MONGOC_NO_MAX_STALENESS) {
-
- if (max_staleness_seconds < MONGOC_SMALLEST_MAX_STALENESS_SECONDS) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected maxStalenessSeconds to be >= %d, %" PRId64 " given", MONGOC_SMALLEST_MAX_STALENESS_SECONDS, max_staleness_seconds);
- mongoc_read_prefs_destroy(new_rp);
-
- return false;
- }
-
- if (max_staleness_seconds > INT32_MAX) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected maxStalenessSeconds to be <= %d, %" PRId64 " given", INT32_MAX, max_staleness_seconds);
- mongoc_read_prefs_destroy(new_rp);
-
- return false;
- }
-
- if (mongoc_read_prefs_get_mode(new_rp) == MONGOC_READ_PRIMARY) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Primary read preference mode conflicts with maxStalenessSeconds");
- mongoc_read_prefs_destroy(new_rp);
-
- return false;
- }
- }
-
- mongoc_read_prefs_set_max_staleness_seconds(new_rp, max_staleness_seconds);
- }
- }
-
- if (mongoc_read_prefs_get_mode(new_rp) == MONGOC_READ_PRIMARY &&
- !bson_empty(mongoc_read_prefs_get_tags(new_rp))) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Primary read preference mode conflicts with tags");
- mongoc_read_prefs_destroy(new_rp);
-
- return false;
- }
-
- /* Make sure maxStalenessSeconds is not combined with primary readPreference */
- if (mongoc_read_prefs_get_mode(new_rp) == MONGOC_READ_PRIMARY &&
- mongoc_read_prefs_get_max_staleness_seconds(new_rp) != MONGOC_NO_MAX_STALENESS) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Primary read preference mode conflicts with maxStalenessSeconds");
- mongoc_read_prefs_destroy(new_rp);
-
- return false;
- }
-
- /* This may be redundant in light of the previous checks (primary with tags
- * or maxStalenessSeconds), but we'll check anyway in case additional
- * validation is implemented. */
- if (!mongoc_read_prefs_is_valid(new_rp)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Read preference is not valid");
- mongoc_read_prefs_destroy(new_rp);
-
- return false;
- }
-
- mongoc_uri_set_read_prefs_t(uri, new_rp);
- mongoc_read_prefs_destroy(new_rp);
-
- return true;
-} /* }}} */
-
-static bool php_phongo_apply_wc_options_to_uri(mongoc_uri_t* uri, bson_t* options) /* {{{ */
-{
- bson_iter_t iter;
- mongoc_write_concern_t* new_wc;
- const mongoc_write_concern_t* old_wc;
- bool ignore_safe = false;
-
- if (!(old_wc = mongoc_uri_get_write_concern(uri))) {
- phongo_throw_exception(PHONGO_ERROR_MONGOC_FAILED, "mongoc_uri_t does not have a write concern");
-
- return false;
- }
-
- /* Return early if there are no options to apply */
- if (bson_empty0(options) || !bson_iter_init(&iter, options)) {
- return true;
- }
-
- new_wc = mongoc_write_concern_copy(old_wc);
-
- while (bson_iter_next(&iter)) {
- const char* key = bson_iter_key(&iter);
-
- if (!ignore_safe && !strcasecmp(key, MONGOC_URI_SAFE)) {
- if (!BSON_ITER_HOLDS_BOOL(&iter)) {
- PHONGO_URI_INVALID_TYPE(iter, "boolean");
- mongoc_write_concern_destroy(new_wc);
-
- return false;
- }
-
- mongoc_write_concern_set_w(new_wc, bson_iter_bool(&iter) ? 1 : MONGOC_WRITE_CONCERN_W_UNACKNOWLEDGED);
- }
-
- if (!strcasecmp(key, MONGOC_URI_WTIMEOUTMS)) {
- int64_t wtimeout;
-
- if (!BSON_ITER_HOLDS_INT(&iter)) {
- PHONGO_URI_INVALID_TYPE(iter, "integer");
- mongoc_write_concern_destroy(new_wc);
-
- return false;
- }
-
- wtimeout = bson_iter_as_int64(&iter);
-
- if (wtimeout < 0) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected wtimeoutMS to be >= 0, %" PRId64 " given", wtimeout);
- mongoc_write_concern_destroy(new_wc);
-
- return false;
- }
-
- mongoc_write_concern_set_wtimeout_int64(new_wc, wtimeout);
- }
-
- if (!strcasecmp(key, MONGOC_URI_JOURNAL)) {
- if (!BSON_ITER_HOLDS_BOOL(&iter)) {
- PHONGO_URI_INVALID_TYPE(iter, "boolean");
- mongoc_write_concern_destroy(new_wc);
-
- return false;
- }
-
- mongoc_write_concern_set_journal(new_wc, bson_iter_bool(&iter));
- }
-
- if (!strcasecmp(key, MONGOC_URI_W)) {
- if (BSON_ITER_HOLDS_INT32(&iter)) {
- int32_t value = bson_iter_int32(&iter);
-
- switch (value) {
- case MONGOC_WRITE_CONCERN_W_ERRORS_IGNORED:
- case MONGOC_WRITE_CONCERN_W_UNACKNOWLEDGED:
- mongoc_write_concern_set_w(new_wc, value);
- break;
-
- default:
- if (value > 0) {
- mongoc_write_concern_set_w(new_wc, value);
- break;
- }
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Unsupported w value: %d", value);
- mongoc_write_concern_destroy(new_wc);
-
- return false;
- }
- } else if (BSON_ITER_HOLDS_UTF8(&iter)) {
- const char* str = bson_iter_utf8(&iter, NULL);
-
- if (0 == strcasecmp(PHONGO_WRITE_CONCERN_W_MAJORITY, str)) {
- mongoc_write_concern_set_w(new_wc, MONGOC_WRITE_CONCERN_W_MAJORITY);
- } else {
- mongoc_write_concern_set_wtag(new_wc, str);
- }
- } else {
- PHONGO_URI_INVALID_TYPE(iter, "32-bit integer or string");
- mongoc_write_concern_destroy(new_wc);
-
- return false;
- }
-
- ignore_safe = true;
- }
- }
-
- if (mongoc_write_concern_get_journal(new_wc)) {
- int32_t w = mongoc_write_concern_get_w(new_wc);
-
- if (w == MONGOC_WRITE_CONCERN_W_UNACKNOWLEDGED || w == MONGOC_WRITE_CONCERN_W_ERRORS_IGNORED) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Journal conflicts with w value: %d", w);
- mongoc_write_concern_destroy(new_wc);
-
- return false;
- }
- }
-
- /* This may be redundant in light of the last check (unacknowledged w with
- journal), but we'll check anyway in case additional validation is
- implemented. */
- if (!mongoc_write_concern_is_valid(new_wc)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Write concern is not valid");
- mongoc_write_concern_destroy(new_wc);
-
- return false;
- }
-
- mongoc_uri_set_write_concern(uri, new_wc);
- mongoc_write_concern_destroy(new_wc);
-
- return true;
-} /* }}} */
-
-#ifdef MONGOC_ENABLE_SSL
-
-static void php_phongo_mongoc_ssl_opts_from_uri(mongoc_ssl_opt_t* ssl_opt, mongoc_uri_t* uri, bool* any_ssl_option_set)
-{
- bool insecure = mongoc_uri_get_option_as_bool(uri, MONGOC_URI_TLSINSECURE, false);
- const char* pem_file = mongoc_uri_get_option_as_utf8(uri, MONGOC_URI_TLSCERTIFICATEKEYFILE, NULL);
- const char* pem_pwd = mongoc_uri_get_option_as_utf8(uri, MONGOC_URI_TLSCERTIFICATEKEYFILEPASSWORD, NULL);
- const char* ca_file = mongoc_uri_get_option_as_utf8(uri, MONGOC_URI_TLSCAFILE, NULL);
-
- ssl_opt->pem_file = pem_file ? estrdup(pem_file) : NULL;
- ssl_opt->pem_pwd = pem_pwd ? estrdup(pem_pwd) : NULL;
- ssl_opt->ca_file = ca_file ? estrdup(ca_file) : NULL;
- ssl_opt->weak_cert_validation = mongoc_uri_get_option_as_bool(uri, MONGOC_URI_TLSALLOWINVALIDCERTIFICATES, insecure);
- ssl_opt->allow_invalid_hostname = mongoc_uri_get_option_as_bool(uri, MONGOC_URI_TLSALLOWINVALIDHOSTNAMES, insecure);
-
- /* Boolean options default to false, so we cannot consider them for
- * any_ssl_option_set. This isn't actually a problem as libmongoc will
- * already have assigned them when creating the client, enabling SSL, and
- * assigning SSL options. Therefore, we only need to check for non-defaults
- * (i.e. non-NULL strings, true booleans). */
- if (pem_file || pem_pwd || ca_file || ssl_opt->weak_cert_validation || ssl_opt->allow_invalid_hostname) {
- *any_ssl_option_set = true;
- }
-}
-
-static inline char* php_phongo_fetch_ssl_opt_string(zval* zoptions, const char* key)
-{
- int plen;
- zend_bool pfree;
- char* pval;
- char* value;
-
- pval = php_array_fetch_string(zoptions, key, &plen, &pfree);
- value = pfree ? pval : estrndup(pval, plen);
-
- return value;
-}
-
-static mongoc_ssl_opt_t* php_phongo_make_ssl_opt(mongoc_uri_t* uri, zval* zoptions)
-{
- mongoc_ssl_opt_t* ssl_opt;
- bool any_ssl_option_set = false;
-
- if (!zoptions) {
- return NULL;
- }
-
-#if defined(MONGOC_ENABLE_SSL_SECURE_CHANNEL) || defined(MONGOC_ENABLE_SSL_SECURE_TRANSPORT)
- if (php_array_existsc(zoptions, "ca_dir")) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "\"ca_dir\" option is not supported by Secure Channel and Secure Transport");
- return NULL;
- }
-
- if (php_array_existsc(zoptions, "capath")) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "\"capath\" option is not supported by Secure Channel and Secure Transport");
- return NULL;
- }
-#endif
-
-#if defined(MONGOC_ENABLE_SSL_LIBRESSL) || defined(MONGOC_ENABLE_SSL_SECURE_TRANSPORT)
- if (php_array_existsc(zoptions, "crl_file")) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "\"crl_file\" option is not supported by LibreSSL and Secure Transport");
- return NULL;
- }
-#endif
-
- ssl_opt = ecalloc(1, sizeof(mongoc_ssl_opt_t));
-
- /* If SSL options are set in the URL, we need to read them and set them on
- * the options struct so we can merge potential options from passed in
- * driverOptions (zoptions) */
- if (mongoc_uri_get_tls(uri)) {
- php_phongo_mongoc_ssl_opts_from_uri(ssl_opt, uri, &any_ssl_option_set);
- }
-
-#define PHONGO_SSL_OPTION_SWAP_STRING(o, n) \
- if ((o)) { \
- efree((char*) (o)); \
- } \
- (o) = php_phongo_fetch_ssl_opt_string(zoptions, n);
-
- /* Apply driver options that don't have a corresponding URI option. These
- * are set directly on the SSL options struct. */
- if (php_array_existsc(zoptions, "ca_dir")) {
- PHONGO_SSL_OPTION_SWAP_STRING(ssl_opt->ca_dir, "ca_dir");
- any_ssl_option_set = true;
- } else if (php_array_existsc(zoptions, "capath")) {
- PHONGO_SSL_OPTION_SWAP_STRING(ssl_opt->ca_dir, "capath");
- any_ssl_option_set = true;
-
- php_error_docref(NULL, E_DEPRECATED, "The \"capath\" context driver option is deprecated. Please use the \"ca_dir\" driver option instead.");
- }
-
- if (php_array_existsc(zoptions, "crl_file")) {
- PHONGO_SSL_OPTION_SWAP_STRING(ssl_opt->crl_file, "crl_file");
- any_ssl_option_set = true;
- }
-
-#undef PHONGO_SSL_OPTION_SWAP_STRING
-
- if (!any_ssl_option_set) {
- efree(ssl_opt);
- return NULL;
- }
-
- return ssl_opt;
-}
-
-static void php_phongo_free_ssl_opt(mongoc_ssl_opt_t* ssl_opt)
-{
- if (ssl_opt->pem_file) {
- efree((char*) ssl_opt->pem_file);
- }
-
- if (ssl_opt->pem_pwd) {
- efree((char*) ssl_opt->pem_pwd);
- }
-
- if (ssl_opt->ca_file) {
- efree((char*) ssl_opt->ca_file);
- }
-
- if (ssl_opt->ca_dir) {
- efree((char*) ssl_opt->ca_dir);
- }
-
- if (ssl_opt->crl_file) {
- efree((char*) ssl_opt->crl_file);
- }
-
- efree(ssl_opt);
-}
-
-static inline bool php_phongo_apply_driver_option_to_uri(mongoc_uri_t* uri, zval* zoptions, const char* driverOptionKey, const char* optionKey)
-{
- bool ret;
- char* value;
-
- value = php_phongo_fetch_ssl_opt_string(zoptions, driverOptionKey);
- ret = mongoc_uri_set_option_as_utf8(uri, optionKey, value);
- efree(value);
-
- return ret;
-}
-
-static bool php_phongo_apply_driver_options_to_uri(mongoc_uri_t* uri, zval* zoptions)
-{
- if (!zoptions) {
- return true;
- }
-
- /* Map TLS driver options to the canonical tls options in the URI. */
- if (php_array_existsc(zoptions, "allow_invalid_hostname")) {
- if (!mongoc_uri_set_option_as_bool(uri, MONGOC_URI_TLSALLOWINVALIDHOSTNAMES, php_array_fetchc_bool(zoptions, "allow_invalid_hostname"))) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Failed to parse \"%s\" driver option", "allow_invalid_hostname");
-
- return false;
- }
-
- php_error_docref(NULL, E_DEPRECATED, "The \"allow_invalid_hostname\" driver option is deprecated. Please use the \"tlsAllowInvalidHostnames\" URI option instead.");
- }
-
- if (php_array_existsc(zoptions, "weak_cert_validation")) {
- if (!mongoc_uri_set_option_as_bool(uri, MONGOC_URI_TLSALLOWINVALIDCERTIFICATES, php_array_fetchc_bool(zoptions, "weak_cert_validation"))) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Failed to parse \"%s\" driver option", "weak_cert_validation");
-
- return false;
- }
-
- php_error_docref(NULL, E_DEPRECATED, "The \"weak_cert_validation\" driver option is deprecated. Please use the \"tlsAllowInvalidCertificates\" URI option instead.");
- } else if (php_array_existsc(zoptions, "allow_self_signed")) {
- if (!mongoc_uri_set_option_as_bool(uri, MONGOC_URI_TLSALLOWINVALIDCERTIFICATES, php_array_fetchc_bool(zoptions, "allow_self_signed"))) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Failed to parse \"%s\" driver option", "allow_self_signed");
-
- return false;
- }
-
- php_error_docref(NULL, E_DEPRECATED, "The \"allow_self_signed\" context driver option is deprecated. Please use the \"tlsAllowInvalidCertificates\" URI option instead.");
- }
-
- if (php_array_existsc(zoptions, "pem_file")) {
- if (!php_phongo_apply_driver_option_to_uri(uri, zoptions, "pem_file", MONGOC_URI_TLSCERTIFICATEKEYFILE)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Failed to parse \"%s\" driver option", "pem_file");
-
- return false;
- }
-
- php_error_docref(NULL, E_DEPRECATED, "The \"pem_file\" driver option is deprecated. Please use the \"tlsCertificateKeyFile\" URI option instead.");
- } else if (php_array_existsc(zoptions, "local_cert")) {
- if (!php_phongo_apply_driver_option_to_uri(uri, zoptions, "local_cert", MONGOC_URI_TLSCERTIFICATEKEYFILE)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Failed to parse \"%s\" driver option", "local_cert");
-
- return false;
- }
-
- php_error_docref(NULL, E_DEPRECATED, "The \"local_cert\" context driver option is deprecated. Please use the \"tlsCertificateKeyFile\" URI option instead.");
- }
-
- if (php_array_existsc(zoptions, "pem_pwd")) {
- if (!php_phongo_apply_driver_option_to_uri(uri, zoptions, "pem_pwd", MONGOC_URI_TLSCERTIFICATEKEYFILEPASSWORD)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Failed to parse \"%s\" driver option", "pem_pwd");
-
- return false;
- }
-
- php_error_docref(NULL, E_DEPRECATED, "The \"pem_pwd\" driver option is deprecated. Please use the \"tlsCertificateKeyFilePassword\" URI option instead.");
- } else if (php_array_existsc(zoptions, "passphrase")) {
- if (!php_phongo_apply_driver_option_to_uri(uri, zoptions, "passphrase", MONGOC_URI_TLSCERTIFICATEKEYFILEPASSWORD)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Failed to parse \"%s\" driver option", "passphrase");
-
- return false;
- }
-
- php_error_docref(NULL, E_DEPRECATED, "The \"passphrase\" context driver option is deprecated. Please use the \"tlsCertificateKeyFilePassword\" URI option instead.");
- }
-
- if (php_array_existsc(zoptions, "ca_file")) {
- if (!php_phongo_apply_driver_option_to_uri(uri, zoptions, "ca_file", MONGOC_URI_TLSCAFILE)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Failed to parse \"%s\" driver option", "ca_file");
-
- return false;
- }
-
- php_error_docref(NULL, E_DEPRECATED, "The \"ca_file\" driver option is deprecated. Please use the \"tlsCAFile\" URI option instead.");
- } else if (php_array_existsc(zoptions, "cafile")) {
- if (!php_phongo_apply_driver_option_to_uri(uri, zoptions, "cafile", MONGOC_URI_TLSCAFILE)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Failed to parse \"%s\" driver option", "cafile");
-
- return false;
- }
-
- php_error_docref(NULL, E_DEPRECATED, "The \"cafile\" context driver option is deprecated. Please use the \"tlsCAFile\" URI option instead.");
- }
-
- return true;
-}
-#endif
-
-static zval* php_phongo_manager_prepare_manager_for_hash(zval* driverOptions, bool* free)
-{
- php_phongo_manager_t* manager;
- zval* autoEncryptionOpts = NULL;
- zval* keyVaultClient = NULL;
- zval* driverOptionsClone = NULL;
- zval* autoEncryptionOptsClone = NULL;
- zval stackAutoEncryptionOptsClone;
-
- *free = false;
-
- if (!driverOptions) {
- return NULL;
- }
-
- if (!php_array_existsc(driverOptions, "autoEncryption")) {
- goto ref;
- }
-
- autoEncryptionOpts = php_array_fetchc(driverOptions, "autoEncryption");
- if (Z_TYPE_P(autoEncryptionOpts) != IS_ARRAY) {
- goto ref;
- }
-
- if (!php_array_existsc(autoEncryptionOpts, "keyVaultClient")) {
- goto ref;
- }
-
- keyVaultClient = php_array_fetchc(autoEncryptionOpts, "keyVaultClient");
- if (Z_TYPE_P(keyVaultClient) != IS_OBJECT || !instanceof_function(Z_OBJCE_P(keyVaultClient), php_phongo_manager_ce)) {
- goto ref;
- }
-
- *free = true;
-
- manager = Z_MANAGER_OBJ_P(keyVaultClient);
-
- driverOptionsClone = ecalloc(1, sizeof(zval));
- autoEncryptionOptsClone = &stackAutoEncryptionOptsClone;
-
- ZVAL_DUP(autoEncryptionOptsClone, autoEncryptionOpts);
- ADD_ASSOC_STRINGL(autoEncryptionOptsClone, "keyVaultClient", manager->client_hash, manager->client_hash_len);
-
- ZVAL_DUP(driverOptionsClone, driverOptions);
- ADD_ASSOC_ZVAL_EX(driverOptionsClone, "autoEncryption", autoEncryptionOptsClone);
-
- return driverOptionsClone;
-
-ref:
- Z_ADDREF_P(driverOptions);
- return driverOptions;
-}
-
-/* Creates a hash for a client by concatenating the URI string with serialized
- * options arrays. On success, a persistent string is returned (i.e. pefree()
- * should be used to free it) and hash_len will be set to the string's length.
- * On error, an exception will have been thrown and NULL will be returned. */
-static char* php_phongo_manager_make_client_hash(const char* uri_string, zval* options, zval* driverOptions, size_t* hash_len)
-{
- char* hash = NULL;
- smart_str var_buf = { 0 };
- php_serialize_data_t var_hash;
- zval* serializable_driver_options = NULL;
- bool free_driver_options = false;
-
- zval args;
-
- array_init_size(&args, 4);
- ADD_ASSOC_LONG_EX(&args, "pid", getpid());
- ADD_ASSOC_STRING(&args, "uri", uri_string);
-
- if (options) {
- ADD_ASSOC_ZVAL_EX(&args, "options", options);
- Z_ADDREF_P(options);
- } else {
- ADD_ASSOC_NULL_EX(&args, "options");
- }
-
- if (driverOptions) {
- serializable_driver_options = php_phongo_manager_prepare_manager_for_hash(driverOptions, &free_driver_options);
- ADD_ASSOC_ZVAL_EX(&args, "driverOptions", serializable_driver_options);
- } else {
- ADD_ASSOC_NULL_EX(&args, "driverOptions");
- }
-
- PHP_VAR_SERIALIZE_INIT(var_hash);
- php_var_serialize(&var_buf, &args, &var_hash);
- PHP_VAR_SERIALIZE_DESTROY(var_hash);
-
- if (!EG(exception)) {
- *hash_len = ZSTR_LEN(var_buf.s);
- hash = estrndup(ZSTR_VAL(var_buf.s), *hash_len);
- }
-
- zval_ptr_dtor(&args);
-
- if (free_driver_options) {
- efree(serializable_driver_options);
- }
-
- smart_str_free(&var_buf);
-
- return hash;
-}
-
-static bool php_phongo_extract_handshake_data(zval* driver, const char* key, char** value, size_t* value_len)
-{
- zval* zvalue;
-
- if (!php_array_exists(driver, key)) {
- *value = NULL;
- *value_len = 0;
-
- return true;
- }
-
- zvalue = php_array_fetch(driver, key);
-
- if (Z_TYPE_P(zvalue) != IS_STRING) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"%s\" handshake option to be a string, %s given", key, PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(zvalue));
- return false;
- }
-
- *value = estrdup(Z_STRVAL_P(zvalue));
- *value_len = Z_STRLEN_P(zvalue);
-
- return true;
-}
-
-static char* php_phongo_concat_handshake_data(const char* default_value, const char* custom_value, size_t custom_value_len)
-{
- char* ret;
- /* Length of the returned value needs to include a trailing space and null byte */
- size_t ret_len = strlen(default_value) + 2;
-
- if (custom_value) {
- /* Increase the length by that of the custom value as well as the separator length */
- ret_len += custom_value_len + PHONGO_METADATA_SEPARATOR_LEN;
- }
-
- ret = ecalloc(ret_len, sizeof(char));
-
- if (custom_value) {
- snprintf(ret, ret_len, "%s%s%s ", default_value, PHONGO_METADATA_SEPARATOR, custom_value);
- } else {
- snprintf(ret, ret_len, "%s ", default_value);
- }
-
- return ret;
-}
-
-static void php_phongo_handshake_data_append(const char* name, size_t name_len, const char* version, size_t version_len, const char* platform, size_t platform_len)
-{
- char* php_version_string;
- size_t php_version_string_len;
- char* driver_name;
- char* driver_version;
- char* full_platform;
-
- php_version_string_len = strlen(PHP_VERSION) + PHONGO_METADATA_PHP_VERSION_PREFIX_LEN + 1;
- php_version_string = ecalloc(php_version_string_len, sizeof(char));
- snprintf(php_version_string, php_version_string_len, "%s%s", PHONGO_METADATA_PHP_VERSION_PREFIX, PHP_VERSION);
-
- driver_name = php_phongo_concat_handshake_data("ext-mongodb:PHP", name, name_len);
- driver_version = php_phongo_concat_handshake_data(PHP_MONGODB_VERSION, version, version_len);
- full_platform = php_phongo_concat_handshake_data(php_version_string, platform, platform_len);
-
- MONGOC_DEBUG(
- "Setting driver handshake data: { name: '%s', version: '%s', platform: '%s' }",
- driver_name,
- driver_version,
- full_platform);
-
- mongoc_handshake_data_append(driver_name, driver_version, full_platform);
-
- efree(php_version_string);
- efree(driver_name);
- efree(driver_version);
- efree(full_platform);
-}
-
-static void php_phongo_set_handshake_data(zval* driverOptions)
-{
- char* name = NULL;
- size_t name_len = 0;
- char* version = NULL;
- size_t version_len = 0;
- char* platform = NULL;
- size_t platform_len = 0;
-
- if (driverOptions && php_array_existsc(driverOptions, "driver")) {
- zval* driver = php_array_fetchc(driverOptions, "driver");
-
- if (Z_TYPE_P(driver) != IS_ARRAY) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"driver\" driver option to be an array, %s given", PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(driver));
- return;
- }
-
- if (!php_phongo_extract_handshake_data(driver, "name", &name, &name_len)) {
- /* Exception already thrown */
- goto cleanup;
- }
-
- if (!php_phongo_extract_handshake_data(driver, "version", &version, &version_len)) {
- /* Exception already thrown */
- goto cleanup;
- }
-
- if (!php_phongo_extract_handshake_data(driver, "platform", &platform, &platform_len)) {
- /* Exception already thrown */
- goto cleanup;
- }
- }
-
- php_phongo_handshake_data_append(name, name_len, version, version_len, platform, platform_len);
-
-cleanup:
- if (name) {
- efree(name);
- }
- if (version) {
- efree(version);
- }
- if (platform) {
- efree(platform);
- }
-}
-
-static mongoc_client_t* php_phongo_make_mongo_client(const mongoc_uri_t* uri, zval* driverOptions) /* {{{ */
-{
- const char *mongoc_version, *bson_version;
-
-#ifdef HAVE_SYSTEM_LIBMONGOC
- mongoc_version = mongoc_get_version();
-#else
- mongoc_version = "bundled";
-#endif
-
-#ifdef HAVE_SYSTEM_LIBBSON
- bson_version = bson_get_version();
-#else
- bson_version = "bundled";
-#endif
-
- MONGOC_DEBUG(
- "Creating Manager, phongo-%s[%s] - mongoc-%s(%s), libbson-%s(%s), php-%s",
- PHP_MONGODB_VERSION,
- PHP_MONGODB_STABILITY,
- MONGOC_VERSION_S,
- mongoc_version,
- BSON_VERSION_S,
- bson_version,
- PHP_VERSION);
-
- php_phongo_set_handshake_data(driverOptions);
-
- return mongoc_client_new_from_uri(uri);
-} /* }}} */
-
-/* Adds a client to the appropriate registry. Persistent and request-scoped
- * clients each have their own registries (i.e. HashTables), which use different
- * forms of memory allocation. Both registries are used for PID tracking.
- * Returns true if the client was successfully added; otherwise, false. */
-bool php_phongo_client_register(php_phongo_manager_t* manager)
-{
- bool is_persistent = manager->use_persistent_client;
- php_phongo_pclient_t* pclient = pecalloc(1, sizeof(php_phongo_pclient_t), is_persistent);
-
- pclient->client = manager->client;
- pclient->created_by_pid = (int) getpid();
- pclient->is_persistent = is_persistent;
-
- if (is_persistent) {
- MONGOC_DEBUG("Stored persistent client with hash: %s", manager->client_hash);
- return zend_hash_str_update_ptr(&MONGODB_G(persistent_clients), manager->client_hash, manager->client_hash_len, pclient) != NULL;
- } else {
- MONGOC_DEBUG("Stored non-persistent client");
- return zend_hash_next_index_insert_ptr(MONGODB_G(request_clients), pclient) != NULL;
- }
-}
-
-/* Removes a client from the request-scoped registry. This function is a NOP for
- * persistent clients, since they are destroyed along with their registry (i.e.
- * HashTable) in GSHUTDOWN. Returns true if the client was successfully removed;
- * otherwise, false. */
-bool php_phongo_client_unregister(php_phongo_manager_t* manager)
-{
- zend_ulong index;
- php_phongo_pclient_t* pclient;
-
- /* Persistent clients do not get unregistered. */
- if (manager->use_persistent_client) {
- MONGOC_DEBUG("Not destroying persistent client for Manager");
-
- return false;
- }
-
- /* Ensure the request-scoped registry is initialized. This is needed because
- * RSHUTDOWN may occur before a Manager's free_object handler is
- * executed. */
- if (MONGODB_G(request_clients) == NULL) {
- return false;
- }
-
- ZEND_HASH_FOREACH_NUM_KEY_PTR(MONGODB_G(request_clients), index, pclient)
- {
- if (pclient->client == manager->client) {
- MONGOC_DEBUG("Destroying non-persistent client for Manager");
-
- return zend_hash_index_del(MONGODB_G(request_clients), index) == SUCCESS;
- }
- }
- ZEND_HASH_FOREACH_END();
-
- return false;
-}
-
-static mongoc_client_t* php_phongo_find_persistent_client(const char* hash, size_t hash_len)
-{
- php_phongo_pclient_t* pclient = zend_hash_str_find_ptr(&MONGODB_G(persistent_clients), hash, hash_len);
-
- if (pclient) {
- return pclient->client;
- }
-
- return NULL;
-}
-
-static bool phongo_manager_set_serverapi_opts(php_phongo_manager_t* manager, zval* driverOptions) /* {{{ */
-{
- zval* zServerApi;
- php_phongo_serverapi_t* server_api;
- bson_error_t error = { 0 };
-
- if (!driverOptions || !php_array_existsc(driverOptions, "serverApi")) {
- return true;
- }
-
- zServerApi = php_array_fetch(driverOptions, "serverApi");
-
- if (Z_TYPE_P(zServerApi) != IS_OBJECT || !instanceof_function(Z_OBJCE_P(zServerApi), php_phongo_serverapi_ce)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"serverApi\" driver option to be %s, %s given", ZSTR_VAL(php_phongo_serverapi_ce->name), PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(zServerApi));
- return false;
- }
-
- server_api = Z_SERVERAPI_OBJ_P(zServerApi);
-
- if (!mongoc_client_set_server_api(manager->client, server_api->server_api, &error)) {
- phongo_throw_exception_from_bson_error_t(&error);
- return false;
- }
-
- return true;
-} /* }}} */
-
-#ifdef MONGOC_ENABLE_CLIENT_SIDE_ENCRYPTION
-static bool phongo_manager_set_auto_encryption_opts(php_phongo_manager_t* manager, zval* driverOptions) /* {{{ */
-{
- zval* zAutoEncryptionOpts;
- bson_error_t error = { 0 };
- mongoc_auto_encryption_opts_t* auto_encryption_opts = NULL;
- bool retval = false;
-
- if (!driverOptions || !php_array_existsc(driverOptions, "autoEncryption")) {
- return true;
- }
-
- zAutoEncryptionOpts = php_array_fetch(driverOptions, "autoEncryption");
-
- if (Z_TYPE_P(zAutoEncryptionOpts) != IS_ARRAY) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"autoEncryption\" driver option to be array, %s given", PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(zAutoEncryptionOpts));
- return false;
- }
-
- auto_encryption_opts = mongoc_auto_encryption_opts_new();
-
- if (php_array_existsc(zAutoEncryptionOpts, "keyVaultClient")) {
- zval* key_vault_client = php_array_fetch(zAutoEncryptionOpts, "keyVaultClient");
-
- if (Z_TYPE_P(key_vault_client) != IS_OBJECT || !instanceof_function(Z_OBJCE_P(key_vault_client), php_phongo_manager_ce)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"keyVaultClient\" encryption option to be %s, %s given", ZSTR_VAL(php_phongo_manager_ce->name), PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(key_vault_client));
- goto cleanup;
- }
-
- /* Ensure the Manager and keyVaultClient are consistent in their use of
- * persistent clients. A non-persistent Manager could theoretically use
- * a persistent keyVaultClient, but this prohibition may help prevent
- * users from inadvertently creating a persistent keyVaultClient. */
- if (manager->use_persistent_client != Z_MANAGER_OBJ_P(key_vault_client)->use_persistent_client) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "The \"disableClientPersistence\" option for a Manager and its \"keyVaultClient\" must be the same");
- goto cleanup;
- }
-
- mongoc_auto_encryption_opts_set_keyvault_client(auto_encryption_opts, Z_MANAGER_OBJ_P(key_vault_client)->client);
-
- /* Copy the keyVaultClient to the Manager to allow for ref-counting (for
- * non-persistent clients) and reset-on-fork behavior. */
- ZVAL_ZVAL(&manager->key_vault_client_manager, key_vault_client, 1, 0);
- }
-
- if (php_array_existsc(zAutoEncryptionOpts, "keyVaultNamespace")) {
- char* key_vault_ns;
- char* db_name;
- char* coll_name;
- int plen;
- zend_bool pfree;
-
- key_vault_ns = php_array_fetch_string(zAutoEncryptionOpts, "keyVaultNamespace", &plen, &pfree);
-
- if (!phongo_split_namespace(key_vault_ns, &db_name, &coll_name)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"keyVaultNamespace\" encryption option to contain a full collection name");
-
- if (pfree) {
- efree(key_vault_ns);
- }
-
- goto cleanup;
- }
-
- mongoc_auto_encryption_opts_set_keyvault_namespace(auto_encryption_opts, db_name, coll_name);
-
- efree(db_name);
- efree(coll_name);
-
- if (pfree) {
- efree(key_vault_ns);
- }
- }
-
- if (php_array_existsc(zAutoEncryptionOpts, "kmsProviders")) {
- zval* kms_providers = php_array_fetch(zAutoEncryptionOpts, "kmsProviders");
- bson_t bson_providers = BSON_INITIALIZER;
-
- if (Z_TYPE_P(kms_providers) != IS_OBJECT && Z_TYPE_P(kms_providers) != IS_ARRAY) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"kmsProviders\" encryption option to be an array or object");
- goto cleanup;
- }
-
- php_phongo_zval_to_bson(kms_providers, PHONGO_BSON_NONE, &bson_providers, NULL);
- if (EG(exception)) {
- goto cleanup;
- }
-
- mongoc_auto_encryption_opts_set_kms_providers(auto_encryption_opts, &bson_providers);
-
- bson_destroy(&bson_providers);
- }
-
- if (php_array_existsc(zAutoEncryptionOpts, "schemaMap")) {
- zval* schema_map = php_array_fetch(zAutoEncryptionOpts, "schemaMap");
- bson_t bson_map = BSON_INITIALIZER;
-
- if (Z_TYPE_P(schema_map) != IS_OBJECT && Z_TYPE_P(schema_map) != IS_ARRAY) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"schemaMap\" encryption option to be an array or object");
- goto cleanup;
- }
-
- php_phongo_zval_to_bson(schema_map, PHONGO_BSON_NONE, &bson_map, NULL);
- if (EG(exception)) {
- goto cleanup;
- }
-
- mongoc_auto_encryption_opts_set_schema_map(auto_encryption_opts, &bson_map);
-
- bson_destroy(&bson_map);
- }
-
- if (php_array_existsc(zAutoEncryptionOpts, "tlsOptions")) {
- zval* tls_options = php_array_fetch(zAutoEncryptionOpts, "tlsOptions");
- bson_t bson_options = BSON_INITIALIZER;
-
- if (Z_TYPE_P(tls_options) != IS_OBJECT && Z_TYPE_P(tls_options) != IS_ARRAY) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"tlsOptions\" encryption option to be an array or object");
- goto cleanup;
- }
-
- php_phongo_zval_to_bson(tls_options, PHONGO_BSON_NONE, &bson_options, NULL);
- if (EG(exception)) {
- goto cleanup;
- }
-
- mongoc_auto_encryption_opts_set_tls_opts(auto_encryption_opts, &bson_options);
-
- bson_destroy(&bson_options);
- }
-
- if (php_array_existsc(zAutoEncryptionOpts, "bypassAutoEncryption")) {
- zend_bool bypass_auto_encryption = php_array_fetch_bool(zAutoEncryptionOpts, "bypassAutoEncryption");
-
- mongoc_auto_encryption_opts_set_bypass_auto_encryption(auto_encryption_opts, bypass_auto_encryption);
- }
-
- if (php_array_existsc(zAutoEncryptionOpts, "extraOptions")) {
- zval* extra_options = php_array_fetch(zAutoEncryptionOpts, "extraOptions");
- bson_t bson_options = BSON_INITIALIZER;
-
- if (Z_TYPE_P(extra_options) != IS_OBJECT && Z_TYPE_P(extra_options) != IS_ARRAY) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"extraOptions\" encryption option to be an array or object");
- goto cleanup;
- }
-
- php_phongo_zval_to_bson(extra_options, PHONGO_BSON_NONE, &bson_options, NULL);
- if (EG(exception)) {
- goto cleanup;
- }
-
- mongoc_auto_encryption_opts_set_extra(auto_encryption_opts, &bson_options);
-
- bson_destroy(&bson_options);
- }
-
- if (!mongoc_client_enable_auto_encryption(manager->client, auto_encryption_opts, &error)) {
- phongo_throw_exception_from_bson_error_t(&error);
- goto cleanup;
- }
-
- retval = true;
-
-cleanup:
- mongoc_auto_encryption_opts_destroy(auto_encryption_opts);
- return retval;
-}
-/* }}} */
-
-/* keyVaultClientManager is an output parameter and will be assigned the
- * keyVaultNamespace Manager (if any). */
-static mongoc_client_encryption_opts_t* phongo_clientencryption_opts_from_zval(zval* defaultKeyVaultClient, zval* options, zval** keyVaultClientManager) /* {{{ */
-{
- mongoc_client_encryption_opts_t* opts;
-
- opts = mongoc_client_encryption_opts_new();
- *keyVaultClientManager = NULL;
-
- if (!options || Z_TYPE_P(options) != IS_ARRAY) {
- /* Returning opts as-is will defer to mongoc_client_encryption_new to
- * raise an error for missing required options */
- return opts;
- }
-
- if (php_array_existsc(options, "keyVaultClient")) {
- zval* key_vault_client = php_array_fetch(options, "keyVaultClient");
-
- if (Z_TYPE_P(key_vault_client) != IS_OBJECT || !instanceof_function(Z_OBJCE_P(key_vault_client), php_phongo_manager_ce)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"keyVaultClient\" encryption option to be %s, %s given", ZSTR_VAL(php_phongo_manager_ce->name), PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(key_vault_client));
- goto cleanup;
- }
-
- mongoc_client_encryption_opts_set_keyvault_client(opts, Z_MANAGER_OBJ_P(key_vault_client)->client);
- *keyVaultClientManager = key_vault_client;
- } else {
- mongoc_client_encryption_opts_set_keyvault_client(opts, Z_MANAGER_OBJ_P(defaultKeyVaultClient)->client);
- *keyVaultClientManager = defaultKeyVaultClient;
- }
-
- if (php_array_existsc(options, "keyVaultNamespace")) {
- char* keyvault_namespace;
- char* db_name;
- char* coll_name;
- int plen;
- zend_bool pfree;
-
- keyvault_namespace = php_array_fetchc_string(options, "keyVaultNamespace", &plen, &pfree);
-
- if (!phongo_split_namespace(keyvault_namespace, &db_name, &coll_name)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"keyVaultNamespace\" encryption option to contain a full collection name");
-
- if (pfree) {
- efree(keyvault_namespace);
- }
-
- goto cleanup;
- }
-
- mongoc_client_encryption_opts_set_keyvault_namespace(opts, db_name, coll_name);
- efree(db_name);
- efree(coll_name);
-
- if (pfree) {
- efree(keyvault_namespace);
- }
- }
-
- if (php_array_existsc(options, "kmsProviders")) {
- zval* kms_providers = php_array_fetchc(options, "kmsProviders");
- bson_t bson_providers = BSON_INITIALIZER;
-
- if (Z_TYPE_P(kms_providers) != IS_ARRAY && Z_TYPE_P(kms_providers) != IS_OBJECT) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"kmsProviders\" encryption option to be an array or object");
- goto cleanup;
- }
-
- php_phongo_zval_to_bson(kms_providers, PHONGO_BSON_NONE, &bson_providers, NULL);
- if (EG(exception)) {
- goto cleanup;
- }
-
- mongoc_client_encryption_opts_set_kms_providers(opts, &bson_providers);
- bson_destroy(&bson_providers);
- }
-
- if (php_array_existsc(options, "tlsOptions")) {
- zval* tls_options = php_array_fetchc(options, "tlsOptions");
- bson_t bson_options = BSON_INITIALIZER;
-
- if (Z_TYPE_P(tls_options) != IS_ARRAY && Z_TYPE_P(tls_options) != IS_OBJECT) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"tlsOptions\" encryption option to be an array or object");
- goto cleanup;
- }
-
- php_phongo_zval_to_bson(tls_options, PHONGO_BSON_NONE, &bson_options, NULL);
- if (EG(exception)) {
- goto cleanup;
- }
-
- mongoc_client_encryption_opts_set_tls_opts(opts, &bson_options);
- bson_destroy(&bson_options);
- }
-
- return opts;
-
-cleanup:
- if (opts) {
- mongoc_client_encryption_opts_destroy(opts);
- }
-
- return NULL;
-} /* }}} */
-
-void phongo_clientencryption_init(php_phongo_clientencryption_t* clientencryption, zval* manager, zval* options) /* {{{ */
-{
- mongoc_client_encryption_t* ce;
- mongoc_client_encryption_opts_t* opts;
- zval* key_vault_client_manager = manager;
- bson_error_t error = { 0 };
-
- opts = phongo_clientencryption_opts_from_zval(manager, options, &key_vault_client_manager);
- if (!opts) {
- /* Exception already thrown */
- goto cleanup;
- }
-
- ce = mongoc_client_encryption_new(opts, &error);
- if (!ce) {
- phongo_throw_exception_from_bson_error_t(&error);
-
- goto cleanup;
- }
-
- clientencryption->client_encryption = ce;
- ZVAL_ZVAL(&clientencryption->key_vault_client_manager, key_vault_client_manager, 1, 0);
-
-cleanup:
- if (opts) {
- mongoc_client_encryption_opts_destroy(opts);
- }
-} /* }}} */
-
-static mongoc_client_encryption_datakey_opts_t* phongo_clientencryption_datakey_opts_from_zval(zval* options) /* {{{ */
-{
- mongoc_client_encryption_datakey_opts_t* opts;
-
- opts = mongoc_client_encryption_datakey_opts_new();
-
- if (!options || Z_TYPE_P(options) != IS_ARRAY) {
- return opts;
- }
-
- if (php_array_existsc(options, "keyAltNames")) {
- zval* zkeyaltnames = php_array_fetchc(options, "keyAltNames");
- HashTable* ht_data;
- uint32_t keyaltnames_count;
- char** keyaltnames;
- uint32_t i = 0;
- uint32_t j = 0;
- bool failed = false;
-
- if (!zkeyaltnames || Z_TYPE_P(zkeyaltnames) != IS_ARRAY) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected keyAltNames to be array, %s given", PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(zkeyaltnames));
- goto cleanup;
- }
-
- ht_data = HASH_OF(zkeyaltnames);
- keyaltnames_count = ht_data ? zend_hash_num_elements(ht_data) : 0;
- keyaltnames = ecalloc(keyaltnames_count, sizeof(char*));
-
- {
- zend_string* string_key = NULL;
- zend_ulong num_key = 0;
- zval* keyaltname;
-
- ZEND_HASH_FOREACH_KEY_VAL(ht_data, num_key, string_key, keyaltname)
- {
- if (i >= keyaltnames_count) {
- phongo_throw_exception(PHONGO_ERROR_LOGIC, "Iterating over too many keyAltNames. Please file a bug report");
- failed = true;
- break;
- }
-
- if (Z_TYPE_P(keyaltname) != IS_STRING) {
- if (string_key) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected keyAltName with index \"%s\" to be string, %s given", ZSTR_VAL(string_key), PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(keyaltname));
- } else {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected keyAltName with index \"%lu\" to be string, %s given", num_key, PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(keyaltname));
- }
-
- failed = true;
- break;
- }
-
- keyaltnames[i] = estrdup(Z_STRVAL_P(keyaltname));
- i++;
- }
- ZEND_HASH_FOREACH_END();
- }
-
- if (!failed) {
- mongoc_client_encryption_datakey_opts_set_keyaltnames(opts, keyaltnames, keyaltnames_count);
- }
-
- for (j = 0; j < i; j++) {
- efree(keyaltnames[j]);
- }
- efree(keyaltnames);
-
- if (failed) {
- goto cleanup;
- }
- }
-
- if (php_array_existsc(options, "masterKey")) {
- bson_t masterkey = BSON_INITIALIZER;
-
- php_phongo_zval_to_bson(php_array_fetchc(options, "masterKey"), PHONGO_BSON_NONE, &masterkey, NULL);
- if (EG(exception)) {
- goto cleanup;
- }
-
- mongoc_client_encryption_datakey_opts_set_masterkey(opts, &masterkey);
- }
-
- return opts;
-
-cleanup:
- if (opts) {
- mongoc_client_encryption_datakey_opts_destroy(opts);
- }
-
- return NULL;
-} /* }}} */
-
-void phongo_clientencryption_create_datakey(php_phongo_clientencryption_t* clientencryption, zval* return_value, char* kms_provider, zval* options) /* {{{ */
-{
- mongoc_client_encryption_datakey_opts_t* opts;
- bson_value_t keyid;
- bson_error_t error = { 0 };
-
- opts = phongo_clientencryption_datakey_opts_from_zval(options);
- if (!opts) {
- /* Exception already thrown */
- goto cleanup;
- }
-
- if (!mongoc_client_encryption_create_datakey(clientencryption->client_encryption, kms_provider, opts, &keyid, &error)) {
- phongo_throw_exception_from_bson_error_t(&error);
- goto cleanup;
- }
-
- if (!php_phongo_bson_value_to_zval(&keyid, return_value)) {
- /* Exception already thrown */
- goto cleanup;
- }
-
-cleanup:
- if (opts) {
- mongoc_client_encryption_datakey_opts_destroy(opts);
- }
-} /* }}} */
-
-static mongoc_client_encryption_encrypt_opts_t* phongo_clientencryption_encrypt_opts_from_zval(zval* options) /* {{{ */
-{
- mongoc_client_encryption_encrypt_opts_t* opts;
-
- opts = mongoc_client_encryption_encrypt_opts_new();
-
- if (!options || Z_TYPE_P(options) != IS_ARRAY) {
- return opts;
- }
-
- if (php_array_existsc(options, "keyId")) {
- bson_value_t keyid;
-
- php_phongo_zval_to_bson_value(php_array_fetchc(options, "keyId"), PHONGO_BSON_NONE, &keyid);
- if (EG(exception)) {
- goto cleanup;
- }
-
- mongoc_client_encryption_encrypt_opts_set_keyid(opts, &keyid);
- }
-
- if (php_array_existsc(options, "keyAltName")) {
- char* keyaltname;
- int plen;
- zend_bool pfree;
-
- keyaltname = php_array_fetch_string(options, "keyAltName", &plen, &pfree);
- mongoc_client_encryption_encrypt_opts_set_keyaltname(opts, keyaltname);
-
- if (pfree) {
- efree(keyaltname);
- }
- }
-
- if (php_array_existsc(options, "algorithm")) {
- char* algorithm;
- int plen;
- zend_bool pfree;
-
- algorithm = php_array_fetch_string(options, "algorithm", &plen, &pfree);
- mongoc_client_encryption_encrypt_opts_set_algorithm(opts, algorithm);
-
- if (pfree) {
- efree(algorithm);
- }
- }
-
- return opts;
-
-cleanup:
- if (opts) {
- mongoc_client_encryption_encrypt_opts_destroy(opts);
- }
-
- return NULL;
-} /* }}} */
-
-void phongo_clientencryption_encrypt(php_phongo_clientencryption_t* clientencryption, zval* zvalue, zval* zciphertext, zval* options) /* {{{ */
-{
- mongoc_client_encryption_encrypt_opts_t* opts;
- bson_value_t ciphertext, value;
- bson_error_t error = { 0 };
-
- php_phongo_zval_to_bson_value(zvalue, PHONGO_BSON_NONE, &value);
-
- opts = phongo_clientencryption_encrypt_opts_from_zval(options);
- if (!opts) {
- /* Exception already thrown */
- goto cleanup;
- }
-
- if (!mongoc_client_encryption_encrypt(clientencryption->client_encryption, &value, opts, &ciphertext, &error)) {
- phongo_throw_exception_from_bson_error_t(&error);
- goto cleanup;
- }
-
- if (!php_phongo_bson_value_to_zval(&ciphertext, zciphertext)) {
- /* Exception already thrown */
- goto cleanup;
- }
-
-cleanup:
- if (opts) {
- mongoc_client_encryption_encrypt_opts_destroy(opts);
- }
-} /* }}} */
-
-void phongo_clientencryption_decrypt(php_phongo_clientencryption_t* clientencryption, zval* zciphertext, zval* zvalue) /* {{{ */
-{
- bson_value_t ciphertext, value;
- bson_error_t error = { 0 };
-
- php_phongo_zval_to_bson_value(zciphertext, PHONGO_BSON_NONE, &ciphertext);
-
- if (!mongoc_client_encryption_decrypt(clientencryption->client_encryption, &ciphertext, &value, &error)) {
- phongo_throw_exception_from_bson_error_t(&error);
- return;
- }
-
- if (!php_phongo_bson_value_to_zval(&value, zvalue)) {
- /* Exception already thrown */
- return;
- }
-}
-/* }}} */
-#else /* MONGOC_ENABLE_CLIENT_SIDE_ENCRYPTION */
-static void phongo_throw_exception_no_cse(php_phongo_error_domain_t domain, const char* message) /* {{{ */
-{
- phongo_throw_exception(domain, "%s Please recompile with support for libmongocrypt using the with-mongodb-client-side-encryption configure switch.", message);
-}
-/* }}} */
-
-static bool phongo_manager_set_auto_encryption_opts(php_phongo_manager_t* manager, zval* driverOptions) /* {{{ */
-{
- if (!driverOptions || !php_array_existsc(driverOptions, "autoEncryption")) {
- return true;
- }
-
- phongo_throw_exception_no_cse(PHONGO_ERROR_INVALID_ARGUMENT, "Cannot enable automatic field-level encryption.");
-
- return false;
-}
-/* }}} */
-
-void phongo_clientencryption_init(php_phongo_clientencryption_t* clientencryption, zval* manager, zval* options) /* {{{ */
-{
- phongo_throw_exception_no_cse(PHONGO_ERROR_RUNTIME, "Cannot configure clientEncryption object.");
-}
-/* }}} */
-
-void phongo_clientencryption_create_datakey(php_phongo_clientencryption_t* clientencryption, zval* return_value, char* kms_provider, zval* options) /* {{{ */
-{
- phongo_throw_exception_no_cse(PHONGO_ERROR_RUNTIME, "Cannot create encryption key.");
-}
-/* }}} */
-
-void phongo_clientencryption_encrypt(php_phongo_clientencryption_t* clientencryption, zval* zvalue, zval* zciphertext, zval* options) /* {{{ */
-{
- phongo_throw_exception_no_cse(PHONGO_ERROR_RUNTIME, "Cannot encrypt value.");
-}
-/* }}} */
-
-void phongo_clientencryption_decrypt(php_phongo_clientencryption_t* clientencryption, zval* zciphertext, zval* zvalue) /* {{{ */
-{
- phongo_throw_exception_no_cse(PHONGO_ERROR_RUNTIME, "Cannot decrypt value.");
-}
-/* }}} */
-#endif
-
-void phongo_manager_init(php_phongo_manager_t* manager, const char* uri_string, zval* options, zval* driverOptions) /* {{{ */
-{
- bson_t bson_options = BSON_INITIALIZER;
- mongoc_uri_t* uri = NULL;
-#ifdef MONGOC_ENABLE_SSL
- mongoc_ssl_opt_t* ssl_opt = NULL;
-#endif
-
- if (!(manager->client_hash = php_phongo_manager_make_client_hash(uri_string, options, driverOptions, &manager->client_hash_len))) {
- /* Exception should already have been thrown and there is nothing to free */
- return;
- }
-
- if (driverOptions && php_array_existsc(driverOptions, "disableClientPersistence")) {
- manager->use_persistent_client = !php_array_fetchc_bool(driverOptions, "disableClientPersistence");
- } else {
- manager->use_persistent_client = true;
- }
-
- if (manager->use_persistent_client && (manager->client = php_phongo_find_persistent_client(manager->client_hash, manager->client_hash_len))) {
- MONGOC_DEBUG("Found client for hash: %s", manager->client_hash);
- goto cleanup;
- }
-
- if (options) {
- php_phongo_zval_to_bson(options, PHONGO_BSON_NONE, &bson_options, NULL);
- }
-
- /* An exception may be thrown during BSON conversion */
- if (EG(exception)) {
- goto cleanup;
- }
-
- if (!(uri = php_phongo_make_uri(uri_string))) {
- /* Exception should already have been thrown */
- goto cleanup;
- }
-
- if (!php_phongo_apply_options_to_uri(uri, &bson_options) ||
- !php_phongo_apply_rc_options_to_uri(uri, &bson_options) ||
- !php_phongo_apply_rp_options_to_uri(uri, &bson_options) ||
- !php_phongo_apply_wc_options_to_uri(uri, &bson_options)) {
- /* Exception should already have been thrown */
- goto cleanup;
- }
-
-#ifdef MONGOC_ENABLE_SSL
- if (!php_phongo_apply_driver_options_to_uri(uri, driverOptions)) {
- /* Exception should already have been thrown */
- goto cleanup;
- }
-
- ssl_opt = php_phongo_make_ssl_opt(uri, driverOptions);
-
- /* An exception may be thrown during SSL option creation */
- if (EG(exception)) {
- goto cleanup;
- }
-
- if (!php_phongo_uri_finalize_tls(uri)) {
- /* Exception should already have been thrown */
- goto cleanup;
- }
-#else
- if (mongoc_uri_get_tls(uri)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Cannot create SSL client. SSL is not enabled in this build.");
- goto cleanup;
- }
-#endif
-
- manager->client = php_phongo_make_mongo_client(uri, driverOptions);
-
- if (!manager->client) {
- phongo_throw_exception(PHONGO_ERROR_RUNTIME, "Failed to create Manager from URI: '%s'", uri_string);
- goto cleanup;
- }
-
- mongoc_client_set_error_api(manager->client, MONGOC_ERROR_API_VERSION_2);
-
-#ifdef MONGOC_ENABLE_SSL
- if (ssl_opt) {
- mongoc_client_set_ssl_opts(manager->client, ssl_opt);
- }
-#endif
-
- if (!phongo_manager_set_auto_encryption_opts(manager, driverOptions)) {
- /* Exception should already have been thrown */
- goto cleanup;
- }
-
- if (!phongo_manager_set_serverapi_opts(manager, driverOptions)) {
- /* Exception should already have been thrown */
- goto cleanup;
- }
-
- if (!phongo_apm_set_callbacks(manager->client)) {
- /* Exception should already have been thrown */
- goto cleanup;
- }
-
- MONGOC_DEBUG("Created client with hash: %s", manager->client_hash);
-
- /* Register the newly created client in the appropriate registry (for either
- * persistent or request-scoped clients). */
- if (!php_phongo_client_register(manager)) {
- phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "Failed to add Manager client to internal registry");
- goto cleanup;
- }
-
-cleanup:
- bson_destroy(&bson_options);
-
- if (uri) {
- mongoc_uri_destroy(uri);
- }
-
-#ifdef MONGOC_ENABLE_SSL
- if (ssl_opt) {
- php_phongo_free_ssl_opt(ssl_opt);
- }
-#endif
-} /* }}} */
-
-bool php_phongo_parse_int64(int64_t* retval, const char* data, size_t data_len) /* {{{ */
-{
- int64_t value;
- char* endptr = NULL;
-
- /* bson_ascii_strtoll() sets errno if conversion fails. If conversion
- * succeeds, we still want to ensure that the entire string was parsed. */
- value = bson_ascii_strtoll(data, &endptr, 10);
-
- if (errno || (endptr && endptr != ((const char*) data + data_len))) {
- return false;
- }
-
- *retval = value;
-
- return true;
-} /* }}} */
-
-/* {{{ Memory allocation wrappers */
-static void* php_phongo_malloc(size_t num_bytes) /* {{{ */
-{
- return pemalloc(num_bytes, 1);
-} /* }}} */
-
-static void* php_phongo_calloc(size_t num_members, size_t num_bytes) /* {{{ */
-{
- return pecalloc(num_members, num_bytes, 1);
-} /* }}} */
-
-static void* php_phongo_realloc(void* mem, size_t num_bytes) /* {{{ */
-{
- return perealloc(mem, num_bytes, 1);
-} /* }}} */
-
-static void php_phongo_free(void* mem) /* {{{ */
-{
- if (mem) {
- pefree(mem, 1);
- }
-} /* }}} */
-
-/* }}} */
-
-/* {{{ M[INIT|SHUTDOWN] R[INIT|SHUTDOWN] G[INIT|SHUTDOWN] MINFO INI */
-
-static void phongo_pclient_reset_once(php_phongo_pclient_t* pclient, int pid)
-{
- if (pclient->last_reset_by_pid != pid) {
- mongoc_client_reset(pclient->client);
- pclient->last_reset_by_pid = pid;
- }
-}
-
-/* Resets the libmongoc client if it has not already been reset for the current
- * PID (based on information in the hash table of persisted libmongoc clients).
- * This ensures that we do not reset a client multiple times from the same child
- * process. */
-void php_phongo_client_reset_once(php_phongo_manager_t* manager, int pid)
-{
- php_phongo_pclient_t* pclient;
-
- /* Reset associated key vault client */
- if (!Z_ISUNDEF(manager->key_vault_client_manager)) {
- php_phongo_client_reset_once(Z_MANAGER_OBJ_P(&manager->key_vault_client_manager), pid);
- }
-
- if (manager->use_persistent_client) {
- pclient = zend_hash_str_find_ptr(&MONGODB_G(persistent_clients), manager->client_hash, manager->client_hash_len);
-
- if (pclient) {
- phongo_pclient_reset_once(pclient, pid);
- }
-
- return;
- }
-
- ZEND_HASH_FOREACH_PTR(MONGODB_G(request_clients), pclient)
- {
- if (pclient->client == manager->client) {
- phongo_pclient_reset_once(pclient, pid);
- return;
- }
- }
- ZEND_HASH_FOREACH_END();
-}
-
-static void php_phongo_pclient_destroy(php_phongo_pclient_t* pclient)
-{
- /* Do not destroy mongoc_client_t objects created by other processes. This
- * ensures that we do not shutdown sockets that may still be in use by our
- * parent process (see: PHPC-1522).
- *
- * This is a leak; however, we are already in GSHUTDOWN for a persistent
- * clients. For a request-scoped client, we are either in the Manager's
- * free_object handler or RSHUTDOWN, but there the application is capable of
- * freeing its Manager and its client before forking. */
- if (pclient->created_by_pid == getpid()) {
- /* Single-threaded clients may run commands (e.g. endSessions) from
- * mongoc_client_destroy, so disable APM to ensure an event is not
- * dispatched while destroying the Manager and its client. This means
- * that certain shutdown commands cannot be observed unless APM is
- * redesigned to not reference a client (see: PHPC-1666).
- *
- * Note: this is only relevant for request-scoped clients. APM
- * subscribers will no longer exist when persistent clients are
- * destroyed in GSHUTDOWN. */
- mongoc_client_set_apm_callbacks(pclient->client, NULL, NULL);
- mongoc_client_destroy(pclient->client);
- }
-
- /* Persistent and request-scoped clients use different memory allocation */
- pefree(pclient, pclient->is_persistent);
-}
-
-/* Returns whether a Manager exists in the request-scoped registry. If found and
- * the output parameter is non-NULL, the Manager's index will be assigned. */
-static bool php_phongo_manager_exists(php_phongo_manager_t* manager, zend_ulong* index_out)
-{
- zend_ulong index;
- php_phongo_manager_t* value;
-
- if (!MONGODB_G(managers) || zend_hash_num_elements(MONGODB_G(managers)) == 0) {
- return false;
- }
-
- ZEND_HASH_FOREACH_NUM_KEY_PTR(MONGODB_G(managers), index, value)
- {
- if (value != manager) {
- continue;
- }
-
- if (index_out) {
- *index_out = index;
- }
-
- return true;
- }
- ZEND_HASH_FOREACH_END();
-
- return false;
-}
-
-/* Adds a Manager to the request-scoped registry. Returns true if the Manager
- * did not exist and was successfully added; otherwise, returns false. */
-bool php_phongo_manager_register(php_phongo_manager_t* manager)
-{
- if (!MONGODB_G(managers)) {
- return false;
- }
-
- if (php_phongo_manager_exists(manager, NULL)) {
- return false;
- }
-
- return zend_hash_next_index_insert_ptr(MONGODB_G(managers), manager) != NULL;
-}
-
-/* Removes a Manager from the request-scoped registry. Returns true if the
- * Manager was found and successfully removed; otherwise, false is returned. */
-bool php_phongo_manager_unregister(php_phongo_manager_t* manager)
-{
- zend_ulong index;
-
- /* Ensure the registry is initialized. This is needed because RSHUTDOWN may
- * occur before a Manager's free_object handler is executed. */
- if (!MONGODB_G(managers)) {
- return false;
- }
-
- if (php_phongo_manager_exists(manager, &index)) {
- return zend_hash_index_del(MONGODB_G(managers), index) == SUCCESS;
- }
-
- return false;
-}
-
-static void php_phongo_pclient_destroy_ptr(zval* ptr)
-{
- php_phongo_pclient_destroy(Z_PTR_P(ptr));
-}
-
-/* {{{ PHP_RINIT_FUNCTION */
-PHP_RINIT_FUNCTION(mongodb)
-{
- /* Initialize HashTable for non-persistent clients, which is initialized to
- * NULL in GINIT and destroyed and reset to NULL in RSHUTDOWN. Although we
- * specify an element destructor here, all request clients should be freed
- * naturally via garbage collection (i.e. the HashTable should be empty at
- * the time it is destroyed in RSHUTDOWN). */
- if (MONGODB_G(request_clients) == NULL) {
- ALLOC_HASHTABLE(MONGODB_G(request_clients));
- zend_hash_init(MONGODB_G(request_clients), 0, NULL, php_phongo_pclient_destroy_ptr, 0);
- }
-
- /* Initialize HashTable for APM subscribers, which is initialized to NULL in
- * GINIT and destroyed and reset to NULL in RSHUTDOWN. Since this HashTable
- * will store subscriber object zvals, we specify ZVAL_PTR_DTOR as its
- * element destructor so that any still-registered subscribers can be freed
- * in RSHUTDOWN. */
- if (MONGODB_G(subscribers) == NULL) {
- ALLOC_HASHTABLE(MONGODB_G(subscribers));
- zend_hash_init(MONGODB_G(subscribers), 0, NULL, ZVAL_PTR_DTOR, 0);
- }
-
- /* Initialize HashTable for registering Manager objects. This is initialized
- * to NULL in GINIT and destroyed and reset to NULL in RSHUTDOWN. Since this
- * HashTable stores pointers to existing php_phongo_manager_t objects (not
- * counted references), the element destructor is intentionally NULL. */
- if (MONGODB_G(managers) == NULL) {
- ALLOC_HASHTABLE(MONGODB_G(managers));
- zend_hash_init(MONGODB_G(managers), 0, NULL, NULL, 0);
- }
-
- return SUCCESS;
-}
-/* }}} */
-
-/* {{{ PHP_GINIT_FUNCTION */
-PHP_GINIT_FUNCTION(mongodb)
-{
-#if defined(COMPILE_DL_MONGODB) && defined(ZTS)
- ZEND_TSRMLS_CACHE_UPDATE();
-#endif
-
- /* Increment the thread counter. */
- bson_atomic_int32_fetch_add(&phongo_num_threads, 1, bson_memory_order_seq_cst);
-
- /* Clear extension globals */
- memset(mongodb_globals, 0, sizeof(zend_mongodb_globals));
-
- /* Initialize HashTable for persistent clients, which will be destroyed in
- * GSHUTDOWN. We specify an element destructor so that persistent clients
- * can be destroyed along with the HashTable. The HashTable's struct is
- * nested within globals, so no allocation is needed (unlike the HashTables
- * allocated in RINIT). */
- zend_hash_init(&mongodb_globals->persistent_clients, 0, NULL, php_phongo_pclient_destroy_ptr, 1);
-}
-/* }}} */
-
-static zend_class_entry* php_phongo_fetch_internal_class(const char* class_name, size_t class_name_len)
-{
- zend_class_entry* pce;
-
- if ((pce = zend_hash_str_find_ptr(CG(class_table), class_name, class_name_len))) {
- return pce;
- }
-
- return NULL;
-}
-
-static HashTable* php_phongo_std_get_gc(phongo_compat_object_handler_type* object, zval** table, int* n) /* {{{ */
-{
- *table = NULL;
- *n = 0;
- return zend_std_get_properties(object);
-} /* }}} */
-
-/* {{{ PHP_MINIT_FUNCTION */
-PHP_MINIT_FUNCTION(mongodb)
-{
- bson_mem_vtable_t bson_mem_vtable = {
- php_phongo_malloc,
- php_phongo_calloc,
- php_phongo_realloc,
- php_phongo_free,
- };
-
- (void) type; /* We don't care if we are loaded via dl() or extension= */
-
- phongo_register_ini_entries(INIT_FUNC_ARGS_PASSTHRU);
-
- /* Assign our custom vtable to libbson, so all memory allocation in libbson
- * (and libmongoc) will use PHP's persistent memory API. After doing so,
- * initialize libmongoc. Later, we will shutdown libmongoc and restore
- * libbson's vtable in the final GSHUTDOWN. */
- bson_mem_set_vtable(&bson_mem_vtable);
- mongoc_init();
-
- /* Prep default object handlers to be used when we register the classes */
- memcpy(&phongo_std_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
- /* Disable cloning by default. Individual classes can opt in if they need to
- * support this (e.g. BSON objects). */
- phongo_std_object_handlers.clone_obj = NULL;
- /* Ensure that get_gc delegates to zend_std_get_properties directly in case
- * our class defines a get_properties handler for debugging purposes. */
- phongo_std_object_handlers.get_gc = php_phongo_std_get_gc;
-
- /* Initialize zend_class_entry dependencies.
- *
- * Although DateTimeImmutable was introduced in PHP 5.5.0,
- * php_date_get_immutable_ce() is not available in PHP versions before
- * 5.5.24 and 5.6.8.
- *
- * Although JsonSerializable was introduced in PHP 5.4.0,
- * php_json_serializable_ce is not exported in PHP versions before 5.4.26
- * and 5.5.10. For later PHP versions, looking up the class manually also
- * helps with distros that disable LTDL_LAZY for dlopen() (e.g. Fedora).
- */
- php_phongo_date_immutable_ce = php_phongo_fetch_internal_class(ZEND_STRL("datetimeimmutable"));
- php_phongo_json_serializable_ce = php_phongo_fetch_internal_class(ZEND_STRL("jsonserializable"));
-
- if (php_phongo_json_serializable_ce == NULL) {
- zend_error(E_ERROR, "JsonSerializable class is not defined. Please ensure that the 'json' module is loaded before the 'mongodb' module.");
- return FAILURE;
- }
-
- /* Register base BSON classes first */
- php_phongo_type_init_ce(INIT_FUNC_ARGS_PASSTHRU);
- php_phongo_serializable_init_ce(INIT_FUNC_ARGS_PASSTHRU);
- php_phongo_unserializable_init_ce(INIT_FUNC_ARGS_PASSTHRU);
-
- php_phongo_binary_interface_init_ce(INIT_FUNC_ARGS_PASSTHRU);
- php_phongo_decimal128_interface_init_ce(INIT_FUNC_ARGS_PASSTHRU);
- php_phongo_javascript_interface_init_ce(INIT_FUNC_ARGS_PASSTHRU);
- php_phongo_maxkey_interface_init_ce(INIT_FUNC_ARGS_PASSTHRU);
- php_phongo_minkey_interface_init_ce(INIT_FUNC_ARGS_PASSTHRU);
- php_phongo_objectid_interface_init_ce(INIT_FUNC_ARGS_PASSTHRU);
- php_phongo_regex_interface_init_ce(INIT_FUNC_ARGS_PASSTHRU);
- php_phongo_timestamp_interface_init_ce(INIT_FUNC_ARGS_PASSTHRU);
- php_phongo_utcdatetime_interface_init_ce(INIT_FUNC_ARGS_PASSTHRU);
-
- php_phongo_binary_init_ce(INIT_FUNC_ARGS_PASSTHRU);
- php_phongo_dbpointer_init_ce(INIT_FUNC_ARGS_PASSTHRU);
- php_phongo_decimal128_init_ce(INIT_FUNC_ARGS_PASSTHRU);
- php_phongo_int64_init_ce(INIT_FUNC_ARGS_PASSTHRU);
- php_phongo_javascript_init_ce(INIT_FUNC_ARGS_PASSTHRU);
- php_phongo_maxkey_init_ce(INIT_FUNC_ARGS_PASSTHRU);
- php_phongo_minkey_init_ce(INIT_FUNC_ARGS_PASSTHRU);
- php_phongo_objectid_init_ce(INIT_FUNC_ARGS_PASSTHRU);
- php_phongo_persistable_init_ce(INIT_FUNC_ARGS_PASSTHRU);
- php_phongo_regex_init_ce(INIT_FUNC_ARGS_PASSTHRU);
- php_phongo_symbol_init_ce(INIT_FUNC_ARGS_PASSTHRU);
- php_phongo_timestamp_init_ce(INIT_FUNC_ARGS_PASSTHRU);
- php_phongo_undefined_init_ce(INIT_FUNC_ARGS_PASSTHRU);
- php_phongo_utcdatetime_init_ce(INIT_FUNC_ARGS_PASSTHRU);
-
- php_phongo_cursor_interface_init_ce(INIT_FUNC_ARGS_PASSTHRU);
-
- php_phongo_bulkwrite_init_ce(INIT_FUNC_ARGS_PASSTHRU);
- php_phongo_clientencryption_init_ce(INIT_FUNC_ARGS_PASSTHRU);
- php_phongo_command_init_ce(INIT_FUNC_ARGS_PASSTHRU);
- php_phongo_cursor_init_ce(INIT_FUNC_ARGS_PASSTHRU);
- php_phongo_cursorid_init_ce(INIT_FUNC_ARGS_PASSTHRU);
- php_phongo_manager_init_ce(INIT_FUNC_ARGS_PASSTHRU);
- php_phongo_query_init_ce(INIT_FUNC_ARGS_PASSTHRU);
- php_phongo_readconcern_init_ce(INIT_FUNC_ARGS_PASSTHRU);
- php_phongo_readpreference_init_ce(INIT_FUNC_ARGS_PASSTHRU);
- php_phongo_server_init_ce(INIT_FUNC_ARGS_PASSTHRU);
- php_phongo_serverapi_init_ce(INIT_FUNC_ARGS_PASSTHRU);
- php_phongo_session_init_ce(INIT_FUNC_ARGS_PASSTHRU);
- php_phongo_writeconcern_init_ce(INIT_FUNC_ARGS_PASSTHRU);
- php_phongo_writeconcernerror_init_ce(INIT_FUNC_ARGS_PASSTHRU);
- php_phongo_writeerror_init_ce(INIT_FUNC_ARGS_PASSTHRU);
- php_phongo_writeresult_init_ce(INIT_FUNC_ARGS_PASSTHRU);
-
- /* Register base exception classes first */
- php_phongo_exception_init_ce(INIT_FUNC_ARGS_PASSTHRU);
- php_phongo_runtimeexception_init_ce(INIT_FUNC_ARGS_PASSTHRU);
- php_phongo_serverexception_init_ce(INIT_FUNC_ARGS_PASSTHRU);
- php_phongo_connectionexception_init_ce(INIT_FUNC_ARGS_PASSTHRU);
- php_phongo_writeexception_init_ce(INIT_FUNC_ARGS_PASSTHRU);
-
- php_phongo_authenticationexception_init_ce(INIT_FUNC_ARGS_PASSTHRU);
- php_phongo_bulkwriteexception_init_ce(INIT_FUNC_ARGS_PASSTHRU);
- php_phongo_commandexception_init_ce(INIT_FUNC_ARGS_PASSTHRU);
- php_phongo_connectiontimeoutexception_init_ce(INIT_FUNC_ARGS_PASSTHRU);
- php_phongo_encryptionexception_init_ce(INIT_FUNC_ARGS_PASSTHRU);
- php_phongo_executiontimeoutexception_init_ce(INIT_FUNC_ARGS_PASSTHRU);
- php_phongo_invalidargumentexception_init_ce(INIT_FUNC_ARGS_PASSTHRU);
- php_phongo_logicexception_init_ce(INIT_FUNC_ARGS_PASSTHRU);
- php_phongo_sslconnectionexception_init_ce(INIT_FUNC_ARGS_PASSTHRU);
- php_phongo_unexpectedvalueexception_init_ce(INIT_FUNC_ARGS_PASSTHRU);
-
- /* Register base APM classes first */
- php_phongo_subscriber_init_ce(INIT_FUNC_ARGS_PASSTHRU);
- php_phongo_commandsubscriber_init_ce(INIT_FUNC_ARGS_PASSTHRU);
- php_phongo_commandfailedevent_init_ce(INIT_FUNC_ARGS_PASSTHRU);
- php_phongo_commandstartedevent_init_ce(INIT_FUNC_ARGS_PASSTHRU);
- php_phongo_commandsucceededevent_init_ce(INIT_FUNC_ARGS_PASSTHRU);
-
- REGISTER_STRING_CONSTANT("MONGODB_VERSION", (char*) PHP_MONGODB_VERSION, CONST_CS | CONST_PERSISTENT);
- REGISTER_STRING_CONSTANT("MONGODB_STABILITY", (char*) PHP_MONGODB_STABILITY, CONST_CS | CONST_PERSISTENT);
-
- return SUCCESS;
-}
-/* }}} */
-
-/* {{{ PHP_MSHUTDOWN_FUNCTION */
-PHP_MSHUTDOWN_FUNCTION(mongodb)
-{
- phongo_unregister_ini_entries(SHUTDOWN_FUNC_ARGS_PASSTHRU);
-
- return SUCCESS;
-}
-/* }}} */
-
-/* {{{ PHP_RSHUTDOWN_FUNCTION */
-PHP_RSHUTDOWN_FUNCTION(mongodb)
-{
- /* Destroy HashTable for APM subscribers, which was initialized in RINIT. */
- if (MONGODB_G(subscribers)) {
- zend_hash_destroy(MONGODB_G(subscribers));
- FREE_HASHTABLE(MONGODB_G(subscribers));
- MONGODB_G(subscribers) = NULL;
- }
-
- /* Destroy HashTable for non-persistent clients, which was initialized in
- * RINIT. This is intentionally done after the APM subscribers to allow any
- * non-persistent clients still referenced by a subscriber (not freed prior
- * to RSHUTDOWN) to be naturally garbage collected and freed by the Manager
- * free_object handler rather than the HashTable's element destructor. There
- * is no need to use zend_hash_graceful_reverse_destroy here like we do for
- * persistent clients; moreover, the HashTable should already be empty. */
- if (MONGODB_G(request_clients)) {
- zend_hash_destroy(MONGODB_G(request_clients));
- FREE_HASHTABLE(MONGODB_G(request_clients));
- MONGODB_G(request_clients) = NULL;
- }
-
- /* Destroy HashTable for Managers, which was initialized in RINIT. */
- if (MONGODB_G(managers)) {
- zend_hash_destroy(MONGODB_G(managers));
- FREE_HASHTABLE(MONGODB_G(managers));
- MONGODB_G(managers) = NULL;
- }
-
- return SUCCESS;
-}
-/* }}} */
-
-/* {{{ PHP_GSHUTDOWN_FUNCTION */
-PHP_GSHUTDOWN_FUNCTION(mongodb)
-{
- /* Destroy persistent client HashTable in reverse order. This is necessary
- * to prevent segmentation faults as clients may reference other clients in
- * encryption settings. */
- zend_hash_graceful_reverse_destroy(&mongodb_globals->persistent_clients);
-
- phongo_log_disable(mongodb_globals->debug_fd);
- mongodb_globals->debug_fd = NULL;
-
- /* Decrement the thread counter. If it reaches zero, we can infer that this
- * is the last thread, MSHUTDOWN has been called, persistent clients from
- * all threads have been destroyed, and it is now safe to shutdown libmongoc
- * and restore libbson's original vtable. */
- if (bson_atomic_int32_fetch_sub(&phongo_num_threads, 1, bson_memory_order_seq_cst) - 1 == 0) {
- mongoc_cleanup();
- bson_mem_restore_vtable();
- }
-}
-/* }}} */
-
-/* {{{ PHP_MINFO_FUNCTION */
-PHP_MINFO_FUNCTION(mongodb)
-{
- php_info_print_table_start();
- php_info_print_table_header(2, "MongoDB support", "enabled");
- php_info_print_table_row(2, "MongoDB extension version", PHP_MONGODB_VERSION);
- php_info_print_table_row(2, "MongoDB extension stability", PHP_MONGODB_STABILITY);
-
-#ifdef HAVE_SYSTEM_LIBBSON
- php_info_print_table_row(2, "libbson headers version", BSON_VERSION_S);
- php_info_print_table_row(2, "libbson library version", bson_get_version());
-#else
- php_info_print_table_row(2, "libbson bundled version", BSON_VERSION_S);
-#endif
-
-#ifdef HAVE_SYSTEM_LIBMONGOC
- php_info_print_table_row(2, "libmongoc headers version", MONGOC_VERSION_S);
- php_info_print_table_row(2, "libmongoc library version", mongoc_get_version());
-#else
- /* Bundled libraries, buildtime = runtime */
- php_info_print_table_row(2, "libmongoc bundled version", MONGOC_VERSION_S);
-#endif
-
-#ifdef MONGOC_ENABLE_SSL
- php_info_print_table_row(2, "libmongoc SSL", "enabled");
-#if defined(MONGOC_ENABLE_SSL_OPENSSL)
- php_info_print_table_row(2, "libmongoc SSL library", "OpenSSL");
-#elif defined(MONGOC_ENABLE_SSL_LIBRESSL)
- php_info_print_table_row(2, "libmongoc SSL library", "LibreSSL");
-#elif defined(MONGOC_ENABLE_SSL_SECURE_TRANSPORT)
- php_info_print_table_row(2, "libmongoc SSL library", "Secure Transport");
-#elif defined(MONGOC_ENABLE_SSL_SECURE_CHANNEL)
- php_info_print_table_row(2, "libmongoc SSL library", "Secure Channel");
-#else
- php_info_print_table_row(2, "libmongoc SSL library", "unknown");
-#endif
-#else /* MONGOC_ENABLE_SSL */
- php_info_print_table_row(2, "libmongoc SSL", "disabled");
-#endif
-
-#ifdef MONGOC_ENABLE_CRYPTO
- php_info_print_table_row(2, "libmongoc crypto", "enabled");
-#if defined(MONGOC_ENABLE_CRYPTO_LIBCRYPTO)
- php_info_print_table_row(2, "libmongoc crypto library", "libcrypto");
-#elif defined(MONGOC_ENABLE_CRYPTO_COMMON_CRYPTO)
- php_info_print_table_row(2, "libmongoc crypto library", "Common Crypto");
-#elif defined(MONGOC_ENABLE_CRYPTO_CNG)
- php_info_print_table_row(2, "libmongoc crypto library", "CNG");
-#else
- php_info_print_table_row(2, "libmongoc crypto library", "unknown");
-#endif
-#ifdef MONGOC_ENABLE_CRYPTO_SYSTEM_PROFILE
- php_info_print_table_row(2, "libmongoc crypto system profile", "enabled");
-#else
- php_info_print_table_row(2, "libmongoc crypto system profile", "disabled");
-#endif
-#else /* MONGOC_ENABLE_CRYPTO */
- php_info_print_table_row(2, "libmongoc crypto", "disabled");
-#endif
-
-#ifdef MONGOC_ENABLE_SASL
- php_info_print_table_row(2, "libmongoc SASL", "enabled");
-#else
- php_info_print_table_row(2, "libmongoc SASL", "disabled");
-#endif
-
-#ifdef MONGOC_ENABLE_ICU
- php_info_print_table_row(2, "libmongoc ICU", "enabled");
-#else
- php_info_print_table_row(2, "libmongoc ICU", "disabled");
-#endif
-
-#ifdef MONGOC_ENABLE_COMPRESSION
- php_info_print_table_row(2, "libmongoc compression", "enabled");
-#ifdef MONGOC_ENABLE_COMPRESSION_SNAPPY
- php_info_print_table_row(2, "libmongoc compression snappy", "enabled");
-#else
- php_info_print_table_row(2, "libmongoc compression snappy", "disabled");
-#endif
-#ifdef MONGOC_ENABLE_COMPRESSION_ZLIB
- php_info_print_table_row(2, "libmongoc compression zlib", "enabled");
-#else
- php_info_print_table_row(2, "libmongoc compression zlib", "disabled");
-#endif
-#ifdef MONGOC_ENABLE_COMPRESSION_ZSTD
- php_info_print_table_row(2, "libmongoc compression zstd", "enabled");
-#else
- php_info_print_table_row(2, "libmongoc compression zstd", "disabled");
-#endif
-#else /* MONGOC_ENABLE_COMPRESSION */
- php_info_print_table_row(2, "libmongoc compression", "disabled");
-#endif
-
-#ifdef MONGOC_ENABLE_CLIENT_SIDE_ENCRYPTION
-#ifdef HAVE_SYSTEM_LIBMONGOCRYPT
- php_info_print_table_row(2, "libmongocrypt headers version", MONGOCRYPT_VERSION);
- php_info_print_table_row(2, "libmongocrypt library version", mongocrypt_version(NULL));
-#else
- php_info_print_table_row(2, "libmongocrypt bundled version", MONGOCRYPT_VERSION);
-#endif
-
-#ifdef MONGOCRYPT_ENABLE_CRYPTO
- php_info_print_table_row(2, "libmongocrypt crypto", "enabled");
-
-#if defined(MONGOCRYPT_ENABLE_CRYPTO_LIBCRYPTO)
- php_info_print_table_row(2, "libmongocrypt crypto library", "libcrypto");
-#elif defined(MONGOCRYPT_ENABLE_CRYPTO_COMMON_CRYPTO)
- php_info_print_table_row(2, "libmongocrypt crypto library", "Common Crypto");
-#elif defined(MONGOCRYPT_ENABLE_CRYPTO_CNG)
- php_info_print_table_row(2, "libmongocrypt crypto library", "CNG");
-#else
- php_info_print_table_row(2, "libmongocrypt crypto library", "unknown");
-#endif
-#else /* MONGOCRYPT_ENABLE_CRYPTO */
- php_info_print_table_row(2, "libmongocrypt crypto", "disabled");
-#endif
-#else /* MONGOC_ENABLE_CLIENT_SIDE_ENCRYPTION */
- php_info_print_table_row(2, "libmongocrypt", "disabled");
-#endif
-
- php_info_print_table_end();
-
- phongo_display_ini_entries(ZEND_MODULE_INFO_FUNC_ARGS_PASSTHRU);
-}
-/* }}} */
-/* }}} */
-
-/* {{{ Shared function entries for disabling constructors and unserialize() */
-PHP_FUNCTION(MongoDB_disabled___construct) /* {{{ */
-{
- phongo_throw_exception(PHONGO_ERROR_RUNTIME, "Accessing private constructor");
-} /* }}} */
-
-PHP_FUNCTION(MongoDB_disabled___wakeup) /* {{{ */
-{
- zend_error_handling error_handling;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- phongo_throw_exception(PHONGO_ERROR_RUNTIME, "%s", "MongoDB\\Driver objects cannot be serialized");
-} /* }}} */
- /* }}} */
-
-/* {{{ mongodb_functions[]
-*/
-ZEND_BEGIN_ARG_INFO_EX(ai_bson_fromPHP, 0, 0, 1)
- ZEND_ARG_INFO(0, value)
-ZEND_END_ARG_INFO();
-
-ZEND_BEGIN_ARG_INFO_EX(ai_bson_toPHP, 0, 0, 1)
- ZEND_ARG_INFO(0, bson)
- ZEND_ARG_ARRAY_INFO(0, typemap, 0)
-ZEND_END_ARG_INFO();
-
-ZEND_BEGIN_ARG_INFO_EX(ai_bson_toJSON, 0, 0, 1)
- ZEND_ARG_INFO(0, bson)
-ZEND_END_ARG_INFO();
-
-ZEND_BEGIN_ARG_INFO_EX(ai_bson_fromJSON, 0, 0, 1)
- ZEND_ARG_INFO(0, json)
-ZEND_END_ARG_INFO();
-
-ZEND_BEGIN_ARG_INFO_EX(ai_mongodb_driver_monitoring_subscriber, 0, 0, 1)
- ZEND_ARG_OBJ_INFO(0, subscriber, MongoDB\\Driver\\Monitoring\\Subscriber, 0)
-ZEND_END_ARG_INFO();
-
-static const zend_function_entry mongodb_functions[] = {
- ZEND_NS_NAMED_FE("MongoDB\\BSON", fromPHP, PHP_FN(MongoDB_BSON_fromPHP), ai_bson_fromPHP)
- ZEND_NS_NAMED_FE("MongoDB\\BSON", toPHP, PHP_FN(MongoDB_BSON_toPHP), ai_bson_toPHP)
- ZEND_NS_NAMED_FE("MongoDB\\BSON", toJSON, PHP_FN(MongoDB_BSON_toJSON), ai_bson_toJSON)
- ZEND_NS_NAMED_FE("MongoDB\\BSON", toCanonicalExtendedJSON, PHP_FN(MongoDB_BSON_toCanonicalExtendedJSON), ai_bson_toJSON)
- ZEND_NS_NAMED_FE("MongoDB\\BSON", toRelaxedExtendedJSON, PHP_FN(MongoDB_BSON_toRelaxedExtendedJSON), ai_bson_toJSON)
- ZEND_NS_NAMED_FE("MongoDB\\BSON", fromJSON, PHP_FN(MongoDB_BSON_fromJSON), ai_bson_fromJSON)
- ZEND_NS_NAMED_FE("MongoDB\\Driver\\Monitoring", addSubscriber, PHP_FN(MongoDB_Driver_Monitoring_addSubscriber), ai_mongodb_driver_monitoring_subscriber)
- ZEND_NS_NAMED_FE("MongoDB\\Driver\\Monitoring", removeSubscriber, PHP_FN(MongoDB_Driver_Monitoring_removeSubscriber), ai_mongodb_driver_monitoring_subscriber)
- PHP_FE_END
-};
-/* }}} */
-
-static const zend_module_dep mongodb_deps[] = {
- ZEND_MOD_REQUIRED("date")
- ZEND_MOD_REQUIRED("json")
- ZEND_MOD_REQUIRED("spl")
- ZEND_MOD_REQUIRED("standard")
- ZEND_MOD_END
-};
-
-/* {{{ mongodb_module_entry
- */
-zend_module_entry mongodb_module_entry = {
- STANDARD_MODULE_HEADER_EX,
- NULL,
- mongodb_deps,
- "mongodb",
- mongodb_functions,
- PHP_MINIT(mongodb),
- PHP_MSHUTDOWN(mongodb),
- PHP_RINIT(mongodb),
- PHP_RSHUTDOWN(mongodb),
- PHP_MINFO(mongodb),
- PHP_MONGODB_VERSION,
- PHP_MODULE_GLOBALS(mongodb),
- PHP_GINIT(mongodb),
- PHP_GSHUTDOWN(mongodb),
- NULL,
- STANDARD_MODULE_PROPERTIES_EX
-};
-/* }}} */
-
-#ifdef COMPILE_DL_MONGODB
-ZEND_GET_MODULE(mongodb)
-#endif
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/php_phongo.h b/mongodb-1.12.0/php_phongo.h
deleted file mode 100644
index 1c18fb1c..00000000
--- a/mongodb-1.12.0/php_phongo.h
+++ /dev/null
@@ -1,237 +0,0 @@
-/*
- * Copyright 2014-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef PHONGO_H
-#define PHONGO_H
-
-/* External libs */
-#include "bson/bson.h"
-#include "mongoc/mongoc.h"
-
-#include "phongo_version.h"
-#include "phongo_compat.h"
-#include "php_phongo_classes.h"
-
-#define phpext_mongodb_ptr &mongodb_module_entry
-extern zend_module_entry mongodb_module_entry;
-
-/* Structure for tracking libmongoc clients (both persisted and non-persisted).
- * The PID is included to ensure that processes do not destroy clients created
- * by other processes (relevant for forking). We avoid using pid_t for Windows
- * compatibility. */
-typedef struct {
- mongoc_client_t* client;
- int created_by_pid;
- int last_reset_by_pid;
- bool is_persistent;
-} php_phongo_pclient_t;
-
-ZEND_BEGIN_MODULE_GLOBALS(mongodb)
- char* debug;
- FILE* debug_fd;
- bool mock_service_id;
- HashTable persistent_clients;
- HashTable* request_clients;
- HashTable* subscribers;
- HashTable* managers;
-ZEND_END_MODULE_GLOBALS(mongodb)
-
-#define MONGODB_G(v) ZEND_MODULE_GLOBALS_ACCESSOR(mongodb, v)
-#if defined(ZTS) && defined(COMPILE_DL_MONGODB)
-ZEND_TSRMLS_CACHE_EXTERN()
-#endif
-
-#define PHONGO_WRITE_CONCERN_W_MAJORITY "majority"
-
-/* This enum is necessary since mongoc_server_description_type_t is private and
- * we need to translate strings returned by mongoc_server_description_type() to
- * Server integer constants. */
-typedef enum {
- PHONGO_SERVER_UNKNOWN = 0,
- PHONGO_SERVER_STANDALONE = 1,
- PHONGO_SERVER_MONGOS = 2,
- PHONGO_SERVER_POSSIBLE_PRIMARY = 3,
- PHONGO_SERVER_RS_PRIMARY = 4,
- PHONGO_SERVER_RS_SECONDARY = 5,
- PHONGO_SERVER_RS_ARBITER = 6,
- PHONGO_SERVER_RS_OTHER = 7,
- PHONGO_SERVER_RS_GHOST = 8,
- PHONGO_SERVER_LOAD_BALANCER = 9,
- PHONGO_SERVER_DESCRIPTION_TYPES = 10,
-} php_phongo_server_description_type_t;
-
-typedef struct {
- php_phongo_server_description_type_t type;
- const char* name;
-} php_phongo_server_description_type_map_t;
-
-extern php_phongo_server_description_type_map_t php_phongo_server_description_type_map[];
-
-typedef enum {
- PHONGO_ERROR_INVALID_ARGUMENT = 1,
- PHONGO_ERROR_RUNTIME = 2,
- PHONGO_ERROR_UNEXPECTED_VALUE = 8,
- PHONGO_ERROR_MONGOC_FAILED = 3,
- PHONGO_ERROR_CONNECTION_FAILED = 7,
- PHONGO_ERROR_LOGIC = 9
-} php_phongo_error_domain_t;
-
-/* This constant is used for determining if a server error for an exceeded query
- * or command should select ExecutionTimeoutException. */
-#define PHONGO_SERVER_ERROR_EXCEEDED_TIME_LIMIT 50
-
-zend_class_entry* phongo_exception_from_mongoc_domain(uint32_t /* mongoc_error_domain_t */ domain, uint32_t /* mongoc_error_code_t */ code);
-zend_class_entry* phongo_exception_from_phongo_domain(php_phongo_error_domain_t domain);
-void phongo_throw_exception(php_phongo_error_domain_t domain, const char* format, ...);
-void phongo_throw_exception_from_bson_error_t(bson_error_t* error);
-void phongo_throw_exception_from_bson_error_t_and_reply(bson_error_t* error, const bson_t* reply);
-
-/* This enum is used for processing options in phongo_execute_parse_options and
- * selecting a libmongoc function to use in phongo_execute_command. The values
- * are important, as READ and WRITE are also used as a bit field to determine
- * whether readPreference, readConcern, and writeConcern options are parsed. */
-typedef enum {
- PHONGO_OPTION_READ_CONCERN = 0x01,
- PHONGO_OPTION_READ_PREFERENCE = 0x02,
- PHONGO_OPTION_WRITE_CONCERN = 0x04,
- PHONGO_COMMAND_RAW = 0x07,
- PHONGO_COMMAND_READ = 0x03,
- PHONGO_COMMAND_WRITE = 0x04,
- PHONGO_COMMAND_READ_WRITE = 0x05,
-} php_phongo_command_type_t;
-
-zend_object_handlers* phongo_get_std_object_handlers(void);
-
-void phongo_clientencryption_init(php_phongo_clientencryption_t* ce_obj, zval* manager, zval* options);
-void phongo_server_init(zval* return_value, zval* manager, uint32_t server_id);
-void phongo_session_init(zval* return_value, zval* manager, mongoc_client_session_t* client_session);
-void phongo_objectid_init(zval* return_value, const bson_oid_t* oid);
-void phongo_readconcern_init(zval* return_value, const mongoc_read_concern_t* read_concern);
-void phongo_readpreference_init(zval* return_value, const mongoc_read_prefs_t* read_prefs);
-void phongo_writeconcern_init(zval* return_value, const mongoc_write_concern_t* write_concern);
-bool phongo_execute_bulk_write(zval* manager, const char* namespace, php_phongo_bulkwrite_t* bulk_write, zval* zwriteConcern, uint32_t server_id, zval* return_value);
-bool phongo_execute_command(zval* manager, php_phongo_command_type_t type, const char* db, zval* zcommand, zval* zreadPreference, uint32_t server_id, zval* return_value);
-bool phongo_execute_query(zval* manager, const char* namespace, zval* zquery, zval* zreadPreference, uint32_t server_id, zval* return_value);
-
-bool phongo_cursor_advance_and_check_for_error(mongoc_cursor_t* cursor);
-
-const mongoc_read_concern_t* phongo_read_concern_from_zval(zval* zread_concern);
-const mongoc_read_prefs_t* phongo_read_preference_from_zval(zval* zread_preference);
-const mongoc_write_concern_t* phongo_write_concern_from_zval(zval* zwrite_concern);
-
-php_phongo_server_description_type_t php_phongo_server_description_type(mongoc_server_description_t* sd);
-
-bool phongo_parse_read_preference(zval* options, zval** zreadPreference);
-bool phongo_parse_session(zval* options, mongoc_client_t* client, bson_t* mongoc_opts, zval** zsession);
-
-zval* php_phongo_prep_legacy_option(zval* options, const char* key, bool* allocated);
-void php_phongo_prep_legacy_option_free(zval* options);
-
-void php_phongo_read_preference_prep_tagsets(zval* tagSets);
-bool php_phongo_read_preference_tags_are_valid(const bson_t* tags);
-
-bool php_phongo_server_to_zval(zval* retval, mongoc_client_t* client, mongoc_server_description_t* sd);
-void php_phongo_read_concern_to_zval(zval* retval, const mongoc_read_concern_t* read_concern);
-void php_phongo_write_concern_to_zval(zval* retval, const mongoc_write_concern_t* write_concern);
-
-void phongo_manager_init(php_phongo_manager_t* manager, const char* uri_string, zval* options, zval* driverOptions);
-bool php_phongo_set_monitoring_callbacks(mongoc_client_t* client);
-
-bool php_phongo_parse_int64(int64_t* retval, const char* data, size_t data_len);
-
-void phongo_clientencryption_create_datakey(php_phongo_clientencryption_t* clientencryption, zval* return_value, char* kms_provider, zval* options);
-void phongo_clientencryption_encrypt(php_phongo_clientencryption_t* clientencryption, zval* zvalue, zval* zciphertext, zval* options);
-void phongo_clientencryption_decrypt(php_phongo_clientencryption_t* clientencryption, zval* zciphertext, zval* zvalue);
-
-zend_bool phongo_writeerror_init(zval* return_value, bson_t* bson);
-zend_bool phongo_writeconcernerror_init(zval* return_value, bson_t* bson);
-
-void php_phongo_client_reset_once(php_phongo_manager_t* manager, int pid);
-
-bool php_phongo_client_register(php_phongo_manager_t* manager);
-bool php_phongo_client_unregister(php_phongo_manager_t* manager);
-
-bool php_phongo_manager_register(php_phongo_manager_t* manager);
-bool php_phongo_manager_unregister(php_phongo_manager_t* manager);
-
-#define PHONGO_CE_FINAL(ce) \
- do { \
- ce->ce_flags |= ZEND_ACC_FINAL; \
- } while (0)
-
-#if PHP_VERSION_ID < 80100
-#define PHONGO_CE_DISABLE_SERIALIZATION(ce) \
- do { \
- ce->serialize = zend_class_serialize_deny; \
- ce->unserialize = zend_class_unserialize_deny; \
- } while (0)
-#else
-#define PHONGO_CE_DISABLE_SERIALIZATION(ce) \
- do { \
- ce->ce_flags |= ZEND_ACC_NOT_SERIALIZABLE; \
- } while (0)
-#endif
-
-#define PHONGO_GET_PROPERTY_HASH_INIT_PROPS(is_temp, intern, props, size) \
- do { \
- if (is_temp) { \
- ALLOC_HASHTABLE(props); \
- zend_hash_init((props), (size), NULL, ZVAL_PTR_DTOR, 0); \
- } else if ((intern)->properties) { \
- (props) = (intern)->properties; \
- } else { \
- ALLOC_HASHTABLE(props); \
- zend_hash_init((props), (size), NULL, ZVAL_PTR_DTOR, 0); \
- (intern)->properties = (props); \
- } \
- } while (0)
-
-#define PHONGO_GET_PROPERTY_HASH_FREE_PROPS(is_temp, props) \
- do { \
- if (is_temp) { \
- zend_hash_destroy((props)); \
- FREE_HASHTABLE(props); \
- } \
- } while (0)
-
-#define PHONGO_ZVAL_CLASS_OR_TYPE_NAME(zv) (Z_TYPE(zv) == IS_OBJECT ? ZSTR_VAL(Z_OBJCE(zv)->name) : zend_get_type_by_const(Z_TYPE(zv)))
-#define PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(zvp) PHONGO_ZVAL_CLASS_OR_TYPE_NAME(*(zvp))
-
-#define PHONGO_ZVAL_EXCEPTION_NAME(e) (ZSTR_VAL(e->ce->name))
-
-#define PHONGO_SET_CREATED_BY_PID(intern) \
- do { \
- (intern)->created_by_pid = (int) getpid(); \
- } while (0)
-
-#define PHONGO_RESET_CLIENT_IF_PID_DIFFERS(intern, manager) \
- do { \
- int pid = (int) getpid(); \
- if ((intern)->created_by_pid != pid) { \
- php_phongo_client_reset_once((manager), pid); \
- } \
- } while (0)
-
-#endif /* PHONGO_H */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/php_phongo_classes.h b/mongodb-1.12.0/php_phongo_classes.h
deleted file mode 100644
index cb6b4df6..00000000
--- a/mongodb-1.12.0/php_phongo_classes.h
+++ /dev/null
@@ -1,372 +0,0 @@
-/*
- * Copyright 2014-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef PHONGO_CLASSES_H
-#define PHONGO_CLASSES_H
-
-#include "php_phongo_structs.h"
-
-/* Export zend_class_entry dependencies, which are initialized in MINIT */
-extern zend_class_entry* php_phongo_date_immutable_ce;
-extern zend_class_entry* php_phongo_json_serializable_ce;
-
-static inline php_phongo_bulkwrite_t* php_bulkwrite_fetch_object(zend_object* obj)
-{
- return (php_phongo_bulkwrite_t*) ((char*) obj - XtOffsetOf(php_phongo_bulkwrite_t, std));
-}
-static inline php_phongo_clientencryption_t* php_clientencryption_fetch_object(zend_object* obj)
-{
- return (php_phongo_clientencryption_t*) ((char*) obj - XtOffsetOf(php_phongo_clientencryption_t, std));
-}
-static inline php_phongo_command_t* php_command_fetch_object(zend_object* obj)
-{
- return (php_phongo_command_t*) ((char*) obj - XtOffsetOf(php_phongo_command_t, std));
-}
-static inline php_phongo_cursor_t* php_cursor_fetch_object(zend_object* obj)
-{
- return (php_phongo_cursor_t*) ((char*) obj - XtOffsetOf(php_phongo_cursor_t, std));
-}
-static inline php_phongo_cursorid_t* php_cursorid_fetch_object(zend_object* obj)
-{
- return (php_phongo_cursorid_t*) ((char*) obj - XtOffsetOf(php_phongo_cursorid_t, std));
-}
-static inline php_phongo_manager_t* php_manager_fetch_object(zend_object* obj)
-{
- return (php_phongo_manager_t*) ((char*) obj - XtOffsetOf(php_phongo_manager_t, std));
-}
-static inline php_phongo_query_t* php_query_fetch_object(zend_object* obj)
-{
- return (php_phongo_query_t*) ((char*) obj - XtOffsetOf(php_phongo_query_t, std));
-}
-static inline php_phongo_readconcern_t* php_readconcern_fetch_object(zend_object* obj)
-{
- return (php_phongo_readconcern_t*) ((char*) obj - XtOffsetOf(php_phongo_readconcern_t, std));
-}
-static inline php_phongo_readpreference_t* php_readpreference_fetch_object(zend_object* obj)
-{
- return (php_phongo_readpreference_t*) ((char*) obj - XtOffsetOf(php_phongo_readpreference_t, std));
-}
-static inline php_phongo_server_t* php_server_fetch_object(zend_object* obj)
-{
- return (php_phongo_server_t*) ((char*) obj - XtOffsetOf(php_phongo_server_t, std));
-}
-static inline php_phongo_serverapi_t* php_serverapi_fetch_object(zend_object* obj)
-{
- return (php_phongo_serverapi_t*) ((char*) obj - XtOffsetOf(php_phongo_serverapi_t, std));
-}
-static inline php_phongo_session_t* php_session_fetch_object(zend_object* obj)
-{
- return (php_phongo_session_t*) ((char*) obj - XtOffsetOf(php_phongo_session_t, std));
-}
-static inline php_phongo_writeconcern_t* php_writeconcern_fetch_object(zend_object* obj)
-{
- return (php_phongo_writeconcern_t*) ((char*) obj - XtOffsetOf(php_phongo_writeconcern_t, std));
-}
-static inline php_phongo_writeconcernerror_t* php_writeconcernerror_fetch_object(zend_object* obj)
-{
- return (php_phongo_writeconcernerror_t*) ((char*) obj - XtOffsetOf(php_phongo_writeconcernerror_t, std));
-}
-static inline php_phongo_writeerror_t* php_writeerror_fetch_object(zend_object* obj)
-{
- return (php_phongo_writeerror_t*) ((char*) obj - XtOffsetOf(php_phongo_writeerror_t, std));
-}
-static inline php_phongo_writeresult_t* php_writeresult_fetch_object(zend_object* obj)
-{
- return (php_phongo_writeresult_t*) ((char*) obj - XtOffsetOf(php_phongo_writeresult_t, std));
-}
-static inline php_phongo_binary_t* php_binary_fetch_object(zend_object* obj)
-{
- return (php_phongo_binary_t*) ((char*) obj - XtOffsetOf(php_phongo_binary_t, std));
-}
-static inline php_phongo_dbpointer_t* php_dbpointer_fetch_object(zend_object* obj)
-{
- return (php_phongo_dbpointer_t*) ((char*) obj - XtOffsetOf(php_phongo_dbpointer_t, std));
-}
-static inline php_phongo_decimal128_t* php_decimal128_fetch_object(zend_object* obj)
-{
- return (php_phongo_decimal128_t*) ((char*) obj - XtOffsetOf(php_phongo_decimal128_t, std));
-}
-static inline php_phongo_int64_t* php_int64_fetch_object(zend_object* obj)
-{
- return (php_phongo_int64_t*) ((char*) obj - XtOffsetOf(php_phongo_int64_t, std));
-}
-static inline php_phongo_javascript_t* php_javascript_fetch_object(zend_object* obj)
-{
- return (php_phongo_javascript_t*) ((char*) obj - XtOffsetOf(php_phongo_javascript_t, std));
-}
-static inline php_phongo_maxkey_t* php_maxkey_fetch_object(zend_object* obj)
-{
- return (php_phongo_maxkey_t*) ((char*) obj - XtOffsetOf(php_phongo_maxkey_t, std));
-}
-static inline php_phongo_minkey_t* php_minkey_fetch_object(zend_object* obj)
-{
- return (php_phongo_minkey_t*) ((char*) obj - XtOffsetOf(php_phongo_minkey_t, std));
-}
-static inline php_phongo_objectid_t* php_objectid_fetch_object(zend_object* obj)
-{
- return (php_phongo_objectid_t*) ((char*) obj - XtOffsetOf(php_phongo_objectid_t, std));
-}
-static inline php_phongo_regex_t* php_regex_fetch_object(zend_object* obj)
-{
- return (php_phongo_regex_t*) ((char*) obj - XtOffsetOf(php_phongo_regex_t, std));
-}
-static inline php_phongo_symbol_t* php_symbol_fetch_object(zend_object* obj)
-{
- return (php_phongo_symbol_t*) ((char*) obj - XtOffsetOf(php_phongo_symbol_t, std));
-}
-static inline php_phongo_timestamp_t* php_timestamp_fetch_object(zend_object* obj)
-{
- return (php_phongo_timestamp_t*) ((char*) obj - XtOffsetOf(php_phongo_timestamp_t, std));
-}
-static inline php_phongo_undefined_t* php_undefined_fetch_object(zend_object* obj)
-{
- return (php_phongo_undefined_t*) ((char*) obj - XtOffsetOf(php_phongo_undefined_t, std));
-}
-static inline php_phongo_utcdatetime_t* php_utcdatetime_fetch_object(zend_object* obj)
-{
- return (php_phongo_utcdatetime_t*) ((char*) obj - XtOffsetOf(php_phongo_utcdatetime_t, std));
-}
-static inline php_phongo_commandfailedevent_t* php_commandfailedevent_fetch_object(zend_object* obj)
-{
- return (php_phongo_commandfailedevent_t*) ((char*) obj - XtOffsetOf(php_phongo_commandfailedevent_t, std));
-}
-static inline php_phongo_commandstartedevent_t* php_commandstartedevent_fetch_object(zend_object* obj)
-{
- return (php_phongo_commandstartedevent_t*) ((char*) obj - XtOffsetOf(php_phongo_commandstartedevent_t, std));
-}
-static inline php_phongo_commandsucceededevent_t* php_commandsucceededevent_fetch_object(zend_object* obj)
-{
- return (php_phongo_commandsucceededevent_t*) ((char*) obj - XtOffsetOf(php_phongo_commandsucceededevent_t, std));
-}
-
-#define Z_CLIENTENCRYPTION_OBJ_P(zv) (php_clientencryption_fetch_object(Z_OBJ_P(zv)))
-#define Z_COMMAND_OBJ_P(zv) (php_command_fetch_object(Z_OBJ_P(zv)))
-#define Z_CURSOR_OBJ_P(zv) (php_cursor_fetch_object(Z_OBJ_P(zv)))
-#define Z_CURSORID_OBJ_P(zv) (php_cursorid_fetch_object(Z_OBJ_P(zv)))
-#define Z_MANAGER_OBJ_P(zv) (php_manager_fetch_object(Z_OBJ_P(zv)))
-#define Z_QUERY_OBJ_P(zv) (php_query_fetch_object(Z_OBJ_P(zv)))
-#define Z_READCONCERN_OBJ_P(zv) (php_readconcern_fetch_object(Z_OBJ_P(zv)))
-#define Z_READPREFERENCE_OBJ_P(zv) (php_readpreference_fetch_object(Z_OBJ_P(zv)))
-#define Z_SERVER_OBJ_P(zv) (php_server_fetch_object(Z_OBJ_P(zv)))
-#define Z_SERVERAPI_OBJ_P(zv) (php_serverapi_fetch_object(Z_OBJ_P(zv)))
-#define Z_SESSION_OBJ_P(zv) (php_session_fetch_object(Z_OBJ_P(zv)))
-#define Z_BULKWRITE_OBJ_P(zv) (php_bulkwrite_fetch_object(Z_OBJ_P(zv)))
-#define Z_WRITECONCERN_OBJ_P(zv) (php_writeconcern_fetch_object(Z_OBJ_P(zv)))
-#define Z_WRITECONCERNERROR_OBJ_P(zv) (php_writeconcernerror_fetch_object(Z_OBJ_P(zv)))
-#define Z_WRITEERROR_OBJ_P(zv) (php_writeerror_fetch_object(Z_OBJ_P(zv)))
-#define Z_WRITERESULT_OBJ_P(zv) (php_writeresult_fetch_object(Z_OBJ_P(zv)))
-#define Z_BINARY_OBJ_P(zv) (php_binary_fetch_object(Z_OBJ_P(zv)))
-#define Z_DBPOINTER_OBJ_P(zv) (php_dbpointer_fetch_object(Z_OBJ_P(zv)))
-#define Z_DECIMAL128_OBJ_P(zv) (php_decimal128_fetch_object(Z_OBJ_P(zv)))
-#define Z_INT64_OBJ_P(zv) (php_int64_fetch_object(Z_OBJ_P(zv)))
-#define Z_JAVASCRIPT_OBJ_P(zv) (php_javascript_fetch_object(Z_OBJ_P(zv)))
-#define Z_MAXKEY_OBJ_P(zv) (php_maxkey_fetch_object(Z_OBJ_P(zv)))
-#define Z_MINKEY_OBJ_P(zv) (php_minkey_fetch_object(Z_OBJ_P(zv)))
-#define Z_OBJECTID_OBJ_P(zv) (php_objectid_fetch_object(Z_OBJ_P(zv)))
-#define Z_REGEX_OBJ_P(zv) (php_regex_fetch_object(Z_OBJ_P(zv)))
-#define Z_SYMBOL_OBJ_P(zv) (php_symbol_fetch_object(Z_OBJ_P(zv)))
-#define Z_TIMESTAMP_OBJ_P(zv) (php_timestamp_fetch_object(Z_OBJ_P(zv)))
-#define Z_UNDEFINED_OBJ_P(zv) (php_undefined_fetch_object(Z_OBJ_P(zv)))
-#define Z_UTCDATETIME_OBJ_P(zv) (php_utcdatetime_fetch_object(Z_OBJ_P(zv)))
-#define Z_COMMANDFAILEDEVENT_OBJ_P(zv) (php_commandfailedevent_fetch_object(Z_OBJ_P(zv)))
-#define Z_COMMANDSTARTEDEVENT_OBJ_P(zv) (php_commandstartedevent_fetch_object(Z_OBJ_P(zv)))
-#define Z_COMMANDSUCCEEDEDEVENT_OBJ_P(zv) (php_commandsucceededevent_fetch_object(Z_OBJ_P(zv)))
-
-#define Z_OBJ_CLIENTENCRYPTION(zo) (php_clientencryption_fetch_object(zo))
-#define Z_OBJ_COMMAND(zo) (php_command_fetch_object(zo))
-#define Z_OBJ_CURSOR(zo) (php_cursor_fetch_object(zo))
-#define Z_OBJ_CURSORID(zo) (php_cursorid_fetch_object(zo))
-#define Z_OBJ_MANAGER(zo) (php_manager_fetch_object(zo))
-#define Z_OBJ_QUERY(zo) (php_query_fetch_object(zo))
-#define Z_OBJ_READCONCERN(zo) (php_readconcern_fetch_object(zo))
-#define Z_OBJ_READPREFERENCE(zo) (php_readpreference_fetch_object(zo))
-#define Z_OBJ_SERVER(zo) (php_server_fetch_object(zo))
-#define Z_OBJ_SERVERAPI(zo) (php_serverapi_fetch_object(zo))
-#define Z_OBJ_SESSION(zo) (php_session_fetch_object(zo))
-#define Z_OBJ_BULKWRITE(zo) (php_bulkwrite_fetch_object(zo))
-#define Z_OBJ_WRITECONCERN(zo) (php_writeconcern_fetch_object(zo))
-#define Z_OBJ_WRITECONCERNERROR(zo) (php_writeconcernerror_fetch_object(zo))
-#define Z_OBJ_WRITEERROR(zo) (php_writeerror_fetch_object(zo))
-#define Z_OBJ_WRITERESULT(zo) (php_writeresult_fetch_object(zo))
-#define Z_OBJ_BINARY(zo) (php_binary_fetch_object(zo))
-#define Z_OBJ_DBPOINTER(zo) (php_dbpointer_fetch_object(zo))
-#define Z_OBJ_DECIMAL128(zo) (php_decimal128_fetch_object(zo))
-#define Z_OBJ_INT64(zo) (php_int64_fetch_object(zo))
-#define Z_OBJ_JAVASCRIPT(zo) (php_javascript_fetch_object(zo))
-#define Z_OBJ_MAXKEY(zo) (php_maxkey_fetch_object(zo))
-#define Z_OBJ_MINKEY(zo) (php_minkey_fetch_object(zo))
-#define Z_OBJ_OBJECTID(zo) (php_objectid_fetch_object(zo))
-#define Z_OBJ_REGEX(zo) (php_regex_fetch_object(zo))
-#define Z_OBJ_SYMBOL(zo) (php_symbol_fetch_object(zo))
-#define Z_OBJ_TIMESTAMP(zo) (php_timestamp_fetch_object(zo))
-#define Z_OBJ_UNDEFINED(zo) (php_undefined_fetch_object(zo))
-#define Z_OBJ_UTCDATETIME(zo) (php_utcdatetime_fetch_object(zo))
-#define Z_OBJ_COMMANDFAILEDEVENT(zo) (php_commandfailedevent_fetch_object(zo))
-#define Z_OBJ_COMMANDSTARTEDEVENT(zo) (php_commandstartedevent_fetch_object(zo))
-#define Z_OBJ_COMMANDSUCCEEDEDEVENT(zo) (php_commandsucceededevent_fetch_object(zo))
-
-extern zend_class_entry* php_phongo_clientencryption_ce;
-extern zend_class_entry* php_phongo_command_ce;
-extern zend_class_entry* php_phongo_cursor_ce;
-extern zend_class_entry* php_phongo_cursorid_ce;
-extern zend_class_entry* php_phongo_manager_ce;
-extern zend_class_entry* php_phongo_query_ce;
-extern zend_class_entry* php_phongo_readconcern_ce;
-extern zend_class_entry* php_phongo_readpreference_ce;
-extern zend_class_entry* php_phongo_server_ce;
-extern zend_class_entry* php_phongo_serverapi_ce;
-extern zend_class_entry* php_phongo_session_ce;
-extern zend_class_entry* php_phongo_bulkwrite_ce;
-extern zend_class_entry* php_phongo_writeconcern_ce;
-extern zend_class_entry* php_phongo_writeconcernerror_ce;
-extern zend_class_entry* php_phongo_writeerror_ce;
-extern zend_class_entry* php_phongo_writeresult_ce;
-
-extern zend_class_entry* php_phongo_cursor_interface_ce;
-
-extern zend_class_entry* php_phongo_exception_ce;
-extern zend_class_entry* php_phongo_logicexception_ce;
-extern zend_class_entry* php_phongo_runtimeexception_ce;
-extern zend_class_entry* php_phongo_serverexception_ce;
-extern zend_class_entry* php_phongo_commandexception_ce;
-extern zend_class_entry* php_phongo_unexpectedvalueexception_ce;
-extern zend_class_entry* php_phongo_invalidargumentexception_ce;
-extern zend_class_entry* php_phongo_connectionexception_ce;
-extern zend_class_entry* php_phongo_authenticationexception_ce;
-extern zend_class_entry* php_phongo_sslconnectionexception_ce;
-extern zend_class_entry* php_phongo_encryptionexception_ce;
-extern zend_class_entry* php_phongo_executiontimeoutexception_ce;
-extern zend_class_entry* php_phongo_connectiontimeoutexception_ce;
-extern zend_class_entry* php_phongo_writeexception_ce;
-extern zend_class_entry* php_phongo_bulkwriteexception_ce;
-
-extern zend_class_entry* php_phongo_type_ce;
-extern zend_class_entry* php_phongo_persistable_ce;
-extern zend_class_entry* php_phongo_unserializable_ce;
-extern zend_class_entry* php_phongo_serializable_ce;
-extern zend_class_entry* php_phongo_binary_ce;
-extern zend_class_entry* php_phongo_dbpointer_ce;
-extern zend_class_entry* php_phongo_decimal128_ce;
-extern zend_class_entry* php_phongo_int64_ce;
-extern zend_class_entry* php_phongo_javascript_ce;
-extern zend_class_entry* php_phongo_maxkey_ce;
-extern zend_class_entry* php_phongo_minkey_ce;
-extern zend_class_entry* php_phongo_objectid_ce;
-extern zend_class_entry* php_phongo_regex_ce;
-extern zend_class_entry* php_phongo_symbol_ce;
-extern zend_class_entry* php_phongo_timestamp_ce;
-extern zend_class_entry* php_phongo_undefined_ce;
-extern zend_class_entry* php_phongo_utcdatetime_ce;
-
-extern zend_class_entry* php_phongo_binary_interface_ce;
-extern zend_class_entry* php_phongo_decimal128_interface_ce;
-extern zend_class_entry* php_phongo_javascript_interface_ce;
-extern zend_class_entry* php_phongo_maxkey_interface_ce;
-extern zend_class_entry* php_phongo_minkey_interface_ce;
-extern zend_class_entry* php_phongo_objectid_interface_ce;
-extern zend_class_entry* php_phongo_regex_interface_ce;
-extern zend_class_entry* php_phongo_timestamp_interface_ce;
-extern zend_class_entry* php_phongo_utcdatetime_interface_ce;
-
-extern zend_class_entry* php_phongo_commandfailedevent_ce;
-extern zend_class_entry* php_phongo_commandstartedevent_ce;
-extern zend_class_entry* php_phongo_commandsubscriber_ce;
-extern zend_class_entry* php_phongo_commandsucceededevent_ce;
-extern zend_class_entry* php_phongo_subscriber_ce;
-
-extern void php_phongo_binary_init_ce(INIT_FUNC_ARGS);
-extern void php_phongo_dbpointer_init_ce(INIT_FUNC_ARGS);
-extern void php_phongo_decimal128_init_ce(INIT_FUNC_ARGS);
-extern void php_phongo_int64_init_ce(INIT_FUNC_ARGS);
-extern void php_phongo_javascript_init_ce(INIT_FUNC_ARGS);
-extern void php_phongo_maxkey_init_ce(INIT_FUNC_ARGS);
-extern void php_phongo_minkey_init_ce(INIT_FUNC_ARGS);
-extern void php_phongo_objectid_init_ce(INIT_FUNC_ARGS);
-extern void php_phongo_persistable_init_ce(INIT_FUNC_ARGS);
-extern void php_phongo_regex_init_ce(INIT_FUNC_ARGS);
-extern void php_phongo_serializable_init_ce(INIT_FUNC_ARGS);
-extern void php_phongo_symbol_init_ce(INIT_FUNC_ARGS);
-extern void php_phongo_timestamp_init_ce(INIT_FUNC_ARGS);
-extern void php_phongo_type_init_ce(INIT_FUNC_ARGS);
-extern void php_phongo_undefined_init_ce(INIT_FUNC_ARGS);
-extern void php_phongo_unserializable_init_ce(INIT_FUNC_ARGS);
-extern void php_phongo_utcdatetime_init_ce(INIT_FUNC_ARGS);
-
-extern void php_phongo_binary_interface_init_ce(INIT_FUNC_ARGS);
-extern void php_phongo_decimal128_interface_init_ce(INIT_FUNC_ARGS);
-extern void php_phongo_javascript_interface_init_ce(INIT_FUNC_ARGS);
-extern void php_phongo_maxkey_interface_init_ce(INIT_FUNC_ARGS);
-extern void php_phongo_minkey_interface_init_ce(INIT_FUNC_ARGS);
-extern void php_phongo_objectid_interface_init_ce(INIT_FUNC_ARGS);
-extern void php_phongo_regex_interface_init_ce(INIT_FUNC_ARGS);
-extern void php_phongo_timestamp_interface_init_ce(INIT_FUNC_ARGS);
-extern void php_phongo_utcdatetime_interface_init_ce(INIT_FUNC_ARGS);
-
-extern void php_phongo_bulkwrite_init_ce(INIT_FUNC_ARGS);
-extern void php_phongo_clientencryption_init_ce(INIT_FUNC_ARGS);
-extern void php_phongo_command_init_ce(INIT_FUNC_ARGS);
-extern void php_phongo_cursor_init_ce(INIT_FUNC_ARGS);
-extern void php_phongo_cursorid_init_ce(INIT_FUNC_ARGS);
-extern void php_phongo_manager_init_ce(INIT_FUNC_ARGS);
-extern void php_phongo_query_init_ce(INIT_FUNC_ARGS);
-extern void php_phongo_readconcern_init_ce(INIT_FUNC_ARGS);
-extern void php_phongo_readpreference_init_ce(INIT_FUNC_ARGS);
-extern void php_phongo_server_init_ce(INIT_FUNC_ARGS);
-extern void php_phongo_serverapi_init_ce(INIT_FUNC_ARGS);
-extern void php_phongo_session_init_ce(INIT_FUNC_ARGS);
-extern void php_phongo_writeconcern_init_ce(INIT_FUNC_ARGS);
-extern void php_phongo_writeconcernerror_init_ce(INIT_FUNC_ARGS);
-extern void php_phongo_writeerror_init_ce(INIT_FUNC_ARGS);
-extern void php_phongo_writeresult_init_ce(INIT_FUNC_ARGS);
-
-extern void php_phongo_cursor_interface_init_ce(INIT_FUNC_ARGS);
-
-extern void php_phongo_authenticationexception_init_ce(INIT_FUNC_ARGS);
-extern void php_phongo_bulkwriteexception_init_ce(INIT_FUNC_ARGS);
-extern void php_phongo_commandexception_init_ce(INIT_FUNC_ARGS);
-extern void php_phongo_connectionexception_init_ce(INIT_FUNC_ARGS);
-extern void php_phongo_connectiontimeoutexception_init_ce(INIT_FUNC_ARGS);
-extern void php_phongo_encryptionexception_init_ce(INIT_FUNC_ARGS);
-extern void php_phongo_exception_init_ce(INIT_FUNC_ARGS);
-extern void php_phongo_executiontimeoutexception_init_ce(INIT_FUNC_ARGS);
-extern void php_phongo_invalidargumentexception_init_ce(INIT_FUNC_ARGS);
-extern void php_phongo_logicexception_init_ce(INIT_FUNC_ARGS);
-extern void php_phongo_runtimeexception_init_ce(INIT_FUNC_ARGS);
-extern void php_phongo_serverexception_init_ce(INIT_FUNC_ARGS);
-extern void php_phongo_sslconnectionexception_init_ce(INIT_FUNC_ARGS);
-extern void php_phongo_unexpectedvalueexception_init_ce(INIT_FUNC_ARGS);
-extern void php_phongo_writeexception_init_ce(INIT_FUNC_ARGS);
-
-extern void php_phongo_commandfailedevent_init_ce(INIT_FUNC_ARGS);
-extern void php_phongo_commandstartedevent_init_ce(INIT_FUNC_ARGS);
-extern void php_phongo_commandsubscriber_init_ce(INIT_FUNC_ARGS);
-extern void php_phongo_commandsucceededevent_init_ce(INIT_FUNC_ARGS);
-extern void php_phongo_subscriber_init_ce(INIT_FUNC_ARGS);
-
-/* Shared function entries for disabling constructors and unserialize() */
-PHP_FUNCTION(MongoDB_disabled___construct);
-PHP_FUNCTION(MongoDB_disabled___wakeup);
-
-#endif /* PHONGO_CLASSES_H */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/php_phongo_structs.h b/mongodb-1.12.0/php_phongo_structs.h
deleted file mode 100644
index e7c8ec20..00000000
--- a/mongodb-1.12.0/php_phongo_structs.h
+++ /dev/null
@@ -1,290 +0,0 @@
-/*
- * Copyright 2015-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef PHONGO_STRUCTS_H
-#define PHONGO_STRUCTS_H
-
-#include <php.h>
-
-#include "php_bson.h"
-
-typedef struct {
- mongoc_bulk_operation_t* bulk;
- size_t num_ops;
- bool ordered;
- int bypass;
- char* database;
- char* collection;
- bool executed;
- zval session;
- zend_object std;
-} php_phongo_bulkwrite_t;
-
-typedef struct {
- mongoc_client_encryption_t* client_encryption;
- zval key_vault_client_manager;
- zend_object std;
-} php_phongo_clientencryption_t;
-
-typedef struct {
- bson_t* bson;
- uint32_t max_await_time_ms;
- uint32_t batch_size;
- zend_object std;
-} php_phongo_command_t;
-
-typedef struct {
- mongoc_cursor_t* cursor;
- zval manager;
- int created_by_pid;
- uint32_t server_id;
- bool advanced;
- php_phongo_bson_state visitor_data;
- long current;
- char* database;
- char* collection;
- zval query;
- zval command;
- zval read_preference;
- zval session;
- zend_object std;
-} php_phongo_cursor_t;
-
-typedef struct {
- bool initialized;
- int64_t id;
- HashTable* properties;
- zend_object std;
-} php_phongo_cursorid_t;
-
-typedef struct {
- mongoc_client_t* client;
- int created_by_pid;
- char* client_hash;
- size_t client_hash_len;
- bool use_persistent_client;
- zval key_vault_client_manager;
- HashTable* subscribers;
- zend_object std;
-} php_phongo_manager_t;
-
-typedef struct {
- bson_t* filter;
- bson_t* opts;
- mongoc_read_concern_t* read_concern;
- uint32_t max_await_time_ms;
- zend_object std;
-} php_phongo_query_t;
-
-typedef struct {
- mongoc_read_concern_t* read_concern;
- HashTable* properties;
- zend_object std;
-} php_phongo_readconcern_t;
-
-typedef struct {
- mongoc_read_prefs_t* read_preference;
- HashTable* properties;
- zend_object std;
-} php_phongo_readpreference_t;
-
-typedef struct {
- zval manager;
- int created_by_pid;
- uint32_t server_id;
- zend_object std;
-} php_phongo_server_t;
-
-typedef struct {
- mongoc_server_api_t* server_api;
- HashTable* properties;
- zend_object std;
-} php_phongo_serverapi_t;
-
-typedef struct {
- mongoc_client_session_t* client_session;
- zval manager;
- int created_by_pid;
- zend_object std;
-} php_phongo_session_t;
-
-typedef struct {
- HashTable* properties;
- mongoc_write_concern_t* write_concern;
- zend_object std;
-} php_phongo_writeconcern_t;
-
-typedef struct {
- int code;
- char* message;
- zval info;
- zend_object std;
-} php_phongo_writeconcernerror_t;
-
-typedef struct {
- int code;
- char* message;
- zval info;
- uint32_t index;
- zend_object std;
-} php_phongo_writeerror_t;
-
-typedef struct {
- mongoc_write_concern_t* write_concern;
- bson_t* reply;
- zval manager;
- uint32_t server_id;
- zend_object std;
-} php_phongo_writeresult_t;
-
-typedef struct {
- char* data;
- int data_len;
- uint8_t type;
- HashTable* properties;
- zend_object std;
-} php_phongo_binary_t;
-
-typedef struct {
- char* ref;
- size_t ref_len;
- char id[25];
- HashTable* properties;
- zend_object std;
-} php_phongo_dbpointer_t;
-
-typedef struct {
- bool initialized;
- bson_decimal128_t decimal;
- HashTable* properties;
- zend_object std;
-} php_phongo_decimal128_t;
-
-typedef struct {
- bool initialized;
- int64_t integer;
- HashTable* properties;
- zend_object std;
-} php_phongo_int64_t;
-
-typedef struct {
- char* code;
- size_t code_len;
- bson_t* scope;
- HashTable* properties;
- zend_object std;
-} php_phongo_javascript_t;
-
-typedef struct {
- zend_object std;
-} php_phongo_maxkey_t;
-
-typedef struct {
- zend_object std;
-} php_phongo_minkey_t;
-
-typedef struct {
- bool initialized;
- char oid[25];
- HashTable* properties;
- zend_object std;
-} php_phongo_objectid_t;
-
-typedef struct {
- char* pattern;
- int pattern_len;
- char* flags;
- int flags_len;
- HashTable* properties;
- zend_object std;
-} php_phongo_regex_t;
-
-typedef struct {
- char* symbol;
- size_t symbol_len;
- HashTable* properties;
- zend_object std;
-} php_phongo_symbol_t;
-
-typedef struct {
- bool initialized;
- uint32_t increment;
- uint32_t timestamp;
- HashTable* properties;
- zend_object std;
-} php_phongo_timestamp_t;
-
-typedef struct {
- zend_object std;
-} php_phongo_undefined_t;
-
-typedef struct {
- bool initialized;
- int64_t milliseconds;
- HashTable* properties;
- zend_object std;
-} php_phongo_utcdatetime_t;
-
-typedef struct {
- zval manager;
- char* command_name;
- uint32_t server_id;
- uint64_t operation_id;
- uint64_t request_id;
- uint64_t duration_micros;
- bson_t* reply;
- zval z_error;
- bool has_service_id;
- bson_oid_t service_id;
- zend_object std;
-} php_phongo_commandfailedevent_t;
-
-typedef struct {
- zval manager;
- char* command_name;
- uint32_t server_id;
- uint64_t operation_id;
- uint64_t request_id;
- bson_t* command;
- char* database_name;
- bool has_service_id;
- bson_oid_t service_id;
- zend_object std;
-} php_phongo_commandstartedevent_t;
-
-typedef struct {
- zval manager;
- char* command_name;
- uint32_t server_id;
- uint64_t operation_id;
- uint64_t request_id;
- uint64_t duration_micros;
- bson_t* reply;
- bool has_service_id;
- bson_oid_t service_id;
- zend_object std;
-} php_phongo_commandsucceededevent_t;
-
-#endif /* PHONGO_STRUCTS */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/scripts/autotools/libbson/FindDependencies.m4 b/mongodb-1.12.0/scripts/autotools/libbson/FindDependencies.m4
deleted file mode 100644
index bf93ca1c..00000000
--- a/mongodb-1.12.0/scripts/autotools/libbson/FindDependencies.m4
+++ /dev/null
@@ -1,117 +0,0 @@
-# Check for strnlen()
-dnl AC_CHECK_FUNC isn't properly respecting _XOPEN_SOURCE for strnlen for unknown reason
-AC_SUBST(BSON_HAVE_STRNLEN, 0)
-AC_CACHE_CHECK([for strnlen],
- bson_cv_have_strnlen,
- [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
-#include <string.h>
-int strnlen () { return 0; }
-]])],
- [bson_cv_have_strnlen=no],
- [bson_cv_have_strnlen=yes])])
-if test "$bson_cv_have_strnlen" = yes; then
- AC_SUBST(BSON_HAVE_STRNLEN, 1)
-fi
-
-# Check for reallocf() (BSD/Darwin)
-AC_SUBST(BSON_HAVE_REALLOCF, 0)
-AC_CACHE_CHECK([for reallocf],
- bson_cv_have_reallocf,
- [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
-#include <stdlib.h>
-int reallocf () { return 0; }
-]])],
- [bson_cv_have_reallocf=no],
- [bson_cv_have_reallocf=yes])])
-if test "$bson_cv_have_reallocf" = yes; then
- AC_SUBST(BSON_HAVE_REALLOCF, 1)
-fi
-
-# Check for syscall()
-AC_SUBST(BSON_HAVE_SYSCALL_TID, 0)
-AC_CACHE_CHECK([for syscall],
- bson_cv_have_syscall_tid,
- [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
-#include <unistd.h>
-#include <sys/syscall.h>
-int syscall () { return 0; }
-]])],
- [bson_cv_have_syscall_tid=no],
- [bson_cv_have_syscall_tid=yes])])
-if test "$bson_cv_have_syscall_tid" = yes -a "$os_darwin" != "yes"; then
- AC_CACHE_CHECK([for SYS_gettid],
- bson_cv_have_sys_gettid_tid,
- [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
-#include <unistd.h>
-#include <sys/syscall.h>
-int gettid () { return SYS_gettid; }
- ]])],
- [bson_cv_have_sys_gettid_tid=yes],
- [bson_cv_have_sys_gettid_tid=no])])
- if test "$bson_cv_have_sys_gettid_tid" = yes; then
- AC_SUBST(BSON_HAVE_SYSCALL_TID, 1)
- fi
-fi
-
-# Check for snprintf()
-AC_SUBST(BSON_HAVE_SNPRINTF, 0)
-AC_CHECK_FUNC(snprintf, [AC_SUBST(BSON_HAVE_SNPRINTF, 1)])
-
-# Check for strlcpy()
-AC_SUBST(BSON_HAVE_STRLCPY, 0)
-AC_CHECK_FUNC(strlcpy, [AC_SUBST(BSON_HAVE_STRLCPY, 1)])
-
-# Check for struct timespec
-AC_SUBST(BSON_HAVE_TIMESPEC, 0)
-AC_CHECK_TYPE([struct timespec], [AC_SUBST(BSON_HAVE_TIMESPEC, 1)], [], [#include <time.h>])
-
-# Check for clock_gettime and if it needs -lrt
-AC_SUBST(BSON_HAVE_CLOCK_GETTIME, 0)
-AC_SEARCH_LIBS([clock_gettime], [rt], [AC_SUBST(BSON_HAVE_CLOCK_GETTIME, 1)])
-# Check if math functions need -lm
-AC_SEARCH_LIBS([floor], [m])
-
-# Check for gmtime_r()
-AC_SUBST(BSON_HAVE_GMTIME_R, 0)
-AC_CHECK_FUNC(gmtime_r, [AC_SUBST(BSON_HAVE_GMTIME_R, 1)])
-
-# Check for rand_r()
-AC_SUBST(BSON_HAVE_RAND_R, 0)
-AC_CHECK_FUNC(rand_r, [AC_SUBST(BSON_HAVE_RAND_R, 1)])
-
-# Check for pthreads. We might need to make this better to handle mingw,
-# but I actually think it is okay to just check for it even though we will
-# use win32 primatives.
-AX_PTHREAD([
- PHP_MONGODB_BUNDLED_CFLAGS="$PHP_MONGODB_BUNDLED_CFLAGS $PTHREAD_CFLAGS"
- PHP_EVAL_LIBLINE([$PTHREAD_LIBS],[MONGODB_SHARED_LIBADD])
-
- # PTHREAD_CFLAGS may come back as "-pthread", which should also be used when
- # linking. We can trust PHP_EVAL_LIBLINE to ignore other values.
- PHP_EVAL_LIBLINE([$PTHREAD_CFLAGS],[MONGODB_SHARED_LIBADD])
-],[
- AC_MSG_ERROR([libbson requires pthreads on non-Windows platforms.])
-])
-
-
-# The following is borrowed from the guile configure script.
-#
-# On past versions of Solaris, believe 8 through 10 at least, you
-# had to write "pthread_once_t foo = { PTHREAD_ONCE_INIT };".
-# This is contrary to POSIX:
-# http://www.opengroup.org/onlinepubs/000095399/functions/pthread_once.html
-# Check here if this style is required.
-#
-# glibc (2.3.6 at least) works both with or without braces, so the
-# test checks whether it works without.
-#
-AC_SUBST(BSON_PTHREAD_ONCE_INIT_NEEDS_BRACES, 0)
-AC_CACHE_CHECK([whether PTHREAD_ONCE_INIT needs braces],
- bson_cv_need_braces_on_pthread_once_init,
- [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <pthread.h>
- pthread_once_t foo = PTHREAD_ONCE_INIT;]])],
- [bson_cv_need_braces_on_pthread_once_init=no],
- [bson_cv_need_braces_on_pthread_once_init=yes])])
-if test "$bson_cv_need_braces_on_pthread_once_init" = yes; then
- AC_SUBST(BSON_PTHREAD_ONCE_INIT_NEEDS_BRACES, 1)
-fi
diff --git a/mongodb-1.12.0/scripts/autotools/libmongoc/CheckCompression.m4 b/mongodb-1.12.0/scripts/autotools/libmongoc/CheckCompression.m4
deleted file mode 100644
index 395ccd66..00000000
--- a/mongodb-1.12.0/scripts/autotools/libmongoc/CheckCompression.m4
+++ /dev/null
@@ -1,93 +0,0 @@
-found_snappy="no"
-found_zlib="no"
-bundled_zlib="no"
-found_zstd="no"
-
-PKG_CHECK_MODULES([PHP_MONGODB_SNAPPY],[snappy],[
- PHP_MONGODB_BUNDLED_CFLAGS="$PHP_MONGODB_BUNDLED_CFLAGS $PHP_MONGODB_SNAPPY_CFLAGS"
- PHP_EVAL_LIBLINE([$PHP_MONGODB_SNAPPY_LIBS],[MONGODB_SHARED_LIBADD])
- found_snappy="yes"
-],[
- PHP_CHECK_LIBRARY([snappy],
- [snappy_uncompress],
- [have_snappy_lib="yes"],
- [have_snappy_lib="no"])
-
- AC_CHECK_HEADER([snappy-c.h],
- [have_snappy_headers=yes],
- [have_snappy_headers=no])
-
- if test "$have_snappy_lib" = "yes" -a "$have_snappy_headers" = "yes"; then
- PHP_ADD_LIBRARY([snappy],,[MONGODB_SHARED_LIBADD])
- found_snappy="yes"
- fi
-])
-
-PKG_CHECK_MODULES([PHP_MONGODB_ZLIB],[zlib],[
- PHP_MONGODB_BUNDLED_CFLAGS="$PHP_MONGODB_BUNDLED_CFLAGS $PHP_MONGODB_ZLIB_CFLAGS"
- PHP_EVAL_LIBLINE([$PHP_MONGODB_ZLIB_LIBS],[MONGODB_SHARED_LIBADD])
- found_zlib="yes"
-],[
- PHP_CHECK_LIBRARY([zlib],
- [compress2],
- [have_zlib_lib="yes"],
- [have_zlib_lib="no"])
-
- AC_CHECK_HEADER([zlib.h],
- [have_zlib_headers=yes],
- [have_zlib_headers=no])
-
- if test "$have_zlib_lib" = "yes" -a "$have_zlib_headers" = "yes"; then
- PHP_ADD_LIBRARY([z],,[MONGODB_SHARED_LIBADD])
- found_zlib="yes"
- fi
-])
-
-dnl If zlib was not found, use libmongoc's bundled version
-AS_IF([test "$found_zlib" != "yes"],[
- bundled_zlib="yes"
-])
-
-PKG_CHECK_MODULES([PHP_MONGODB_ZSTD],[libzstd],[
- PHP_MONGODB_BUNDLED_CFLAGS="$PHP_MONGODB_BUNDLED_CFLAGS $PHP_MONGODB_ZSTD_CFLAGS"
- PHP_EVAL_LIBLINE([$PHP_MONGODB_ZSTD_LIBS],[MONGODB_SHARED_LIBADD])
- found_zstd="yes"
-],[
- PHP_CHECK_LIBRARY([zstd],
- [ZSTD_compress],
- [have_zstd_lib="yes"],
- [have_zstd_lib="no"])
-
- AC_CHECK_HEADER([zstd.h],
- [have_zstd_headers=yes],
- [have_zstd_headers=no])
-
- if test "$have_zstd_lib" = "yes" -a "$have_zstd_headers" = "yes"; then
- PHP_ADD_LIBRARY([zstd],,[MONGODB_SHARED_LIBADD])
- found_zstd="yes"
- fi
-])
-
-if test "$found_snappy" = "yes" -o "$found_zlib" = "yes" -o "$bundled_zlib" = "yes" -o "$found_zstd" = "yes"; then
- AC_SUBST(MONGOC_ENABLE_COMPRESSION, 1)
- if test "$found_snappy" = "yes"; then
- AC_SUBST(MONGOC_ENABLE_COMPRESSION_SNAPPY, 1)
- else
- AC_SUBST(MONGOC_ENABLE_COMPRESSION_SNAPPY, 0)
- fi
- if test "$found_zlib" = "yes" -o "$bundled_zlib" = "yes"; then
- AC_SUBST(MONGOC_ENABLE_COMPRESSION_ZLIB, 1)
- else
- AC_SUBST(MONGOC_ENABLE_COMPRESSION_ZLIB, 0)
- fi
- if test "$found_zstd" = "yes"; then
- AC_SUBST(MONGOC_ENABLE_COMPRESSION_ZSTD, 1)
- else
- AC_SUBST(MONGOC_ENABLE_COMPRESSION_ZSTD, 0)
- fi
-else
- AC_SUBST(MONGOC_ENABLE_COMPRESSION, 0)
- AC_SUBST(MONGOC_ENABLE_COMPRESSION_SNAPPY, 0)
- AC_SUBST(MONGOC_ENABLE_COMPRESSION_ZLIB, 0)
- AC_SUBST(MONGOC_ENABLE_COMPRESSION_ZSTD, 0)
-fi
diff --git a/mongodb-1.12.0/scripts/autotools/libmongoc/FindDependencies.m4 b/mongodb-1.12.0/scripts/autotools/libmongoc/FindDependencies.m4
deleted file mode 100644
index 0f50fc27..00000000
--- a/mongodb-1.12.0/scripts/autotools/libmongoc/FindDependencies.m4
+++ /dev/null
@@ -1,45 +0,0 @@
-# Solaris needs to link against socket libs
-if test "$os_solaris" = "yes"; then
- PHP_MONGODB_BUNDLED_CFLAGS="$PHP_MONGODB_BUNDLED_CFLAGS -D__EXTENSIONS__"
- PHP_MONGODB_BUNDLED_CFLAGS="$PHP_MONGODB_BUNDLED_CFLAGS -D_XOPEN_SOURCE=1"
- PHP_MONGODB_BUNDLED_CFLAGS="$PHP_MONGODB_BUNDLED_CFLAGS -D_XOPEN_SOURCE_EXTENDED=1"
- PHP_ADD_LIBRARY([socket],,[MONGODB_SHARED_LIBADD])
- PHP_ADD_LIBRARY([nsl],,[MONGODB_SHARED_LIBADD])
-fi
-
-# Check for shm functions
-AC_CHECK_FUNCS([shm_open],[],[
- AC_CHECK_LIB([rt],
- [shm_open],
- [PHP_ADD_LIBRARY([rt],,[MONGODB_SHARED_LIBADD])],
- [])
-])
-
-# Check for sched_getcpu
-AC_CHECK_FUNC([sched_getcpu],
- [AC_SUBST(MONGOC_HAVE_SCHED_GETCPU, 1)],
- [AC_SUBST(MONGOC_HAVE_SCHED_GETCPU, 0)])
-
-AC_CHECK_TYPE([socklen_t],
- [AC_SUBST(MONGOC_HAVE_SOCKLEN, 1)],
- [AC_SUBST(MONGOC_HAVE_SOCKLEN, 0)],
- [#include <sys/socket.h>])
-
-AC_CHECK_MEMBER([struct sockaddr_storage.ss_family],
- [AC_SUBST(MONGOC_HAVE_SS_FAMILY, 1)],
- [AC_SUBST(MONGOC_HAVE_SS_FAMILY, 0)],
- [#include <sys/socket.h>])
-
-# Check for pthreads. libmongoc's original FindDependencies.m4 script did not
-# require pthreads, but it does appear to be necessary on non-Windows platforms
-# based on mongoc-openssl.c and mongoc-thread-private.h.
-AX_PTHREAD([
- PHP_MONGODB_BUNDLED_CFLAGS="$PHP_MONGODB_BUNDLED_CFLAGS $PTHREAD_CFLAGS"
- PHP_EVAL_LIBLINE([$PTHREAD_LIBS],[MONGODB_SHARED_LIBADD])
-
- # PTHREAD_CFLAGS may come back as "-pthread", which should also be used when
- # linking. We can trust PHP_EVAL_LIBLINE to ignore other values.
- PHP_EVAL_LIBLINE([$PTHREAD_CFLAGS],[MONGODB_SHARED_LIBADD])
-],[
- AC_MSG_ERROR([libmongoc requires pthreads on non-Windows platforms.])
-])
diff --git a/mongodb-1.12.0/scripts/autotools/libmongoc/PlatformFlags.m4 b/mongodb-1.12.0/scripts/autotools/libmongoc/PlatformFlags.m4
deleted file mode 100644
index ae3420f8..00000000
--- a/mongodb-1.12.0/scripts/autotools/libmongoc/PlatformFlags.m4
+++ /dev/null
@@ -1,15 +0,0 @@
-dnl Ignore OpenSSL deprecation warnings on OSX
-AS_IF([test "$os_darwin" = "yes"],
- [AX_CHECK_COMPILE_FLAG([-Wno-deprecated-declarations], [STD_CFLAGS="$STD_CFLAGS -Wno-deprecated-declarations"])])
-dnl We know there are some cast-align issues on OSX
-AS_IF([test "$os_darwin" = "yes"],
- [AX_CHECK_COMPILE_FLAG([-Wno-cast-align], [STD_CFLAGS="$STD_CFLAGS -Wno-cast-align"])])
-AS_IF([test "$os_darwin" = "yes"],
- [AX_CHECK_COMPILE_FLAG([-Wno-unneeded-internal-declaration], [STD_CFLAGS="$STD_CFLAGS -Wno-unneeded-internal-declaration"])])
-AS_IF([test "$os_darwin" = "yes"],
- [AX_CHECK_COMPILE_FLAG([-Wno-error=unused-command-line-argument], [STD_CFLAGS="$STD_CFLAGS -Wno-error=unused-command-line-argument"])])
-dnl We know there are some cast-align issues on Solaris
-AS_IF([test "$os_solaris" = "yes"],
- [AX_CHECK_COMPILE_FLAG([-Wno-cast-align], [STD_CFLAGS="$STD_CFLAGS -Wno-cast-align"])])
-
-
diff --git a/mongodb-1.12.0/src/BSON/Binary.c b/mongodb-1.12.0/src/BSON/Binary.c
deleted file mode 100644
index b8c875fe..00000000
--- a/mongodb-1.12.0/src/BSON/Binary.c
+++ /dev/null
@@ -1,493 +0,0 @@
-/*
- * Copyright 2014-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-#include <ext/standard/base64.h>
-#include <Zend/zend_interfaces.h>
-#include <Zend/zend_operators.h>
-#include <ext/standard/php_var.h>
-#include <zend_smart_str.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-
-#define PHONGO_BINARY_UUID_SIZE 16
-
-zend_class_entry* php_phongo_binary_ce;
-
-/* Initialize the object and return whether it was successful. An exception will
- * be thrown on error. */
-static bool php_phongo_binary_init(php_phongo_binary_t* intern, const char* data, size_t data_len, zend_long type) /* {{{ */
-{
- if (type < 0 || type > UINT8_MAX) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected type to be an unsigned 8-bit integer, %" PHONGO_LONG_FORMAT " given", type);
- return false;
- }
-
- if ((type == BSON_SUBTYPE_UUID_DEPRECATED || type == BSON_SUBTYPE_UUID) && data_len != PHONGO_BINARY_UUID_SIZE) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected UUID length to be %d bytes, %d given", PHONGO_BINARY_UUID_SIZE, data_len);
- return false;
- }
-
- intern->data = estrndup(data, data_len);
- intern->data_len = data_len;
- intern->type = (uint8_t) type;
-
- return true;
-} /* }}} */
-
-/* Initialize the object from a HashTable and return whether it was successful.
- * An exception will be thrown on error. */
-static bool php_phongo_binary_init_from_hash(php_phongo_binary_t* intern, HashTable* props) /* {{{ */
-{
- zval *data, *type;
-
- if ((data = zend_hash_str_find(props, "data", sizeof("data") - 1)) && Z_TYPE_P(data) == IS_STRING &&
- (type = zend_hash_str_find(props, "type", sizeof("type") - 1)) && Z_TYPE_P(type) == IS_LONG) {
-
- return php_phongo_binary_init(intern, Z_STRVAL_P(data), Z_STRLEN_P(data), Z_LVAL_P(type));
- }
-
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"data\" string and \"type\" integer fields", ZSTR_VAL(php_phongo_binary_ce->name));
- return false;
-} /* }}} */
-
-static HashTable* php_phongo_binary_get_properties_hash(phongo_compat_object_handler_type* object, bool is_temp) /* {{{ */
-{
- php_phongo_binary_t* intern;
- HashTable* props;
-
- intern = Z_OBJ_BINARY(PHONGO_COMPAT_GET_OBJ(object));
-
- PHONGO_GET_PROPERTY_HASH_INIT_PROPS(is_temp, intern, props, 2);
-
- if (!intern->data) {
- return props;
- }
-
- {
- zval data, type;
-
- ZVAL_STRINGL(&data, intern->data, intern->data_len);
- zend_hash_str_update(props, "data", sizeof("data") - 1, &data);
-
- ZVAL_LONG(&type, intern->type);
- zend_hash_str_update(props, "type", sizeof("type") - 1, &type);
- }
-
- return props;
-} /* }}} */
-
-/* {{{ proto void MongoDB\BSON\Binary::__construct(string $data, int $type)
- Construct a new BSON binary type */
-static PHP_METHOD(Binary, __construct)
-{
- zend_error_handling error_handling;
- php_phongo_binary_t* intern;
- char* data;
- size_t data_len;
- zend_long type;
-
- intern = Z_BINARY_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "sl", &data, &data_len, &type) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- php_phongo_binary_init(intern, data, data_len, type);
-} /* }}} */
-
-/* {{{ proto MongoDB\BSON\Binary MongoDB\BSON\Binary::__set_state(array $properties)
-*/
-static PHP_METHOD(Binary, __set_state)
-{
- zend_error_handling error_handling;
- php_phongo_binary_t* intern;
- HashTable* props;
- zval* array;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &array) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- object_init_ex(return_value, php_phongo_binary_ce);
-
- intern = Z_BINARY_OBJ_P(return_value);
- props = Z_ARRVAL_P(array);
-
- php_phongo_binary_init_from_hash(intern, props);
-} /* }}} */
-
-/* {{{ proto string MongoDB\BSON\Binary::__toString()
- Return the Binary's data string. */
-static PHP_METHOD(Binary, __toString)
-{
- zend_error_handling error_handling;
- php_phongo_binary_t* intern;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- intern = Z_BINARY_OBJ_P(getThis());
-
- RETURN_STRINGL(intern->data, intern->data_len);
-} /* }}} */
-
-/* {{{ proto string MongoDB\BSON\Binary::getData()
-*/
-static PHP_METHOD(Binary, getData)
-{
- zend_error_handling error_handling;
- php_phongo_binary_t* intern;
-
- intern = Z_BINARY_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- RETURN_STRINGL(intern->data, intern->data_len);
-} /* }}} */
-
-/* {{{ proto integer MongoDB\BSON\Binary::getType()
-*/
-static PHP_METHOD(Binary, getType)
-{
- zend_error_handling error_handling;
- php_phongo_binary_t* intern;
-
- intern = Z_BINARY_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- RETURN_LONG(intern->type);
-} /* }}} */
-
-/* {{{ proto array MongoDB\BSON\Binary::jsonSerialize()
-*/
-static PHP_METHOD(Binary, jsonSerialize)
-{
- zend_error_handling error_handling;
- php_phongo_binary_t* intern;
- char type[3];
- int type_len;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- intern = Z_BINARY_OBJ_P(getThis());
-
- array_init_size(return_value, 2);
-
- {
- zend_string* data = php_base64_encode((unsigned char*) intern->data, intern->data_len);
- ADD_ASSOC_STRINGL(return_value, "$binary", ZSTR_VAL(data), ZSTR_LEN(data));
- zend_string_free(data);
- }
-
- type_len = snprintf(type, sizeof(type), "%02x", intern->type);
- ADD_ASSOC_STRINGL(return_value, "$type", type, type_len);
-} /* }}} */
-
-/* {{{ proto string MongoDB\BSON\Binary::serialize()
-*/
-static PHP_METHOD(Binary, serialize)
-{
- zend_error_handling error_handling;
- php_phongo_binary_t* intern;
- zval retval;
- php_serialize_data_t var_hash;
- smart_str buf = { 0 };
-
- intern = Z_BINARY_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- array_init_size(&retval, 2);
- ADD_ASSOC_STRINGL(&retval, "data", intern->data, intern->data_len);
- ADD_ASSOC_LONG_EX(&retval, "type", intern->type);
-
- PHP_VAR_SERIALIZE_INIT(var_hash);
- php_var_serialize(&buf, &retval, &var_hash);
- smart_str_0(&buf);
- PHP_VAR_SERIALIZE_DESTROY(var_hash);
-
- PHONGO_RETVAL_SMART_STR(buf);
-
- smart_str_free(&buf);
- zval_ptr_dtor(&retval);
-} /* }}} */
-
-/* {{{ proto void MongoDB\BSON\Binary::unserialize(string $serialized)
-*/
-static PHP_METHOD(Binary, unserialize)
-{
- zend_error_handling error_handling;
- php_phongo_binary_t* intern;
- char* serialized;
- size_t serialized_len;
- zval props;
- php_unserialize_data_t var_hash;
-
- intern = Z_BINARY_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &serialized, &serialized_len) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- PHP_VAR_UNSERIALIZE_INIT(var_hash);
- if (!php_var_unserialize(&props, (const unsigned char**) &serialized, (unsigned char*) serialized + serialized_len, &var_hash)) {
- zval_ptr_dtor(&props);
- phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "%s unserialization failed", ZSTR_VAL(php_phongo_binary_ce->name));
-
- PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
- return;
- }
- PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
-
- php_phongo_binary_init_from_hash(intern, HASH_OF(&props));
- zval_ptr_dtor(&props);
-} /* }}} */
-
-/* {{{ proto array MongoDB\Driver\Binary::__serialize()
-*/
-static PHP_METHOD(Binary, __serialize)
-{
- PHONGO_PARSE_PARAMETERS_NONE();
-
- RETURN_ARR(php_phongo_binary_get_properties_hash(PHONGO_COMPAT_OBJ_P(getThis()), true));
-} /* }}} */
-
-/* {{{ proto void MongoDB\Driver\Binary::__unserialize(array $data)
-*/
-static PHP_METHOD(Binary, __unserialize)
-{
- zval* data;
-
- PHONGO_PARSE_PARAMETERS_START(1, 1)
- Z_PARAM_ARRAY(data)
- PHONGO_PARSE_PARAMETERS_END();
-
- php_phongo_binary_init_from_hash(Z_BINARY_OBJ_P(getThis()), Z_ARRVAL_P(data));
-} /* }}} */
-
-/* {{{ MongoDB\BSON\Binary function entries */
-/* clang-format off */
-ZEND_BEGIN_ARG_INFO_EX(ai_Binary___construct, 0, 0, 2)
- ZEND_ARG_INFO(0, data)
- ZEND_ARG_INFO(0, type)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_Binary___set_state, 0, 0, 1)
- ZEND_ARG_ARRAY_INFO(0, properties, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(ai_Binary___toString, 0, 0, IS_STRING, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_Binary___unserialize, 0, 0, 1)
- ZEND_ARG_ARRAY_INFO(0, data, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(ai_Binary_jsonSerialize, 0, 0, IS_ARRAY, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_Binary_unserialize, 0, 0, 1)
- ZEND_ARG_INFO(0, serialized)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_Binary_void, 0, 0, 0)
-ZEND_END_ARG_INFO()
-
-static zend_function_entry php_phongo_binary_me[] = {
- PHP_ME(Binary, __construct, ai_Binary___construct, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Binary, __serialize, ai_Binary_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Binary, __set_state, ai_Binary___set_state, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
- PHP_ME(Binary, __toString, ai_Binary___toString, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Binary, __unserialize, ai_Binary___unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Binary, jsonSerialize, ai_Binary_jsonSerialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Binary, serialize, ai_Binary_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Binary, unserialize, ai_Binary_unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Binary, getData, ai_Binary_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Binary, getType, ai_Binary_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_FE_END
-};
-/* clang-format on */
-/* }}} */
-
-/* {{{ MongoDB\BSON\Binary object handlers */
-static zend_object_handlers php_phongo_handler_binary;
-
-static void php_phongo_binary_free_object(zend_object* object) /* {{{ */
-{
- php_phongo_binary_t* intern = Z_OBJ_BINARY(object);
-
- zend_object_std_dtor(&intern->std);
-
- if (intern->data) {
- efree(intern->data);
- }
-
- if (intern->properties) {
- zend_hash_destroy(intern->properties);
- FREE_HASHTABLE(intern->properties);
- }
-} /* }}} */
-
-static zend_object* php_phongo_binary_create_object(zend_class_entry* class_type) /* {{{ */
-{
- php_phongo_binary_t* intern = NULL;
-
- intern = PHONGO_ALLOC_OBJECT_T(php_phongo_binary_t, class_type);
-
- zend_object_std_init(&intern->std, class_type);
- object_properties_init(&intern->std, class_type);
-
- intern->std.handlers = &php_phongo_handler_binary;
-
- return &intern->std;
-} /* }}} */
-
-static zend_object* php_phongo_binary_clone_object(phongo_compat_object_handler_type* object) /* {{{ */
-{
- php_phongo_binary_t* intern;
- php_phongo_binary_t* new_intern;
- zend_object* new_object;
-
- intern = Z_OBJ_BINARY(PHONGO_COMPAT_GET_OBJ(object));
- new_object = php_phongo_binary_create_object(PHONGO_COMPAT_GET_OBJ(object)->ce);
-
- new_intern = Z_OBJ_BINARY(new_object);
- zend_objects_clone_members(&new_intern->std, &intern->std);
-
- php_phongo_binary_init(new_intern, intern->data, intern->data_len, intern->type);
-
- return new_object;
-} /* }}} */
-
-static int php_phongo_binary_compare_objects(zval* o1, zval* o2) /* {{{ */
-{
- php_phongo_binary_t *intern1, *intern2;
-
- ZEND_COMPARE_OBJECTS_FALLBACK(o1, o2);
-
- intern1 = Z_BINARY_OBJ_P(o1);
- intern2 = Z_BINARY_OBJ_P(o2);
-
- /* MongoDB compares binary types first by the data length, then by the type
- * byte, and finally by the binary data itself. */
- if (intern1->data_len != intern2->data_len) {
- return intern1->data_len < intern2->data_len ? -1 : 1;
- }
-
- if (intern1->type != intern2->type) {
- return intern1->type < intern2->type ? -1 : 1;
- }
-
- return zend_binary_strcmp(intern1->data, intern1->data_len, intern2->data, intern2->data_len);
-} /* }}} */
-
-static HashTable* php_phongo_binary_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
-{
- *is_temp = 1;
- return php_phongo_binary_get_properties_hash(object, true);
-} /* }}} */
-
-static HashTable* php_phongo_binary_get_properties(phongo_compat_object_handler_type* object) /* {{{ */
-{
- return php_phongo_binary_get_properties_hash(object, false);
-} /* }}} */
-/* }}} */
-
-void php_phongo_binary_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\BSON", "Binary", php_phongo_binary_me);
- php_phongo_binary_ce = zend_register_internal_class(&ce);
- php_phongo_binary_ce->create_object = php_phongo_binary_create_object;
- PHONGO_CE_FINAL(php_phongo_binary_ce);
-
- zend_class_implements(php_phongo_binary_ce, 1, php_phongo_binary_interface_ce);
- zend_class_implements(php_phongo_binary_ce, 1, php_phongo_json_serializable_ce);
- zend_class_implements(php_phongo_binary_ce, 1, php_phongo_type_ce);
- zend_class_implements(php_phongo_binary_ce, 1, zend_ce_serializable);
-
-#if PHP_VERSION_ID >= 80000
- zend_class_implements(php_phongo_binary_ce, 1, zend_ce_stringable);
-#endif
-
- memcpy(&php_phongo_handler_binary, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
- PHONGO_COMPAT_SET_COMPARE_OBJECTS_HANDLER(binary);
- php_phongo_handler_binary.clone_obj = php_phongo_binary_clone_object;
- php_phongo_handler_binary.get_debug_info = php_phongo_binary_get_debug_info;
- php_phongo_handler_binary.get_properties = php_phongo_binary_get_properties;
- php_phongo_handler_binary.free_obj = php_phongo_binary_free_object;
- php_phongo_handler_binary.offset = XtOffsetOf(php_phongo_binary_t, std);
-
- zend_declare_class_constant_long(php_phongo_binary_ce, ZEND_STRL("TYPE_GENERIC"), BSON_SUBTYPE_BINARY);
- zend_declare_class_constant_long(php_phongo_binary_ce, ZEND_STRL("TYPE_FUNCTION"), BSON_SUBTYPE_FUNCTION);
- zend_declare_class_constant_long(php_phongo_binary_ce, ZEND_STRL("TYPE_OLD_BINARY"), BSON_SUBTYPE_BINARY_DEPRECATED);
- zend_declare_class_constant_long(php_phongo_binary_ce, ZEND_STRL("TYPE_OLD_UUID"), BSON_SUBTYPE_UUID_DEPRECATED);
- zend_declare_class_constant_long(php_phongo_binary_ce, ZEND_STRL("TYPE_UUID"), BSON_SUBTYPE_UUID);
- zend_declare_class_constant_long(php_phongo_binary_ce, ZEND_STRL("TYPE_MD5"), BSON_SUBTYPE_MD5);
- zend_declare_class_constant_long(php_phongo_binary_ce, ZEND_STRL("TYPE_ENCRYPTED"), BSON_SUBTYPE_ENCRYPTED);
- zend_declare_class_constant_long(php_phongo_binary_ce, ZEND_STRL("TYPE_COLUMN"), BSON_SUBTYPE_COLUMN);
- zend_declare_class_constant_long(php_phongo_binary_ce, ZEND_STRL("TYPE_USER_DEFINED"), BSON_SUBTYPE_USER);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/BSON/BinaryInterface.c b/mongodb-1.12.0/src/BSON/BinaryInterface.c
deleted file mode 100644
index eb2921d9..00000000
--- a/mongodb-1.12.0/src/BSON/BinaryInterface.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright 2017-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-
-zend_class_entry* php_phongo_binary_interface_ce;
-
-/* {{{ MongoDB\BSON\BinaryInterface function entries */
-/* clang-format off */
-ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(ai_BinaryInterface___toString, 0, 0, IS_STRING, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_BinaryInterface_void, 0, 0, 0)
-ZEND_END_ARG_INFO()
-
-static zend_function_entry php_phongo_binary_interface_me[] = {
- ZEND_ABSTRACT_ME(BinaryInterface, getData, ai_BinaryInterface_void)
- ZEND_ABSTRACT_ME(BinaryInterface, getType, ai_BinaryInterface_void)
- ZEND_ABSTRACT_ME(BinaryInterface, __toString, ai_BinaryInterface___toString)
- PHP_FE_END
-};
-/* clang-format on */
-/* }}} */
-
-void php_phongo_binary_interface_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\BSON", "BinaryInterface", php_phongo_binary_interface_me);
- php_phongo_binary_interface_ce = zend_register_internal_interface(&ce);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/BSON/DBPointer.c b/mongodb-1.12.0/src/BSON/DBPointer.c
deleted file mode 100644
index e8c6ed3f..00000000
--- a/mongodb-1.12.0/src/BSON/DBPointer.c
+++ /dev/null
@@ -1,383 +0,0 @@
-/*
- * Copyright 2014-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-#include <Zend/zend_interfaces.h>
-#include <ext/standard/php_var.h>
-#include <zend_smart_str.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-#include "php_bson.h"
-
-zend_class_entry* php_phongo_dbpointer_ce;
-
-/* Initialize the object and return whether it was successful. An exception will
- * be thrown on error. */
-static bool php_phongo_dbpointer_init(php_phongo_dbpointer_t* intern, const char* ref, size_t ref_len, const char* id, size_t id_len) /* {{{ */
-{
- if (strlen(ref) != (size_t) ref_len) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Ref cannot contain null bytes");
- return false;
- }
-
- if (!bson_oid_is_valid(id, id_len)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Error parsing ObjectId string: %s", id);
- return false;
- }
-
- intern->ref = estrndup(ref, ref_len);
- intern->ref_len = ref_len;
-
- memset(intern->id, 0, sizeof(intern->id));
- strncpy(intern->id, id, sizeof(intern->id) - 1);
-
- return true;
-} /* }}} */
-
-/* Initialize the object from a HashTable and return whether it was successful.
- * An exception will be thrown on error. */
-static bool php_phongo_dbpointer_init_from_hash(php_phongo_dbpointer_t* intern, HashTable* props) /* {{{ */
-{
- zval *ref, *id;
-
- if ((ref = zend_hash_str_find(props, "ref", sizeof("ref") - 1)) && Z_TYPE_P(ref) == IS_STRING &&
- (id = zend_hash_str_find(props, "id", sizeof("id") - 1)) && Z_TYPE_P(id) == IS_STRING) {
-
- return php_phongo_dbpointer_init(intern, Z_STRVAL_P(ref), Z_STRLEN_P(ref), Z_STRVAL_P(id), Z_STRLEN_P(id));
- }
-
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"ref\" and \"id\" string fields", ZSTR_VAL(php_phongo_dbpointer_ce->name));
- return false;
-} /* }}} */
-
-HashTable* php_phongo_dbpointer_get_properties_hash(phongo_compat_object_handler_type* object, bool is_temp) /* {{{ */
-{
- php_phongo_dbpointer_t* intern;
- HashTable* props;
-
- intern = Z_OBJ_DBPOINTER(PHONGO_COMPAT_GET_OBJ(object));
-
- PHONGO_GET_PROPERTY_HASH_INIT_PROPS(is_temp, intern, props, 2);
-
- if (!intern->ref) {
- return props;
- }
-
- {
- zval ref, id;
-
- ZVAL_STRING(&ref, intern->ref);
- ZVAL_STRING(&id, intern->id);
- zend_hash_str_update(props, "ref", sizeof("ref") - 1, &ref);
- zend_hash_str_update(props, "id", sizeof("id") - 1, &id);
- }
-
- return props;
-} /* }}} */
-
-/* {{{ proto string MongoDB\BSON\DBPointer::__toString()
- Return the DBPointer's namespace string and ObjectId. */
-static PHP_METHOD(DBPointer, __toString)
-{
- zend_error_handling error_handling;
- php_phongo_dbpointer_t* intern;
- char* retval;
- int retval_len;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- intern = Z_DBPOINTER_OBJ_P(getThis());
-
- retval_len = spprintf(&retval, 0, "[%s/%s]", intern->ref, intern->id);
- RETVAL_STRINGL(retval, retval_len);
- efree(retval);
-} /* }}} */
-
-/* {{{ proto array MongoDB\BSON\Symbol::jsonSerialize()
-*/
-static PHP_METHOD(DBPointer, jsonSerialize)
-{
- zend_error_handling error_handling;
- php_phongo_dbpointer_t* intern;
- zval zdb_pointer;
- zval zoid;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- intern = Z_DBPOINTER_OBJ_P(getThis());
-
- array_init_size(&zdb_pointer, 2);
- array_init_size(&zoid, 1);
- ADD_ASSOC_STRINGL(&zdb_pointer, "$ref", intern->ref, intern->ref_len);
- ADD_ASSOC_STRING(&zoid, "$oid", intern->id);
- ADD_ASSOC_ZVAL(&zdb_pointer, "$id", &zoid);
-
- array_init_size(return_value, 1);
- ADD_ASSOC_ZVAL(return_value, "$dbPointer", &zdb_pointer);
-} /* }}} */
-
-/* {{{ proto string MongoDB\BSON\DBPointer::serialize()
-*/
-static PHP_METHOD(DBPointer, serialize)
-{
- zend_error_handling error_handling;
- php_phongo_dbpointer_t* intern;
- zval retval;
- php_serialize_data_t var_hash;
- smart_str buf = { 0 };
-
- intern = Z_DBPOINTER_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- array_init_size(&retval, 2);
- ADD_ASSOC_STRINGL(&retval, "ref", intern->ref, intern->ref_len);
- ADD_ASSOC_STRING(&retval, "id", intern->id);
-
- PHP_VAR_SERIALIZE_INIT(var_hash);
- php_var_serialize(&buf, &retval, &var_hash);
- smart_str_0(&buf);
- PHP_VAR_SERIALIZE_DESTROY(var_hash);
-
- PHONGO_RETVAL_SMART_STR(buf);
-
- smart_str_free(&buf);
- zval_ptr_dtor(&retval);
-} /* }}} */
-
-/* {{{ proto void MongoDB\BSON\DBPointer::unserialize(string $serialized)
-*/
-static PHP_METHOD(DBPointer, unserialize)
-{
- zend_error_handling error_handling;
- php_phongo_dbpointer_t* intern;
- char* serialized;
- size_t serialized_len;
- zval props;
- php_unserialize_data_t var_hash;
-
- intern = Z_DBPOINTER_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &serialized, &serialized_len) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- PHP_VAR_UNSERIALIZE_INIT(var_hash);
- if (!php_var_unserialize(&props, (const unsigned char**) &serialized, (unsigned char*) serialized + serialized_len, &var_hash)) {
- zval_ptr_dtor(&props);
- phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "%s unserialization failed", ZSTR_VAL(php_phongo_dbpointer_ce->name));
-
- PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
- return;
- }
- PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
-
- php_phongo_dbpointer_init_from_hash(intern, HASH_OF(&props));
- zval_ptr_dtor(&props);
-} /* }}} */
-
-/* {{{ proto array MongoDB\Driver\DBPointer::__serialize()
-*/
-static PHP_METHOD(DBPointer, __serialize)
-{
- PHONGO_PARSE_PARAMETERS_NONE();
-
- RETURN_ARR(php_phongo_dbpointer_get_properties_hash(PHONGO_COMPAT_OBJ_P(getThis()), true));
-} /* }}} */
-
-/* {{{ proto void MongoDB\Driver\DBPointer::__unserialize(array $data)
-*/
-static PHP_METHOD(DBPointer, __unserialize)
-{
- zval* data;
-
- PHONGO_PARSE_PARAMETERS_START(1, 1)
- Z_PARAM_ARRAY(data)
- PHONGO_PARSE_PARAMETERS_END();
-
- php_phongo_dbpointer_init_from_hash(Z_DBPOINTER_OBJ_P(getThis()), Z_ARRVAL_P(data));
-} /* }}} */
-
-/* {{{ MongoDB\BSON\DBPointer function entries */
-/* clang-format off */
-ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(ai_DBPointer___toString, 0, 0, IS_STRING, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_DBPointer___unserialize, 0, 0, 1)
- ZEND_ARG_ARRAY_INFO(0, data, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(ai_DBPointer_jsonSerialize, 0, 0, IS_ARRAY, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_DBPointer_unserialize, 0, 0, 1)
- ZEND_ARG_INFO(0, serialized)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_DBPointer_void, 0, 0, 0)
-ZEND_END_ARG_INFO()
-
-static zend_function_entry php_phongo_dbpointer_me[] = {
- /* __set_state intentionally missing */
- PHP_ME(DBPointer, __serialize, ai_DBPointer_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(DBPointer, __toString, ai_DBPointer___toString, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(DBPointer, __unserialize, ai_DBPointer___unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(DBPointer, jsonSerialize, ai_DBPointer_jsonSerialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(DBPointer, serialize, ai_DBPointer_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(DBPointer, unserialize, ai_DBPointer_unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- ZEND_NAMED_ME(__construct, PHP_FN(MongoDB_disabled___construct), ai_DBPointer_void, ZEND_ACC_PRIVATE | ZEND_ACC_FINAL)
- PHP_FE_END
-};
-/* clang-format on */
-/* }}} */
-
-/* {{{ MongoDB\BSON\DBPointer object handlers */
-static zend_object_handlers php_phongo_handler_dbpointer;
-
-static void php_phongo_dbpointer_free_object(zend_object* object) /* {{{ */
-{
- php_phongo_dbpointer_t* intern = Z_OBJ_DBPOINTER(object);
-
- zend_object_std_dtor(&intern->std);
-
- if (intern->ref) {
- efree(intern->ref);
- }
-
- if (intern->properties) {
- zend_hash_destroy(intern->properties);
- FREE_HASHTABLE(intern->properties);
- }
-} /* }}} */
-
-zend_object* php_phongo_dbpointer_create_object(zend_class_entry* class_type) /* {{{ */
-{
- php_phongo_dbpointer_t* intern = NULL;
-
- intern = PHONGO_ALLOC_OBJECT_T(php_phongo_dbpointer_t, class_type);
- zend_object_std_init(&intern->std, class_type);
- object_properties_init(&intern->std, class_type);
-
- intern->std.handlers = &php_phongo_handler_dbpointer;
-
- return &intern->std;
-} /* }}} */
-
-static zend_object* php_phongo_dbpointer_clone_object(phongo_compat_object_handler_type* object) /* {{{ */
-{
- php_phongo_dbpointer_t* intern;
- php_phongo_dbpointer_t* new_intern;
- zend_object* new_object;
-
- intern = Z_OBJ_DBPOINTER(PHONGO_COMPAT_GET_OBJ(object));
- new_object = php_phongo_dbpointer_create_object(PHONGO_COMPAT_GET_OBJ(object)->ce);
-
- new_intern = Z_OBJ_DBPOINTER(new_object);
- zend_objects_clone_members(&new_intern->std, &intern->std);
-
- php_phongo_dbpointer_init(new_intern, intern->ref, intern->ref_len, intern->id, 24);
-
- return new_object;
-} /* }}} */
-
-static int php_phongo_dbpointer_compare_objects(zval* o1, zval* o2) /* {{{ */
-{
- php_phongo_dbpointer_t *intern1, *intern2;
- int retval;
-
- ZEND_COMPARE_OBJECTS_FALLBACK(o1, o2);
-
- intern1 = Z_DBPOINTER_OBJ_P(o1);
- intern2 = Z_DBPOINTER_OBJ_P(o2);
-
- retval = strcmp(intern1->ref, intern2->ref);
-
- if (retval != 0) {
- return retval;
- }
-
- return strcmp(intern1->id, intern2->id);
-} /* }}} */
-
-static HashTable* php_phongo_dbpointer_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
-{
- *is_temp = 1;
- return php_phongo_dbpointer_get_properties_hash(object, true);
-} /* }}} */
-
-static HashTable* php_phongo_dbpointer_get_properties(phongo_compat_object_handler_type* object) /* {{{ */
-{
- return php_phongo_dbpointer_get_properties_hash(object, false);
-} /* }}} */
-/* }}} */
-
-void php_phongo_dbpointer_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\BSON", "DBPointer", php_phongo_dbpointer_me);
- php_phongo_dbpointer_ce = zend_register_internal_class(&ce);
- php_phongo_dbpointer_ce->create_object = php_phongo_dbpointer_create_object;
- PHONGO_CE_FINAL(php_phongo_dbpointer_ce);
-
- zend_class_implements(php_phongo_dbpointer_ce, 1, php_phongo_json_serializable_ce);
- zend_class_implements(php_phongo_dbpointer_ce, 1, php_phongo_type_ce);
- zend_class_implements(php_phongo_dbpointer_ce, 1, zend_ce_serializable);
-
-#if PHP_VERSION_ID >= 80000
- zend_class_implements(php_phongo_dbpointer_ce, 1, zend_ce_stringable);
-#endif
-
- memcpy(&php_phongo_handler_dbpointer, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
- PHONGO_COMPAT_SET_COMPARE_OBJECTS_HANDLER(dbpointer);
- php_phongo_handler_dbpointer.clone_obj = php_phongo_dbpointer_clone_object;
- php_phongo_handler_dbpointer.get_debug_info = php_phongo_dbpointer_get_debug_info;
- php_phongo_handler_dbpointer.get_properties = php_phongo_dbpointer_get_properties;
- php_phongo_handler_dbpointer.free_obj = php_phongo_dbpointer_free_object;
- php_phongo_handler_dbpointer.offset = XtOffsetOf(php_phongo_dbpointer_t, std);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/BSON/Decimal128.c b/mongodb-1.12.0/src/BSON/Decimal128.c
deleted file mode 100644
index b8931f21..00000000
--- a/mongodb-1.12.0/src/BSON/Decimal128.c
+++ /dev/null
@@ -1,399 +0,0 @@
-/*
- * Copyright 2015-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-#include <Zend/zend_interfaces.h>
-#include <ext/standard/php_var.h>
-#include <zend_smart_str.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-
-zend_class_entry* php_phongo_decimal128_ce;
-
-/* Initialize the object and return whether it was successful. An exception will
- * be thrown on error. */
-static bool php_phongo_decimal128_init(php_phongo_decimal128_t* intern, const char* value) /* {{{ */
-{
- if (!bson_decimal128_from_string(value, &intern->decimal)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Error parsing Decimal128 string: %s", value);
- return false;
- }
-
- intern->initialized = true;
-
- return true;
-} /* }}} */
-
-/* Initialize the object from a HashTable and return whether it was successful.
- * An exception will be thrown on error. */
-static bool php_phongo_decimal128_init_from_hash(php_phongo_decimal128_t* intern, HashTable* props) /* {{{ */
-{
- zval* dec;
-
- if ((dec = zend_hash_str_find(props, "dec", sizeof("dec") - 1)) && Z_TYPE_P(dec) == IS_STRING) {
- return php_phongo_decimal128_init(intern, Z_STRVAL_P(dec));
- }
-
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"dec\" string field", ZSTR_VAL(php_phongo_decimal128_ce->name));
- return false;
-} /* }}} */
-
-static HashTable* php_phongo_decimal128_get_properties_hash(phongo_compat_object_handler_type* object, bool is_temp) /* {{{ */
-{
- php_phongo_decimal128_t* intern;
- HashTable* props;
- char outbuf[BSON_DECIMAL128_STRING] = "";
-
- intern = Z_OBJ_DECIMAL128(PHONGO_COMPAT_GET_OBJ(object));
-
- PHONGO_GET_PROPERTY_HASH_INIT_PROPS(is_temp, intern, props, 1);
-
- if (!intern->initialized) {
- return props;
- }
-
- bson_decimal128_to_string(&intern->decimal, outbuf);
-
- {
- zval dec;
-
- ZVAL_STRING(&dec, outbuf);
- zend_hash_str_update(props, "dec", sizeof("dec") - 1, &dec);
- }
-
- return props;
-} /* }}} */
-
-/* {{{ proto void MongoDB\BSON\Decimal128::__construct(string $value)
- Construct a new BSON Decimal128 type */
-static PHP_METHOD(Decimal128, __construct)
-{
- zend_error_handling error_handling;
- php_phongo_decimal128_t* intern;
- char* value;
- size_t value_len;
-
- intern = Z_DECIMAL128_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &value, &value_len) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- php_phongo_decimal128_init(intern, value);
-} /* }}} */
-
-/* {{{ proto MongoDB\BSON\Decimal128 MongoDB\BSON\Decimal128::__set_state(array $properties)
-*/
-static PHP_METHOD(Decimal128, __set_state)
-{
- zend_error_handling error_handling;
- php_phongo_decimal128_t* intern;
- HashTable* props;
- zval* array;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &array) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- object_init_ex(return_value, php_phongo_decimal128_ce);
-
- intern = Z_DECIMAL128_OBJ_P(return_value);
- props = Z_ARRVAL_P(array);
-
- php_phongo_decimal128_init_from_hash(intern, props);
-} /* }}} */
-
-/* {{{ proto string MongoDB\BSON\Decimal128::__toString()
-*/
-static PHP_METHOD(Decimal128, __toString)
-{
- zend_error_handling error_handling;
- php_phongo_decimal128_t* intern;
- char outbuf[BSON_DECIMAL128_STRING];
-
- intern = Z_DECIMAL128_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- bson_decimal128_to_string(&intern->decimal, outbuf);
-
- RETURN_STRING(outbuf);
-} /* }}} */
-
-/* {{{ proto array MongoDB\BSON\Decimal128::jsonSerialize()
-*/
-static PHP_METHOD(Decimal128, jsonSerialize)
-{
- zend_error_handling error_handling;
- php_phongo_decimal128_t* intern;
- char outbuf[BSON_DECIMAL128_STRING] = "";
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- intern = Z_DECIMAL128_OBJ_P(getThis());
-
- array_init_size(return_value, 1);
- bson_decimal128_to_string(&intern->decimal, outbuf);
- ADD_ASSOC_STRING(return_value, "$numberDecimal", outbuf);
-} /* }}} */
-
-/* {{{ proto string MongoDB\BSON\Decimal128::serialize()
-*/
-static PHP_METHOD(Decimal128, serialize)
-{
- zend_error_handling error_handling;
- php_phongo_decimal128_t* intern;
- zval retval;
- php_serialize_data_t var_hash;
- smart_str buf = { 0 };
- char outbuf[BSON_DECIMAL128_STRING];
-
- intern = Z_DECIMAL128_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- bson_decimal128_to_string(&intern->decimal, outbuf);
- array_init_size(&retval, 1);
- ADD_ASSOC_STRING(&retval, "dec", outbuf);
-
- PHP_VAR_SERIALIZE_INIT(var_hash);
- php_var_serialize(&buf, &retval, &var_hash);
- smart_str_0(&buf);
- PHP_VAR_SERIALIZE_DESTROY(var_hash);
-
- PHONGO_RETVAL_SMART_STR(buf);
-
- smart_str_free(&buf);
- zval_ptr_dtor(&retval);
-} /* }}} */
-
-/* {{{ proto void MongoDB\BSON\Decimal128::unserialize(string $serialized)
-*/
-static PHP_METHOD(Decimal128, unserialize)
-{
- zend_error_handling error_handling;
- php_phongo_decimal128_t* intern;
- char* serialized;
- size_t serialized_len;
- zval props;
- php_unserialize_data_t var_hash;
-
- intern = Z_DECIMAL128_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &serialized, &serialized_len) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- PHP_VAR_UNSERIALIZE_INIT(var_hash);
- if (!php_var_unserialize(&props, (const unsigned char**) &serialized, (unsigned char*) serialized + serialized_len, &var_hash)) {
- zval_ptr_dtor(&props);
- phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "%s unserialization failed", ZSTR_VAL(php_phongo_decimal128_ce->name));
-
- PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
- return;
- }
- PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
-
- php_phongo_decimal128_init_from_hash(intern, HASH_OF(&props));
- zval_ptr_dtor(&props);
-} /* }}} */
-
-/* {{{ proto array MongoDB\Driver\Decimal128::__serialize()
-*/
-static PHP_METHOD(Decimal128, __serialize)
-{
- PHONGO_PARSE_PARAMETERS_NONE();
-
- RETURN_ARR(php_phongo_decimal128_get_properties_hash(PHONGO_COMPAT_OBJ_P(getThis()), true));
-} /* }}} */
-
-/* {{{ proto void MongoDB\Driver\Decimal128::__unserialize(array $data)
-*/
-static PHP_METHOD(Decimal128, __unserialize)
-{
- zval* data;
-
- PHONGO_PARSE_PARAMETERS_START(1, 1)
- Z_PARAM_ARRAY(data)
- PHONGO_PARSE_PARAMETERS_END();
-
- php_phongo_decimal128_init_from_hash(Z_DECIMAL128_OBJ_P(getThis()), Z_ARRVAL_P(data));
-} /* }}} */
-
-/* {{{ MongoDB\BSON\Decimal128 function entries */
-/* clang-format off */
-ZEND_BEGIN_ARG_INFO_EX(ai_Decimal128___construct, 0, 0, 1)
- ZEND_ARG_INFO(0, value)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_Decimal128___set_state, 0, 0, 1)
- ZEND_ARG_ARRAY_INFO(0, properties, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(ai_Decimal128___toString, 0, 0, IS_STRING, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_Decimal128___unserialize, 0, 0, 1)
- ZEND_ARG_ARRAY_INFO(0, data, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(ai_Decimal128_jsonSerialize, 0, 0, IS_ARRAY, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_Decimal128_unserialize, 0, 0, 1)
- ZEND_ARG_INFO(0, serialized)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_Decimal128_void, 0, 0, 0)
-ZEND_END_ARG_INFO()
-
-static zend_function_entry php_phongo_decimal128_me[] = {
- PHP_ME(Decimal128, __construct, ai_Decimal128___construct, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Decimal128, __serialize, ai_Decimal128_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Decimal128, __set_state, ai_Decimal128___set_state, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
- PHP_ME(Decimal128, __toString, ai_Decimal128___toString, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Decimal128, __unserialize, ai_Decimal128___unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Decimal128, jsonSerialize, ai_Decimal128_jsonSerialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Decimal128, serialize, ai_Decimal128_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Decimal128, unserialize, ai_Decimal128_unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_FE_END
-};
-/* clang-format on */
-/* }}} */
-
-/* {{{ MongoDB\BSON\Decimal128 object handlers */
-static zend_object_handlers php_phongo_handler_decimal128;
-
-static void php_phongo_decimal128_free_object(zend_object* object) /* {{{ */
-{
- php_phongo_decimal128_t* intern = Z_OBJ_DECIMAL128(object);
-
- zend_object_std_dtor(&intern->std);
-
- if (intern->properties) {
- zend_hash_destroy(intern->properties);
- FREE_HASHTABLE(intern->properties);
- }
-} /* }}} */
-
-static zend_object* php_phongo_decimal128_create_object(zend_class_entry* class_type) /* {{{ */
-{
- php_phongo_decimal128_t* intern = NULL;
-
- intern = PHONGO_ALLOC_OBJECT_T(php_phongo_decimal128_t, class_type);
-
- zend_object_std_init(&intern->std, class_type);
- object_properties_init(&intern->std, class_type);
-
- intern->std.handlers = &php_phongo_handler_decimal128;
-
- return &intern->std;
-} /* }}} */
-
-static zend_object* php_phongo_decimal128_clone_object(phongo_compat_object_handler_type* object) /* {{{ */
-{
- php_phongo_decimal128_t* intern;
- php_phongo_decimal128_t* new_intern;
- zend_object* new_object;
-
- intern = Z_OBJ_DECIMAL128(PHONGO_COMPAT_GET_OBJ(object));
- new_object = php_phongo_decimal128_create_object(PHONGO_COMPAT_GET_OBJ(object)->ce);
-
- new_intern = Z_OBJ_DECIMAL128(new_object);
- zend_objects_clone_members(&new_intern->std, &intern->std);
-
- // Use memcpy to copy bson value to avoid converting to string and back
- memcpy(&new_intern->decimal, &intern->decimal, sizeof(bson_decimal128_t));
- new_intern->initialized = true;
-
- return new_object;
-} /* }}} */
-
-static HashTable* php_phongo_decimal128_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
-{
- *is_temp = 1;
- return php_phongo_decimal128_get_properties_hash(object, true);
-} /* }}} */
-
-static HashTable* php_phongo_decimal128_get_properties(phongo_compat_object_handler_type* object) /* {{{ */
-{
- return php_phongo_decimal128_get_properties_hash(object, false);
-} /* }}} */
-/* }}} */
-
-void php_phongo_decimal128_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\BSON", "Decimal128", php_phongo_decimal128_me);
- php_phongo_decimal128_ce = zend_register_internal_class(&ce);
- php_phongo_decimal128_ce->create_object = php_phongo_decimal128_create_object;
- PHONGO_CE_FINAL(php_phongo_decimal128_ce);
-
- zend_class_implements(php_phongo_decimal128_ce, 1, php_phongo_decimal128_interface_ce);
- zend_class_implements(php_phongo_decimal128_ce, 1, php_phongo_json_serializable_ce);
- zend_class_implements(php_phongo_decimal128_ce, 1, php_phongo_type_ce);
- zend_class_implements(php_phongo_decimal128_ce, 1, zend_ce_serializable);
-
-#if PHP_VERSION_ID >= 80000
- zend_class_implements(php_phongo_decimal128_ce, 1, zend_ce_stringable);
-#endif
-
- memcpy(&php_phongo_handler_decimal128, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
- php_phongo_handler_decimal128.clone_obj = php_phongo_decimal128_clone_object;
- php_phongo_handler_decimal128.get_debug_info = php_phongo_decimal128_get_debug_info;
- php_phongo_handler_decimal128.get_properties = php_phongo_decimal128_get_properties;
- php_phongo_handler_decimal128.free_obj = php_phongo_decimal128_free_object;
- php_phongo_handler_decimal128.offset = XtOffsetOf(php_phongo_decimal128_t, std);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/BSON/Decimal128Interface.c b/mongodb-1.12.0/src/BSON/Decimal128Interface.c
deleted file mode 100644
index ea2151b3..00000000
--- a/mongodb-1.12.0/src/BSON/Decimal128Interface.c
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright 2017-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-
-zend_class_entry* php_phongo_decimal128_interface_ce;
-
-/* {{{ MongoDB\BSON\Decimal128Interface function entries */
-/* clang-format off */
-ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(ai_Decimal128Interface___toString, 0, 0, IS_STRING, 0)
-ZEND_END_ARG_INFO()
-
-static zend_function_entry php_phongo_decimal128_interface_me[] = {
- ZEND_ABSTRACT_ME(Decimal128Interface, __toString, ai_Decimal128Interface___toString)
- PHP_FE_END
-};
-/* clang-format on */
-/* }}} */
-
-void php_phongo_decimal128_interface_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\BSON", "Decimal128Interface", php_phongo_decimal128_interface_me);
- php_phongo_decimal128_interface_ce = zend_register_internal_interface(&ce);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/BSON/Int64.c b/mongodb-1.12.0/src/BSON/Int64.c
deleted file mode 100644
index 152da47e..00000000
--- a/mongodb-1.12.0/src/BSON/Int64.c
+++ /dev/null
@@ -1,360 +0,0 @@
-/*
- * Copyright 2018-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-#include <Zend/zend_interfaces.h>
-#include <ext/standard/php_var.h>
-#include <zend_smart_str.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-#include "php_bson.h"
-
-zend_class_entry* php_phongo_int64_ce;
-
-/* Initialize the object and return whether it was successful. */
-static bool php_phongo_int64_init(php_phongo_int64_t* intern, int64_t integer) /* {{{ */
-{
- intern->integer = integer;
- intern->initialized = true;
-
- return true;
-} /* }}} */
-
-/* Initialize the object from a numeric string and return whether it was
- * successful. An exception will be thrown on error. */
-static bool php_phongo_int64_init_from_string(php_phongo_int64_t* intern, const char* s_integer, size_t s_integer_len) /* {{{ */
-{
- int64_t integer;
-
- if (!php_phongo_parse_int64(&integer, s_integer, s_integer_len)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Error parsing \"%s\" as 64-bit integer for %s initialization", s_integer, ZSTR_VAL(php_phongo_int64_ce->name));
- return false;
- }
-
- return php_phongo_int64_init(intern, integer);
-} /* }}} */
-
-/* Initialize the object from a HashTable and return whether it was successful.
- * An exception will be thrown on error. */
-static bool php_phongo_int64_init_from_hash(php_phongo_int64_t* intern, HashTable* props) /* {{{ */
-{
- zval* value;
-
- if ((value = zend_hash_str_find(props, "integer", sizeof("integer") - 1)) && Z_TYPE_P(value) == IS_STRING) {
- return php_phongo_int64_init_from_string(intern, Z_STRVAL_P(value), Z_STRLEN_P(value));
- }
-
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"integer\" string field", ZSTR_VAL(php_phongo_int64_ce->name));
- return false;
-} /* }}} */
-
-HashTable* php_phongo_int64_get_properties_hash(phongo_compat_object_handler_type* object, bool is_temp) /* {{{ */
-{
- php_phongo_int64_t* intern;
- HashTable* props;
-
- intern = Z_OBJ_INT64(PHONGO_COMPAT_GET_OBJ(object));
-
- PHONGO_GET_PROPERTY_HASH_INIT_PROPS(is_temp, intern, props, 2);
-
- if (!intern->initialized) {
- return props;
- }
-
- {
- zval value;
-
- ZVAL_INT64_STRING(&value, intern->integer);
- zend_hash_str_update(props, "integer", sizeof("integer") - 1, &value);
- }
-
- return props;
-} /* }}} */
-
-/* {{{ proto string MongoDB\BSON\Int64::__toString()
- Return the Int64's value as a string. */
-static PHP_METHOD(Int64, __toString)
-{
- zend_error_handling error_handling;
- php_phongo_int64_t* intern;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- intern = Z_INT64_OBJ_P(getThis());
-
- ZVAL_INT64_STRING(return_value, intern->integer);
-} /* }}} */
-
-/* {{{ proto array MongoDB\BSON\Int64::jsonSerialize()
-*/
-static PHP_METHOD(Int64, jsonSerialize)
-{
- zend_error_handling error_handling;
- php_phongo_int64_t* intern;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- intern = Z_INT64_OBJ_P(getThis());
-
- array_init_size(return_value, 1);
-
- ADD_ASSOC_INT64_AS_STRING(return_value, "$numberLong", intern->integer);
-} /* }}} */
-
-/* {{{ proto string MongoDB\BSON\Int64::serialize()
-*/
-static PHP_METHOD(Int64, serialize)
-{
- zend_error_handling error_handling;
- php_phongo_int64_t* intern;
- zval retval;
- php_serialize_data_t var_hash;
- smart_str buf = { 0 };
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- intern = Z_INT64_OBJ_P(getThis());
-
- array_init_size(&retval, 1);
- ADD_ASSOC_INT64_AS_STRING(&retval, "integer", intern->integer);
-
- PHP_VAR_SERIALIZE_INIT(var_hash);
- php_var_serialize(&buf, &retval, &var_hash);
- smart_str_0(&buf);
- PHP_VAR_SERIALIZE_DESTROY(var_hash);
-
- PHONGO_RETVAL_SMART_STR(buf);
-
- smart_str_free(&buf);
- zval_ptr_dtor(&retval);
-} /* }}} */
-
-/* {{{ proto void MongoDB\BSON\Int64::unserialize(string $serialized)
-*/
-static PHP_METHOD(Int64, unserialize)
-{
- zend_error_handling error_handling;
- php_phongo_int64_t* intern;
- char* serialized;
- size_t serialized_len;
- zval props;
- php_unserialize_data_t var_hash;
-
- intern = Z_INT64_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &serialized, &serialized_len) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- PHP_VAR_UNSERIALIZE_INIT(var_hash);
- if (!php_var_unserialize(&props, (const unsigned char**) &serialized, (unsigned char*) serialized + serialized_len, &var_hash)) {
- zval_ptr_dtor(&props);
- phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "%s unserialization failed", ZSTR_VAL(php_phongo_int64_ce->name));
-
- PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
- return;
- }
- PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
-
- php_phongo_int64_init_from_hash(intern, HASH_OF(&props));
- zval_ptr_dtor(&props);
-} /* }}} */
-
-/* {{{ proto array MongoDB\Driver\Int64::__serialize()
-*/
-static PHP_METHOD(Int64, __serialize)
-{
- PHONGO_PARSE_PARAMETERS_NONE();
-
- RETURN_ARR(php_phongo_int64_get_properties_hash(PHONGO_COMPAT_OBJ_P(getThis()), true));
-} /* }}} */
-
-/* {{{ proto void MongoDB\Driver\Int64::__unserialize(array $data)
-*/
-static PHP_METHOD(Int64, __unserialize)
-{
- zval* data;
-
- PHONGO_PARSE_PARAMETERS_START(1, 1)
- Z_PARAM_ARRAY(data)
- PHONGO_PARSE_PARAMETERS_END();
-
- php_phongo_int64_init_from_hash(Z_INT64_OBJ_P(getThis()), Z_ARRVAL_P(data));
-} /* }}} */
-
-/* {{{ MongoDB\BSON\Int64 function entries */
-/* clang-format off */
-ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(ai_Int64___toString, 0, 0, IS_STRING, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_Int64___unserialize, 0, 0, 1)
- ZEND_ARG_ARRAY_INFO(0, data, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(ai_Int64_jsonSerialize, 0, 0, IS_ARRAY, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_Int64_unserialize, 0, 0, 1)
- ZEND_ARG_INFO(0, serialized)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_Int64_void, 0, 0, 0)
-ZEND_END_ARG_INFO()
-
-static zend_function_entry php_phongo_int64_me[] = {
- /* __set_state intentionally missing */
- PHP_ME(Int64, __serialize, ai_Int64_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Int64, __toString, ai_Int64___toString, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Int64, __unserialize, ai_Int64___unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Int64, jsonSerialize, ai_Int64_jsonSerialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Int64, serialize, ai_Int64_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Int64, unserialize, ai_Int64_unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- ZEND_NAMED_ME(__construct, PHP_FN(MongoDB_disabled___construct), ai_Int64_void, ZEND_ACC_PRIVATE | ZEND_ACC_FINAL)
- PHP_FE_END
-};
-/* clang-format on */
-/* }}} */
-
-/* {{{ MongoDB\BSON\Int64 object handlers */
-static zend_object_handlers php_phongo_handler_int64;
-
-static void php_phongo_int64_free_object(zend_object* object) /* {{{ */
-{
- php_phongo_int64_t* intern = Z_OBJ_INT64(object);
-
- zend_object_std_dtor(&intern->std);
-
- if (intern->properties) {
- zend_hash_destroy(intern->properties);
- FREE_HASHTABLE(intern->properties);
- }
-} /* }}} */
-
-zend_object* php_phongo_int64_create_object(zend_class_entry* class_type) /* {{{ */
-{
- php_phongo_int64_t* intern = NULL;
-
- intern = PHONGO_ALLOC_OBJECT_T(php_phongo_int64_t, class_type);
- zend_object_std_init(&intern->std, class_type);
- object_properties_init(&intern->std, class_type);
-
- intern->std.handlers = &php_phongo_handler_int64;
-
- return &intern->std;
-} /* }}} */
-
-static zend_object* php_phongo_int64_clone_object(phongo_compat_object_handler_type* object) /* {{{ */
-{
- php_phongo_int64_t* intern;
- php_phongo_int64_t* new_intern;
- zend_object* new_object;
-
- intern = Z_OBJ_INT64(PHONGO_COMPAT_GET_OBJ(object));
- new_object = php_phongo_int64_create_object(PHONGO_COMPAT_GET_OBJ(object)->ce);
-
- new_intern = Z_OBJ_INT64(new_object);
- zend_objects_clone_members(&new_intern->std, &intern->std);
-
- php_phongo_int64_init(new_intern, intern->integer);
-
- return new_object;
-} /* }}} */
-
-static int php_phongo_int64_compare_objects(zval* o1, zval* o2) /* {{{ */
-{
- php_phongo_int64_t *intern1, *intern2;
-
- ZEND_COMPARE_OBJECTS_FALLBACK(o1, o2);
-
- intern1 = Z_INT64_OBJ_P(o1);
- intern2 = Z_INT64_OBJ_P(o2);
-
- if (intern1->integer != intern2->integer) {
- return intern1->integer < intern2->integer ? -1 : 1;
- }
-
- return 0;
-} /* }}} */
-
-static HashTable* php_phongo_int64_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
-{
- *is_temp = 1;
- return php_phongo_int64_get_properties_hash(object, true);
-} /* }}} */
-
-static HashTable* php_phongo_int64_get_properties(phongo_compat_object_handler_type* object) /* {{{ */
-{
- return php_phongo_int64_get_properties_hash(object, false);
-} /* }}} */
-/* }}} */
-
-void php_phongo_int64_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\BSON", "Int64", php_phongo_int64_me);
- php_phongo_int64_ce = zend_register_internal_class(&ce);
- php_phongo_int64_ce->create_object = php_phongo_int64_create_object;
- PHONGO_CE_FINAL(php_phongo_int64_ce);
-
- zend_class_implements(php_phongo_int64_ce, 1, php_phongo_json_serializable_ce);
- zend_class_implements(php_phongo_int64_ce, 1, php_phongo_type_ce);
- zend_class_implements(php_phongo_int64_ce, 1, zend_ce_serializable);
-
-#if PHP_VERSION_ID >= 80000
- zend_class_implements(php_phongo_int64_ce, 1, zend_ce_stringable);
-#endif
-
- memcpy(&php_phongo_handler_int64, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
- PHONGO_COMPAT_SET_COMPARE_OBJECTS_HANDLER(int64);
- php_phongo_handler_int64.clone_obj = php_phongo_int64_clone_object;
- php_phongo_handler_int64.get_debug_info = php_phongo_int64_get_debug_info;
- php_phongo_handler_int64.get_properties = php_phongo_int64_get_properties;
- php_phongo_handler_int64.free_obj = php_phongo_int64_free_object;
- php_phongo_handler_int64.offset = XtOffsetOf(php_phongo_int64_t, std);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/BSON/Javascript.c b/mongodb-1.12.0/src/BSON/Javascript.c
deleted file mode 100644
index a941954d..00000000
--- a/mongodb-1.12.0/src/BSON/Javascript.c
+++ /dev/null
@@ -1,532 +0,0 @@
-/*
- * Copyright 2014-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-#include <Zend/zend_interfaces.h>
-#include <ext/standard/php_var.h>
-#include <zend_smart_str.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-#include "php_bson.h"
-
-zend_class_entry* php_phongo_javascript_ce;
-
-/* Initialize the object and return whether it was successful. An exception will
- * be thrown on error. */
-static bool php_phongo_javascript_init(php_phongo_javascript_t* intern, const char* code, size_t code_len, zval* scope) /* {{{ */
-{
- if (scope && Z_TYPE_P(scope) != IS_OBJECT && Z_TYPE_P(scope) != IS_ARRAY && Z_TYPE_P(scope) != IS_NULL) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected scope to be array or object, %s given", zend_get_type_by_const(Z_TYPE_P(scope)));
- return false;
- }
-
- if (strlen(code) != (size_t) code_len) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Code cannot contain null bytes");
- return false;
- }
-
- intern->code = estrndup(code, code_len);
- intern->code_len = code_len;
-
- if (scope && (Z_TYPE_P(scope) == IS_OBJECT || Z_TYPE_P(scope) == IS_ARRAY)) {
- intern->scope = bson_new();
- php_phongo_zval_to_bson(scope, PHONGO_BSON_NONE, intern->scope, NULL);
- } else {
- intern->scope = NULL;
- }
-
- return true;
-} /* }}} */
-
-/* Initialize the object from a HashTable and return whether it was successful.
- * An exception will be thrown on error. */
-static bool php_phongo_javascript_init_from_hash(php_phongo_javascript_t* intern, HashTable* props) /* {{{ */
-{
- zval *code, *scope;
-
- if ((code = zend_hash_str_find(props, "code", sizeof("code") - 1)) && Z_TYPE_P(code) == IS_STRING) {
- scope = zend_hash_str_find(props, "scope", sizeof("scope") - 1);
-
- return php_phongo_javascript_init(intern, Z_STRVAL_P(code), Z_STRLEN_P(code), scope);
- }
-
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"code\" string field", ZSTR_VAL(php_phongo_javascript_ce->name));
- return false;
-} /* }}} */
-
-HashTable* php_phongo_javascript_get_properties_hash(phongo_compat_object_handler_type* object, bool is_temp) /* {{{ */
-{
- php_phongo_javascript_t* intern;
- HashTable* props;
-
- intern = Z_OBJ_JAVASCRIPT(PHONGO_COMPAT_GET_OBJ(object));
-
- PHONGO_GET_PROPERTY_HASH_INIT_PROPS(is_temp, intern, props, 2);
-
- if (!intern->code) {
- return props;
- }
-
- {
- zval code;
-
- ZVAL_STRING(&code, intern->code);
- zend_hash_str_update(props, "code", sizeof("code") - 1, &code);
-
- if (intern->scope) {
- php_phongo_bson_state state;
-
- PHONGO_BSON_INIT_STATE(state);
- if (!php_phongo_bson_to_zval_ex(bson_get_data(intern->scope), intern->scope->len, &state)) {
- zval_ptr_dtor(&state.zchild);
- goto failure;
- }
-
- zend_hash_str_update(props, "scope", sizeof("scope") - 1, &state.zchild);
- } else {
- zval scope;
-
- ZVAL_NULL(&scope);
- zend_hash_str_update(props, "scope", sizeof("scope") - 1, &scope);
- }
- }
-
- return props;
-
-failure:
- PHONGO_GET_PROPERTY_HASH_FREE_PROPS(is_temp, props);
- return NULL;
-} /* }}} */
-
-/* {{{ proto void MongoDB\BSON\Javascript::__construct(string $code[, array|object $scope])
- Construct a new BSON Javascript type. The scope is a document mapping
- identifiers and values, representing the scope in which the code string will
- be evaluated. Note that this type cannot be represented as Extended JSON. */
-static PHP_METHOD(Javascript, __construct)
-{
- zend_error_handling error_handling;
- php_phongo_javascript_t* intern;
- char* code;
- size_t code_len;
- zval* scope = NULL;
-
- intern = Z_JAVASCRIPT_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|A!", &code, &code_len, &scope) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- php_phongo_javascript_init(intern, code, code_len, scope);
-} /* }}} */
-
-/* {{{ proto MongoDB\BSON\Javascript MongoDB\BSON\Javascript::__set_state(array $properties)
-*/
-static PHP_METHOD(Javascript, __set_state)
-{
- zend_error_handling error_handling;
- php_phongo_javascript_t* intern;
- HashTable* props;
- zval* array;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &array) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- object_init_ex(return_value, php_phongo_javascript_ce);
-
- intern = Z_JAVASCRIPT_OBJ_P(return_value);
- props = Z_ARRVAL_P(array);
-
- php_phongo_javascript_init_from_hash(intern, props);
-} /* }}} */
-
-/* {{{ proto string MongoDB\BSON\Javascript::__toString()
- Return the Javascript's code string. */
-static PHP_METHOD(Javascript, __toString)
-{
- zend_error_handling error_handling;
- php_phongo_javascript_t* intern;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- intern = Z_JAVASCRIPT_OBJ_P(getThis());
-
- RETURN_STRINGL(intern->code, intern->code_len);
-} /* }}} */
-
-/* {{{ proto string MongoDB\BSON\Javascript::getCode()
-*/
-static PHP_METHOD(Javascript, getCode)
-{
- zend_error_handling error_handling;
- php_phongo_javascript_t* intern;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- intern = Z_JAVASCRIPT_OBJ_P(getThis());
-
- RETURN_STRINGL(intern->code, intern->code_len);
-} /* }}} */
-
-/* {{{ proto object|null MongoDB\BSON\Javascript::getScope()
-*/
-static PHP_METHOD(Javascript, getScope)
-{
- zend_error_handling error_handling;
- php_phongo_javascript_t* intern;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- intern = Z_JAVASCRIPT_OBJ_P(getThis());
-
- if (!intern->scope) {
- RETURN_NULL();
- }
-
- if (intern->scope->len) {
- php_phongo_bson_state state;
-
- PHONGO_BSON_INIT_STATE(state);
-
- if (!php_phongo_bson_to_zval_ex(bson_get_data(intern->scope), intern->scope->len, &state)) {
- zval_ptr_dtor(&state.zchild);
- return;
- }
-
- RETURN_ZVAL(&state.zchild, 0, 1);
- } else {
- RETURN_NULL();
- }
-} /* }}} */
-
-/* {{{ proto array MongoDB\BSON\Javascript::jsonSerialize()
-*/
-static PHP_METHOD(Javascript, jsonSerialize)
-{
- zend_error_handling error_handling;
- php_phongo_javascript_t* intern;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- intern = Z_JAVASCRIPT_OBJ_P(getThis());
-
- array_init_size(return_value, 2);
- ADD_ASSOC_STRINGL(return_value, "$code", intern->code, intern->code_len);
-
- if (intern->scope && intern->scope->len) {
- php_phongo_bson_state state;
-
- PHONGO_BSON_INIT_STATE(state);
- if (!php_phongo_bson_to_zval_ex(bson_get_data(intern->scope), intern->scope->len, &state)) {
- zval_ptr_dtor(&state.zchild);
- return;
- }
-
- ADD_ASSOC_ZVAL_EX(return_value, "$scope", &state.zchild);
- }
-} /* }}} */
-
-/* {{{ proto string MongoDB\BSON\Javascript::serialize()
-*/
-static PHP_METHOD(Javascript, serialize)
-{
- zend_error_handling error_handling;
- php_phongo_javascript_t* intern;
- zval retval;
- php_phongo_bson_state state;
- php_serialize_data_t var_hash;
- smart_str buf = { 0 };
-
- PHONGO_BSON_INIT_STATE(state);
-
- intern = Z_JAVASCRIPT_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- if (intern->scope && intern->scope->len) {
- if (!php_phongo_bson_to_zval_ex(bson_get_data(intern->scope), intern->scope->len, &state)) {
- zval_ptr_dtor(&state.zchild);
- return;
- }
- } else {
- ZVAL_NULL(&state.zchild);
- }
-
- array_init_size(&retval, 2);
- ADD_ASSOC_STRINGL(&retval, "code", intern->code, intern->code_len);
- ADD_ASSOC_ZVAL(&retval, "scope", &state.zchild);
-
- PHP_VAR_SERIALIZE_INIT(var_hash);
- php_var_serialize(&buf, &retval, &var_hash);
- smart_str_0(&buf);
- PHP_VAR_SERIALIZE_DESTROY(var_hash);
-
- PHONGO_RETVAL_SMART_STR(buf);
-
- smart_str_free(&buf);
- zval_ptr_dtor(&retval);
-} /* }}} */
-
-/* {{{ proto void MongoDB\BSON\Javascript::unserialize(string $serialized)
-*/
-static PHP_METHOD(Javascript, unserialize)
-{
- zend_error_handling error_handling;
- php_phongo_javascript_t* intern;
- char* serialized;
- size_t serialized_len;
- zval props;
- php_unserialize_data_t var_hash;
-
- intern = Z_JAVASCRIPT_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &serialized, &serialized_len) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- PHP_VAR_UNSERIALIZE_INIT(var_hash);
- if (!php_var_unserialize(&props, (const unsigned char**) &serialized, (unsigned char*) serialized + serialized_len, &var_hash)) {
- zval_ptr_dtor(&props);
- phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "%s unserialization failed", ZSTR_VAL(php_phongo_javascript_ce->name));
-
- PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
- return;
- }
- PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
-
- php_phongo_javascript_init_from_hash(intern, HASH_OF(&props));
- zval_ptr_dtor(&props);
-} /* }}} */
-
-/* {{{ proto array MongoDB\Driver\Javascript::__serialize()
-*/
-static PHP_METHOD(Javascript, __serialize)
-{
- PHONGO_PARSE_PARAMETERS_NONE();
-
- RETURN_ARR(php_phongo_javascript_get_properties_hash(PHONGO_COMPAT_OBJ_P(getThis()), true));
-} /* }}} */
-
-/* {{{ proto void MongoDB\Driver\Javascript::__unserialize(array $data)
-*/
-static PHP_METHOD(Javascript, __unserialize)
-{
- zval* data;
-
- PHONGO_PARSE_PARAMETERS_START(1, 1)
- Z_PARAM_ARRAY(data)
- PHONGO_PARSE_PARAMETERS_END();
-
- php_phongo_javascript_init_from_hash(Z_JAVASCRIPT_OBJ_P(getThis()), Z_ARRVAL_P(data));
-} /* }}} */
-
-/* {{{ MongoDB\BSON\Javascript function entries */
-/* clang-format off */
-ZEND_BEGIN_ARG_INFO_EX(ai_Javascript___construct, 0, 0, 1)
- ZEND_ARG_INFO(0, javascript)
- ZEND_ARG_INFO(0, scope)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_Javascript___set_state, 0, 0, 1)
- ZEND_ARG_ARRAY_INFO(0, properties, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(ai_Javascript___toString, 0, 0, IS_STRING, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_Javascript___unserialize, 0, 0, 1)
- ZEND_ARG_ARRAY_INFO(0, data, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(ai_Javascript_jsonSerialize, 0, 0, IS_ARRAY, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_Javascript_unserialize, 0, 0, 1)
- ZEND_ARG_INFO(0, serialized)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_Javascript_void, 0, 0, 0)
-ZEND_END_ARG_INFO()
-
-static zend_function_entry php_phongo_javascript_me[] = {
- PHP_ME(Javascript, __construct, ai_Javascript___construct, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Javascript, __serialize, ai_Javascript_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Javascript, __set_state, ai_Javascript___set_state, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
- PHP_ME(Javascript, __toString, ai_Javascript___toString, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Javascript, __unserialize, ai_Javascript___unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Javascript, jsonSerialize, ai_Javascript_jsonSerialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Javascript, serialize, ai_Javascript_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Javascript, unserialize, ai_Javascript_unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Javascript, getCode, ai_Javascript_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Javascript, getScope, ai_Javascript_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_FE_END
-};
-/* clang-format on */
-/* }}} */
-
-/* {{{ MongoDB\BSON\Javascript object handlers */
-static zend_object_handlers php_phongo_handler_javascript;
-
-static void php_phongo_javascript_free_object(zend_object* object) /* {{{ */
-{
- php_phongo_javascript_t* intern = Z_OBJ_JAVASCRIPT(object);
-
- zend_object_std_dtor(&intern->std);
-
- if (intern->code) {
- efree(intern->code);
- }
- if (intern->scope) {
- bson_destroy(intern->scope);
- intern->scope = NULL;
- }
-
- if (intern->properties) {
- zend_hash_destroy(intern->properties);
- FREE_HASHTABLE(intern->properties);
- }
-} /* }}} */
-
-zend_object* php_phongo_javascript_create_object(zend_class_entry* class_type) /* {{{ */
-{
- php_phongo_javascript_t* intern = NULL;
-
- intern = PHONGO_ALLOC_OBJECT_T(php_phongo_javascript_t, class_type);
- zend_object_std_init(&intern->std, class_type);
- object_properties_init(&intern->std, class_type);
-
- intern->std.handlers = &php_phongo_handler_javascript;
-
- return &intern->std;
-} /* }}} */
-
-static zend_object* php_phongo_javascript_clone_object(phongo_compat_object_handler_type* object) /* {{{ */
-{
- php_phongo_javascript_t* intern;
- php_phongo_javascript_t* new_intern;
- zend_object* new_object;
-
- intern = Z_OBJ_JAVASCRIPT(PHONGO_COMPAT_GET_OBJ(object));
- new_object = php_phongo_javascript_create_object(PHONGO_COMPAT_GET_OBJ(object)->ce);
-
- new_intern = Z_OBJ_JAVASCRIPT(new_object);
- zend_objects_clone_members(&new_intern->std, &intern->std);
-
- php_phongo_javascript_init(new_intern, intern->code, intern->code_len, NULL);
- new_intern->scope = bson_copy(intern->scope);
-
- return new_object;
-} /* }}} */
-
-static int php_phongo_javascript_compare_objects(zval* o1, zval* o2) /* {{{ */
-{
- php_phongo_javascript_t *intern1, *intern2;
-
- ZEND_COMPARE_OBJECTS_FALLBACK(o1, o2);
-
- intern1 = Z_JAVASCRIPT_OBJ_P(o1);
- intern2 = Z_JAVASCRIPT_OBJ_P(o2);
-
- /* Do not consider the scope document for comparisons */
- return strcmp(intern1->code, intern2->code);
-} /* }}} */
-
-static HashTable* php_phongo_javascript_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
-{
- *is_temp = 1;
- return php_phongo_javascript_get_properties_hash(object, true);
-} /* }}} */
-
-static HashTable* php_phongo_javascript_get_properties(phongo_compat_object_handler_type* object) /* {{{ */
-{
- return php_phongo_javascript_get_properties_hash(object, false);
-} /* }}} */
-/* }}} */
-
-void php_phongo_javascript_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\BSON", "Javascript", php_phongo_javascript_me);
- php_phongo_javascript_ce = zend_register_internal_class(&ce);
- php_phongo_javascript_ce->create_object = php_phongo_javascript_create_object;
- PHONGO_CE_FINAL(php_phongo_javascript_ce);
-
- zend_class_implements(php_phongo_javascript_ce, 1, php_phongo_javascript_interface_ce);
- zend_class_implements(php_phongo_javascript_ce, 1, php_phongo_json_serializable_ce);
- zend_class_implements(php_phongo_javascript_ce, 1, php_phongo_type_ce);
- zend_class_implements(php_phongo_javascript_ce, 1, zend_ce_serializable);
-
-#if PHP_VERSION_ID >= 80000
- zend_class_implements(php_phongo_javascript_ce, 1, zend_ce_stringable);
-#endif
-
- memcpy(&php_phongo_handler_javascript, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
- PHONGO_COMPAT_SET_COMPARE_OBJECTS_HANDLER(javascript);
- php_phongo_handler_javascript.clone_obj = php_phongo_javascript_clone_object;
- php_phongo_handler_javascript.get_debug_info = php_phongo_javascript_get_debug_info;
- php_phongo_handler_javascript.get_properties = php_phongo_javascript_get_properties;
- php_phongo_handler_javascript.free_obj = php_phongo_javascript_free_object;
- php_phongo_handler_javascript.offset = XtOffsetOf(php_phongo_javascript_t, std);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/BSON/JavascriptInterface.c b/mongodb-1.12.0/src/BSON/JavascriptInterface.c
deleted file mode 100644
index 7cb2a061..00000000
--- a/mongodb-1.12.0/src/BSON/JavascriptInterface.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright 2017-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-
-zend_class_entry* php_phongo_javascript_interface_ce;
-
-/* {{{ MongoDB\BSON\JavascriptInterface function entries */
-/* clang-format off */
-ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(ai_JavascriptInterface___toString, 0, 0, IS_STRING, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_JavascriptInterface_void, 0, 0, 0)
-ZEND_END_ARG_INFO()
-
-static zend_function_entry php_phongo_javascript_interface_me[] = {
- ZEND_ABSTRACT_ME(JavascriptInterface, getCode, ai_JavascriptInterface_void)
- ZEND_ABSTRACT_ME(JavascriptInterface, getScope, ai_JavascriptInterface_void)
- ZEND_ABSTRACT_ME(JavascriptInterface, __toString, ai_JavascriptInterface___toString)
- PHP_FE_END
-};
-/* clang-format on */
-/* }}} */
-
-void php_phongo_javascript_interface_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\BSON", "JavascriptInterface", php_phongo_javascript_interface_me);
- php_phongo_javascript_interface_ce = zend_register_internal_interface(&ce);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/BSON/MaxKey.c b/mongodb-1.12.0/src/BSON/MaxKey.c
deleted file mode 100644
index 43fa7ef3..00000000
--- a/mongodb-1.12.0/src/BSON/MaxKey.c
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * Copyright 2014-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-#include <Zend/zend_interfaces.h>
-#include <ext/standard/php_var.h>
-#include <zend_smart_str.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-
-zend_class_entry* php_phongo_maxkey_ce;
-
-/* {{{ proto MongoDB\BSON\MaxKey MongoDB\BSON\MaxKey::__set_state(array $properties)
-*/
-static PHP_METHOD(MaxKey, __set_state)
-{
- zend_error_handling error_handling;
- zval* array;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &array) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- object_init_ex(return_value, php_phongo_maxkey_ce);
-} /* }}} */
-
-/* {{{ proto array MongoDB\BSON\MaxKey::jsonSerialize()
-*/
-static PHP_METHOD(MaxKey, jsonSerialize)
-{
- zend_error_handling error_handling;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- array_init_size(return_value, 1);
- ADD_ASSOC_LONG_EX(return_value, "$maxKey", 1);
-} /* }}} */
-
-/* {{{ proto string MongoDB\BSON\MaxKey::serialize()
-*/
-static PHP_METHOD(MaxKey, serialize)
-{
- zend_error_handling error_handling;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- RETURN_STRING("");
-} /* }}} */
-
-/* {{{ proto void MongoDB\BSON\MaxKey::unserialize(string $serialized)
-*/
-static PHP_METHOD(MaxKey, unserialize)
-{
- zend_error_handling error_handling;
- char* serialized;
- size_t serialized_len;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &serialized, &serialized_len) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-} /* }}} */
-
-/* {{{ proto array MongoDB\Driver\MaxKey::__serialize()
-*/
-static PHP_METHOD(MaxKey, __serialize)
-{
- PHONGO_PARSE_PARAMETERS_NONE();
-
- array_init_size(return_value, 0);
-} /* }}} */
-
-/* {{{ proto void MongoDB\Driver\MaxKey::__unserialize(array $data)
-*/
-static PHP_METHOD(MaxKey, __unserialize)
-{
- zval* data;
-
- PHONGO_PARSE_PARAMETERS_START(1, 1)
- Z_PARAM_ARRAY(data)
- PHONGO_PARSE_PARAMETERS_END();
-} /* }}} */
-
-/* {{{ MongoDB\BSON\MaxKey function entries */
-/* clang-format off */
-ZEND_BEGIN_ARG_INFO_EX(ai_MaxKey___set_state, 0, 0, 1)
- ZEND_ARG_ARRAY_INFO(0, properties, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_MaxKey___unserialize, 0, 0, 1)
- ZEND_ARG_ARRAY_INFO(0, data, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(ai_MaxKey_jsonSerialize, 0, 0, IS_ARRAY, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_MaxKey_unserialize, 0, 0, 1)
- ZEND_ARG_INFO(0, serialized)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_MaxKey_void, 0, 0, 0)
-ZEND_END_ARG_INFO()
-
-static zend_function_entry php_phongo_maxkey_me[] = {
- PHP_ME(MaxKey, __serialize, ai_MaxKey_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(MaxKey, __set_state, ai_MaxKey___set_state, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
- PHP_ME(MaxKey, __unserialize, ai_MaxKey___unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(MaxKey, jsonSerialize, ai_MaxKey_jsonSerialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(MaxKey, serialize, ai_MaxKey_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(MaxKey, unserialize, ai_MaxKey_unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_FE_END
-};
-/* clang-format on */
-/* }}} */
-
-/* {{{ MongoDB\BSON\MaxKey object handlers */
-static zend_object_handlers php_phongo_handler_maxkey;
-
-static void php_phongo_maxkey_free_object(zend_object* object) /* {{{ */
-{
- php_phongo_maxkey_t* intern = Z_OBJ_MAXKEY(object);
-
- zend_object_std_dtor(&intern->std);
-} /* }}} */
-
-static zend_object* php_phongo_maxkey_create_object(zend_class_entry* class_type) /* {{{ */
-{
- php_phongo_maxkey_t* intern = NULL;
-
- intern = PHONGO_ALLOC_OBJECT_T(php_phongo_maxkey_t, class_type);
- zend_object_std_init(&intern->std, class_type);
- object_properties_init(&intern->std, class_type);
-
- intern->std.handlers = &php_phongo_handler_maxkey;
-
- return &intern->std;
-} /* }}} */
-/* }}} */
-
-void php_phongo_maxkey_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\BSON", "MaxKey", php_phongo_maxkey_me);
- php_phongo_maxkey_ce = zend_register_internal_class(&ce);
- php_phongo_maxkey_ce->create_object = php_phongo_maxkey_create_object;
- PHONGO_CE_FINAL(php_phongo_maxkey_ce);
-
- zend_class_implements(php_phongo_maxkey_ce, 1, php_phongo_maxkey_interface_ce);
- zend_class_implements(php_phongo_maxkey_ce, 1, php_phongo_json_serializable_ce);
- zend_class_implements(php_phongo_maxkey_ce, 1, php_phongo_type_ce);
- zend_class_implements(php_phongo_maxkey_ce, 1, zend_ce_serializable);
-
- memcpy(&php_phongo_handler_maxkey, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
- /* Re-assign default handler previously removed in php_phongo.c */
- php_phongo_handler_maxkey.clone_obj = zend_objects_clone_obj;
- php_phongo_handler_maxkey.free_obj = php_phongo_maxkey_free_object;
- php_phongo_handler_maxkey.offset = XtOffsetOf(php_phongo_maxkey_t, std);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/BSON/MaxKeyInterface.c b/mongodb-1.12.0/src/BSON/MaxKeyInterface.c
deleted file mode 100644
index 73b8b873..00000000
--- a/mongodb-1.12.0/src/BSON/MaxKeyInterface.c
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2017-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-
-zend_class_entry* php_phongo_maxkey_interface_ce;
-
-/* {{{ MongoDB\BSON\MaxKeyInterface function entries */
-static zend_function_entry php_phongo_maxkey_interface_me[] = {
- PHP_FE_END
-};
-/* }}} */
-
-void php_phongo_maxkey_interface_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\BSON", "MaxKeyInterface", php_phongo_maxkey_interface_me);
- php_phongo_maxkey_interface_ce = zend_register_internal_interface(&ce);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/BSON/MinKey.c b/mongodb-1.12.0/src/BSON/MinKey.c
deleted file mode 100644
index 260acda8..00000000
--- a/mongodb-1.12.0/src/BSON/MinKey.c
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * Copyright 2014-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-#include <Zend/zend_interfaces.h>
-#include <ext/standard/php_var.h>
-#include <zend_smart_str.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-
-zend_class_entry* php_phongo_minkey_ce;
-
-/* {{{ proto MongoDB\BSON\MinKey MongoDB\BSON\MinKey::__set_state(array $properties)
-*/
-static PHP_METHOD(MinKey, __set_state)
-{
- zend_error_handling error_handling;
- zval* array;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &array) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- object_init_ex(return_value, php_phongo_minkey_ce);
-} /* }}} */
-
-/* {{{ proto array MongoDB\BSON\MinKey::jsonSerialize()
-*/
-static PHP_METHOD(MinKey, jsonSerialize)
-{
- zend_error_handling error_handling;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- array_init_size(return_value, 1);
- ADD_ASSOC_LONG_EX(return_value, "$minKey", 1);
-} /* }}} */
-
-/* {{{ proto string MongoDB\BSON\MinKey::serialize()
-*/
-static PHP_METHOD(MinKey, serialize)
-{
- zend_error_handling error_handling;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- RETURN_STRING("");
-} /* }}} */
-
-/* {{{ proto void MongoDB\BSON\MinKey::unserialize(string $serialized)
-*/
-static PHP_METHOD(MinKey, unserialize)
-{
- zend_error_handling error_handling;
- char* serialized;
- size_t serialized_len;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &serialized, &serialized_len) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-} /* }}} */
-
-/* {{{ proto array MongoDB\Driver\MinKey::__serialize()
-*/
-static PHP_METHOD(MinKey, __serialize)
-{
- PHONGO_PARSE_PARAMETERS_NONE();
-
- array_init_size(return_value, 0);
-} /* }}} */
-
-/* {{{ proto void MongoDB\Driver\MinKey::__unserialize(array $data)
-*/
-static PHP_METHOD(MinKey, __unserialize)
-{
- zval* data;
-
- PHONGO_PARSE_PARAMETERS_START(1, 1)
- Z_PARAM_ARRAY(data)
- PHONGO_PARSE_PARAMETERS_END();
-} /* }}} */
-
-/* {{{ MongoDB\BSON\MinKey function entries */
-/* clang-format off */
-ZEND_BEGIN_ARG_INFO_EX(ai_MinKey___set_state, 0, 0, 1)
- ZEND_ARG_ARRAY_INFO(0, properties, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_MinKey___unserialize, 0, 0, 1)
- ZEND_ARG_ARRAY_INFO(0, data, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(ai_MinKey_jsonSerialize, 0, 0, IS_ARRAY, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_MinKey_unserialize, 0, 0, 1)
- ZEND_ARG_INFO(0, serialized)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_MinKey_void, 0, 0, 0)
-ZEND_END_ARG_INFO()
-
-static zend_function_entry php_phongo_minkey_me[] = {
- PHP_ME(MinKey, __serialize, ai_MinKey_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(MinKey, __set_state, ai_MinKey___set_state, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
- PHP_ME(MinKey, __unserialize, ai_MinKey___unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(MinKey, jsonSerialize, ai_MinKey_jsonSerialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(MinKey, serialize, ai_MinKey_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(MinKey, unserialize, ai_MinKey_unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_FE_END
-};
-/* clang-format on */
-/* }}} */
-
-/* {{{ MongoDB\BSON\MinKey object handlers */
-static zend_object_handlers php_phongo_handler_minkey;
-
-static void php_phongo_minkey_free_object(zend_object* object) /* {{{ */
-{
- php_phongo_minkey_t* intern = Z_OBJ_MINKEY(object);
-
- zend_object_std_dtor(&intern->std);
-} /* }}} */
-
-static zend_object* php_phongo_minkey_create_object(zend_class_entry* class_type) /* {{{ */
-{
- php_phongo_minkey_t* intern = NULL;
-
- intern = PHONGO_ALLOC_OBJECT_T(php_phongo_minkey_t, class_type);
-
- zend_object_std_init(&intern->std, class_type);
- object_properties_init(&intern->std, class_type);
-
- intern->std.handlers = &php_phongo_handler_minkey;
-
- return &intern->std;
-} /* }}} */
-/* }}} */
-
-void php_phongo_minkey_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\BSON", "MinKey", php_phongo_minkey_me);
- php_phongo_minkey_ce = zend_register_internal_class(&ce);
- php_phongo_minkey_ce->create_object = php_phongo_minkey_create_object;
- PHONGO_CE_FINAL(php_phongo_minkey_ce);
-
- zend_class_implements(php_phongo_minkey_ce, 1, php_phongo_minkey_interface_ce);
- zend_class_implements(php_phongo_minkey_ce, 1, php_phongo_json_serializable_ce);
- zend_class_implements(php_phongo_minkey_ce, 1, php_phongo_type_ce);
- zend_class_implements(php_phongo_minkey_ce, 1, zend_ce_serializable);
-
- memcpy(&php_phongo_handler_minkey, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
- /* Re-assign default handler previously removed in php_phongo.c */
- php_phongo_handler_minkey.clone_obj = zend_objects_clone_obj;
- php_phongo_handler_minkey.free_obj = php_phongo_minkey_free_object;
- php_phongo_handler_minkey.offset = XtOffsetOf(php_phongo_minkey_t, std);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/BSON/MinKeyInterface.c b/mongodb-1.12.0/src/BSON/MinKeyInterface.c
deleted file mode 100644
index f6b8df27..00000000
--- a/mongodb-1.12.0/src/BSON/MinKeyInterface.c
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2017-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-
-zend_class_entry* php_phongo_minkey_interface_ce;
-
-/* {{{ MongoDB\BSON\MinKeyInterface function entries */
-static zend_function_entry php_phongo_minkey_interface_me[] = {
- PHP_FE_END
-};
-/* }}} */
-
-void php_phongo_minkey_interface_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\BSON", "MinKeyInterface", php_phongo_minkey_interface_me);
- php_phongo_minkey_interface_ce = zend_register_internal_interface(&ce);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/BSON/ObjectId.c b/mongodb-1.12.0/src/BSON/ObjectId.c
deleted file mode 100644
index c0690be6..00000000
--- a/mongodb-1.12.0/src/BSON/ObjectId.c
+++ /dev/null
@@ -1,453 +0,0 @@
-/*
- * Copyright 2014-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-#include <Zend/zend_interfaces.h>
-#include <ext/standard/php_var.h>
-#include <zend_smart_str.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-
-#define PHONGO_OID_SIZE sizeof(((php_phongo_objectid_t*) 0)->oid)
-#define PHONGO_OID_LEN (PHONGO_OID_SIZE - 1)
-
-zend_class_entry* php_phongo_objectid_ce;
-
-/* Initialize the object with a generated value and return whether it was
- * successful. */
-static bool php_phongo_objectid_init(php_phongo_objectid_t* intern)
-{
- bson_oid_t oid;
-
- intern->initialized = true;
-
- bson_oid_init(&oid, NULL);
- bson_oid_to_string(&oid, intern->oid);
-
- return true;
-}
-
-/* Initialize the object from a hex string and return whether it was successful.
- * An exception will be thrown on error. */
-static bool php_phongo_objectid_init_from_hex_string(php_phongo_objectid_t* intern, const char* hex, size_t hex_len) /* {{{ */
-{
- if (bson_oid_is_valid(hex, hex_len)) {
- bson_oid_t oid;
-
- bson_oid_init_from_string(&oid, hex);
- bson_oid_to_string(&oid, intern->oid);
- intern->initialized = true;
-
- return true;
- }
-
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Error parsing ObjectId string: %s", hex);
-
- return false;
-} /* }}} */
-
-/* Initialize the object from a HashTable and return whether it was successful.
- * An exception will be thrown on error. */
-static bool php_phongo_objectid_init_from_hash(php_phongo_objectid_t* intern, HashTable* props) /* {{{ */
-{
- zval* z_oid;
-
- z_oid = zend_hash_str_find(props, "oid", sizeof("oid") - 1);
-
- if (z_oid && Z_TYPE_P(z_oid) == IS_STRING) {
- return php_phongo_objectid_init_from_hex_string(intern, Z_STRVAL_P(z_oid), Z_STRLEN_P(z_oid));
- }
-
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"oid\" string field", ZSTR_VAL(php_phongo_objectid_ce->name));
- return false;
-} /* }}} */
-
-static HashTable* php_phongo_objectid_get_properties_hash(phongo_compat_object_handler_type* object, bool is_temp) /* {{{ */
-{
- php_phongo_objectid_t* intern;
- HashTable* props;
-
- intern = Z_OBJ_OBJECTID(PHONGO_COMPAT_GET_OBJ(object));
-
- PHONGO_GET_PROPERTY_HASH_INIT_PROPS(is_temp, intern, props, 1);
-
- if (!intern->initialized) {
- return props;
- }
-
- {
- zval zv;
-
- ZVAL_STRING(&zv, intern->oid);
- zend_hash_str_update(props, "oid", sizeof("oid") - 1, &zv);
- }
-
- return props;
-} /* }}} */
-
-/* {{{ proto void MongoDB\BSON\ObjectId::__construct([string $id])
- Constructs a new BSON ObjectId type, optionally from a hex string. */
-static PHP_METHOD(ObjectId, __construct)
-{
- zend_error_handling error_handling;
- php_phongo_objectid_t* intern;
- char* id = NULL;
- size_t id_len;
-
- intern = Z_OBJECTID_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s!", &id, &id_len) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- if (id) {
- php_phongo_objectid_init_from_hex_string(intern, id, id_len);
- } else {
- php_phongo_objectid_init(intern);
- }
-} /* }}} */
-
-/* {{{ proto integer MongoDB\BSON\ObjectId::getTimestamp()
-*/
-static PHP_METHOD(ObjectId, getTimestamp)
-{
- zend_error_handling error_handling;
- php_phongo_objectid_t* intern;
- bson_oid_t tmp_oid;
-
- intern = Z_OBJECTID_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- bson_oid_init_from_string(&tmp_oid, intern->oid);
- RETVAL_LONG(bson_oid_get_time_t(&tmp_oid));
-} /* }}} */
-
-/* {{{ proto MongoDB\BSON\ObjectId MongoDB\BSON\ObjectId::__set_state(array $properties)
-*/
-static PHP_METHOD(ObjectId, __set_state)
-{
- zend_error_handling error_handling;
- php_phongo_objectid_t* intern;
- HashTable* props;
- zval* array;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &array) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- object_init_ex(return_value, php_phongo_objectid_ce);
-
- intern = Z_OBJECTID_OBJ_P(return_value);
- props = Z_ARRVAL_P(array);
-
- php_phongo_objectid_init_from_hash(intern, props);
-} /* }}} */
-
-/* {{{ proto string MongoDB\BSON\ObjectId::__toString()
-*/
-static PHP_METHOD(ObjectId, __toString)
-{
- zend_error_handling error_handling;
- php_phongo_objectid_t* intern;
-
- intern = Z_OBJECTID_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- RETURN_STRINGL(intern->oid, PHONGO_OID_LEN);
-} /* }}} */
-
-/* {{{ proto array MongoDB\BSON\ObjectId::jsonSerialize()
-*/
-static PHP_METHOD(ObjectId, jsonSerialize)
-{
- zend_error_handling error_handling;
- php_phongo_objectid_t* intern;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- intern = Z_OBJECTID_OBJ_P(getThis());
-
- array_init_size(return_value, 1);
- ADD_ASSOC_STRINGL(return_value, "$oid", intern->oid, PHONGO_OID_LEN);
-} /* }}} */
-
-/* {{{ proto string MongoDB\BSON\ObjectId::serialize()
-*/
-static PHP_METHOD(ObjectId, serialize)
-{
- zend_error_handling error_handling;
- php_phongo_objectid_t* intern;
- zval retval;
- php_serialize_data_t var_hash;
- smart_str buf = { 0 };
-
- intern = Z_OBJECTID_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- array_init_size(&retval, 1);
- ADD_ASSOC_STRINGL(&retval, "oid", intern->oid, PHONGO_OID_LEN);
-
- PHP_VAR_SERIALIZE_INIT(var_hash);
- php_var_serialize(&buf, &retval, &var_hash);
- smart_str_0(&buf);
- PHP_VAR_SERIALIZE_DESTROY(var_hash);
-
- PHONGO_RETVAL_SMART_STR(buf);
-
- smart_str_free(&buf);
- zval_ptr_dtor(&retval);
-} /* }}} */
-
-/* {{{ proto void MongoDB\BSON\ObjectId::unserialize(string $serialized)
-*/
-static PHP_METHOD(ObjectId, unserialize)
-{
- zend_error_handling error_handling;
- php_phongo_objectid_t* intern;
- char* serialized;
- size_t serialized_len;
- zval props;
- php_unserialize_data_t var_hash;
-
- intern = Z_OBJECTID_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &serialized, &serialized_len) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- PHP_VAR_UNSERIALIZE_INIT(var_hash);
- if (!php_var_unserialize(&props, (const unsigned char**) &serialized, (unsigned char*) serialized + serialized_len, &var_hash)) {
- zval_ptr_dtor(&props);
- phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "%s unserialization failed", ZSTR_VAL(php_phongo_objectid_ce->name));
-
- PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
- return;
- }
- PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
-
- php_phongo_objectid_init_from_hash(intern, HASH_OF(&props));
- zval_ptr_dtor(&props);
-} /* }}} */
-
-/* {{{ proto array MongoDB\Driver\ObjectId::__serialize()
-*/
-static PHP_METHOD(ObjectId, __serialize)
-{
- PHONGO_PARSE_PARAMETERS_NONE();
-
- RETURN_ARR(php_phongo_objectid_get_properties_hash(PHONGO_COMPAT_OBJ_P(getThis()), true));
-} /* }}} */
-
-/* {{{ proto void MongoDB\Driver\ObjectId::__unserialize(array $data)
-*/
-static PHP_METHOD(ObjectId, __unserialize)
-{
- zval* data;
-
- PHONGO_PARSE_PARAMETERS_START(1, 1)
- Z_PARAM_ARRAY(data)
- PHONGO_PARSE_PARAMETERS_END();
-
- php_phongo_objectid_init_from_hash(Z_OBJECTID_OBJ_P(getThis()), Z_ARRVAL_P(data));
-} /* }}} */
-
-/* {{{ MongoDB\BSON\ObjectId function entries */
-/* clang-format off */
-ZEND_BEGIN_ARG_INFO_EX(ai_ObjectId___construct, 0, 0, 0)
- ZEND_ARG_INFO(0, id)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_ObjectId___set_state, 0, 0, 1)
- ZEND_ARG_ARRAY_INFO(0, properties, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(ai_ObjectId___toString, 0, 0, IS_STRING, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_ObjectId___unserialize, 0, 0, 1)
- ZEND_ARG_ARRAY_INFO(0, data, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(ai_ObjectId_jsonSerialize, 0, 0, IS_ARRAY, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_ObjectId_unserialize, 0, 0, 1)
- ZEND_ARG_INFO(0, serialized)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_ObjectId_void, 0, 0, 0)
-ZEND_END_ARG_INFO()
-
-static zend_function_entry php_phongo_objectid_me[] = {
- PHP_ME(ObjectId, __construct, ai_ObjectId___construct, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(ObjectId, getTimestamp, ai_ObjectId_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(ObjectId, __serialize, ai_ObjectId_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(ObjectId, __set_state, ai_ObjectId___set_state, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
- PHP_ME(ObjectId, __toString, ai_ObjectId___toString, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(ObjectId, __unserialize, ai_ObjectId___unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(ObjectId, jsonSerialize, ai_ObjectId_jsonSerialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(ObjectId, serialize, ai_ObjectId_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(ObjectId, unserialize, ai_ObjectId_unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_FE_END
-};
-/* clang-format on */
-/* }}} */
-
-/* {{{ MongoDB\BSON\ObjectId object handlers */
-static zend_object_handlers php_phongo_handler_objectid;
-
-static void php_phongo_objectid_free_object(zend_object* object) /* {{{ */
-{
- php_phongo_objectid_t* intern = Z_OBJ_OBJECTID(object);
-
- zend_object_std_dtor(&intern->std);
-
- if (intern->properties) {
- zend_hash_destroy(intern->properties);
- FREE_HASHTABLE(intern->properties);
- }
-} /* }}} */
-
-static zend_object* php_phongo_objectid_create_object(zend_class_entry* class_type) /* {{{ */
-{
- php_phongo_objectid_t* intern = NULL;
-
- intern = PHONGO_ALLOC_OBJECT_T(php_phongo_objectid_t, class_type);
-
- zend_object_std_init(&intern->std, class_type);
- object_properties_init(&intern->std, class_type);
-
- intern->std.handlers = &php_phongo_handler_objectid;
-
- return &intern->std;
-} /* }}} */
-
-static zend_object* php_phongo_objectid_clone_object(phongo_compat_object_handler_type* object) /* {{{ */
-{
- php_phongo_objectid_t* intern;
- php_phongo_objectid_t* new_intern;
- zend_object* new_object;
-
- intern = Z_OBJ_OBJECTID(PHONGO_COMPAT_GET_OBJ(object));
- new_object = php_phongo_objectid_create_object(PHONGO_COMPAT_GET_OBJ(object)->ce);
-
- new_intern = Z_OBJ_OBJECTID(new_object);
- zend_objects_clone_members(&new_intern->std, &intern->std);
-
- // Use memcpy to copy bson value to avoid converting to string and back
- memcpy(&new_intern->oid, &intern->oid, PHONGO_OID_SIZE);
- new_intern->initialized = true;
-
- return new_object;
-} /* }}} */
-
-static int php_phongo_objectid_compare_objects(zval* o1, zval* o2) /* {{{ */
-{
- php_phongo_objectid_t* intern1;
- php_phongo_objectid_t* intern2;
-
- ZEND_COMPARE_OBJECTS_FALLBACK(o1, o2);
-
- intern1 = Z_OBJECTID_OBJ_P(o1);
- intern2 = Z_OBJECTID_OBJ_P(o2);
-
- return strcmp(intern1->oid, intern2->oid);
-} /* }}} */
-
-static HashTable* php_phongo_objectid_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
-{
- *is_temp = 1;
- return php_phongo_objectid_get_properties_hash(object, true);
-} /* }}} */
-
-static HashTable* php_phongo_objectid_get_properties(phongo_compat_object_handler_type* object) /* {{{ */
-{
- return php_phongo_objectid_get_properties_hash(object, false);
-} /* }}} */
-/* }}} */
-
-void php_phongo_objectid_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\BSON", "ObjectId", php_phongo_objectid_me);
- php_phongo_objectid_ce = zend_register_internal_class(&ce);
- php_phongo_objectid_ce->create_object = php_phongo_objectid_create_object;
- PHONGO_CE_FINAL(php_phongo_objectid_ce);
-
- zend_class_implements(php_phongo_objectid_ce, 1, php_phongo_objectid_interface_ce);
- zend_class_implements(php_phongo_objectid_ce, 1, php_phongo_json_serializable_ce);
- zend_class_implements(php_phongo_objectid_ce, 1, php_phongo_type_ce);
- zend_class_implements(php_phongo_objectid_ce, 1, zend_ce_serializable);
-
-#if PHP_VERSION_ID >= 80000
- zend_class_implements(php_phongo_objectid_ce, 1, zend_ce_stringable);
-#endif
-
- memcpy(&php_phongo_handler_objectid, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
- PHONGO_COMPAT_SET_COMPARE_OBJECTS_HANDLER(objectid);
- php_phongo_handler_objectid.clone_obj = php_phongo_objectid_clone_object;
- php_phongo_handler_objectid.get_debug_info = php_phongo_objectid_get_debug_info;
- php_phongo_handler_objectid.get_properties = php_phongo_objectid_get_properties;
- php_phongo_handler_objectid.free_obj = php_phongo_objectid_free_object;
- php_phongo_handler_objectid.offset = XtOffsetOf(php_phongo_objectid_t, std);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/BSON/ObjectIdInterface.c b/mongodb-1.12.0/src/BSON/ObjectIdInterface.c
deleted file mode 100644
index bdb04f14..00000000
--- a/mongodb-1.12.0/src/BSON/ObjectIdInterface.c
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2017-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-
-zend_class_entry* php_phongo_objectid_interface_ce;
-
-/* {{{ MongoDB\BSON\ObjectIdInterface function entries */
-/* clang-format off */
-ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(ai_ObjectIdInterface___toString, 0, 0, IS_STRING, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_ObjectIdInterface_void, 0, 0, 0)
-ZEND_END_ARG_INFO()
-
-static zend_function_entry php_phongo_objectid_interface_me[] = {
- ZEND_ABSTRACT_ME(ObjectIdInterface, getTimestamp, ai_ObjectIdInterface_void)
- ZEND_ABSTRACT_ME(ObjectIdInterface, __toString, ai_ObjectIdInterface___toString)
- PHP_FE_END
-};
-/* clang-format on */
-/* }}} */
-
-void php_phongo_objectid_interface_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\BSON", "ObjectIdInterface", php_phongo_objectid_interface_me);
- php_phongo_objectid_interface_ce = zend_register_internal_interface(&ce);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/BSON/Persistable.c b/mongodb-1.12.0/src/BSON/Persistable.c
deleted file mode 100644
index b3c4d784..00000000
--- a/mongodb-1.12.0/src/BSON/Persistable.c
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 2014-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-
-zend_class_entry* php_phongo_persistable_ce;
-
-/* {{{ MongoDB\BSON\Persistable function entries */
-static zend_function_entry php_phongo_persistable_me[] = {
- PHP_FE_END
-};
-/* }}} */
-
-void php_phongo_persistable_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\BSON", "Persistable", php_phongo_persistable_me);
- php_phongo_persistable_ce = zend_register_internal_interface(&ce);
- zend_class_implements(php_phongo_persistable_ce, 2, php_phongo_unserializable_ce, php_phongo_serializable_ce);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/BSON/Regex.c b/mongodb-1.12.0/src/BSON/Regex.c
deleted file mode 100644
index cfba5d35..00000000
--- a/mongodb-1.12.0/src/BSON/Regex.c
+++ /dev/null
@@ -1,494 +0,0 @@
-/*
- * Copyright 2014-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-#include <Zend/zend_interfaces.h>
-#include <ext/standard/php_var.h>
-#include <zend_smart_str.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-
-zend_class_entry* php_phongo_regex_ce;
-
-/* qsort() compare callback for alphabetizing regex flags upon initialization */
-static int php_phongo_regex_compare_flags(const void* f1, const void* f2) /* {{{ */
-{
- if (*(const char*) f1 == *(const char*) f2) {
- return 0;
- }
-
- return (*(const char*) f1 > *(const char*) f2) ? 1 : -1;
-} /* }}} */
-
-/* Initialize the object and return whether it was successful. An exception will
- * be thrown on error. */
-static bool php_phongo_regex_init(php_phongo_regex_t* intern, const char* pattern, size_t pattern_len, const char* flags, size_t flags_len) /* {{{ */
-{
- if (strlen(pattern) != (size_t) pattern_len) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Pattern cannot contain null bytes");
- return false;
- }
- intern->pattern = estrndup(pattern, pattern_len);
- intern->pattern_len = pattern_len;
-
- if (flags) {
- if (strlen(flags) != (size_t) flags_len) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Flags cannot contain null bytes");
- return false;
- }
- intern->flags = estrndup(flags, flags_len);
- intern->flags_len = flags_len;
- /* Ensure flags are alphabetized upon initialization */
- qsort((void*) intern->flags, flags_len, 1, php_phongo_regex_compare_flags);
- } else {
- intern->flags = estrdup("");
- intern->flags_len = 0;
- }
-
- return true;
-} /* }}} */
-
-/* Initialize the object from a HashTable and return whether it was successful.
- * An exception will be thrown on error. */
-static bool php_phongo_regex_init_from_hash(php_phongo_regex_t* intern, HashTable* props) /* {{{ */
-{
- zval *pattern, *flags;
-
- if ((pattern = zend_hash_str_find(props, "pattern", sizeof("pattern") - 1)) && Z_TYPE_P(pattern) == IS_STRING &&
- (flags = zend_hash_str_find(props, "flags", sizeof("flags") - 1)) && Z_TYPE_P(flags) == IS_STRING) {
-
- return php_phongo_regex_init(intern, Z_STRVAL_P(pattern), Z_STRLEN_P(pattern), Z_STRVAL_P(flags), Z_STRLEN_P(flags));
- }
-
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"pattern\" and \"flags\" string fields", ZSTR_VAL(php_phongo_regex_ce->name));
- return false;
-} /* }}} */
-
-static HashTable* php_phongo_regex_get_properties_hash(phongo_compat_object_handler_type* object, bool is_temp) /* {{{ */
-{
- php_phongo_regex_t* intern;
- HashTable* props;
-
- intern = Z_OBJ_REGEX(PHONGO_COMPAT_GET_OBJ(object));
-
- PHONGO_GET_PROPERTY_HASH_INIT_PROPS(is_temp, intern, props, 2);
-
- if (!intern->pattern) {
- return props;
- }
-
- {
- zval pattern, flags;
-
- ZVAL_STRINGL(&pattern, intern->pattern, intern->pattern_len);
- zend_hash_str_update(props, "pattern", sizeof("pattern") - 1, &pattern);
-
- ZVAL_STRINGL(&flags, intern->flags, intern->flags_len);
- zend_hash_str_update(props, "flags", sizeof("flags") - 1, &flags);
- }
-
- return props;
-} /* }}} */
-
-/* {{{ proto void MongoDB\BSON\Regex::__construct(string $pattern [, string $flags])
- Constructs a new BSON regular expression type. */
-static PHP_METHOD(Regex, __construct)
-{
- zend_error_handling error_handling;
- php_phongo_regex_t* intern;
- char* pattern;
- size_t pattern_len;
- char* flags = NULL;
- size_t flags_len = 0;
-
- intern = Z_REGEX_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|s", &pattern, &pattern_len, &flags, &flags_len) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- php_phongo_regex_init(intern, pattern, pattern_len, flags, flags_len);
-} /* }}} */
-
-/* {{{ proto string MongoDB\BSON\Regex::getPattern()
-*/
-static PHP_METHOD(Regex, getPattern)
-{
- zend_error_handling error_handling;
- php_phongo_regex_t* intern;
-
- intern = Z_REGEX_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- RETURN_STRINGL(intern->pattern, intern->pattern_len);
-} /* }}} */
-
-/* {{{ proto string MongoDB\BSON\Regex::getFlags()
-*/
-static PHP_METHOD(Regex, getFlags)
-{
- zend_error_handling error_handling;
- php_phongo_regex_t* intern;
-
- intern = Z_REGEX_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- RETURN_STRINGL(intern->flags, intern->flags_len);
-} /* }}} */
-
-/* {{{ proto MongoDB\BSON\Regex MongoDB\BSON\Regex::__set_state(array $properties)
-*/
-static PHP_METHOD(Regex, __set_state)
-{
- zend_error_handling error_handling;
- php_phongo_regex_t* intern;
- HashTable* props;
- zval* array;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &array) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- object_init_ex(return_value, php_phongo_regex_ce);
-
- intern = Z_REGEX_OBJ_P(return_value);
- props = Z_ARRVAL_P(array);
-
- php_phongo_regex_init_from_hash(intern, props);
-} /* }}} */
-
-/* {{{ proto string MongoDB\BSON\Regex::__toString()
- Returns a string in the form: /pattern/flags */
-static PHP_METHOD(Regex, __toString)
-{
- zend_error_handling error_handling;
- php_phongo_regex_t* intern;
- char* regex;
- int regex_len;
-
- intern = Z_REGEX_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- regex_len = spprintf(&regex, 0, "/%s/%s", intern->pattern, intern->flags);
- RETVAL_STRINGL(regex, regex_len);
- efree(regex);
-} /* }}} */
-
-/* {{{ proto array MongoDB\BSON\Regex::jsonSerialize()
-*/
-static PHP_METHOD(Regex, jsonSerialize)
-{
- zend_error_handling error_handling;
- php_phongo_regex_t* intern;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- intern = Z_REGEX_OBJ_P(getThis());
-
- array_init_size(return_value, 2);
- ADD_ASSOC_STRINGL(return_value, "$regex", intern->pattern, intern->pattern_len);
- ADD_ASSOC_STRINGL(return_value, "$options", intern->flags, intern->flags_len);
-} /* }}} */
-
-/* {{{ proto string MongoDB\BSON\Regex::serialize()
-*/
-static PHP_METHOD(Regex, serialize)
-{
- zend_error_handling error_handling;
- php_phongo_regex_t* intern;
- zval retval;
- php_serialize_data_t var_hash;
- smart_str buf = { 0 };
-
- intern = Z_REGEX_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- array_init_size(&retval, 2);
- ADD_ASSOC_STRINGL(&retval, "pattern", intern->pattern, intern->pattern_len);
- ADD_ASSOC_STRINGL(&retval, "flags", intern->flags, intern->flags_len);
-
- PHP_VAR_SERIALIZE_INIT(var_hash);
- php_var_serialize(&buf, &retval, &var_hash);
- smart_str_0(&buf);
- PHP_VAR_SERIALIZE_DESTROY(var_hash);
-
- PHONGO_RETVAL_SMART_STR(buf);
-
- smart_str_free(&buf);
- zval_ptr_dtor(&retval);
-} /* }}} */
-
-/* {{{ proto void MongoDB\BSON\Regex::unserialize(string $serialized)
-*/
-static PHP_METHOD(Regex, unserialize)
-{
- zend_error_handling error_handling;
- php_phongo_regex_t* intern;
- char* serialized;
- size_t serialized_len;
- zval props;
- php_unserialize_data_t var_hash;
-
- intern = Z_REGEX_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &serialized, &serialized_len) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- PHP_VAR_UNSERIALIZE_INIT(var_hash);
- if (!php_var_unserialize(&props, (const unsigned char**) &serialized, (unsigned char*) serialized + serialized_len, &var_hash)) {
- zval_ptr_dtor(&props);
- phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "%s unserialization failed", ZSTR_VAL(php_phongo_regex_ce->name));
-
- PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
- return;
- }
- PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
-
- php_phongo_regex_init_from_hash(intern, HASH_OF(&props));
- zval_ptr_dtor(&props);
-} /* }}} */
-
-/* {{{ proto array MongoDB\Driver\Regex::__serialize()
-*/
-static PHP_METHOD(Regex, __serialize)
-{
- PHONGO_PARSE_PARAMETERS_NONE();
-
- RETURN_ARR(php_phongo_regex_get_properties_hash(PHONGO_COMPAT_OBJ_P(getThis()), true));
-} /* }}} */
-
-/* {{{ proto void MongoDB\Driver\Regex::__unserialize(array $data)
-*/
-static PHP_METHOD(Regex, __unserialize)
-{
- zval* data;
-
- PHONGO_PARSE_PARAMETERS_START(1, 1)
- Z_PARAM_ARRAY(data)
- PHONGO_PARSE_PARAMETERS_END();
-
- php_phongo_regex_init_from_hash(Z_REGEX_OBJ_P(getThis()), Z_ARRVAL_P(data));
-} /* }}} */
-
-/* {{{ MongoDB\BSON\Regex function entries */
-/* clang-format off */
-ZEND_BEGIN_ARG_INFO_EX(ai_Regex___construct, 0, 0, 1)
- ZEND_ARG_INFO(0, pattern)
- ZEND_ARG_INFO(0, flags)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_Regex___set_state, 0, 0, 1)
- ZEND_ARG_ARRAY_INFO(0, properties, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(ai_Regex___toString, 0, 0, IS_STRING, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_Regex___unserialize, 0, 0, 1)
- ZEND_ARG_ARRAY_INFO(0, data, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(ai_Regex_jsonSerialize, 0, 0, IS_ARRAY, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_Regex_unserialize, 0, 0, 1)
- ZEND_ARG_INFO(0, serialized)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_Regex_void, 0, 0, 0)
-ZEND_END_ARG_INFO()
-
-static zend_function_entry php_phongo_regex_me[] = {
- PHP_ME(Regex, __construct, ai_Regex___construct, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Regex, __serialize, ai_Regex_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Regex, __set_state, ai_Regex___set_state, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
- PHP_ME(Regex, __toString, ai_Regex___toString, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Regex, __unserialize, ai_Regex___unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Regex, jsonSerialize, ai_Regex_jsonSerialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Regex, serialize, ai_Regex_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Regex, unserialize, ai_Regex_unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Regex, getPattern, ai_Regex_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Regex, getFlags, ai_Regex_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_FE_END
-};
-/* clang-format on */
-/* }}} */
-
-/* {{{ MongoDB\BSON\Regex object handlers */
-static zend_object_handlers php_phongo_handler_regex;
-
-static void php_phongo_regex_free_object(zend_object* object) /* {{{ */
-{
- php_phongo_regex_t* intern = Z_OBJ_REGEX(object);
-
- zend_object_std_dtor(&intern->std);
-
- if (intern->pattern) {
- efree(intern->pattern);
- }
-
- if (intern->flags) {
- efree(intern->flags);
- }
-
- if (intern->properties) {
- zend_hash_destroy(intern->properties);
- FREE_HASHTABLE(intern->properties);
- }
-} /* }}} */
-
-static zend_object* php_phongo_regex_create_object(zend_class_entry* class_type) /* {{{ */
-{
- php_phongo_regex_t* intern = NULL;
-
- intern = PHONGO_ALLOC_OBJECT_T(php_phongo_regex_t, class_type);
-
- zend_object_std_init(&intern->std, class_type);
- object_properties_init(&intern->std, class_type);
-
- intern->std.handlers = &php_phongo_handler_regex;
-
- return &intern->std;
-} /* }}} */
-
-static zend_object* php_phongo_regex_clone_object(phongo_compat_object_handler_type* object) /* {{{ */
-{
- php_phongo_regex_t* intern;
- php_phongo_regex_t* new_intern;
- zend_object* new_object;
-
- intern = Z_OBJ_REGEX(PHONGO_COMPAT_GET_OBJ(object));
- new_object = php_phongo_regex_create_object(PHONGO_COMPAT_GET_OBJ(object)->ce);
-
- new_intern = Z_OBJ_REGEX(new_object);
- zend_objects_clone_members(&new_intern->std, &intern->std);
-
- php_phongo_regex_init(new_intern, intern->pattern, intern->pattern_len, intern->flags, intern->flags_len);
-
- return new_object;
-} /* }}} */
-
-static int php_phongo_regex_compare_objects(zval* o1, zval* o2) /* {{{ */
-{
- php_phongo_regex_t *intern1, *intern2;
- int retval;
-
- ZEND_COMPARE_OBJECTS_FALLBACK(o1, o2);
-
- intern1 = Z_REGEX_OBJ_P(o1);
- intern2 = Z_REGEX_OBJ_P(o2);
-
- /* MongoDB compares the pattern string before the flags. */
- retval = strcmp(intern1->pattern, intern2->pattern);
-
- if (retval != 0) {
- return retval;
- }
-
- return strcmp(intern1->flags, intern2->flags);
-} /* }}} */
-
-static HashTable* php_phongo_regex_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
-{
- *is_temp = 1;
- return php_phongo_regex_get_properties_hash(object, true);
-} /* }}} */
-
-static HashTable* php_phongo_regex_get_properties(phongo_compat_object_handler_type* object) /* {{{ */
-{
- return php_phongo_regex_get_properties_hash(object, false);
-} /* }}} */
-/* }}} */
-
-void php_phongo_regex_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\BSON", "Regex", php_phongo_regex_me);
- php_phongo_regex_ce = zend_register_internal_class(&ce);
- php_phongo_regex_ce->create_object = php_phongo_regex_create_object;
- PHONGO_CE_FINAL(php_phongo_regex_ce);
-
- zend_class_implements(php_phongo_regex_ce, 1, php_phongo_regex_interface_ce);
- zend_class_implements(php_phongo_regex_ce, 1, php_phongo_type_ce);
- zend_class_implements(php_phongo_regex_ce, 1, zend_ce_serializable);
- zend_class_implements(php_phongo_regex_ce, 1, php_phongo_json_serializable_ce);
-
-#if PHP_VERSION_ID >= 80000
- zend_class_implements(php_phongo_regex_ce, 1, zend_ce_stringable);
-#endif
-
- memcpy(&php_phongo_handler_regex, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
- PHONGO_COMPAT_SET_COMPARE_OBJECTS_HANDLER(regex);
- php_phongo_handler_regex.clone_obj = php_phongo_regex_clone_object;
- php_phongo_handler_regex.get_debug_info = php_phongo_regex_get_debug_info;
- php_phongo_handler_regex.get_properties = php_phongo_regex_get_properties;
- php_phongo_handler_regex.free_obj = php_phongo_regex_free_object;
- php_phongo_handler_regex.offset = XtOffsetOf(php_phongo_regex_t, std);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/BSON/RegexInterface.c b/mongodb-1.12.0/src/BSON/RegexInterface.c
deleted file mode 100644
index c4c8737d..00000000
--- a/mongodb-1.12.0/src/BSON/RegexInterface.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright 2017-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-
-zend_class_entry* php_phongo_regex_interface_ce;
-
-/* {{{ MongoDB\BSON\RegexInterface function entries */
-/* clang-format off */
-ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(ai_RegexInterface___toString, 0, 0, IS_STRING, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_RegexInterface_void, 0, 0, 0)
-ZEND_END_ARG_INFO()
-
-static zend_function_entry php_phongo_regex_interface_me[] = {
- ZEND_ABSTRACT_ME(RegexInterface, getFlags, ai_RegexInterface_void)
- ZEND_ABSTRACT_ME(RegexInterface, getPattern, ai_RegexInterface_void)
- ZEND_ABSTRACT_ME(RegexInterface, __toString, ai_RegexInterface___toString)
- PHP_FE_END
-};
-/* clang-format on */
-/* }}} */
-
-void php_phongo_regex_interface_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\BSON", "RegexInterface", php_phongo_regex_interface_me);
- php_phongo_regex_interface_ce = zend_register_internal_interface(&ce);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/BSON/Serializable.c b/mongodb-1.12.0/src/BSON/Serializable.c
deleted file mode 100644
index decd8289..00000000
--- a/mongodb-1.12.0/src/BSON/Serializable.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright 2014-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-
-zend_class_entry* php_phongo_serializable_ce;
-
-/* {{{ MongoDB\BSON\Serializable function entries */
-ZEND_BEGIN_ARG_INFO_EX(ai_Serializable_void, 0, 0, 0)
-ZEND_END_ARG_INFO()
-
-static zend_function_entry php_phongo_serializable_me[] = {
- /* clang-format off */
- ZEND_ABSTRACT_ME(Serializable, bsonSerialize, ai_Serializable_void)
- PHP_FE_END
- /* clang-format on */
-};
-/* }}} */
-
-void php_phongo_serializable_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\BSON", "Serializable", php_phongo_serializable_me);
- php_phongo_serializable_ce = zend_register_internal_interface(&ce);
- zend_class_implements(php_phongo_serializable_ce, 1, php_phongo_type_ce);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/BSON/Symbol.c b/mongodb-1.12.0/src/BSON/Symbol.c
deleted file mode 100644
index 5f3c7b13..00000000
--- a/mongodb-1.12.0/src/BSON/Symbol.c
+++ /dev/null
@@ -1,351 +0,0 @@
-/*
- * Copyright 2014-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-#include <Zend/zend_interfaces.h>
-#include <ext/standard/php_var.h>
-#include <zend_smart_str.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-#include "php_bson.h"
-
-zend_class_entry* php_phongo_symbol_ce;
-
-/* Initialize the object and return whether it was successful. An exception will
- * be thrown on error. */
-static bool php_phongo_symbol_init(php_phongo_symbol_t* intern, const char* symbol, size_t symbol_len) /* {{{ */
-{
- if (strlen(symbol) != (size_t) symbol_len) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Symbol cannot contain null bytes");
- return false;
- }
-
- intern->symbol = estrndup(symbol, symbol_len);
- intern->symbol_len = symbol_len;
-
- return true;
-} /* }}} */
-
-/* Initialize the object from a HashTable and return whether it was successful.
- * An exception will be thrown on error. */
-static bool php_phongo_symbol_init_from_hash(php_phongo_symbol_t* intern, HashTable* props) /* {{{ */
-{
- zval* symbol;
-
- if ((symbol = zend_hash_str_find(props, "symbol", sizeof("symbol") - 1)) && Z_TYPE_P(symbol) == IS_STRING) {
- return php_phongo_symbol_init(intern, Z_STRVAL_P(symbol), Z_STRLEN_P(symbol));
- }
-
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"symbol\" string field", ZSTR_VAL(php_phongo_symbol_ce->name));
- return false;
-} /* }}} */
-
-HashTable* php_phongo_symbol_get_properties_hash(phongo_compat_object_handler_type* object, bool is_temp) /* {{{ */
-{
- php_phongo_symbol_t* intern;
- HashTable* props;
-
- intern = Z_OBJ_SYMBOL(PHONGO_COMPAT_GET_OBJ(object));
-
- PHONGO_GET_PROPERTY_HASH_INIT_PROPS(is_temp, intern, props, 2);
-
- if (!intern->symbol) {
- return props;
- }
-
- {
- zval symbol;
-
- ZVAL_STRING(&symbol, intern->symbol);
- zend_hash_str_update(props, "symbol", sizeof("symbol") - 1, &symbol);
- }
-
- return props;
-} /* }}} */
-
-/* {{{ proto string MongoDB\BSON\Symbol::__toString()
- Return the Symbol's symbol string. */
-static PHP_METHOD(Symbol, __toString)
-{
- zend_error_handling error_handling;
- php_phongo_symbol_t* intern;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- intern = Z_SYMBOL_OBJ_P(getThis());
-
- RETURN_STRINGL(intern->symbol, intern->symbol_len);
-} /* }}} */
-
-/* {{{ proto array MongoDB\BSON\Symbol::jsonSerialize()
-*/
-static PHP_METHOD(Symbol, jsonSerialize)
-{
- zend_error_handling error_handling;
- php_phongo_symbol_t* intern;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- intern = Z_SYMBOL_OBJ_P(getThis());
-
- array_init_size(return_value, 1);
- ADD_ASSOC_STRINGL(return_value, "$symbol", intern->symbol, intern->symbol_len);
-} /* }}} */
-
-/* {{{ proto string MongoDB\BSON\Symbol::serialize()
-*/
-static PHP_METHOD(Symbol, serialize)
-{
- zend_error_handling error_handling;
- php_phongo_symbol_t* intern;
- zval retval;
- php_serialize_data_t var_hash;
- smart_str buf = { 0 };
-
- intern = Z_SYMBOL_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- array_init_size(&retval, 1);
- ADD_ASSOC_STRINGL(&retval, "symbol", intern->symbol, intern->symbol_len);
-
- PHP_VAR_SERIALIZE_INIT(var_hash);
- php_var_serialize(&buf, &retval, &var_hash);
- smart_str_0(&buf);
- PHP_VAR_SERIALIZE_DESTROY(var_hash);
-
- PHONGO_RETVAL_SMART_STR(buf);
-
- smart_str_free(&buf);
- zval_ptr_dtor(&retval);
-} /* }}} */
-
-/* {{{ proto void MongoDB\BSON\Symbol::unserialize(string $serialized)
-*/
-static PHP_METHOD(Symbol, unserialize)
-{
- zend_error_handling error_handling;
- php_phongo_symbol_t* intern;
- char* serialized;
- size_t serialized_len;
- zval props;
- php_unserialize_data_t var_hash;
-
- intern = Z_SYMBOL_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &serialized, &serialized_len) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- PHP_VAR_UNSERIALIZE_INIT(var_hash);
- if (!php_var_unserialize(&props, (const unsigned char**) &serialized, (unsigned char*) serialized + serialized_len, &var_hash)) {
- zval_ptr_dtor(&props);
- phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "%s unserialization failed", ZSTR_VAL(php_phongo_symbol_ce->name));
-
- PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
- return;
- }
- PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
-
- php_phongo_symbol_init_from_hash(intern, HASH_OF(&props));
- zval_ptr_dtor(&props);
-} /* }}} */
-
-/* {{{ proto array MongoDB\Driver\Symbol::__serialize()
-*/
-static PHP_METHOD(Symbol, __serialize)
-{
- PHONGO_PARSE_PARAMETERS_NONE();
-
- ZVAL_ARR(return_value, php_phongo_symbol_get_properties_hash(PHONGO_COMPAT_OBJ_P(getThis()), true));
-} /* }}} */
-
-/* {{{ proto void MongoDB\Driver\Symbol::__unserialize(array $data)
-*/
-static PHP_METHOD(Symbol, __unserialize)
-{
- zval* data;
-
- PHONGO_PARSE_PARAMETERS_START(1, 1)
- Z_PARAM_ARRAY(data)
- PHONGO_PARSE_PARAMETERS_END();
-
- php_phongo_symbol_init_from_hash(Z_SYMBOL_OBJ_P(getThis()), Z_ARRVAL_P(data));
-} /* }}} */
-
-/* {{{ MongoDB\BSON\Symbol function entries */
-/* clang-format off */
-ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(ai_Symbol___toString, 0, 0, IS_STRING, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_Symbol___unserialize, 0, 0, 1)
- ZEND_ARG_ARRAY_INFO(0, data, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(ai_Symbol_jsonSerialize, 0, 0, IS_ARRAY, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_Symbol_unserialize, 0, 0, 1)
- ZEND_ARG_INFO(0, serialized)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_Symbol_void, 0, 0, 0)
-ZEND_END_ARG_INFO()
-
-static zend_function_entry php_phongo_symbol_me[] = {
- /* __set_state intentionally missing */
- PHP_ME(Symbol, __serialize, ai_Symbol_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Symbol, __toString, ai_Symbol___toString, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Symbol, __unserialize, ai_Symbol___unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Symbol, jsonSerialize, ai_Symbol_jsonSerialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Symbol, serialize, ai_Symbol_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Symbol, unserialize, ai_Symbol_unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- ZEND_NAMED_ME(__construct, PHP_FN(MongoDB_disabled___construct), ai_Symbol_void, ZEND_ACC_PRIVATE | ZEND_ACC_FINAL)
- PHP_FE_END
-};
-/* clang-format on */
-/* }}} */
-
-/* {{{ MongoDB\BSON\Symbol object handlers */
-static zend_object_handlers php_phongo_handler_symbol;
-
-static void php_phongo_symbol_free_object(zend_object* object) /* {{{ */
-{
- php_phongo_symbol_t* intern = Z_OBJ_SYMBOL(object);
-
- zend_object_std_dtor(&intern->std);
-
- if (intern->symbol) {
- efree(intern->symbol);
- }
-
- if (intern->properties) {
- zend_hash_destroy(intern->properties);
- FREE_HASHTABLE(intern->properties);
- }
-} /* }}} */
-
-zend_object* php_phongo_symbol_create_object(zend_class_entry* class_type) /* {{{ */
-{
- php_phongo_symbol_t* intern = NULL;
-
- intern = PHONGO_ALLOC_OBJECT_T(php_phongo_symbol_t, class_type);
- zend_object_std_init(&intern->std, class_type);
- object_properties_init(&intern->std, class_type);
-
- intern->std.handlers = &php_phongo_handler_symbol;
-
- return &intern->std;
-} /* }}} */
-
-static zend_object* php_phongo_symbol_clone_object(phongo_compat_object_handler_type* object) /* {{{ */
-{
- php_phongo_symbol_t* intern;
- php_phongo_symbol_t* new_intern;
- zend_object* new_object;
-
- intern = Z_OBJ_SYMBOL(PHONGO_COMPAT_GET_OBJ(object));
- new_object = php_phongo_symbol_create_object(PHONGO_COMPAT_GET_OBJ(object)->ce);
-
- new_intern = Z_OBJ_SYMBOL(new_object);
- zend_objects_clone_members(&new_intern->std, &intern->std);
-
- php_phongo_symbol_init(new_intern, intern->symbol, intern->symbol_len);
-
- return new_object;
-} /* }}} */
-
-static int php_phongo_symbol_compare_objects(zval* o1, zval* o2) /* {{{ */
-{
- php_phongo_symbol_t *intern1, *intern2;
-
- ZEND_COMPARE_OBJECTS_FALLBACK(o1, o2);
-
- intern1 = Z_SYMBOL_OBJ_P(o1);
- intern2 = Z_SYMBOL_OBJ_P(o2);
-
- return strcmp(intern1->symbol, intern2->symbol);
-} /* }}} */
-
-static HashTable* php_phongo_symbol_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
-{
- *is_temp = 1;
- return php_phongo_symbol_get_properties_hash(object, true);
-} /* }}} */
-
-static HashTable* php_phongo_symbol_get_properties(phongo_compat_object_handler_type* object) /* {{{ */
-{
- return php_phongo_symbol_get_properties_hash(object, false);
-} /* }}} */
-/* }}} */
-
-void php_phongo_symbol_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\BSON", "Symbol", php_phongo_symbol_me);
- php_phongo_symbol_ce = zend_register_internal_class(&ce);
- php_phongo_symbol_ce->create_object = php_phongo_symbol_create_object;
- PHONGO_CE_FINAL(php_phongo_symbol_ce);
-
- zend_class_implements(php_phongo_symbol_ce, 1, php_phongo_json_serializable_ce);
- zend_class_implements(php_phongo_symbol_ce, 1, php_phongo_type_ce);
- zend_class_implements(php_phongo_symbol_ce, 1, zend_ce_serializable);
-
-#if PHP_VERSION_ID >= 80000
- zend_class_implements(php_phongo_symbol_ce, 1, zend_ce_stringable);
-#endif
-
- memcpy(&php_phongo_handler_symbol, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
- PHONGO_COMPAT_SET_COMPARE_OBJECTS_HANDLER(symbol);
- php_phongo_handler_symbol.clone_obj = php_phongo_symbol_clone_object;
- php_phongo_handler_symbol.get_debug_info = php_phongo_symbol_get_debug_info;
- php_phongo_handler_symbol.get_properties = php_phongo_symbol_get_properties;
- php_phongo_handler_symbol.free_obj = php_phongo_symbol_free_object;
- php_phongo_handler_symbol.offset = XtOffsetOf(php_phongo_symbol_t, std);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/BSON/Timestamp.c b/mongodb-1.12.0/src/BSON/Timestamp.c
deleted file mode 100644
index e354c148..00000000
--- a/mongodb-1.12.0/src/BSON/Timestamp.c
+++ /dev/null
@@ -1,536 +0,0 @@
-/*
- * Copyright 2014-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-#include <Zend/zend_interfaces.h>
-#include <ext/standard/php_var.h>
-#include <zend_smart_str.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-
-zend_class_entry* php_phongo_timestamp_ce;
-
-/* Initialize the object and return whether it was successful. An exception will
- * be thrown on error. */
-static bool php_phongo_timestamp_init(php_phongo_timestamp_t* intern, int64_t increment, int64_t timestamp) /* {{{ */
-{
- if (increment < 0 || increment > UINT32_MAX) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected increment to be an unsigned 32-bit integer, %" PRId64 " given", increment);
- return false;
- }
-
- if (timestamp < 0 || timestamp > UINT32_MAX) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected timestamp to be an unsigned 32-bit integer, %" PRId64 " given", timestamp);
- return false;
- }
-
- intern->increment = (uint32_t) increment;
- intern->timestamp = (uint32_t) timestamp;
- intern->initialized = true;
-
- return true;
-} /* }}} */
-
-/* Initialize the object from numeric strings and return whether it was
- * successful. An exception will be thrown on error. */
-static bool php_phongo_timestamp_init_from_string(php_phongo_timestamp_t* intern, const char* s_increment, size_t s_increment_len, const char* s_timestamp, size_t s_timestamp_len) /* {{{ */
-{
- int64_t increment, timestamp;
-
- if (!php_phongo_parse_int64(&increment, s_increment, s_increment_len)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Error parsing \"%s\" as 64-bit integer increment for %s initialization", s_increment, ZSTR_VAL(php_phongo_timestamp_ce->name));
- return false;
- }
-
- if (!php_phongo_parse_int64(&timestamp, s_timestamp, s_timestamp_len)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Error parsing \"%s\" as 64-bit integer timestamp for %s initialization", s_timestamp, ZSTR_VAL(php_phongo_timestamp_ce->name));
- return false;
- }
-
- return php_phongo_timestamp_init(intern, increment, timestamp);
-} /* }}} */
-
-/* Initialize the object from a HashTable and return whether it was successful.
- * An exception will be thrown on error. */
-static bool php_phongo_timestamp_init_from_hash(php_phongo_timestamp_t* intern, HashTable* props) /* {{{ */
-{
- zval *increment, *timestamp;
-
- if ((increment = zend_hash_str_find(props, "increment", sizeof("increment") - 1)) && Z_TYPE_P(increment) == IS_LONG &&
- (timestamp = zend_hash_str_find(props, "timestamp", sizeof("timestamp") - 1)) && Z_TYPE_P(timestamp) == IS_LONG) {
-
- return php_phongo_timestamp_init(intern, Z_LVAL_P(increment), Z_LVAL_P(timestamp));
- }
- if ((increment = zend_hash_str_find(props, "increment", sizeof("increment") - 1)) && Z_TYPE_P(increment) == IS_STRING &&
- (timestamp = zend_hash_str_find(props, "timestamp", sizeof("timestamp") - 1)) && Z_TYPE_P(timestamp) == IS_STRING) {
-
- return php_phongo_timestamp_init_from_string(intern, Z_STRVAL_P(increment), Z_STRLEN_P(increment), Z_STRVAL_P(timestamp), Z_STRLEN_P(timestamp));
- }
-
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"increment\" and \"timestamp\" integer or numeric string fields", ZSTR_VAL(php_phongo_timestamp_ce->name));
- return false;
-} /* }}} */
-
-static HashTable* php_phongo_timestamp_get_properties_hash(phongo_compat_object_handler_type* object, bool is_temp) /* {{{ */
-{
- php_phongo_timestamp_t* intern;
- HashTable* props;
- char s_increment[24];
- char s_timestamp[24];
- int s_increment_len;
- int s_timestamp_len;
-
- intern = Z_OBJ_TIMESTAMP(PHONGO_COMPAT_GET_OBJ(object));
-
- PHONGO_GET_PROPERTY_HASH_INIT_PROPS(is_temp, intern, props, 2);
-
- if (!intern->initialized) {
- return props;
- }
-
- s_increment_len = snprintf(s_increment, sizeof(s_increment), "%" PRIu32, intern->increment);
- s_timestamp_len = snprintf(s_timestamp, sizeof(s_timestamp), "%" PRIu32, intern->timestamp);
-
- {
- zval increment, timestamp;
-
- ZVAL_STRINGL(&increment, s_increment, s_increment_len);
- zend_hash_str_update(props, "increment", sizeof("increment") - 1, &increment);
-
- ZVAL_STRINGL(&timestamp, s_timestamp, s_timestamp_len);
- zend_hash_str_update(props, "timestamp", sizeof("timestamp") - 1, &timestamp);
- }
-
- return props;
-} /* }}} */
-
-/* {{{ proto void MongoDB\BSON\Timestamp::__construct(int|string $increment, int|string $timestamp)
- Construct a new BSON timestamp type, which consists of a 4-byte increment and
- 4-byte timestamp. */
-static PHP_METHOD(Timestamp, __construct)
-{
- zend_error_handling error_handling;
- php_phongo_timestamp_t* intern;
- zval * increment = NULL, *timestamp = NULL;
-
- intern = Z_TIMESTAMP_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &increment, &timestamp) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- if (Z_TYPE_P(increment) == IS_LONG && Z_TYPE_P(timestamp) == IS_LONG) {
- php_phongo_timestamp_init(intern, Z_LVAL_P(increment), Z_LVAL_P(timestamp));
- return;
- }
-
- if (Z_TYPE_P(increment) == IS_LONG) {
- convert_to_string(increment);
- }
-
- if (Z_TYPE_P(increment) != IS_STRING) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected increment to be an unsigned 32-bit integer or string, %s given", PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(increment));
- return;
- }
-
- if (Z_TYPE_P(timestamp) == IS_LONG) {
- convert_to_string(timestamp);
- }
-
- if (Z_TYPE_P(timestamp) != IS_STRING) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected timestamp to be an unsigned 32-bit integer or string, %s given", PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(timestamp));
- return;
- }
-
- php_phongo_timestamp_init_from_string(intern, Z_STRVAL_P(increment), Z_STRLEN_P(increment), Z_STRVAL_P(timestamp), Z_STRLEN_P(timestamp));
-} /* }}} */
-
-/* {{{ proto integer MongoDB\BSON\Timestamp::getIncrement()
-*/
-static PHP_METHOD(Timestamp, getIncrement)
-{
- zend_error_handling error_handling;
- php_phongo_timestamp_t* intern;
-
- intern = Z_TIMESTAMP_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- RETVAL_LONG(intern->increment);
-} /* }}} */
-
-/* {{{ proto integer MongoDB\BSON\Timestamp::getTimestamp()
-*/
-static PHP_METHOD(Timestamp, getTimestamp)
-{
- zend_error_handling error_handling;
- php_phongo_timestamp_t* intern;
-
- intern = Z_TIMESTAMP_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- RETVAL_LONG(intern->timestamp);
-} /* }}} */
-
-/* {{{ proto MongoDB\BSON\Timestamp MongoDB\BSON\Timestamp::__set_state(array $properties)
-*/
-static PHP_METHOD(Timestamp, __set_state)
-{
- zend_error_handling error_handling;
- php_phongo_timestamp_t* intern;
- HashTable* props;
- zval* array;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &array) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- object_init_ex(return_value, php_phongo_timestamp_ce);
-
- intern = Z_TIMESTAMP_OBJ_P(return_value);
- props = Z_ARRVAL_P(array);
-
- php_phongo_timestamp_init_from_hash(intern, props);
-} /* }}} */
-
-/* {{{ proto string MongoDB\BSON\Timestamp::__toString()
- Returns a string in the form: [increment:timestamp] */
-static PHP_METHOD(Timestamp, __toString)
-{
- zend_error_handling error_handling;
- php_phongo_timestamp_t* intern;
- char* retval;
- int retval_len;
-
- intern = Z_TIMESTAMP_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- retval_len = spprintf(&retval, 0, "[%" PRIu32 ":%" PRIu32 "]", intern->increment, intern->timestamp);
- RETVAL_STRINGL(retval, retval_len);
- efree(retval);
-} /* }}} */
-
-/* {{{ proto array MongoDB\BSON\Timestamp::jsonSerialize()
-*/
-static PHP_METHOD(Timestamp, jsonSerialize)
-{
- zend_error_handling error_handling;
- php_phongo_timestamp_t* intern;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- intern = Z_TIMESTAMP_OBJ_P(getThis());
-
- array_init_size(return_value, 1);
-
- {
- zval ts;
-
- array_init_size(&ts, 2);
- ADD_ASSOC_LONG_EX(&ts, "t", intern->timestamp);
- ADD_ASSOC_LONG_EX(&ts, "i", intern->increment);
- ADD_ASSOC_ZVAL_EX(return_value, "$timestamp", &ts);
- }
-} /* }}} */
-
-/* {{{ proto string MongoDB\BSON\Timestamp::serialize()
-*/
-static PHP_METHOD(Timestamp, serialize)
-{
- zend_error_handling error_handling;
- php_phongo_timestamp_t* intern;
- zval retval;
- php_serialize_data_t var_hash;
- smart_str buf = { 0 };
- char s_increment[12];
- char s_timestamp[12];
- int s_increment_len;
- int s_timestamp_len;
-
- intern = Z_TIMESTAMP_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- s_increment_len = snprintf(s_increment, sizeof(s_increment), "%" PRIu32, intern->increment);
- s_timestamp_len = snprintf(s_timestamp, sizeof(s_timestamp), "%" PRIu32, intern->timestamp);
-
- array_init_size(&retval, 2);
- ADD_ASSOC_STRINGL(&retval, "increment", s_increment, s_increment_len);
- ADD_ASSOC_STRINGL(&retval, "timestamp", s_timestamp, s_timestamp_len);
-
- PHP_VAR_SERIALIZE_INIT(var_hash);
- php_var_serialize(&buf, &retval, &var_hash);
- smart_str_0(&buf);
- PHP_VAR_SERIALIZE_DESTROY(var_hash);
-
- PHONGO_RETVAL_SMART_STR(buf);
-
- smart_str_free(&buf);
- zval_ptr_dtor(&retval);
-} /* }}} */
-
-/* {{{ proto void MongoDB\BSON\Timestamp::unserialize(string $serialized)
-*/
-static PHP_METHOD(Timestamp, unserialize)
-{
- zend_error_handling error_handling;
- php_phongo_timestamp_t* intern;
- char* serialized;
- size_t serialized_len;
- zval props;
- php_unserialize_data_t var_hash;
-
- intern = Z_TIMESTAMP_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &serialized, &serialized_len) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- PHP_VAR_UNSERIALIZE_INIT(var_hash);
- if (!php_var_unserialize(&props, (const unsigned char**) &serialized, (unsigned char*) serialized + serialized_len, &var_hash)) {
- zval_ptr_dtor(&props);
- phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "%s unserialization failed", ZSTR_VAL(php_phongo_timestamp_ce->name));
-
- PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
- return;
- }
- PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
-
- php_phongo_timestamp_init_from_hash(intern, HASH_OF(&props));
- zval_ptr_dtor(&props);
-} /* }}} */
-
-/* {{{ proto array MongoDB\Driver\Timestamp::__serialize()
-*/
-static PHP_METHOD(Timestamp, __serialize)
-{
- PHONGO_PARSE_PARAMETERS_NONE();
-
- RETURN_ARR(php_phongo_timestamp_get_properties_hash(PHONGO_COMPAT_OBJ_P(getThis()), true));
-} /* }}} */
-
-/* {{{ proto void MongoDB\Driver\Timestamp::__unserialize(array $data)
-*/
-static PHP_METHOD(Timestamp, __unserialize)
-{
- zval* data;
-
- PHONGO_PARSE_PARAMETERS_START(1, 1)
- Z_PARAM_ARRAY(data)
- PHONGO_PARSE_PARAMETERS_END();
-
- php_phongo_timestamp_init_from_hash(Z_TIMESTAMP_OBJ_P(getThis()), Z_ARRVAL_P(data));
-} /* }}} */
-
-/* {{{ MongoDB\BSON\Timestamp function entries */
-/* clang-format off */
-ZEND_BEGIN_ARG_INFO_EX(ai_Timestamp___construct, 0, 0, 2)
- ZEND_ARG_INFO(0, increment)
- ZEND_ARG_INFO(0, timestamp)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_Timestamp___set_state, 0, 0, 1)
- ZEND_ARG_ARRAY_INFO(0, properties, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(ai_Timestamp___toString, 0, 0, IS_STRING, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_Timestamp___unserialize, 0, 0, 1)
- ZEND_ARG_ARRAY_INFO(0, data, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(ai_Timestamp_jsonSerialize, 0, 0, IS_ARRAY, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_Timestamp_unserialize, 0, 0, 1)
- ZEND_ARG_INFO(0, serialized)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_Timestamp_void, 0, 0, 0)
-ZEND_END_ARG_INFO()
-
-static zend_function_entry php_phongo_timestamp_me[] = {
- PHP_ME(Timestamp, __construct, ai_Timestamp___construct, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Timestamp, __serialize, ai_Timestamp_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Timestamp, __set_state, ai_Timestamp___set_state, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
- PHP_ME(Timestamp, __toString, ai_Timestamp___toString, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Timestamp, __unserialize, ai_Timestamp___unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Timestamp, jsonSerialize, ai_Timestamp_jsonSerialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Timestamp, serialize, ai_Timestamp_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Timestamp, unserialize, ai_Timestamp_unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Timestamp, getIncrement, ai_Timestamp_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Timestamp, getTimestamp, ai_Timestamp_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_FE_END
-};
-/* clang-format on */
-/* }}} */
-
-/* {{{ MongoDB\BSON\Timestamp object handlers */
-static zend_object_handlers php_phongo_handler_timestamp;
-
-static void php_phongo_timestamp_free_object(zend_object* object) /* {{{ */
-{
- php_phongo_timestamp_t* intern = Z_OBJ_TIMESTAMP(object);
-
- zend_object_std_dtor(&intern->std);
-
- if (intern->properties) {
- zend_hash_destroy(intern->properties);
- FREE_HASHTABLE(intern->properties);
- }
-} /* }}} */
-
-static zend_object* php_phongo_timestamp_create_object(zend_class_entry* class_type) /* {{{ */
-{
- php_phongo_timestamp_t* intern = NULL;
-
- intern = PHONGO_ALLOC_OBJECT_T(php_phongo_timestamp_t, class_type);
-
- zend_object_std_init(&intern->std, class_type);
- object_properties_init(&intern->std, class_type);
-
- intern->std.handlers = &php_phongo_handler_timestamp;
-
- return &intern->std;
-} /* }}} */
-
-static zend_object* php_phongo_timestamp_clone_object(phongo_compat_object_handler_type* object) /* {{{ */
-{
- php_phongo_timestamp_t* intern;
- php_phongo_timestamp_t* new_intern;
- zend_object* new_object;
-
- intern = Z_OBJ_TIMESTAMP(PHONGO_COMPAT_GET_OBJ(object));
- new_object = php_phongo_timestamp_create_object(PHONGO_COMPAT_GET_OBJ(object)->ce);
-
- new_intern = Z_OBJ_TIMESTAMP(new_object);
- zend_objects_clone_members(&new_intern->std, &intern->std);
-
- php_phongo_timestamp_init(new_intern, intern->increment, intern->timestamp);
-
- return new_object;
-} /* }}} */
-
-static int php_phongo_timestamp_compare_objects(zval* o1, zval* o2) /* {{{ */
-{
- php_phongo_timestamp_t *intern1, *intern2;
-
- ZEND_COMPARE_OBJECTS_FALLBACK(o1, o2);
-
- intern1 = Z_TIMESTAMP_OBJ_P(o1);
- intern2 = Z_TIMESTAMP_OBJ_P(o2);
-
- /* MongoDB compares the timestamp before the increment. */
- if (intern1->timestamp != intern2->timestamp) {
- return intern1->timestamp < intern2->timestamp ? -1 : 1;
- }
-
- if (intern1->increment != intern2->increment) {
- return intern1->increment < intern2->increment ? -1 : 1;
- }
-
- return 0;
-} /* }}} */
-
-static HashTable* php_phongo_timestamp_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
-{
- *is_temp = 1;
- return php_phongo_timestamp_get_properties_hash(object, true);
-} /* }}} */
-
-static HashTable* php_phongo_timestamp_get_properties(phongo_compat_object_handler_type* object) /* {{{ */
-{
- return php_phongo_timestamp_get_properties_hash(object, false);
-} /* }}} */
-/* }}} */
-
-void php_phongo_timestamp_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\BSON", "Timestamp", php_phongo_timestamp_me);
- php_phongo_timestamp_ce = zend_register_internal_class(&ce);
- php_phongo_timestamp_ce->create_object = php_phongo_timestamp_create_object;
- PHONGO_CE_FINAL(php_phongo_timestamp_ce);
-
- zend_class_implements(php_phongo_timestamp_ce, 1, php_phongo_timestamp_interface_ce);
- zend_class_implements(php_phongo_timestamp_ce, 1, php_phongo_json_serializable_ce);
- zend_class_implements(php_phongo_timestamp_ce, 1, php_phongo_type_ce);
- zend_class_implements(php_phongo_timestamp_ce, 1, zend_ce_serializable);
-
-#if PHP_VERSION_ID >= 80000
- zend_class_implements(php_phongo_timestamp_ce, 1, zend_ce_stringable);
-#endif
-
- memcpy(&php_phongo_handler_timestamp, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
- PHONGO_COMPAT_SET_COMPARE_OBJECTS_HANDLER(timestamp);
- php_phongo_handler_timestamp.clone_obj = php_phongo_timestamp_clone_object;
- php_phongo_handler_timestamp.get_debug_info = php_phongo_timestamp_get_debug_info;
- php_phongo_handler_timestamp.get_properties = php_phongo_timestamp_get_properties;
- php_phongo_handler_timestamp.free_obj = php_phongo_timestamp_free_object;
- php_phongo_handler_timestamp.offset = XtOffsetOf(php_phongo_timestamp_t, std);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/BSON/TimestampInterface.c b/mongodb-1.12.0/src/BSON/TimestampInterface.c
deleted file mode 100644
index ea4377b6..00000000
--- a/mongodb-1.12.0/src/BSON/TimestampInterface.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright 2017-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-
-zend_class_entry* php_phongo_timestamp_interface_ce;
-
-/* {{{ MongoDB\BSON\TimestampInterface function entries */
-/* clang-format off */
-ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(ai_TimestampInterface___toString, 0, 0, IS_STRING, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_TimestampInterface_void, 0, 0, 0)
-ZEND_END_ARG_INFO()
-
-static zend_function_entry php_phongo_timestamp_interface_me[] = {
- ZEND_ABSTRACT_ME(TimestampInterface, getIncrement, ai_TimestampInterface_void)
- ZEND_ABSTRACT_ME(TimestampInterface, getTimestamp, ai_TimestampInterface_void)
- ZEND_ABSTRACT_ME(TimestampInterface, __toString, ai_TimestampInterface___toString)
- PHP_FE_END
-};
-/* clang-format on */
-/* }}} */
-
-void php_phongo_timestamp_interface_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\BSON", "TimestampInterface", php_phongo_timestamp_interface_me);
- php_phongo_timestamp_interface_ce = zend_register_internal_interface(&ce);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/BSON/Type.c b/mongodb-1.12.0/src/BSON/Type.c
deleted file mode 100644
index a7d41793..00000000
--- a/mongodb-1.12.0/src/BSON/Type.c
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2014-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-
-zend_class_entry* php_phongo_type_ce;
-
-/* {{{ MongoDB\BSON\Type function entries */
-static zend_function_entry php_phongo_type_me[] = {
- PHP_FE_END
-};
-/* }}} */
-
-void php_phongo_type_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\BSON", "Type", php_phongo_type_me);
- php_phongo_type_ce = zend_register_internal_interface(&ce);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/BSON/UTCDateTime.c b/mongodb-1.12.0/src/BSON/UTCDateTime.c
deleted file mode 100644
index 3b09e896..00000000
--- a/mongodb-1.12.0/src/BSON/UTCDateTime.c
+++ /dev/null
@@ -1,531 +0,0 @@
-/*
- * Copyright 2014-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <math.h>
-
-#include <php.h>
-#include <Zend/zend_interfaces.h>
-#include <ext/date/php_date.h>
-#include <ext/standard/php_var.h>
-#include <zend_smart_str.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifdef PHP_WIN32
-#include "win32/time.h"
-#endif
-#include "phongo_compat.h"
-#include "php_phongo.h"
-
-zend_class_entry* php_phongo_utcdatetime_ce;
-
-/* Initialize the object and return whether it was successful. */
-static bool php_phongo_utcdatetime_init(php_phongo_utcdatetime_t* intern, int64_t milliseconds) /* {{{ */
-{
- intern->milliseconds = milliseconds;
- intern->initialized = true;
-
- return true;
-} /* }}} */
-
-/* Initialize the object from a numeric string and return whether it was
- * successful. An exception will be thrown on error. */
-static bool php_phongo_utcdatetime_init_from_string(php_phongo_utcdatetime_t* intern, const char* s_milliseconds, size_t s_milliseconds_len) /* {{{ */
-{
- int64_t milliseconds;
-
- if (!php_phongo_parse_int64(&milliseconds, s_milliseconds, s_milliseconds_len)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Error parsing \"%s\" as 64-bit integer for %s initialization", s_milliseconds, ZSTR_VAL(php_phongo_utcdatetime_ce->name));
- return false;
- }
-
- return php_phongo_utcdatetime_init(intern, milliseconds);
-} /* }}} */
-
-/* Initialize the object from a HashTable and return whether it was successful.
- * An exception will be thrown on error. */
-static bool php_phongo_utcdatetime_init_from_hash(php_phongo_utcdatetime_t* intern, HashTable* props) /* {{{ */
-{
- zval* milliseconds;
-
- if ((milliseconds = zend_hash_str_find(props, "milliseconds", sizeof("milliseconds") - 1)) && Z_TYPE_P(milliseconds) == IS_LONG) {
- return php_phongo_utcdatetime_init(intern, Z_LVAL_P(milliseconds));
- }
-
- if ((milliseconds = zend_hash_str_find(props, "milliseconds", sizeof("milliseconds") - 1)) && Z_TYPE_P(milliseconds) == IS_STRING) {
- return php_phongo_utcdatetime_init_from_string(intern, Z_STRVAL_P(milliseconds), Z_STRLEN_P(milliseconds));
- }
-
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"milliseconds\" integer or numeric string field", ZSTR_VAL(php_phongo_utcdatetime_ce->name));
- return false;
-} /* }}} */
-
-/* Initialize the object from the current time and return whether it was
- * successful. */
-static bool php_phongo_utcdatetime_init_from_current_time(php_phongo_utcdatetime_t* intern) /* {{{ */
-{
- int64_t sec, usec;
- struct timeval cur_time;
-
- bson_gettimeofday(&cur_time);
- sec = cur_time.tv_sec;
- usec = cur_time.tv_usec;
-
- intern->milliseconds = (sec * 1000) + (usec / 1000);
- intern->initialized = true;
-
- return true;
-} /* }}} */
-
-/* Initialize the object from a DateTime object and return whether it was
- * successful. */
-static bool php_phongo_utcdatetime_init_from_date(php_phongo_utcdatetime_t* intern, php_date_obj* datetime_obj) /* {{{ */
-{
- int64_t sec, usec;
-
- /* The following assignments use the same logic as date_format() in php_date.c */
- sec = datetime_obj->time->sse;
- usec = (int64_t) floor(datetime_obj->time->us);
-
- intern->milliseconds = (sec * 1000) + (usec / 1000);
- intern->initialized = true;
-
- return true;
-} /* }}} */
-
-static HashTable* php_phongo_utcdatetime_get_properties_hash(phongo_compat_object_handler_type* object, bool is_temp) /* {{{ */
-{
- php_phongo_utcdatetime_t* intern;
- HashTable* props;
-
- intern = Z_OBJ_UTCDATETIME(PHONGO_COMPAT_GET_OBJ(object));
-
- PHONGO_GET_PROPERTY_HASH_INIT_PROPS(is_temp, intern, props, 1);
-
- if (!intern->initialized) {
- return props;
- }
-
- {
- zval milliseconds;
-
- ZVAL_INT64_STRING(&milliseconds, intern->milliseconds);
- zend_hash_str_update(props, "milliseconds", sizeof("milliseconds") - 1, &milliseconds);
- }
-
- return props;
-} /* }}} */
-
-/* {{{ proto void MongoDB\BSON\UTCDateTime::__construct([int|float|string|DateTimeInterface $milliseconds = null])
- Construct a new BSON UTCDateTime type from either the current time,
- milliseconds since the epoch, or a DateTimeInterface object. Defaults to the
- current time. */
-static PHP_METHOD(UTCDateTime, __construct)
-{
- zend_error_handling error_handling;
- php_phongo_utcdatetime_t* intern;
- zval* milliseconds = NULL;
-
- intern = Z_UTCDATETIME_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "|z!", &milliseconds) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- if (milliseconds == NULL) {
- php_phongo_utcdatetime_init_from_current_time(intern);
- return;
- }
-
- if (Z_TYPE_P(milliseconds) == IS_OBJECT) {
- if (instanceof_function(Z_OBJCE_P(milliseconds), php_date_get_date_ce()) ||
- (php_phongo_date_immutable_ce && instanceof_function(Z_OBJCE_P(milliseconds), php_phongo_date_immutable_ce))) {
-
- php_phongo_utcdatetime_init_from_date(intern, Z_PHPDATE_P(milliseconds));
- } else {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected instance of DateTimeInterface, %s given", ZSTR_VAL(Z_OBJCE_P(milliseconds)->name));
- }
- return;
- }
-
- if (Z_TYPE_P(milliseconds) == IS_LONG) {
- php_phongo_utcdatetime_init(intern, Z_LVAL_P(milliseconds));
- return;
- }
-
- if (Z_TYPE_P(milliseconds) == IS_DOUBLE) {
- char tmp[24];
- int tmp_len;
-
- tmp_len = snprintf(tmp, sizeof(tmp), "%.0f", Z_DVAL_P(milliseconds) > 0 ? floor(Z_DVAL_P(milliseconds)) : ceil(Z_DVAL_P(milliseconds)));
-
- php_phongo_utcdatetime_init_from_string(intern, tmp, tmp_len);
- return;
- }
-
- if (Z_TYPE_P(milliseconds) != IS_STRING) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected integer or string, %s given", PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(milliseconds));
- return;
- }
-
- php_phongo_utcdatetime_init_from_string(intern, Z_STRVAL_P(milliseconds), Z_STRLEN_P(milliseconds));
-} /* }}} */
-
-/* {{{ proto MongoDB\BSON\UTCDateTime MongoDB\BSON\UTCDateTime::__set_state(array $properties)
-*/
-static PHP_METHOD(UTCDateTime, __set_state)
-{
- zend_error_handling error_handling;
- php_phongo_utcdatetime_t* intern;
- HashTable* props;
- zval* array;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &array) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- object_init_ex(return_value, php_phongo_utcdatetime_ce);
-
- intern = Z_UTCDATETIME_OBJ_P(return_value);
- props = Z_ARRVAL_P(array);
-
- php_phongo_utcdatetime_init_from_hash(intern, props);
-} /* }}} */
-
-/* {{{ proto string MongoDB\BSON\UTCDateTime::__toString()
- Returns the UTCDateTime's milliseconds as a string */
-static PHP_METHOD(UTCDateTime, __toString)
-{
- zend_error_handling error_handling;
- php_phongo_utcdatetime_t* intern;
-
- intern = Z_UTCDATETIME_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- ZVAL_INT64_STRING(return_value, intern->milliseconds);
-} /* }}} */
-
-/* {{{ proto DateTime MongoDB\BSON\UTCDateTime::toDateTime()
- Returns a DateTime object representing this UTCDateTime */
-static PHP_METHOD(UTCDateTime, toDateTime)
-{
- zend_error_handling error_handling;
- php_phongo_utcdatetime_t* intern;
- php_date_obj* datetime_obj;
- char* sec;
- size_t sec_len;
-
- intern = Z_UTCDATETIME_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- object_init_ex(return_value, php_date_get_date_ce());
- datetime_obj = Z_PHPDATE_P(return_value);
-
- sec_len = spprintf(&sec, 0, "@%" PRId64, intern->milliseconds / 1000);
- php_date_initialize(datetime_obj, sec, sec_len, NULL, NULL, 0);
- efree(sec);
-
- datetime_obj->time->us = (intern->milliseconds % 1000) * 1000;
-}
-/* }}} */
-
-/* {{{ proto array MongoDB\BSON\UTCDateTime::jsonSerialize()
-*/
-static PHP_METHOD(UTCDateTime, jsonSerialize)
-{
- zend_error_handling error_handling;
- php_phongo_utcdatetime_t* intern;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- intern = Z_UTCDATETIME_OBJ_P(getThis());
-
- array_init_size(return_value, 1);
-
- {
- zval udt;
-
- array_init_size(&udt, 1);
- ADD_ASSOC_INT64_AS_STRING(&udt, "$numberLong", intern->milliseconds);
- ADD_ASSOC_ZVAL_EX(return_value, "$date", &udt);
- }
-} /* }}} */
-
-/* {{{ proto string MongoDB\BSON\UTCDateTime::serialize()
-*/
-static PHP_METHOD(UTCDateTime, serialize)
-{
- zend_error_handling error_handling;
- php_phongo_utcdatetime_t* intern;
- zval retval;
- php_serialize_data_t var_hash;
- smart_str buf = { 0 };
-
- intern = Z_UTCDATETIME_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- array_init_size(&retval, 1);
- ADD_ASSOC_INT64_AS_STRING(&retval, "milliseconds", intern->milliseconds);
-
- PHP_VAR_SERIALIZE_INIT(var_hash);
- php_var_serialize(&buf, &retval, &var_hash);
- smart_str_0(&buf);
- PHP_VAR_SERIALIZE_DESTROY(var_hash);
-
- PHONGO_RETVAL_SMART_STR(buf);
-
- smart_str_free(&buf);
- zval_ptr_dtor(&retval);
-} /* }}} */
-
-/* {{{ proto void MongoDB\BSON\UTCDateTime::unserialize(string $serialized)
-*/
-static PHP_METHOD(UTCDateTime, unserialize)
-{
- zend_error_handling error_handling;
- php_phongo_utcdatetime_t* intern;
- char* serialized;
- size_t serialized_len;
- zval props;
- php_unserialize_data_t var_hash;
-
- intern = Z_UTCDATETIME_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &serialized, &serialized_len) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- PHP_VAR_UNSERIALIZE_INIT(var_hash);
- if (!php_var_unserialize(&props, (const unsigned char**) &serialized, (unsigned char*) serialized + serialized_len, &var_hash)) {
- zval_ptr_dtor(&props);
- phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "%s unserialization failed", ZSTR_VAL(php_phongo_utcdatetime_ce->name));
-
- PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
- return;
- }
- PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
-
- php_phongo_utcdatetime_init_from_hash(intern, HASH_OF(&props));
- zval_ptr_dtor(&props);
-} /* }}} */
-
-/* {{{ proto array MongoDB\Driver\UTCDateTime::__serialize()
-*/
-static PHP_METHOD(UTCDateTime, __serialize)
-{
- PHONGO_PARSE_PARAMETERS_NONE();
-
- RETURN_ARR(php_phongo_utcdatetime_get_properties_hash(PHONGO_COMPAT_OBJ_P(getThis()), true));
-} /* }}} */
-
-/* {{{ proto void MongoDB\Driver\UTCDateTime::__unserialize(array $data)
-*/
-static PHP_METHOD(UTCDateTime, __unserialize)
-{
- zval* data;
-
- PHONGO_PARSE_PARAMETERS_START(1, 1)
- Z_PARAM_ARRAY(data)
- PHONGO_PARSE_PARAMETERS_END();
-
- php_phongo_utcdatetime_init_from_hash(Z_UTCDATETIME_OBJ_P(getThis()), Z_ARRVAL_P(data));
-} /* }}} */
-
-/* {{{ MongoDB\BSON\UTCDateTime function entries */
-/* clang-format off */
-ZEND_BEGIN_ARG_INFO_EX(ai_UTCDateTime___construct, 0, 0, 0)
- ZEND_ARG_INFO(0, milliseconds)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_UTCDateTime___set_state, 0, 0, 1)
- ZEND_ARG_ARRAY_INFO(0, properties, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(ai_UTCDateTime___toString, 0, 0, IS_STRING, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_UTCDateTime___unserialize, 0, 0, 1)
- ZEND_ARG_ARRAY_INFO(0, data, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(ai_UTCDateTime_jsonSerialize, 0, 0, IS_ARRAY, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_UTCDateTime_unserialize, 0, 0, 1)
- ZEND_ARG_INFO(0, serialized)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_UTCDateTime_void, 0, 0, 0)
-ZEND_END_ARG_INFO()
-
-static zend_function_entry php_phongo_utcdatetime_me[] = {
- PHP_ME(UTCDateTime, __construct, ai_UTCDateTime___construct, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(UTCDateTime, __serialize, ai_UTCDateTime_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(UTCDateTime, __set_state, ai_UTCDateTime___set_state, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
- PHP_ME(UTCDateTime, __toString, ai_UTCDateTime___toString, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(UTCDateTime, __unserialize, ai_UTCDateTime___unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(UTCDateTime, jsonSerialize, ai_UTCDateTime_jsonSerialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(UTCDateTime, serialize, ai_UTCDateTime_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(UTCDateTime, unserialize, ai_UTCDateTime_unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(UTCDateTime, toDateTime, ai_UTCDateTime_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_FE_END
-};
-/* clang-format on */
-/* }}} */
-
-/* {{{ MongoDB\BSON\UTCDateTime object handlers */
-static zend_object_handlers php_phongo_handler_utcdatetime;
-
-static void php_phongo_utcdatetime_free_object(zend_object* object) /* {{{ */
-{
- php_phongo_utcdatetime_t* intern = Z_OBJ_UTCDATETIME(object);
-
- zend_object_std_dtor(&intern->std);
-
- if (intern->properties) {
- zend_hash_destroy(intern->properties);
- FREE_HASHTABLE(intern->properties);
- }
-} /* }}} */
-
-static zend_object* php_phongo_utcdatetime_create_object(zend_class_entry* class_type) /* {{{ */
-{
- php_phongo_utcdatetime_t* intern = NULL;
-
- intern = PHONGO_ALLOC_OBJECT_T(php_phongo_utcdatetime_t, class_type);
-
- zend_object_std_init(&intern->std, class_type);
- object_properties_init(&intern->std, class_type);
-
- intern->std.handlers = &php_phongo_handler_utcdatetime;
-
- return &intern->std;
-} /* }}} */
-
-static zend_object* php_phongo_utcdatetime_clone_object(phongo_compat_object_handler_type* object) /* {{{ */
-{
- php_phongo_utcdatetime_t* intern;
- php_phongo_utcdatetime_t* new_intern;
- zend_object* new_object;
-
- intern = Z_OBJ_UTCDATETIME(PHONGO_COMPAT_GET_OBJ(object));
- new_object = php_phongo_utcdatetime_create_object(PHONGO_COMPAT_GET_OBJ(object)->ce);
-
- new_intern = Z_OBJ_UTCDATETIME(new_object);
- zend_objects_clone_members(&new_intern->std, &intern->std);
-
- php_phongo_utcdatetime_init(new_intern, intern->milliseconds);
-
- return new_object;
-} /* }}} */
-
-static int php_phongo_utcdatetime_compare_objects(zval* o1, zval* o2) /* {{{ */
-{
- php_phongo_utcdatetime_t *intern1, *intern2;
-
- ZEND_COMPARE_OBJECTS_FALLBACK(o1, o2);
-
- intern1 = Z_UTCDATETIME_OBJ_P(o1);
- intern2 = Z_UTCDATETIME_OBJ_P(o2);
-
- if (intern1->milliseconds != intern2->milliseconds) {
- return intern1->milliseconds < intern2->milliseconds ? -1 : 1;
- }
-
- return 0;
-} /* }}} */
-
-static HashTable* php_phongo_utcdatetime_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
-{
- *is_temp = 1;
- return php_phongo_utcdatetime_get_properties_hash(object, true);
-} /* }}} */
-
-static HashTable* php_phongo_utcdatetime_get_properties(phongo_compat_object_handler_type* object) /* {{{ */
-{
- return php_phongo_utcdatetime_get_properties_hash(object, false);
-} /* }}} */
-/* }}} */
-
-void php_phongo_utcdatetime_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\BSON", "UTCDateTime", php_phongo_utcdatetime_me);
- php_phongo_utcdatetime_ce = zend_register_internal_class(&ce);
- php_phongo_utcdatetime_ce->create_object = php_phongo_utcdatetime_create_object;
- PHONGO_CE_FINAL(php_phongo_utcdatetime_ce);
-
- zend_class_implements(php_phongo_utcdatetime_ce, 1, php_phongo_utcdatetime_interface_ce);
- zend_class_implements(php_phongo_utcdatetime_ce, 1, php_phongo_json_serializable_ce);
- zend_class_implements(php_phongo_utcdatetime_ce, 1, php_phongo_type_ce);
- zend_class_implements(php_phongo_utcdatetime_ce, 1, zend_ce_serializable);
-
-#if PHP_VERSION_ID >= 80000
- zend_class_implements(php_phongo_utcdatetime_ce, 1, zend_ce_stringable);
-#endif
-
- memcpy(&php_phongo_handler_utcdatetime, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
- PHONGO_COMPAT_SET_COMPARE_OBJECTS_HANDLER(utcdatetime);
- php_phongo_handler_utcdatetime.clone_obj = php_phongo_utcdatetime_clone_object;
- php_phongo_handler_utcdatetime.get_debug_info = php_phongo_utcdatetime_get_debug_info;
- php_phongo_handler_utcdatetime.get_properties = php_phongo_utcdatetime_get_properties;
- php_phongo_handler_utcdatetime.free_obj = php_phongo_utcdatetime_free_object;
- php_phongo_handler_utcdatetime.offset = XtOffsetOf(php_phongo_utcdatetime_t, std);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/BSON/UTCDateTimeInterface.c b/mongodb-1.12.0/src/BSON/UTCDateTimeInterface.c
deleted file mode 100644
index 13ab6f07..00000000
--- a/mongodb-1.12.0/src/BSON/UTCDateTimeInterface.c
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2017-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-
-zend_class_entry* php_phongo_utcdatetime_interface_ce;
-
-/* {{{ MongoDB\BSON\UTCDateTimeInterface function entries */
-/* clang-format off */
-ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(ai_UTCDateTimeInterface___toString, 0, 0, IS_STRING, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_UTCDateTimeInterface_void, 0, 0, 0)
-ZEND_END_ARG_INFO()
-
-static zend_function_entry php_phongo_utcdatetime_interface_me[] = {
- ZEND_ABSTRACT_ME(UTCDateTimeInterface, toDateTime, ai_UTCDateTimeInterface_void)
- ZEND_ABSTRACT_ME(UTCDateTimeInterface, __toString, ai_UTCDateTimeInterface___toString)
- PHP_FE_END
-};
-/* clang-format on */
-/* }}} */
-
-void php_phongo_utcdatetime_interface_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\BSON", "UTCDateTimeInterface", php_phongo_utcdatetime_interface_me);
- php_phongo_utcdatetime_interface_ce = zend_register_internal_interface(&ce);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/BSON/Undefined.c b/mongodb-1.12.0/src/BSON/Undefined.c
deleted file mode 100644
index 9a9c4b00..00000000
--- a/mongodb-1.12.0/src/BSON/Undefined.c
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * Copyright 2014-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-#include <Zend/zend_interfaces.h>
-#include <ext/standard/php_var.h>
-#include <zend_smart_str.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-
-zend_class_entry* php_phongo_undefined_ce;
-
-/* {{{ proto string MongoDB\BSON\Undefined::__toString()
- Return the empty string. */
-static PHP_METHOD(Undefined, __toString)
-{
- zend_error_handling error_handling;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- RETURN_STRINGL("", 0);
-} /* }}} */
-
-/* {{{ proto array MongoDB\BSON\Undefined::jsonSerialize()
-*/
-static PHP_METHOD(Undefined, jsonSerialize)
-{
- zend_error_handling error_handling;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- array_init_size(return_value, 1);
- ADD_ASSOC_BOOL_EX(return_value, "$undefined", 1);
-} /* }}} */
-
-/* {{{ proto string MongoDB\BSON\Undefined::serialize()
-*/
-static PHP_METHOD(Undefined, serialize)
-{
- zend_error_handling error_handling;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- RETURN_STRING("");
-} /* }}} */
-
-/* {{{ proto void MongoDB\BSON\Undefined::unserialize(string $serialized)
-*/
-static PHP_METHOD(Undefined, unserialize)
-{
- zend_error_handling error_handling;
- char* serialized;
- size_t serialized_len;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &serialized, &serialized_len) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-} /* }}} */
-
-/* {{{ proto array MongoDB\Driver\Undefined::__serialize()
-*/
-static PHP_METHOD(Undefined, __serialize)
-{
- PHONGO_PARSE_PARAMETERS_NONE();
-
- array_init_size(return_value, 0);
-} /* }}} */
-
-/* {{{ proto void MongoDB\Driver\Undefined::__unserialize(array $data)
-*/
-static PHP_METHOD(Undefined, __unserialize)
-{
- zval* data;
-
- PHONGO_PARSE_PARAMETERS_START(1, 1)
- Z_PARAM_ARRAY(data)
- PHONGO_PARSE_PARAMETERS_END();
-} /* }}} */
-
-/* {{{ MongoDB\BSON\Undefined function entries */
-/* clang-format off */
-ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(ai_Undefined___toString, 0, 0, IS_STRING, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_Undefined___unserialize, 0, 0, 1)
- ZEND_ARG_ARRAY_INFO(0, data, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(ai_Undefined_jsonSerialize, 0, 0, IS_ARRAY, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_Undefined_unserialize, 0, 0, 1)
- ZEND_ARG_INFO(0, serialized)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_Undefined_void, 0, 0, 0)
-ZEND_END_ARG_INFO()
-
-static zend_function_entry php_phongo_undefined_me[] = {
- /* __set_state intentionally missing */
- PHP_ME(Undefined, __serialize, ai_Undefined_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Undefined, __toString, ai_Undefined___toString, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Undefined, __unserialize, ai_Undefined___unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Undefined, jsonSerialize, ai_Undefined_jsonSerialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Undefined, serialize, ai_Undefined_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Undefined, unserialize, ai_Undefined_unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- ZEND_NAMED_ME(__construct, PHP_FN(MongoDB_disabled___construct), ai_Undefined_void, ZEND_ACC_PRIVATE | ZEND_ACC_FINAL)
- PHP_FE_END
-};
-/* clang-format on */
-/* }}} */
-
-/* {{{ MongoDB\BSON\Undefined object handlers */
-static zend_object_handlers php_phongo_handler_undefined;
-
-static void php_phongo_undefined_free_object(zend_object* object) /* {{{ */
-{
- php_phongo_undefined_t* intern = Z_OBJ_UNDEFINED(object);
-
- zend_object_std_dtor(&intern->std);
-} /* }}} */
-
-static zend_object* php_phongo_undefined_create_object(zend_class_entry* class_type) /* {{{ */
-{
- php_phongo_undefined_t* intern = NULL;
-
- intern = PHONGO_ALLOC_OBJECT_T(php_phongo_undefined_t, class_type);
- zend_object_std_init(&intern->std, class_type);
- object_properties_init(&intern->std, class_type);
-
- intern->std.handlers = &php_phongo_handler_undefined;
-
- return &intern->std;
-} /* }}} */
-/* }}} */
-
-void php_phongo_undefined_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\BSON", "Undefined", php_phongo_undefined_me);
- php_phongo_undefined_ce = zend_register_internal_class(&ce);
- php_phongo_undefined_ce->create_object = php_phongo_undefined_create_object;
- PHONGO_CE_FINAL(php_phongo_undefined_ce);
-
- zend_class_implements(php_phongo_undefined_ce, 1, php_phongo_json_serializable_ce);
- zend_class_implements(php_phongo_undefined_ce, 1, php_phongo_type_ce);
- zend_class_implements(php_phongo_undefined_ce, 1, zend_ce_serializable);
-
-#if PHP_VERSION_ID >= 80000
- zend_class_implements(php_phongo_undefined_ce, 1, zend_ce_stringable);
-#endif
-
- memcpy(&php_phongo_handler_undefined, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
- /* Re-assign default handler previously removed in php_phongo.c */
- php_phongo_handler_undefined.clone_obj = zend_objects_clone_obj;
- php_phongo_handler_undefined.free_obj = php_phongo_undefined_free_object;
- php_phongo_handler_undefined.offset = XtOffsetOf(php_phongo_undefined_t, std);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/BSON/Unserializable.c b/mongodb-1.12.0/src/BSON/Unserializable.c
deleted file mode 100644
index 27b9331c..00000000
--- a/mongodb-1.12.0/src/BSON/Unserializable.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright 2014-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-
-zend_class_entry* php_phongo_unserializable_ce;
-
-/* {{{ MongoDB\BSON\Unserializable function entries */
-ZEND_BEGIN_ARG_INFO_EX(ai_Unserializable_bsonUnserialize, 0, 0, 1)
- ZEND_ARG_ARRAY_INFO(0, data, 0)
-ZEND_END_ARG_INFO()
-
-static zend_function_entry php_phongo_unserializable_me[] = {
- /* clang-format off */
- ZEND_ABSTRACT_ME(Unserializable, bsonUnserialize, ai_Unserializable_bsonUnserialize)
- PHP_FE_END
- /* clang-format on */
-};
-/* }}} */
-
-void php_phongo_unserializable_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\BSON", "Unserializable", php_phongo_unserializable_me);
- php_phongo_unserializable_ce = zend_register_internal_interface(&ce);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/BSON/functions.c b/mongodb-1.12.0/src/BSON/functions.c
deleted file mode 100644
index 20638a58..00000000
--- a/mongodb-1.12.0/src/BSON/functions.c
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Copyright 2014-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-#include "php_bson.h"
-
-typedef enum {
- PHONGO_JSON_MODE_LEGACY,
- PHONGO_JSON_MODE_CANONICAL,
- PHONGO_JSON_MODE_RELAXED,
-} php_phongo_json_mode_t;
-
-/* {{{ proto string MongoDB\BSON\fromPHP(array|object $value)
- Returns the BSON representation of a PHP value */
-PHP_FUNCTION(MongoDB_BSON_fromPHP)
-{
- zend_error_handling error_handling;
- zval* data;
- bson_t* bson;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "A", &data) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- bson = bson_new();
- php_phongo_zval_to_bson(data, PHONGO_BSON_NONE, bson, NULL);
-
- RETVAL_STRINGL((const char*) bson_get_data(bson), bson->len);
- bson_destroy(bson);
-} /* }}} */
-
-/* {{{ proto array|object MongoDB\BSON\toPHP(string $bson [, array $typemap = array()])
- Returns the PHP representation of a BSON value, optionally converting it into a custom class */
-PHP_FUNCTION(MongoDB_BSON_toPHP)
-{
- zend_error_handling error_handling;
- char* data;
- size_t data_len;
- zval* typemap = NULL;
- php_phongo_bson_state state;
-
- PHONGO_BSON_INIT_STATE(state);
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|a!", &data, &data_len, &typemap) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- if (!php_phongo_bson_typemap_to_state(typemap, &state.map)) {
- return;
- }
-
- if (!php_phongo_bson_to_zval_ex((const unsigned char*) data, data_len, &state)) {
- zval_ptr_dtor(&state.zchild);
- php_phongo_bson_typemap_dtor(&state.map);
- RETURN_NULL();
- }
-
- php_phongo_bson_typemap_dtor(&state.map);
-
- RETURN_ZVAL(&state.zchild, 0, 1);
-} /* }}} */
-
-/* {{{ proto string MongoDB\BSON\fromJSON(string $json)
- Returns the BSON representation of a JSON value */
-PHP_FUNCTION(MongoDB_BSON_fromJSON)
-{
- zend_error_handling error_handling;
- char* json;
- size_t json_len;
- bson_t bson = BSON_INITIALIZER;
- bson_error_t error = { 0 };
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &json, &json_len) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- if (bson_init_from_json(&bson, (const char*) json, json_len, &error)) {
- RETVAL_STRINGL((const char*) bson_get_data(&bson), bson.len);
- bson_destroy(&bson);
- } else {
- phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "%s", error.domain == BSON_ERROR_JSON ? error.message : "Error parsing JSON");
- }
-} /* }}} */
-
-static void phongo_bson_to_json(INTERNAL_FUNCTION_PARAMETERS, php_phongo_json_mode_t mode)
-{
- zend_error_handling error_handling;
- char* data;
- size_t data_len;
- const bson_t* bson;
- bool eof = false;
- bson_reader_t* reader;
- char* json = NULL;
- size_t json_len;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &data, &data_len) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- reader = bson_reader_new_from_data((const unsigned char*) data, data_len);
- bson = bson_reader_read(reader, NULL);
-
- if (!bson) {
- phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "Could not read document from BSON reader");
- bson_reader_destroy(reader);
- return;
- }
-
- if (mode == PHONGO_JSON_MODE_LEGACY) {
- json = bson_as_json(bson, &json_len);
- } else if (mode == PHONGO_JSON_MODE_CANONICAL) {
- json = bson_as_canonical_extended_json(bson, &json_len);
- } else if (mode == PHONGO_JSON_MODE_RELAXED) {
- json = bson_as_relaxed_extended_json(bson, &json_len);
- }
-
- if (!json) {
- phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "Could not convert BSON document to a JSON string");
- bson_reader_destroy(reader);
- return;
- }
-
- RETVAL_STRINGL(json, json_len);
- bson_free(json);
-
- if (bson_reader_read(reader, &eof) || !eof) {
- phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "Reading document did not exhaust input buffer");
- }
-
- bson_reader_destroy(reader);
-} /* }}} */
-
-/* {{{ proto string MongoDB\BSON\toJSON(string $bson)
- Returns the legacy extended JSON representation of a BSON value */
-PHP_FUNCTION(MongoDB_BSON_toJSON)
-{
- phongo_bson_to_json(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHONGO_JSON_MODE_LEGACY);
-} /* }}} */
-
-/* {{{ proto string MongoDB\BSON\toCanonicalExtendedJSON(string $bson)
- Returns the canonical extended JSON representation of a BSON value */
-PHP_FUNCTION(MongoDB_BSON_toCanonicalExtendedJSON)
-{
- phongo_bson_to_json(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHONGO_JSON_MODE_CANONICAL);
-} /* }}} */
-
-/* {{{ proto string MongoDB\BSON\toRelaxedExtendedJSON(string $bson)
- Returns the relaxed extended JSON representation of a BSON value */
-PHP_FUNCTION(MongoDB_BSON_toRelaxedExtendedJSON)
-{
- phongo_bson_to_json(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHONGO_JSON_MODE_RELAXED);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/BSON/functions.h b/mongodb-1.12.0/src/BSON/functions.h
deleted file mode 100644
index 00556fe3..00000000
--- a/mongodb-1.12.0/src/BSON/functions.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2014-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef PHONGO_BSON_FUNCTIONS_H
-#define PHONGO_BSON_FUNCTIONS_H
-
-#include <php.h>
-
-PHP_FUNCTION(MongoDB_BSON_fromPHP);
-PHP_FUNCTION(MongoDB_BSON_toPHP);
-
-PHP_FUNCTION(MongoDB_BSON_fromJSON);
-PHP_FUNCTION(MongoDB_BSON_toJSON);
-PHP_FUNCTION(MongoDB_BSON_toCanonicalExtendedJSON);
-PHP_FUNCTION(MongoDB_BSON_toRelaxedExtendedJSON);
-
-#endif /* PHONGO_BSON_FUNCTIONS_H */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/LIBMONGOCRYPT_VERSION_CURRENT b/mongodb-1.12.0/src/LIBMONGOCRYPT_VERSION_CURRENT
deleted file mode 100644
index f0bb29e7..00000000
--- a/mongodb-1.12.0/src/LIBMONGOCRYPT_VERSION_CURRENT
+++ /dev/null
@@ -1 +0,0 @@
-1.3.0
diff --git a/mongodb-1.12.0/src/LIBMONGOC_VERSION_CURRENT b/mongodb-1.12.0/src/LIBMONGOC_VERSION_CURRENT
deleted file mode 100644
index 39893559..00000000
--- a/mongodb-1.12.0/src/LIBMONGOC_VERSION_CURRENT
+++ /dev/null
@@ -1 +0,0 @@
-1.20.0
diff --git a/mongodb-1.12.0/src/MongoDB/BulkWrite.c b/mongodb-1.12.0/src/MongoDB/BulkWrite.c
deleted file mode 100644
index e583ba2f..00000000
--- a/mongodb-1.12.0/src/MongoDB/BulkWrite.c
+++ /dev/null
@@ -1,684 +0,0 @@
-/*
- * Copyright 2015-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-#include <Zend/zend_interfaces.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "php_array_api.h"
-#include "phongo_compat.h"
-#include "php_phongo.h"
-#include "php_bson.h"
-
-#define PHONGO_BULKWRITE_BYPASS_UNSET -1
-
-zend_class_entry* php_phongo_bulkwrite_ce;
-
-/* Extracts the "_id" field of a BSON document into a return value. */
-static void php_phongo_bulkwrite_extract_id(bson_t* doc, zval** return_value) /* {{{ */
-{
- zval* id = NULL;
- php_phongo_bson_state state;
-
- PHONGO_BSON_INIT_STATE(state);
- state.map.root_type = PHONGO_TYPEMAP_NATIVE_ARRAY;
-
- if (!php_phongo_bson_to_zval_ex(bson_get_data(doc), doc->len, &state)) {
- goto cleanup;
- }
-
- id = php_array_fetchc(&state.zchild, "_id");
-
- if (id) {
- ZVAL_ZVAL(*return_value, id, 1, 0);
- }
-
-cleanup:
- zval_ptr_dtor(&state.zchild);
-} /* }}} */
-
-/* Returns whether any top-level field names in the document contain a "$". */
-static inline bool php_phongo_bulkwrite_update_has_operators(bson_t* bupdate) /* {{{ */
-{
- bson_iter_t iter;
-
- if (bson_iter_init(&iter, bupdate)) {
- while (bson_iter_next(&iter)) {
- if (strchr(bson_iter_key(&iter), '$')) {
- return true;
- }
- }
- }
-
- return false;
-} /* }}} */
-
-/* Returns whether the update document is considered an aggregation pipeline */
-static inline bool php_phongo_bulkwrite_update_is_pipeline(bson_t* bupdate) /* {{{ */
-{
- bson_iter_t iter;
- bson_iter_t child;
- const char* key;
- int i = 0;
- char* i_str;
-
- if (!bson_iter_init(&iter, bupdate)) {
- return false;
- }
-
- while (bson_iter_next(&iter)) {
- key = bson_iter_key(&iter);
- i_str = bson_strdup_printf("%d", i++);
-
- if (strcmp(key, i_str)) {
- bson_free(i_str);
- return false;
- }
-
- bson_free(i_str);
-
- if (BSON_ITER_HOLDS_DOCUMENT(&iter)) {
- if (!bson_iter_recurse(&iter, &child)) {
- return false;
- }
- if (!bson_iter_next(&child)) {
- return false;
- }
- key = bson_iter_key(&child);
- if (key[0] != '$') {
- return false;
- }
- } else {
- return false;
- }
- }
-
- /* should return false when the document is empty */
- return i != 0;
-} /* }}} */
-
-/* Returns whether the BSON array's keys are a sequence of integer strings
- * starting with "0". BSON_APPEND_ARRAY considers it the caller's responsibility
- * to ensure that the array's keys are properly formatted. */
-static inline bool php_phongo_bulkwrite_bson_array_has_valid_keys(bson_t* array) /* {{{ */
-{
- bson_iter_t iter;
-
- if (bson_empty(array)) {
- return true;
- }
-
- if (bson_iter_init(&iter, array)) {
- char key[12];
- int count = 0;
-
- while (bson_iter_next(&iter)) {
- bson_snprintf(key, sizeof(key), "%d", count);
-
- if (0 != strcmp(key, bson_iter_key(&iter))) {
- return false;
- }
-
- count++;
- }
- }
-
- return true;
-} /* }}} */
-
-/* Appends an array field for the given opts document and key. Returns true on
- * success; otherwise, false is returned and an exception is thrown. */
-static bool php_phongo_bulkwrite_opts_append_array(bson_t* opts, const char* key, zval* zarr) /* {{{ */
-{
- zval* value = php_array_fetch(zarr, key);
- bson_t b = BSON_INITIALIZER;
-
- if (Z_TYPE_P(value) != IS_OBJECT && Z_TYPE_P(value) != IS_ARRAY) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"%s\" option to be array or object, %s given", key, zend_get_type_by_const(Z_TYPE_P(value)));
- return false;
- }
-
- php_phongo_zval_to_bson(value, PHONGO_BSON_NONE, &b, NULL);
-
- if (EG(exception)) {
- bson_destroy(&b);
- return false;
- }
-
- if (!php_phongo_bulkwrite_bson_array_has_valid_keys(&b)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "\"%s\" option has invalid keys for a BSON array", key);
- bson_destroy(&b);
- return false;
- }
-
- if (!BSON_APPEND_ARRAY(opts, key, &b)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Error appending \"%s\" option", key);
- bson_destroy(&b);
- return false;
- }
-
- bson_destroy(&b);
- return true;
-} /* }}} */
-
-/* Appends a document field for the given opts document and key. Returns true on
- * success; otherwise, false is returned and an exception is thrown. */
-static bool php_phongo_bulkwrite_opts_append_document(bson_t* opts, const char* key, zval* zarr) /* {{{ */
-{
- zval* value = php_array_fetch(zarr, key);
- bson_t b = BSON_INITIALIZER;
-
- if (Z_TYPE_P(value) != IS_OBJECT && Z_TYPE_P(value) != IS_ARRAY) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"%s\" option to be array or object, %s given", key, zend_get_type_by_const(Z_TYPE_P(value)));
- return false;
- }
-
- php_phongo_zval_to_bson(value, PHONGO_BSON_NONE, &b, NULL);
-
- if (EG(exception)) {
- bson_destroy(&b);
- return false;
- }
-
- if (!BSON_APPEND_DOCUMENT(opts, key, &b)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Error appending \"%s\" option", key);
- bson_destroy(&b);
- return false;
- }
-
- bson_destroy(&b);
- return true;
-} /* }}} */
-
-#define PHONGO_BULKWRITE_APPEND_BOOL(opt, value) \
- if (!BSON_APPEND_BOOL(boptions, (opt), (value))) { \
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Error appending \"%s\" option", (opt)); \
- return false; \
- }
-
-#define PHONGO_BULKWRITE_APPEND_INT32(opt, value) \
- if (!BSON_APPEND_INT32(boptions, (opt), (value))) { \
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Error appending \"%s\" option", (opt)); \
- return false; \
- }
-
-#define PHONGO_BULKWRITE_OPT_ARRAY(opt) \
- if (zoptions && php_array_existsc(zoptions, (opt))) { \
- if (!php_phongo_bulkwrite_opts_append_array(boptions, (opt), zoptions)) { \
- return false; \
- } \
- }
-
-#define PHONGO_BULKWRITE_OPT_DOCUMENT(opt) \
- if (zoptions && php_array_existsc(zoptions, (opt))) { \
- if (!php_phongo_bulkwrite_opts_append_document(boptions, (opt), zoptions)) { \
- return false; \
- } \
- }
-
-/* Initialize the "hint" option. Returns true on success; otherwise, false is
- * returned and an exception is thrown.
- *
- * The "hint" option must be a string or document. Check for both types and
- * merge into BSON options accordingly. */
-static bool php_phongo_bulkwrite_opt_hint(bson_t* boptions, zval* zoptions) /* {{{ */
-{
- /* The "hint" option (or "$hint" modifier) must be a string or document.
- * Check for both types and merge into BSON options accordingly. */
- if (zoptions && php_array_existsc(zoptions, "hint")) {
- zend_uchar type = Z_TYPE_P(php_array_fetchc(zoptions, "hint"));
-
- if (type == IS_STRING) {
- zval* value = php_array_fetchc(zoptions, "hint");
-
- if (!bson_append_utf8(boptions, "hint", 4, Z_STRVAL_P(value), Z_STRLEN_P(value))) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Error appending \"hint\" option");
- return false;
- }
- } else if (type == IS_OBJECT || type == IS_ARRAY) {
- PHONGO_BULKWRITE_OPT_DOCUMENT("hint");
- } else {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"hint\" option to be string, array, or object, %s given", zend_get_type_by_const(type));
- return false;
- }
- }
-
- return true;
-} /* }}} */
-
-/* Applies options (including defaults) for an update operation. */
-static bool php_phongo_bulkwrite_update_apply_options(bson_t* boptions, zval* zoptions) /* {{{ */
-{
- bool multi = false, upsert = false;
-
- if (zoptions) {
- multi = php_array_fetchc_bool(zoptions, "multi");
- upsert = php_array_fetchc_bool(zoptions, "upsert");
- }
-
- PHONGO_BULKWRITE_APPEND_BOOL("multi", multi);
- PHONGO_BULKWRITE_APPEND_BOOL("upsert", upsert);
- PHONGO_BULKWRITE_OPT_ARRAY("arrayFilters");
- PHONGO_BULKWRITE_OPT_DOCUMENT("collation");
-
- if (!php_phongo_bulkwrite_opt_hint(boptions, zoptions)) {
- return false;
- }
-
- return true;
-} /* }}} */
-
-/* Applies options (including defaults) for an delete operation. */
-static bool php_phongo_bulkwrite_delete_apply_options(bson_t* boptions, zval* zoptions) /* {{{ */
-{
- int32_t limit = 0;
-
- if (zoptions) {
- limit = php_array_fetchc_bool(zoptions, "limit") ? 1 : 0;
- }
-
- PHONGO_BULKWRITE_APPEND_INT32("limit", limit);
- PHONGO_BULKWRITE_OPT_DOCUMENT("collation");
-
- if (!php_phongo_bulkwrite_opt_hint(boptions, zoptions)) {
- return false;
- }
-
- return true;
-} /* }}} */
-
-#undef PHONGO_BULKWRITE_APPEND_BOOL
-#undef PHONGO_BULKWRITE_APPEND_INT32
-#undef PHONGO_BULKWRITE_OPT_DOCUMENT
-
-/* {{{ proto void MongoDB\Driver\BulkWrite::__construct([array $options = array()])
- Constructs a new BulkWrite */
-static PHP_METHOD(BulkWrite, __construct)
-{
- zend_error_handling error_handling;
- php_phongo_bulkwrite_t* intern;
- zval* options = NULL;
- zend_bool ordered = 1;
-
- intern = Z_BULKWRITE_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "|a!", &options) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- if (options && php_array_existsc(options, "ordered")) {
- ordered = php_array_fetchc_bool(options, "ordered");
- }
-
- intern->bulk = mongoc_bulk_operation_new(ordered);
- intern->ordered = ordered;
- intern->bypass = PHONGO_BULKWRITE_BYPASS_UNSET;
- intern->num_ops = 0;
- intern->executed = false;
-
- if (options && php_array_existsc(options, "bypassDocumentValidation")) {
- zend_bool bypass = php_array_fetchc_bool(options, "bypassDocumentValidation");
- mongoc_bulk_operation_set_bypass_document_validation(intern->bulk, bypass);
- intern->bypass = bypass;
- }
-} /* }}} */
-
-/* {{{ proto mixed MongoDB\Driver\BulkWrite::insert(array|object $document)
- Adds an insert operation to the BulkWrite */
-static PHP_METHOD(BulkWrite, insert)
-{
- zend_error_handling error_handling;
- php_phongo_bulkwrite_t* intern;
- zval* zdocument;
- bson_t bdocument = BSON_INITIALIZER, boptions = BSON_INITIALIZER;
- bson_t* bson_out = NULL;
- int bson_flags = PHONGO_BSON_ADD_ID;
- bson_error_t error = { 0 };
-
- intern = Z_BULKWRITE_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "A", &zdocument) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- bson_flags |= PHONGO_BSON_RETURN_ID;
-
- php_phongo_zval_to_bson(zdocument, bson_flags, &bdocument, &bson_out);
-
- if (EG(exception)) {
- goto cleanup;
- }
-
- if (!mongoc_bulk_operation_insert_with_opts(intern->bulk, &bdocument, &boptions, &error)) {
- phongo_throw_exception_from_bson_error_t(&error);
- goto cleanup;
- }
-
- intern->num_ops++;
-
- if (!bson_out) {
- phongo_throw_exception(PHONGO_ERROR_LOGIC, "Did not receive result from bulk write. Please file a bug report.");
- goto cleanup;
- }
-
- php_phongo_bulkwrite_extract_id(bson_out, &return_value);
-
-cleanup:
- bson_destroy(&bdocument);
- bson_destroy(&boptions);
- bson_clear(&bson_out);
-} /* }}} */
-
-/* {{{ proto void MongoDB\Driver\BulkWrite::update(array|object $query, array|object $newObj[, array $updateOptions = array()])
- Adds an update operation to the BulkWrite */
-static PHP_METHOD(BulkWrite, update)
-{
- zend_error_handling error_handling;
- php_phongo_bulkwrite_t* intern;
- zval * zquery, *zupdate, *zoptions = NULL;
- bson_t bquery = BSON_INITIALIZER, bupdate = BSON_INITIALIZER, boptions = BSON_INITIALIZER;
- bson_error_t error = { 0 };
-
- intern = Z_BULKWRITE_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "AA|a!", &zquery, &zupdate, &zoptions) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- php_phongo_zval_to_bson(zquery, PHONGO_BSON_NONE, &bquery, NULL);
-
- if (EG(exception)) {
- goto cleanup;
- }
-
- php_phongo_zval_to_bson(zupdate, PHONGO_BSON_NONE, &bupdate, NULL);
-
- if (EG(exception)) {
- goto cleanup;
- }
-
- if (!php_phongo_bulkwrite_update_apply_options(&boptions, zoptions)) {
- goto cleanup;
- }
-
- if (php_phongo_bulkwrite_update_has_operators(&bupdate) || php_phongo_bulkwrite_update_is_pipeline(&bupdate)) {
- if (zoptions && php_array_fetchc_bool(zoptions, "multi")) {
- if (!mongoc_bulk_operation_update_many_with_opts(intern->bulk, &bquery, &bupdate, &boptions, &error)) {
- phongo_throw_exception_from_bson_error_t(&error);
- goto cleanup;
- }
- } else {
- if (!mongoc_bulk_operation_update_one_with_opts(intern->bulk, &bquery, &bupdate, &boptions, &error)) {
- phongo_throw_exception_from_bson_error_t(&error);
- goto cleanup;
- }
- }
- } else {
- if (zoptions && php_array_fetchc_bool(zoptions, "multi")) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Replacement document conflicts with true \"multi\" option");
- goto cleanup;
- }
-
- if (!mongoc_bulk_operation_replace_one_with_opts(intern->bulk, &bquery, &bupdate, &boptions, &error)) {
- phongo_throw_exception_from_bson_error_t(&error);
- goto cleanup;
- }
- }
-
- intern->num_ops++;
-
-cleanup:
- bson_destroy(&bquery);
- bson_destroy(&bupdate);
- bson_destroy(&boptions);
-} /* }}} */
-
-/* {{{ proto void MongoDB\Driver\BulkWrite::delete(array|object $query[, array $deleteOptions = array()])
- Adds a delete operation to the BulkWrite */
-static PHP_METHOD(BulkWrite, delete)
-{
- zend_error_handling error_handling;
- php_phongo_bulkwrite_t* intern;
- zval * zquery, *zoptions = NULL;
- bson_t bquery = BSON_INITIALIZER, boptions = BSON_INITIALIZER;
- bson_error_t error = { 0 };
-
- intern = Z_BULKWRITE_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "A|a!", &zquery, &zoptions) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- php_phongo_zval_to_bson(zquery, PHONGO_BSON_NONE, &bquery, NULL);
-
- if (EG(exception)) {
- goto cleanup;
- }
-
- if (!php_phongo_bulkwrite_delete_apply_options(&boptions, zoptions)) {
- goto cleanup;
- }
-
- if (zoptions && php_array_fetchc_bool(zoptions, "limit")) {
- if (!mongoc_bulk_operation_remove_one_with_opts(intern->bulk, &bquery, &boptions, &error)) {
- phongo_throw_exception_from_bson_error_t(&error);
- goto cleanup;
- }
- } else {
- if (!mongoc_bulk_operation_remove_many_with_opts(intern->bulk, &bquery, &boptions, &error)) {
- phongo_throw_exception_from_bson_error_t(&error);
- goto cleanup;
- }
- }
-
- intern->num_ops++;
-
-cleanup:
- bson_destroy(&bquery);
- bson_destroy(&boptions);
-} /* }}} */
-
-/* {{{ proto integer MongoDB\Driver\BulkWrite::count()
- Returns the number of operations that have been added to the BulkWrite */
-static PHP_METHOD(BulkWrite, count)
-{
- zend_error_handling error_handling;
- php_phongo_bulkwrite_t* intern;
-
- intern = Z_BULKWRITE_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- RETURN_LONG(intern->num_ops);
-} /* }}} */
-
-/* {{{ MongoDB\Driver\BulkWrite function entries */
-/* clang-format off */
-ZEND_BEGIN_ARG_INFO_EX(ai_BulkWrite___construct, 0, 0, 0)
- ZEND_ARG_ARRAY_INFO(0, options, 1)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(ai_BulkWrite_count, 0, 0, IS_LONG, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_BulkWrite_insert, 0, 0, 1)
- ZEND_ARG_INFO(0, document)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_BulkWrite_update, 0, 0, 2)
- ZEND_ARG_INFO(0, query)
- ZEND_ARG_INFO(0, newObj)
- ZEND_ARG_ARRAY_INFO(0, updateOptions, 1)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_BulkWrite_delete, 0, 0, 1)
- ZEND_ARG_INFO(0, query)
- ZEND_ARG_ARRAY_INFO(0, deleteOptions, 1)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_BulkWrite_void, 0, 0, 0)
-ZEND_END_ARG_INFO()
-
-static zend_function_entry php_phongo_bulkwrite_me[] = {
- PHP_ME(BulkWrite, __construct, ai_BulkWrite___construct, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(BulkWrite, insert, ai_BulkWrite_insert, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(BulkWrite, update, ai_BulkWrite_update, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(BulkWrite, delete, ai_BulkWrite_delete, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(BulkWrite, count, ai_BulkWrite_count, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- ZEND_NAMED_ME(__wakeup, PHP_FN(MongoDB_disabled___wakeup), ai_BulkWrite_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_FE_END
-};
-/* clang-format on */
-/* }}} */
-
-/* {{{ MongoDB\Driver\BulkWrite object handlers */
-static zend_object_handlers php_phongo_handler_bulkwrite;
-
-static void php_phongo_bulkwrite_free_object(zend_object* object) /* {{{ */
-{
- php_phongo_bulkwrite_t* intern = Z_OBJ_BULKWRITE(object);
-
- zend_object_std_dtor(&intern->std);
-
- if (intern->bulk) {
- mongoc_bulk_operation_destroy(intern->bulk);
- }
-
- if (intern->database) {
- efree(intern->database);
- }
-
- if (intern->collection) {
- efree(intern->collection);
- }
-
- if (!Z_ISUNDEF(intern->session)) {
- zval_ptr_dtor(&intern->session);
- }
-} /* }}} */
-
-static zend_object* php_phongo_bulkwrite_create_object(zend_class_entry* class_type) /* {{{ */
-{
- php_phongo_bulkwrite_t* intern = NULL;
-
- intern = PHONGO_ALLOC_OBJECT_T(php_phongo_bulkwrite_t, class_type);
-
- zend_object_std_init(&intern->std, class_type);
- object_properties_init(&intern->std, class_type);
-
- intern->std.handlers = &php_phongo_handler_bulkwrite;
-
- return &intern->std;
-} /* }}} */
-
-static HashTable* php_phongo_bulkwrite_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
-{
- zval retval = ZVAL_STATIC_INIT;
- php_phongo_bulkwrite_t* intern = NULL;
-
- *is_temp = 1;
- intern = Z_OBJ_BULKWRITE(PHONGO_COMPAT_GET_OBJ(object));
- array_init(&retval);
-
- if (intern->database) {
- ADD_ASSOC_STRING(&retval, "database", intern->database);
- } else {
- ADD_ASSOC_NULL_EX(&retval, "database");
- }
-
- if (intern->collection) {
- ADD_ASSOC_STRING(&retval, "collection", intern->collection);
- } else {
- ADD_ASSOC_NULL_EX(&retval, "collection");
- }
-
- ADD_ASSOC_BOOL_EX(&retval, "ordered", intern->ordered);
-
- if (intern->bypass != PHONGO_BULKWRITE_BYPASS_UNSET) {
- ADD_ASSOC_BOOL_EX(&retval, "bypassDocumentValidation", intern->bypass);
- } else {
- ADD_ASSOC_NULL_EX(&retval, "bypassDocumentValidation");
- }
-
- ADD_ASSOC_BOOL_EX(&retval, "executed", intern->executed);
- ADD_ASSOC_LONG_EX(&retval, "server_id", mongoc_bulk_operation_get_hint(intern->bulk));
-
- if (!Z_ISUNDEF(intern->session)) {
- ADD_ASSOC_ZVAL_EX(&retval, "session", &intern->session);
- Z_ADDREF(intern->session);
- } else {
- ADD_ASSOC_NULL_EX(&retval, "session");
- }
-
- if (mongoc_bulk_operation_get_write_concern(intern->bulk)) {
- zval write_concern;
-
- php_phongo_write_concern_to_zval(&write_concern, mongoc_bulk_operation_get_write_concern(intern->bulk));
- ADD_ASSOC_ZVAL_EX(&retval, "write_concern", &write_concern);
- } else {
- ADD_ASSOC_NULL_EX(&retval, "write_concern");
- }
-
- return Z_ARRVAL(retval);
-} /* }}} */
-/* }}} */
-
-void php_phongo_bulkwrite_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver", "BulkWrite", php_phongo_bulkwrite_me);
- php_phongo_bulkwrite_ce = zend_register_internal_class(&ce);
- php_phongo_bulkwrite_ce->create_object = php_phongo_bulkwrite_create_object;
- PHONGO_CE_FINAL(php_phongo_bulkwrite_ce);
- PHONGO_CE_DISABLE_SERIALIZATION(php_phongo_bulkwrite_ce);
-
- memcpy(&php_phongo_handler_bulkwrite, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
- php_phongo_handler_bulkwrite.get_debug_info = php_phongo_bulkwrite_get_debug_info;
- php_phongo_handler_bulkwrite.free_obj = php_phongo_bulkwrite_free_object;
- php_phongo_handler_bulkwrite.offset = XtOffsetOf(php_phongo_bulkwrite_t, std);
-
- zend_class_implements(php_phongo_bulkwrite_ce, 1, zend_ce_countable);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/MongoDB/ClientEncryption.c b/mongodb-1.12.0/src/MongoDB/ClientEncryption.c
deleted file mode 100644
index 8b3953ba..00000000
--- a/mongodb-1.12.0/src/MongoDB/ClientEncryption.c
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * Copyright 2019-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-#include <Zend/zend_interfaces.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-
-zend_class_entry* php_phongo_clientencryption_ce;
-
-/* {{{ proto MongoDB\BSON\Binary MongoDB\Driver\ClientEncryption::createDataKey(string $kmsProvider[, array $options])
- Creates a new key document and inserts into the key vault collection. */
-static PHP_METHOD(ClientEncryption, createDataKey)
-{
- char* kms_provider = NULL;
- size_t kms_provider_len = 0;
- zval* options = NULL;
- zend_error_handling error_handling;
- php_phongo_clientencryption_t* intern;
-
- intern = Z_CLIENTENCRYPTION_OBJ_P(getThis());
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|a!", &kms_provider, &kms_provider_len, &options) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
-
- zend_restore_error_handling(&error_handling);
-
- phongo_clientencryption_create_datakey(intern, return_value, kms_provider, options);
-} /* }}} */
-
-/* {{{ proto MongoDB\BSON\Binary MongoDB\Driver\ClientEncryption::encrypt(mixed $value[, array $options])
- Encrypts a value with a given key and algorithm */
-static PHP_METHOD(ClientEncryption, encrypt)
-{
- zval* value = NULL;
- zval* options = NULL;
- zend_error_handling error_handling;
- php_phongo_clientencryption_t* intern;
-
- intern = Z_CLIENTENCRYPTION_OBJ_P(getThis());
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|a!", &value, &options) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
-
- zend_restore_error_handling(&error_handling);
-
- phongo_clientencryption_encrypt(intern, value, return_value, options);
-} /* }}} */
-
-/* {{{ proto mixed MongoDB\Driver\ClientEncryption::decrypt(MongoDB\BSON\BinaryInterface $value)
- Decrypts an encrypted value (BSON binary of subtype 6). Returns the original BSON value */
-static PHP_METHOD(ClientEncryption, decrypt)
-{
- zval* ciphertext;
- zend_error_handling error_handling;
- php_phongo_clientencryption_t* intern;
-
- intern = Z_CLIENTENCRYPTION_OBJ_P(getThis());
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &ciphertext, php_phongo_binary_interface_ce) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
-
- zend_restore_error_handling(&error_handling);
-
- phongo_clientencryption_decrypt(intern, ciphertext, return_value);
-} /* }}} */
-
-ZEND_BEGIN_ARG_INFO_EX(ai_ClientEncryption_createDataKey, 0, 0, 1)
- ZEND_ARG_INFO(0, kmsProvider)
- ZEND_ARG_ARRAY_INFO(0, options, 1)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_ClientEncryption_encrypt, 0, 0, 1)
- ZEND_ARG_INFO(0, value)
- ZEND_ARG_ARRAY_INFO(0, options, 1)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_ClientEncryption_decrypt, 0, 0, 1)
- ZEND_ARG_OBJ_INFO(0, keyVaultClient, MongoDB\\BSON\\BinaryInterface, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_ClientEncryption_void, 0, 0, 0)
-ZEND_END_ARG_INFO()
-
-static zend_function_entry php_phongo_clientencryption_me[] = {
- /* clang-format off */
- PHP_ME(ClientEncryption, createDataKey, ai_ClientEncryption_createDataKey, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(ClientEncryption, encrypt, ai_ClientEncryption_encrypt, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(ClientEncryption, decrypt, ai_ClientEncryption_decrypt, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- ZEND_NAMED_ME(__construct, PHP_FN(MongoDB_disabled___construct), ai_ClientEncryption_void, ZEND_ACC_PRIVATE | ZEND_ACC_FINAL)
- ZEND_NAMED_ME(__wakeup, PHP_FN(MongoDB_disabled___wakeup), ai_ClientEncryption_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_FE_END
- /* clang-format on */
-};
-/* }}} */
-
-/* {{{ MongoDB\Driver\ClientEncryption object handlers */
-static zend_object_handlers php_phongo_handler_clientencryption;
-
-static void php_phongo_clientencryption_free_object(zend_object* object) /* {{{ */
-{
- php_phongo_clientencryption_t* intern = Z_OBJ_CLIENTENCRYPTION(object);
-
- zend_object_std_dtor(&intern->std);
-
- if (intern->client_encryption) {
- mongoc_client_encryption_destroy(intern->client_encryption);
- }
-
- /* Free the keyVaultClient last to ensure that a potential non-persistent
- * client outlives the mongoc_client_encryption_t as needed */
- if (!Z_ISUNDEF(intern->key_vault_client_manager)) {
- zval_ptr_dtor(&intern->key_vault_client_manager);
- }
-} /* }}} */
-
-static zend_object* php_phongo_clientencryption_create_object(zend_class_entry* class_type) /* {{{ */
-{
- php_phongo_clientencryption_t* intern = NULL;
-
- intern = PHONGO_ALLOC_OBJECT_T(php_phongo_clientencryption_t, class_type);
-
- zend_object_std_init(&intern->std, class_type);
- object_properties_init(&intern->std, class_type);
-
- intern->std.handlers = &php_phongo_handler_clientencryption;
-
- return &intern->std;
-} /* }}} */
-
-static HashTable* php_phongo_clientencryption_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
-{
- php_phongo_clientencryption_t* intern = NULL;
- zval retval = ZVAL_STATIC_INIT;
-
- *is_temp = 1;
- intern = Z_OBJ_CLIENTENCRYPTION(PHONGO_COMPAT_GET_OBJ(object));
-
- array_init(&retval);
-
- return Z_ARRVAL(retval);
-} /* }}} */
-/* }}} */
-
-void php_phongo_clientencryption_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver", "ClientEncryption", php_phongo_clientencryption_me);
- php_phongo_clientencryption_ce = zend_register_internal_class(&ce);
- php_phongo_clientencryption_ce->create_object = php_phongo_clientencryption_create_object;
- PHONGO_CE_FINAL(php_phongo_clientencryption_ce);
- PHONGO_CE_DISABLE_SERIALIZATION(php_phongo_clientencryption_ce);
-
- memcpy(&php_phongo_handler_clientencryption, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
- php_phongo_handler_clientencryption.get_debug_info = php_phongo_clientencryption_get_debug_info;
- php_phongo_handler_clientencryption.free_obj = php_phongo_clientencryption_free_object;
- php_phongo_handler_clientencryption.offset = XtOffsetOf(php_phongo_clientencryption_t, std);
-
- zend_declare_class_constant_string(php_phongo_clientencryption_ce, ZEND_STRL("AEAD_AES_256_CBC_HMAC_SHA_512_DETERMINISTIC"), MONGOC_AEAD_AES_256_CBC_HMAC_SHA_512_DETERMINISTIC);
- zend_declare_class_constant_string(php_phongo_clientencryption_ce, ZEND_STRL("AEAD_AES_256_CBC_HMAC_SHA_512_RANDOM"), MONGOC_AEAD_AES_256_CBC_HMAC_SHA_512_RANDOM);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/MongoDB/Command.c b/mongodb-1.12.0/src/MongoDB/Command.c
deleted file mode 100644
index 1abdd687..00000000
--- a/mongodb-1.12.0/src/MongoDB/Command.c
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * Copyright 2014-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-#include <Zend/zend_interfaces.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "php_array_api.h"
-#include "phongo_compat.h"
-#include "php_phongo.h"
-#include "php_bson.h"
-
-zend_class_entry* php_phongo_command_ce;
-
-/* Initialize the "maxAwaitTimeMS" option. Returns true on success; otherwise,
- * false is returned and an exception is thrown.
- *
- * The "maxAwaitTimeMS" option is assigned to the cursor after query execution
- * via mongoc_cursor_set_max_await_time_ms(). */
-static bool php_phongo_command_init_max_await_time_ms(php_phongo_command_t* intern, zval* options) /* {{{ */
-{
- int64_t max_await_time_ms;
-
- if (!php_array_existsc(options, "maxAwaitTimeMS")) {
- return true;
- }
-
- max_await_time_ms = php_array_fetchc_long(options, "maxAwaitTimeMS");
-
- if (max_await_time_ms < 0) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"maxAwaitTimeMS\" option to be >= 0, %" PRId64 " given", max_await_time_ms);
- return false;
- }
-
- if (max_await_time_ms > UINT32_MAX) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"maxAwaitTimeMS\" option to be <= %" PRIu32 ", %" PRId64 " given", UINT32_MAX, max_await_time_ms);
- return false;
- }
-
- intern->max_await_time_ms = (uint32_t) max_await_time_ms;
-
- return true;
-} /* }}} */
-
-/* Initializes the php_phongo_command_init from options argument. This
- * function will fall back to a modifier in the absence of a top-level option
- * (where applicable). */
-static bool php_phongo_command_init(php_phongo_command_t* intern, zval* filter, zval* options) /* {{{ */
-{
- bson_iter_t iter;
- bson_iter_t sub_iter;
-
- intern->bson = bson_new();
- intern->batch_size = 0;
- intern->max_await_time_ms = 0;
-
- php_phongo_zval_to_bson(filter, PHONGO_BSON_NONE, intern->bson, NULL);
-
- /* Note: if any exceptions are thrown, we can simply return as PHP will
- * invoke php_phongo_query_free_object to destruct the object. */
- if (EG(exception)) {
- return false;
- }
-
- if (bson_iter_init(&iter, intern->bson) && bson_iter_find_descendant(&iter, "cursor.batchSize", &sub_iter) && BSON_ITER_HOLDS_INT(&sub_iter)) {
- int64_t batch_size = bson_iter_as_int64(&sub_iter);
-
- if (batch_size >= 0 && batch_size <= UINT32_MAX) {
- intern->batch_size = (uint32_t) batch_size;
- }
- }
-
- if (!options) {
- return true;
- }
-
- if (!php_phongo_command_init_max_await_time_ms(intern, options)) {
- return false;
- }
-
- return true;
-} /* }}} */
-
-/* {{{ proto void MongoDB\Driver\Command::__construct(array|object $document[, array $options = array()])
- Constructs a new Command */
-static PHP_METHOD(Command, __construct)
-{
- zend_error_handling error_handling;
- php_phongo_command_t* intern;
- zval* document;
- zval* options = NULL;
-
- intern = Z_COMMAND_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "A|a!", &document, &options) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- php_phongo_command_init(intern, document, options);
-} /* }}} */
-
-/* {{{ MongoDB\Driver\Command function entries */
-ZEND_BEGIN_ARG_INFO_EX(ai_Command___construct, 0, 0, 1)
- ZEND_ARG_INFO(0, document)
- ZEND_ARG_ARRAY_INFO(0, options, 1)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_Command_void, 0, 0, 0)
-ZEND_END_ARG_INFO()
-
-static zend_function_entry php_phongo_command_me[] = {
- /* clang-format off */
- PHP_ME(Command, __construct, ai_Command___construct, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- ZEND_NAMED_ME(__wakeup, PHP_FN(MongoDB_disabled___wakeup), ai_Command_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_FE_END
- /* clang-format on */
-};
-/* }}} */
-
-/* {{{ MongoDB\Driver\Command object handlers */
-static zend_object_handlers php_phongo_handler_command;
-
-static void php_phongo_command_free_object(zend_object* object) /* {{{ */
-{
- php_phongo_command_t* intern = Z_OBJ_COMMAND(object);
-
- zend_object_std_dtor(&intern->std);
-
- if (intern->bson) {
- bson_clear(&intern->bson);
- }
-} /* }}} */
-
-static zend_object* php_phongo_command_create_object(zend_class_entry* class_type) /* {{{ */
-{
- php_phongo_command_t* intern = NULL;
-
- intern = PHONGO_ALLOC_OBJECT_T(php_phongo_command_t, class_type);
-
- zend_object_std_init(&intern->std, class_type);
- object_properties_init(&intern->std, class_type);
-
- intern->std.handlers = &php_phongo_handler_command;
-
- return &intern->std;
-} /* }}} */
-
-static HashTable* php_phongo_command_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
-{
- php_phongo_command_t* intern;
- zval retval = ZVAL_STATIC_INIT;
-
- *is_temp = 1;
- intern = Z_OBJ_COMMAND(PHONGO_COMPAT_GET_OBJ(object));
-
- array_init_size(&retval, 1);
-
- if (intern->bson) {
- zval zv;
-
- if (!php_phongo_bson_to_zval(bson_get_data(intern->bson), intern->bson->len, &zv)) {
- zval_ptr_dtor(&zv);
- goto done;
- }
-
- ADD_ASSOC_ZVAL_EX(&retval, "command", &zv);
- } else {
- ADD_ASSOC_NULL_EX(&retval, "command");
- }
-
-done:
- return Z_ARRVAL(retval);
-
-} /* }}} */
-/* }}} */
-
-void php_phongo_command_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver", "Command", php_phongo_command_me);
- php_phongo_command_ce = zend_register_internal_class(&ce);
- php_phongo_command_ce->create_object = php_phongo_command_create_object;
- PHONGO_CE_FINAL(php_phongo_command_ce);
- PHONGO_CE_DISABLE_SERIALIZATION(php_phongo_command_ce);
-
- memcpy(&php_phongo_handler_command, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
- php_phongo_handler_command.get_debug_info = php_phongo_command_get_debug_info;
- php_phongo_handler_command.free_obj = php_phongo_command_free_object;
- php_phongo_handler_command.offset = XtOffsetOf(php_phongo_command_t, std);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/MongoDB/Cursor.c b/mongodb-1.12.0/src/MongoDB/Cursor.c
deleted file mode 100644
index 1afb3347..00000000
--- a/mongodb-1.12.0/src/MongoDB/Cursor.c
+++ /dev/null
@@ -1,563 +0,0 @@
-/*
- * Copyright 2014-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-#include <Zend/zend_interfaces.h>
-#include <ext/spl/spl_iterators.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-#include "php_bson.h"
-
-zend_class_entry* php_phongo_cursor_ce;
-
-/* Check if the cursor is exhausted (i.e. ID is zero) and free any reference to
- * the session. Calling this function during iteration will allow an implicit
- * session to return to the pool immediately after a getMore indicates that the
- * server has no more results to return. */
-static void php_phongo_cursor_free_session_if_exhausted(php_phongo_cursor_t* cursor) /* {{{ */
-{
- if (mongoc_cursor_get_id(cursor->cursor)) {
- return;
- }
-
- if (!Z_ISUNDEF(cursor->session)) {
- zval_ptr_dtor(&cursor->session);
- ZVAL_UNDEF(&cursor->session);
- }
-} /* }}} */
-
-static void php_phongo_cursor_free_current(php_phongo_cursor_t* cursor) /* {{{ */
-{
- if (!Z_ISUNDEF(cursor->visitor_data.zchild)) {
- zval_ptr_dtor(&cursor->visitor_data.zchild);
- ZVAL_UNDEF(&cursor->visitor_data.zchild);
- }
-} /* }}} */
-
-/* {{{ proto void MongoDB\Driver\Cursor::setTypeMap(array $typemap)
- Sets a type map to use for BSON unserialization */
-static PHP_METHOD(Cursor, setTypeMap)
-{
- zend_error_handling error_handling;
- php_phongo_cursor_t* intern;
- php_phongo_bson_state state;
- zval* typemap = NULL;
- bool restore_current_element = false;
-
- PHONGO_BSON_INIT_STATE(state);
-
- intern = Z_CURSOR_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "a!", &typemap) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- if (!php_phongo_bson_typemap_to_state(typemap, &state.map)) {
- return;
- }
-
- /* Check if the existing element needs to be freed before we overwrite
- * visitor_data, which contains the only reference to it. */
- if (!Z_ISUNDEF(intern->visitor_data.zchild)) {
- php_phongo_cursor_free_current(intern);
- restore_current_element = true;
- }
-
- php_phongo_bson_typemap_dtor(&intern->visitor_data.map);
-
- intern->visitor_data = state;
-
- /* If the cursor has a current element, we just freed it and should restore
- * it with a new type map applied. */
- if (restore_current_element && mongoc_cursor_current(intern->cursor)) {
- const bson_t* doc = mongoc_cursor_current(intern->cursor);
-
- if (!php_phongo_bson_to_zval_ex(bson_get_data(doc), doc->len, &intern->visitor_data)) {
- php_phongo_cursor_free_current(intern);
- }
- }
-} /* }}} */
-
-static int php_phongo_cursor_to_array_apply(zend_object_iterator* iter, void* puser) /* {{{ */
-{
- zval* data;
- zval* return_value = (zval*) puser;
-
- data = iter->funcs->get_current_data(iter);
-
- if (EG(exception)) {
- return ZEND_HASH_APPLY_STOP;
- }
- if (Z_ISUNDEF_P(data)) {
- return ZEND_HASH_APPLY_STOP;
- }
- Z_TRY_ADDREF_P(data);
- add_next_index_zval(return_value, data);
-
- return ZEND_HASH_APPLY_KEEP;
-} /* }}} */
-
-static void php_phongo_cursor_id_new_from_id(zval* object, int64_t cursorid) /* {{{ */
-{
- php_phongo_cursorid_t* intern;
-
- object_init_ex(object, php_phongo_cursorid_ce);
-
- intern = Z_CURSORID_OBJ_P(object);
- intern->id = cursorid;
- intern->initialized = true;
-} /* }}} */
-
-/* {{{ proto array MongoDB\Driver\Cursor::toArray()
- Returns an array of all result documents for this cursor */
-static PHP_METHOD(Cursor, toArray)
-{
- zend_error_handling error_handling;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- array_init(return_value);
-
- if (spl_iterator_apply(getThis(), php_phongo_cursor_to_array_apply, (void*) return_value) != SUCCESS) {
- zval_dtor(return_value);
- RETURN_NULL();
- }
-} /* }}} */
-
-/* {{{ proto MongoDB\Driver\CursorId MongoDB\Driver\Cursor::getId()
- Returns the CursorId for this cursor */
-static PHP_METHOD(Cursor, getId)
-{
- zend_error_handling error_handling;
- php_phongo_cursor_t* intern;
-
- intern = Z_CURSOR_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- php_phongo_cursor_id_new_from_id(return_value, mongoc_cursor_get_id(intern->cursor));
-} /* }}} */
-
-/* {{{ proto MongoDB\Driver\Server MongoDB\Driver\Cursor::getServer()
- Returns the Server object to which this cursor is attached */
-static PHP_METHOD(Cursor, getServer)
-{
- zend_error_handling error_handling;
- php_phongo_cursor_t* intern;
-
- intern = Z_CURSOR_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- phongo_server_init(return_value, &intern->manager, intern->server_id);
-} /* }}} */
-
-/* {{{ proto boolean MongoDB\Driver\Cursor::isDead()
- Checks if a cursor is still alive */
-static PHP_METHOD(Cursor, isDead)
-{
- zend_error_handling error_handling;
- php_phongo_cursor_t* intern;
-
- intern = Z_CURSOR_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- RETURN_BOOL(!mongoc_cursor_more(intern->cursor));
-} /* }}} */
-
-PHP_METHOD(Cursor, current)
-{
- zend_error_handling error_handling;
- php_phongo_cursor_t* intern = Z_CURSOR_OBJ_P(getThis());
- zval* data;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- data = &intern->visitor_data.zchild;
-
- if (Z_ISUNDEF_P(data)) {
- RETURN_NULL();
- } else {
- ZVAL_COPY_DEREF(return_value, data);
- }
-}
-
-PHP_METHOD(Cursor, key)
-{
- zend_error_handling error_handling;
- php_phongo_cursor_t* intern = Z_CURSOR_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- if (Z_ISUNDEF(intern->visitor_data.zchild)) {
- RETURN_NULL();
- }
-
- RETURN_LONG(intern->current);
-}
-
-PHP_METHOD(Cursor, next)
-{
- zend_error_handling error_handling;
- php_phongo_cursor_t* intern = Z_CURSOR_OBJ_P(getThis());
- const bson_t* doc;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- php_phongo_cursor_free_current(intern);
-
- /* If the intern has already advanced, increment its position. Otherwise,
- * the first call to mongoc_cursor_next() will be made below and we should
- * leave its position at zero. */
- if (intern->advanced) {
- intern->current++;
- } else {
- intern->advanced = true;
- }
-
- if (mongoc_cursor_next(intern->cursor, &doc)) {
- if (!php_phongo_bson_to_zval_ex(bson_get_data(doc), doc->len, &intern->visitor_data)) {
- /* Free invalid result, but don't return as we want to free the
- * session if the intern is exhausted. */
- php_phongo_cursor_free_current(intern);
- }
- } else {
- bson_error_t error = { 0 };
- const bson_t* doc = NULL;
-
- if (mongoc_cursor_error_document(intern->cursor, &error, &doc)) {
- /* Intentionally not destroying the intern as it will happen
- * naturally now that there are no more results */
- phongo_throw_exception_from_bson_error_t_and_reply(&error, doc);
- }
- }
-
- php_phongo_cursor_free_session_if_exhausted(intern);
-}
-
-PHP_METHOD(Cursor, valid)
-{
- zend_error_handling error_handling;
- php_phongo_cursor_t* intern = Z_CURSOR_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- RETURN_BOOL(!Z_ISUNDEF(intern->visitor_data.zchild));
-}
-
-PHP_METHOD(Cursor, rewind)
-{
- zend_error_handling error_handling;
- php_phongo_cursor_t* intern = Z_CURSOR_OBJ_P(getThis());
- const bson_t* doc;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- /* If the intern was never advanced (e.g. command intern), do so now */
- if (!intern->advanced) {
- intern->advanced = true;
-
- if (!phongo_cursor_advance_and_check_for_error(intern->cursor)) {
- /* Exception should already have been thrown */
- return;
- }
- }
-
- if (intern->current > 0) {
- phongo_throw_exception(PHONGO_ERROR_LOGIC, "Cursors cannot rewind after starting iteration");
- return;
- }
-
- php_phongo_cursor_free_current(intern);
-
- doc = mongoc_cursor_current(intern->cursor);
-
- if (doc) {
- if (!php_phongo_bson_to_zval_ex(bson_get_data(doc), doc->len, &intern->visitor_data)) {
- /* Free invalid result, but don't return as we want to free the
- * session if the intern is exhausted. */
- php_phongo_cursor_free_current(intern);
- }
- }
-
- php_phongo_cursor_free_session_if_exhausted(intern);
-}
-
-/* {{{ MongoDB\Driver\Cursor function entries */
-/* clang-format off */
-ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(ai_Cursor_current, 0, 0, IS_MIXED, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(ai_Cursor_key, 0, 0, IS_MIXED, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(ai_Cursor_next, 0, 0, IS_VOID, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(ai_Cursor_valid, 0, 0, _IS_BOOL, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(ai_Cursor_rewind, 0, 0, IS_VOID, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_Cursor_setTypeMap, 0, 0, 1)
- ZEND_ARG_ARRAY_INFO(0, typemap, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_Cursor_void, 0, 0, 0)
-ZEND_END_ARG_INFO()
-
-static zend_function_entry php_phongo_cursor_me[] = {
- PHP_ME(Cursor, setTypeMap, ai_Cursor_setTypeMap, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Cursor, toArray, ai_Cursor_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Cursor, getId, ai_Cursor_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Cursor, getServer, ai_Cursor_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Cursor, isDead, ai_Cursor_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
-
- PHP_ME(Cursor, current, ai_Cursor_current, ZEND_ACC_PUBLIC)
- PHP_ME(Cursor, key, ai_Cursor_key, ZEND_ACC_PUBLIC)
- PHP_ME(Cursor, next, ai_Cursor_next, ZEND_ACC_PUBLIC)
- PHP_ME(Cursor, valid, ai_Cursor_valid, ZEND_ACC_PUBLIC)
- PHP_ME(Cursor, rewind, ai_Cursor_rewind, ZEND_ACC_PUBLIC)
-
- ZEND_NAMED_ME(__construct, PHP_FN(MongoDB_disabled___construct), ai_Cursor_void, ZEND_ACC_PRIVATE | ZEND_ACC_FINAL)
- ZEND_NAMED_ME(__wakeup, PHP_FN(MongoDB_disabled___wakeup), ai_Cursor_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_FE_END
-};
-/* clang-format on */
-/* }}} */
-
-/* {{{ MongoDB\Driver\Cursor object handlers */
-static zend_object_handlers php_phongo_handler_cursor;
-
-static void php_phongo_cursor_free_object(zend_object* object) /* {{{ */
-{
- php_phongo_cursor_t* intern = Z_OBJ_CURSOR(object);
-
- zend_object_std_dtor(&intern->std);
-
- /* If this Cursor was created in a different process, reset the client so
- * that mongoc_cursor_destroy does not issue a killCursors command for an
- * active cursor owned by a parent process. */
- PHONGO_RESET_CLIENT_IF_PID_DIFFERS(intern, Z_MANAGER_OBJ_P(&intern->manager));
-
- if (intern->cursor) {
- mongoc_cursor_destroy(intern->cursor);
- }
-
- if (intern->database) {
- efree(intern->database);
- }
-
- if (intern->collection) {
- efree(intern->collection);
- }
-
- if (!Z_ISUNDEF(intern->query)) {
- zval_ptr_dtor(&intern->query);
- }
-
- if (!Z_ISUNDEF(intern->command)) {
- zval_ptr_dtor(&intern->command);
- }
-
- if (!Z_ISUNDEF(intern->read_preference)) {
- zval_ptr_dtor(&intern->read_preference);
- }
-
- if (!Z_ISUNDEF(intern->session)) {
- zval_ptr_dtor(&intern->session);
- }
-
- if (!Z_ISUNDEF(intern->manager)) {
- zval_ptr_dtor(&intern->manager);
- }
-
- php_phongo_bson_typemap_dtor(&intern->visitor_data.map);
-
- php_phongo_cursor_free_current(intern);
-} /* }}} */
-
-static zend_object* php_phongo_cursor_create_object(zend_class_entry* class_type) /* {{{ */
-{
- php_phongo_cursor_t* intern = NULL;
-
- intern = PHONGO_ALLOC_OBJECT_T(php_phongo_cursor_t, class_type);
-
- zend_object_std_init(&intern->std, class_type);
- object_properties_init(&intern->std, class_type);
-
- PHONGO_SET_CREATED_BY_PID(intern);
-
- intern->std.handlers = &php_phongo_handler_cursor;
-
- return &intern->std;
-} /* }}} */
-
-static HashTable* php_phongo_cursor_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
-{
- php_phongo_cursor_t* intern;
- zval retval = ZVAL_STATIC_INIT;
-
- *is_temp = 1;
- intern = Z_OBJ_CURSOR(PHONGO_COMPAT_GET_OBJ(object));
-
- array_init_size(&retval, 10);
-
- if (intern->database) {
- ADD_ASSOC_STRING(&retval, "database", intern->database);
- } else {
- ADD_ASSOC_NULL_EX(&retval, "database");
- }
-
- if (intern->collection) {
- ADD_ASSOC_STRING(&retval, "collection", intern->collection);
- } else {
- ADD_ASSOC_NULL_EX(&retval, "collection");
- }
-
- if (!Z_ISUNDEF(intern->query)) {
- ADD_ASSOC_ZVAL_EX(&retval, "query", &intern->query);
- Z_ADDREF(intern->query);
- } else {
- ADD_ASSOC_NULL_EX(&retval, "query");
- }
-
- if (!Z_ISUNDEF(intern->command)) {
- ADD_ASSOC_ZVAL_EX(&retval, "command", &intern->command);
- Z_ADDREF(intern->command);
- } else {
- ADD_ASSOC_NULL_EX(&retval, "command");
- }
-
- if (!Z_ISUNDEF(intern->read_preference)) {
- ADD_ASSOC_ZVAL_EX(&retval, "readPreference", &intern->read_preference);
- Z_ADDREF(intern->read_preference);
- } else {
- ADD_ASSOC_NULL_EX(&retval, "readPreference");
- }
-
- if (!Z_ISUNDEF(intern->session)) {
- ADD_ASSOC_ZVAL_EX(&retval, "session", &intern->session);
- Z_ADDREF(intern->session);
- } else {
- ADD_ASSOC_NULL_EX(&retval, "session");
- }
-
- ADD_ASSOC_BOOL_EX(&retval, "isDead", !mongoc_cursor_more(intern->cursor));
-
- ADD_ASSOC_LONG_EX(&retval, "currentIndex", intern->current);
-
- if (!Z_ISUNDEF(intern->visitor_data.zchild)) {
- ADD_ASSOC_ZVAL_EX(&retval, "currentDocument", &intern->visitor_data.zchild);
- Z_ADDREF(intern->visitor_data.zchild);
- } else {
- ADD_ASSOC_NULL_EX(&retval, "currentDocument");
- }
-
- {
- zval server;
-
- phongo_server_init(&server, &intern->manager, intern->server_id);
- ADD_ASSOC_ZVAL_EX(&retval, "server", &server);
- }
-
- return Z_ARRVAL(retval);
-
-} /* }}} */
-/* }}} */
-
-void php_phongo_cursor_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver", "Cursor", php_phongo_cursor_me);
- php_phongo_cursor_ce = zend_register_internal_class(&ce);
- php_phongo_cursor_ce->create_object = php_phongo_cursor_create_object;
- PHONGO_CE_FINAL(php_phongo_cursor_ce);
- PHONGO_CE_DISABLE_SERIALIZATION(php_phongo_cursor_ce);
-
- zend_class_implements(php_phongo_cursor_ce, 1, zend_ce_iterator);
- zend_class_implements(php_phongo_cursor_ce, 1, php_phongo_cursor_interface_ce);
-
- memcpy(&php_phongo_handler_cursor, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
- php_phongo_handler_cursor.get_debug_info = php_phongo_cursor_get_debug_info;
- php_phongo_handler_cursor.free_obj = php_phongo_cursor_free_object;
- php_phongo_handler_cursor.offset = XtOffsetOf(php_phongo_cursor_t, std);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/MongoDB/CursorId.c b/mongodb-1.12.0/src/MongoDB/CursorId.c
deleted file mode 100644
index d1020a7a..00000000
--- a/mongodb-1.12.0/src/MongoDB/CursorId.c
+++ /dev/null
@@ -1,335 +0,0 @@
-/*
- * Copyright 2014-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-#include <Zend/zend_interfaces.h>
-#include <ext/standard/php_var.h>
-#include <zend_smart_str.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-
-zend_class_entry* php_phongo_cursorid_ce;
-
-/* Initialize the object from a numeric string and return whether it was
- * successful. An exception will be thrown on error. */
-static bool php_phongo_cursorid_init_from_string(php_phongo_cursorid_t* intern, const char* s_id, size_t s_id_len) /* {{{ */
-{
- int64_t id;
-
- if (!php_phongo_parse_int64(&id, s_id, s_id_len)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Error parsing \"%s\" as 64-bit id for %s initialization", s_id, ZSTR_VAL(php_phongo_cursorid_ce->name));
- return false;
- }
-
- intern->id = id;
- intern->initialized = true;
- return true;
-} /* }}} */
-
-/* Initialize the object from a HashTable and return whether it was successful.
- * An exception will be thrown on error. */
-static bool php_phongo_cursorid_init_from_hash(php_phongo_cursorid_t* intern, HashTable* props) /* {{{ */
-{
- zval* value;
-
- if ((value = zend_hash_str_find(props, "id", sizeof("id") - 1)) && Z_TYPE_P(value) == IS_STRING) {
- return php_phongo_cursorid_init_from_string(intern, Z_STRVAL_P(value), Z_STRLEN_P(value));
- }
-
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"id\" string field", ZSTR_VAL(php_phongo_cursorid_ce->name));
- return false;
-} /* }}} */
-
-static HashTable* php_phongo_cursorid_get_properties_hash(phongo_compat_object_handler_type* object, bool is_temp, bool is_serialize) /* {{{ */
-{
- php_phongo_cursorid_t* intern;
- HashTable* props;
-
- intern = Z_OBJ_CURSORID(PHONGO_COMPAT_GET_OBJ(object));
-
- PHONGO_GET_PROPERTY_HASH_INIT_PROPS(is_temp, intern, props, 1);
-
- if (!intern->initialized) {
- return props;
- }
-
- {
- zval value;
-
- if (is_serialize) {
- ZVAL_INT64_STRING(&value, intern->id);
- } else {
-#if SIZEOF_ZEND_LONG == 4
- if (intern->id > INT32_MAX || intern->id < INT32_MIN) {
- ZVAL_INT64_STRING(&value, intern->id);
- } else {
- ZVAL_LONG(&value, intern->id);
- }
-#else
- ZVAL_LONG(&value, intern->id);
-#endif
- }
- zend_hash_str_update(props, "id", sizeof("id") - 1, &value);
- }
-
- return props;
-} /* }}} */
-
-/* {{{ proto MongoDB\Driver\CursorId MongoDB\Driver\CursorId::__set_state(array $properties)
-*/
-static PHP_METHOD(CursorId, __set_state)
-{
- zend_error_handling error_handling;
- php_phongo_cursorid_t* intern;
- HashTable* props;
- zval* array;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &array) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- object_init_ex(return_value, php_phongo_cursorid_ce);
-
- intern = Z_CURSORID_OBJ_P(return_value);
- props = Z_ARRVAL_P(array);
-
- php_phongo_cursorid_init_from_hash(intern, props);
-} /* }}} */
-
-/* {{{ proto string MongoDB\Driver\CursorId::__toString()
- Returns the string representation of the CursorId */
-static PHP_METHOD(CursorId, __toString)
-{
- zend_error_handling error_handling;
- php_phongo_cursorid_t* intern;
- char* tmp;
- int tmp_len;
-
- intern = Z_CURSORID_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- tmp_len = spprintf(&tmp, 0, "%" PRId64, intern->id);
- RETVAL_STRINGL(tmp, tmp_len);
- efree(tmp);
-} /* }}} */
-
-/* {{{ proto string MongoDB\Driver\CursorId::serialize()
-*/
-static PHP_METHOD(CursorId, serialize)
-{
- zend_error_handling error_handling;
- php_phongo_cursorid_t* intern;
- zval retval;
- php_serialize_data_t var_hash;
- smart_str buf = { 0 };
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- intern = Z_CURSORID_OBJ_P(getThis());
-
- array_init_size(&retval, 1);
- ADD_ASSOC_INT64_AS_STRING(&retval, "id", intern->id);
-
- PHP_VAR_SERIALIZE_INIT(var_hash);
- php_var_serialize(&buf, &retval, &var_hash);
- smart_str_0(&buf);
- PHP_VAR_SERIALIZE_DESTROY(var_hash);
-
- PHONGO_RETVAL_SMART_STR(buf);
-
- smart_str_free(&buf);
- zval_ptr_dtor(&retval);
-} /* }}} */
-
-/* {{{ proto void MongoDB\Driver\CursorId::unserialize(string $serialized)
-*/
-static PHP_METHOD(CursorId, unserialize)
-{
- zend_error_handling error_handling;
- php_phongo_cursorid_t* intern;
- char* serialized;
- size_t serialized_len;
- zval props;
- php_unserialize_data_t var_hash;
-
- intern = Z_CURSORID_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &serialized, &serialized_len) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- PHP_VAR_UNSERIALIZE_INIT(var_hash);
- if (!php_var_unserialize(&props, (const unsigned char**) &serialized, (unsigned char*) serialized + serialized_len, &var_hash)) {
- zval_ptr_dtor(&props);
- phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "%s unserialization failed", ZSTR_VAL(php_phongo_cursorid_ce->name));
-
- PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
- return;
- }
- PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
-
- php_phongo_cursorid_init_from_hash(intern, HASH_OF(&props));
- zval_ptr_dtor(&props);
-} /* }}} */
-
-/* {{{ proto array MongoDB\Driver\CursorId::__serialize()
-*/
-static PHP_METHOD(CursorId, __serialize)
-{
- PHONGO_PARSE_PARAMETERS_NONE();
-
- RETURN_ARR(php_phongo_cursorid_get_properties_hash(PHONGO_COMPAT_OBJ_P(getThis()), true, true));
-} /* }}} */
-
-/* {{{ proto void MongoDB\Driver\CursorId::__unserialize(array $data)
-*/
-static PHP_METHOD(CursorId, __unserialize)
-{
- zval* data;
-
- PHONGO_PARSE_PARAMETERS_START(1, 1)
- Z_PARAM_ARRAY(data)
- PHONGO_PARSE_PARAMETERS_END();
-
- php_phongo_cursorid_init_from_hash(Z_CURSORID_OBJ_P(getThis()), Z_ARRVAL_P(data));
-} /* }}} */
-
-/* {{{ MongoDB\Driver\CursorId function entries */
-/* clang-format off */
-ZEND_BEGIN_ARG_INFO_EX(ai_CursorId___set_state, 0, 0, 1)
- ZEND_ARG_ARRAY_INFO(0, properties, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(ai_CursorId___toString, 0, 0, IS_STRING, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_CursorId___unserialize, 0, 0, 1)
- ZEND_ARG_ARRAY_INFO(0, data, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_CursorId_unserialize, 0, 0, 1)
- ZEND_ARG_INFO(0, serialized)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_CursorId_void, 0, 0, 0)
-ZEND_END_ARG_INFO()
-
-static zend_function_entry php_phongo_cursorid_me[] = {
- PHP_ME(CursorId, __serialize, ai_CursorId_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(CursorId, __set_state, ai_CursorId___set_state, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
- PHP_ME(CursorId, __toString, ai_CursorId___toString, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(CursorId, __unserialize, ai_CursorId___unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(CursorId, serialize, ai_CursorId_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(CursorId, unserialize, ai_CursorId_unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- ZEND_NAMED_ME(__construct, PHP_FN(MongoDB_disabled___construct), ai_CursorId_void, ZEND_ACC_PRIVATE | ZEND_ACC_FINAL)
- PHP_FE_END
-};
-/* clang-format on */
-/* }}} */
-
-/* {{{ MongoDB\Driver\CursorId object handlers */
-static zend_object_handlers php_phongo_handler_cursorid;
-
-static void php_phongo_cursorid_free_object(zend_object* object) /* {{{ */
-{
- php_phongo_cursorid_t* intern = Z_OBJ_CURSORID(object);
-
- zend_object_std_dtor(&intern->std);
-
- if (intern->properties) {
- zend_hash_destroy(intern->properties);
- FREE_HASHTABLE(intern->properties);
- }
-} /* }}} */
-
-static zend_object* php_phongo_cursorid_create_object(zend_class_entry* class_type) /* {{{ */
-{
- php_phongo_cursorid_t* intern = NULL;
-
- intern = PHONGO_ALLOC_OBJECT_T(php_phongo_cursorid_t, class_type);
-
- zend_object_std_init(&intern->std, class_type);
- object_properties_init(&intern->std, class_type);
-
- intern->std.handlers = &php_phongo_handler_cursorid;
-
- return &intern->std;
-} /* }}} */
-
-static HashTable* php_phongo_cursorid_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
-{
- *is_temp = 1;
- return php_phongo_cursorid_get_properties_hash(object, true, false);
-} /* }}} */
-/* }}} */
-
-static HashTable* php_phongo_cursorid_get_properties(phongo_compat_object_handler_type* object) /* {{{ */
-{
- return php_phongo_cursorid_get_properties_hash(object, false, false);
-} /* }}} */
-
-void php_phongo_cursorid_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver", "CursorId", php_phongo_cursorid_me);
- php_phongo_cursorid_ce = zend_register_internal_class(&ce);
- php_phongo_cursorid_ce->create_object = php_phongo_cursorid_create_object;
- PHONGO_CE_FINAL(php_phongo_cursorid_ce);
-
- zend_class_implements(php_phongo_cursorid_ce, 1, zend_ce_serializable);
-
-#if PHP_VERSION_ID >= 80000
- zend_class_implements(php_phongo_cursorid_ce, 1, zend_ce_stringable);
-#endif
-
- memcpy(&php_phongo_handler_cursorid, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
- php_phongo_handler_cursorid.get_debug_info = php_phongo_cursorid_get_debug_info;
- php_phongo_handler_cursorid.get_properties = php_phongo_cursorid_get_properties;
- php_phongo_handler_cursorid.free_obj = php_phongo_cursorid_free_object;
- php_phongo_handler_cursorid.offset = XtOffsetOf(php_phongo_cursorid_t, std);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/MongoDB/CursorInterface.c b/mongodb-1.12.0/src/MongoDB/CursorInterface.c
deleted file mode 100644
index 886245f2..00000000
--- a/mongodb-1.12.0/src/MongoDB/CursorInterface.c
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright 2018-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-#include <Zend/zend_interfaces.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-
-zend_class_entry* php_phongo_cursor_interface_ce;
-
-/* {{{ MongoDB\BSON\CursorInterface function entries */
-ZEND_BEGIN_ARG_INFO_EX(ai_CursorInterface_setTypeMap, 0, 0, 1)
- ZEND_ARG_ARRAY_INFO(0, typemap, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_CursorInterface_void, 0, 0, 0)
-ZEND_END_ARG_INFO()
-
-static zend_function_entry php_phongo_cursor_interface_me[] = {
- /* clang-format off */
- ZEND_ABSTRACT_ME(CursorInterface, getId, ai_CursorInterface_void)
- ZEND_ABSTRACT_ME(CursorInterface, getServer, ai_CursorInterface_void)
- ZEND_ABSTRACT_ME(CursorInterface, isDead, ai_CursorInterface_void)
- ZEND_ABSTRACT_ME(CursorInterface, setTypeMap, ai_CursorInterface_setTypeMap)
- ZEND_ABSTRACT_ME(CursorInterface, toArray, ai_CursorInterface_void)
- PHP_FE_END
- /* clang-format on */
-};
-/* }}} */
-
-void php_phongo_cursor_interface_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver", "CursorInterface", php_phongo_cursor_interface_me);
- php_phongo_cursor_interface_ce = zend_register_internal_interface(&ce);
-
- zend_class_implements(php_phongo_cursor_interface_ce, 1, zend_ce_traversable);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/MongoDB/Exception/AuthenticationException.c b/mongodb-1.12.0/src/MongoDB/Exception/AuthenticationException.c
deleted file mode 100644
index 35daa99b..00000000
--- a/mongodb-1.12.0/src/MongoDB/Exception/AuthenticationException.c
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2014-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-
-zend_class_entry* php_phongo_authenticationexception_ce;
-
-/* {{{ MongoDB\Driver\Exception\AuthenticationException function entries */
-static zend_function_entry php_phongo_authenticationexception_me[] = {
- PHP_FE_END
-};
-/* }}} */
-
-void php_phongo_authenticationexception_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver\\Exception", "AuthenticationException", php_phongo_authenticationexception_me);
- php_phongo_authenticationexception_ce = zend_register_internal_class_ex(&ce, php_phongo_connectionexception_ce);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/MongoDB/Exception/BulkWriteException.c b/mongodb-1.12.0/src/MongoDB/Exception/BulkWriteException.c
deleted file mode 100644
index 59a1efaf..00000000
--- a/mongodb-1.12.0/src/MongoDB/Exception/BulkWriteException.c
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2015-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-
-zend_class_entry* php_phongo_bulkwriteexception_ce;
-
-/* {{{ MongoDB\Driver\Exception\BulkWriteException function entries */
-static zend_function_entry php_phongo_bulkwriteexception_me[] = {
- PHP_FE_END
-};
-/* }}} */
-
-void php_phongo_bulkwriteexception_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver\\Exception", "BulkWriteException", php_phongo_bulkwriteexception_me);
- php_phongo_bulkwriteexception_ce = zend_register_internal_class_ex(&ce, php_phongo_writeexception_ce);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/MongoDB/Exception/CommandException.c b/mongodb-1.12.0/src/MongoDB/Exception/CommandException.c
deleted file mode 100644
index b04ce980..00000000
--- a/mongodb-1.12.0/src/MongoDB/Exception/CommandException.c
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright 2018-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-
-zend_class_entry* php_phongo_commandexception_ce;
-
-/* {{{ proto document MongoDB\Driver\Exception\CommandException::getResultDocument()
- Returns the result document from the failed command. */
-static PHP_METHOD(CommandException, getResultDocument)
-{
- zend_error_handling error_handling;
- zval* resultdocument;
- zval rv;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- resultdocument = zend_read_property(php_phongo_commandexception_ce, PHONGO_COMPAT_OBJ_P(getThis()), ZEND_STRL("resultDocument"), 0, &rv);
-
- RETURN_ZVAL(resultdocument, 1, 0);
-} /* }}} */
-
-/* {{{ MongoDB\Driver\Exception\CommandException function entries */
-ZEND_BEGIN_ARG_INFO_EX(ai_CommandException_void, 0, 0, 0)
-ZEND_END_ARG_INFO()
-
-static zend_function_entry php_phongo_commandexception_me[] = {
- /* clang-format off */
- PHP_ME(CommandException, getResultDocument, ai_CommandException_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_FE_END
- /* clang-format on */
-};
-/* }}} */
-
-void php_phongo_commandexception_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver\\Exception", "CommandException", php_phongo_commandexception_me);
- php_phongo_commandexception_ce = zend_register_internal_class_ex(&ce, php_phongo_serverexception_ce);
-
- zend_declare_property_null(php_phongo_commandexception_ce, ZEND_STRL("resultDocument"), ZEND_ACC_PROTECTED);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/MongoDB/Exception/ConnectionException.c b/mongodb-1.12.0/src/MongoDB/Exception/ConnectionException.c
deleted file mode 100644
index 61974a87..00000000
--- a/mongodb-1.12.0/src/MongoDB/Exception/ConnectionException.c
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2014-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-
-zend_class_entry* php_phongo_connectionexception_ce;
-
-/* {{{ MongoDB\Driver\Exception\ConnectionException function entries */
-static zend_function_entry php_phongo_connectionexception_me[] = {
- PHP_FE_END
-};
-/* }}} */
-
-void php_phongo_connectionexception_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver\\Exception", "ConnectionException", php_phongo_connectionexception_me);
- php_phongo_connectionexception_ce = zend_register_internal_class_ex(&ce, php_phongo_runtimeexception_ce);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/MongoDB/Exception/ConnectionTimeoutException.c b/mongodb-1.12.0/src/MongoDB/Exception/ConnectionTimeoutException.c
deleted file mode 100644
index 1d8a5354..00000000
--- a/mongodb-1.12.0/src/MongoDB/Exception/ConnectionTimeoutException.c
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 2015-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-
-zend_class_entry* php_phongo_connectiontimeoutexception_ce;
-
-/* {{{ MongoDB\Driver\Exception\ConnectionTimeoutException function entries */
-static zend_function_entry php_phongo_connectiontimeoutexception_me[] = {
- PHP_FE_END
-};
-/* }}} */
-
-void php_phongo_connectiontimeoutexception_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver\\Exception", "ConnectionTimeoutException", php_phongo_connectiontimeoutexception_me);
- php_phongo_connectiontimeoutexception_ce = zend_register_internal_class_ex(&ce, php_phongo_connectionexception_ce);
- PHONGO_CE_FINAL(php_phongo_connectiontimeoutexception_ce);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/MongoDB/Exception/EncryptionException.c b/mongodb-1.12.0/src/MongoDB/Exception/EncryptionException.c
deleted file mode 100644
index 35229937..00000000
--- a/mongodb-1.12.0/src/MongoDB/Exception/EncryptionException.c
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2014-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-
-zend_class_entry* php_phongo_encryptionexception_ce;
-
-/* {{{ MongoDB\Driver\Exception\EncryptionException function entries */
-static zend_function_entry php_phongo_encryptionexception_me[] = {
- PHP_FE_END
-};
-/* }}} */
-
-void php_phongo_encryptionexception_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver\\Exception", "EncryptionException", php_phongo_encryptionexception_me);
- php_phongo_encryptionexception_ce = zend_register_internal_class_ex(&ce, php_phongo_runtimeexception_ce);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/MongoDB/Exception/Exception.c b/mongodb-1.12.0/src/MongoDB/Exception/Exception.c
deleted file mode 100644
index f7be640a..00000000
--- a/mongodb-1.12.0/src/MongoDB/Exception/Exception.c
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2014-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-#include <zend_exceptions.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-
-zend_class_entry* php_phongo_exception_ce;
-
-/* {{{ MongoDB\Driver\Exception\Exception function entries */
-static zend_function_entry php_phongo_exception_me[] = {
- PHP_FE_END
-};
-/* }}} */
-
-void php_phongo_exception_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver\\Exception", "Exception", php_phongo_exception_me);
- php_phongo_exception_ce = zend_register_internal_interface(&ce);
- zend_class_implements(php_phongo_exception_ce, 1, zend_ce_throwable);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/MongoDB/Exception/ExecutionTimeoutException.c b/mongodb-1.12.0/src/MongoDB/Exception/ExecutionTimeoutException.c
deleted file mode 100644
index 23bafd04..00000000
--- a/mongodb-1.12.0/src/MongoDB/Exception/ExecutionTimeoutException.c
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 2015-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-
-zend_class_entry* php_phongo_executiontimeoutexception_ce;
-
-/* {{{ MongoDB\Driver\Exception\ExecutionTimeoutException function entries */
-static zend_function_entry php_phongo_executiontimeoutexception_me[] = {
- PHP_FE_END
-};
-/* }}} */
-
-void php_phongo_executiontimeoutexception_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver\\Exception", "ExecutionTimeoutException", php_phongo_executiontimeoutexception_me);
- php_phongo_executiontimeoutexception_ce = zend_register_internal_class_ex(&ce, php_phongo_serverexception_ce);
- PHONGO_CE_FINAL(php_phongo_executiontimeoutexception_ce);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/MongoDB/Exception/InvalidArgumentException.c b/mongodb-1.12.0/src/MongoDB/Exception/InvalidArgumentException.c
deleted file mode 100644
index cdc94f44..00000000
--- a/mongodb-1.12.0/src/MongoDB/Exception/InvalidArgumentException.c
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2015-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-#include <ext/spl/spl_exceptions.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-
-zend_class_entry* php_phongo_invalidargumentexception_ce;
-
-/* {{{ MongoDB\Driver\Exception\InvalidArgumentException function entries */
-static zend_function_entry php_phongo_invalidargumentexception_me[] = {
- PHP_FE_END
-};
-/* }}} */
-
-void php_phongo_invalidargumentexception_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver\\Exception", "InvalidArgumentException", php_phongo_invalidargumentexception_me);
- php_phongo_invalidargumentexception_ce = zend_register_internal_class_ex(&ce, spl_ce_InvalidArgumentException);
- zend_class_implements(php_phongo_invalidargumentexception_ce, 1, php_phongo_exception_ce);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/MongoDB/Exception/LogicException.c b/mongodb-1.12.0/src/MongoDB/Exception/LogicException.c
deleted file mode 100644
index ca563cb2..00000000
--- a/mongodb-1.12.0/src/MongoDB/Exception/LogicException.c
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2015-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-#include <ext/spl/spl_exceptions.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-
-zend_class_entry* php_phongo_logicexception_ce;
-
-/* {{{ MongoDB\Driver\Exception\LogicException function entries */
-static zend_function_entry php_phongo_logicexception_me[] = {
- PHP_FE_END
-};
-/* }}} */
-
-void php_phongo_logicexception_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver\\Exception", "LogicException", php_phongo_logicexception_me);
- php_phongo_logicexception_ce = zend_register_internal_class_ex(&ce, spl_ce_LogicException);
- zend_class_implements(php_phongo_logicexception_ce, 1, php_phongo_exception_ce);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/MongoDB/Exception/RuntimeException.c b/mongodb-1.12.0/src/MongoDB/Exception/RuntimeException.c
deleted file mode 100644
index a7a7489b..00000000
--- a/mongodb-1.12.0/src/MongoDB/Exception/RuntimeException.c
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright 2015-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-#include <ext/spl/spl_exceptions.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-#include "php_array_api.h"
-
-zend_class_entry* php_phongo_runtimeexception_ce;
-
-static bool php_phongo_has_string_array_element(zval* labels, char* label)
-{
- HashTable* ht_data;
-
- if (Z_TYPE_P(labels) != IS_ARRAY) {
- return false;
- }
-
- ht_data = HASH_OF(labels);
-
- {
- zval* z_label;
-
- ZEND_HASH_FOREACH_VAL_IND(ht_data, z_label)
- {
- if ((Z_TYPE_P(z_label) == IS_STRING) && (strcmp(Z_STRVAL_P(z_label), label) == 0)) {
- return true;
- }
- }
- ZEND_HASH_FOREACH_END();
- }
-
- return false;
-}
-
-/* {{{ proto bool MongoDB\Driver\Exception\RuntimeException::hasErrorLabel(string $label)
- Returns whether a specific error label has been set */
-static PHP_METHOD(RuntimeException, hasErrorLabel)
-{
- zend_error_handling error_handling;
- char* label;
- size_t label_len;
- zval* error_labels;
- zval rv;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &label, &label_len) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- error_labels = zend_read_property(php_phongo_runtimeexception_ce, PHONGO_COMPAT_OBJ_P(getThis()), ZEND_STRL("errorLabels"), 0, &rv);
-
- RETURN_BOOL(php_phongo_has_string_array_element(error_labels, label));
-} /* }}} */
-
-ZEND_BEGIN_ARG_INFO_EX(ai_RuntimeException_hasErrorLabel, 0, 0, 1)
- ZEND_ARG_INFO(0, label)
-ZEND_END_ARG_INFO()
-
-/* {{{ MongoDB\Driver\Exception\RuntimeException function entries */
-static zend_function_entry php_phongo_runtimeexception_me[] = {
- /* clang-format off */
- PHP_ME(RuntimeException, hasErrorLabel, ai_RuntimeException_hasErrorLabel, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_FE_END
- /* clang-format on */
-};
-/* }}} */
-
-void php_phongo_runtimeexception_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver\\Exception", "RuntimeException", php_phongo_runtimeexception_me);
- php_phongo_runtimeexception_ce = zend_register_internal_class_ex(&ce, spl_ce_RuntimeException);
- zend_class_implements(php_phongo_runtimeexception_ce, 1, php_phongo_exception_ce);
-
- zend_declare_property_null(php_phongo_runtimeexception_ce, ZEND_STRL("errorLabels"), ZEND_ACC_PROTECTED);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/MongoDB/Exception/SSLConnectionException.c b/mongodb-1.12.0/src/MongoDB/Exception/SSLConnectionException.c
deleted file mode 100644
index 7a6f43ff..00000000
--- a/mongodb-1.12.0/src/MongoDB/Exception/SSLConnectionException.c
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 2014-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-
-zend_class_entry* php_phongo_sslconnectionexception_ce;
-
-/* {{{ MongoDB\Driver\Exception\SSLConnectionException function entries */
-static zend_function_entry php_phongo_sslconnectionexception_me[] = {
- PHP_FE_END
-};
-/* }}} */
-
-void php_phongo_sslconnectionexception_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver\\Exception", "SSLConnectionException", php_phongo_sslconnectionexception_me);
- php_phongo_sslconnectionexception_ce = zend_register_internal_class_ex(&ce, php_phongo_connectionexception_ce);
- PHONGO_CE_FINAL(php_phongo_sslconnectionexception_ce);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/MongoDB/Exception/ServerException.c b/mongodb-1.12.0/src/MongoDB/Exception/ServerException.c
deleted file mode 100644
index 4d9af828..00000000
--- a/mongodb-1.12.0/src/MongoDB/Exception/ServerException.c
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2018-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-
-zend_class_entry* php_phongo_serverexception_ce;
-
-/* {{{ MongoDB\Driver\Exception\ServerException function entries */
-static zend_function_entry php_phongo_serverexception_me[] = {
- PHP_FE_END
-};
-/* }}} */
-
-void php_phongo_serverexception_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver\\Exception", "ServerException", php_phongo_serverexception_me);
- php_phongo_serverexception_ce = zend_register_internal_class_ex(&ce, php_phongo_runtimeexception_ce);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/MongoDB/Exception/UnexpectedValueException.c b/mongodb-1.12.0/src/MongoDB/Exception/UnexpectedValueException.c
deleted file mode 100644
index 8c6a2082..00000000
--- a/mongodb-1.12.0/src/MongoDB/Exception/UnexpectedValueException.c
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2014-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-#include <ext/spl/spl_exceptions.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-
-zend_class_entry* php_phongo_unexpectedvalueexception_ce;
-
-/* {{{ MongoDB\Driver\Exception\UnexpectedValueException function entries */
-static zend_function_entry php_phongo_unexpectedvalueexception_me[] = {
- PHP_FE_END
-};
-/* }}} */
-
-void php_phongo_unexpectedvalueexception_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver\\Exception", "UnexpectedValueException", php_phongo_unexpectedvalueexception_me);
- php_phongo_unexpectedvalueexception_ce = zend_register_internal_class_ex(&ce, spl_ce_UnexpectedValueException);
- zend_class_implements(php_phongo_unexpectedvalueexception_ce, 1, php_phongo_exception_ce);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/MongoDB/Exception/WriteException.c b/mongodb-1.12.0/src/MongoDB/Exception/WriteException.c
deleted file mode 100644
index 9c42f961..00000000
--- a/mongodb-1.12.0/src/MongoDB/Exception/WriteException.c
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright 2014-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-
-zend_class_entry* php_phongo_writeexception_ce;
-
-/* {{{ proto MongoDB\Driver\WriteResult MongoDB\Driver\Exception\WriteException::getWriteResult()
- Returns the WriteResult from the failed write operation. */
-static PHP_METHOD(WriteException, getWriteResult)
-{
- zend_error_handling error_handling;
- zval* writeresult;
- zval rv;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- writeresult = zend_read_property(php_phongo_writeexception_ce, PHONGO_COMPAT_OBJ_P(getThis()), ZEND_STRL("writeResult"), 0, &rv);
-
- RETURN_ZVAL(writeresult, 1, 0);
-} /* }}} */
-
-/* {{{ MongoDB\Driver\Exception\WriteException function entries */
-ZEND_BEGIN_ARG_INFO_EX(ai_WriteException_void, 0, 0, 0)
-ZEND_END_ARG_INFO()
-
-static zend_function_entry php_phongo_writeexception_me[] = {
- /* clang-format off */
- PHP_ME(WriteException, getWriteResult, ai_WriteException_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_FE_END
- /* clang-format on */
-};
-/* }}} */
-
-void php_phongo_writeexception_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver\\Exception", "WriteException", php_phongo_writeexception_me);
- php_phongo_writeexception_ce = zend_register_internal_class_ex(&ce, php_phongo_serverexception_ce);
- php_phongo_writeexception_ce->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;
-
- zend_declare_property_null(php_phongo_writeexception_ce, ZEND_STRL("writeResult"), ZEND_ACC_PROTECTED);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/MongoDB/Manager.c b/mongodb-1.12.0/src/MongoDB/Manager.c
deleted file mode 100644
index 17db3e1d..00000000
--- a/mongodb-1.12.0/src/MongoDB/Manager.c
+++ /dev/null
@@ -1,1031 +0,0 @@
-/*
- * Copyright 2014-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-#include <Zend/zend_hash.h>
-#include <Zend/zend_interfaces.h>
-#include <ext/standard/file.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "php_array_api.h"
-#include "phongo_compat.h"
-#include "php_phongo.h"
-#include "Session.h"
-#include "src/phongo_apm.h"
-
-#define PHONGO_MANAGER_URI_DEFAULT "mongodb://127.0.0.1/"
-
-#undef MONGOC_LOG_DOMAIN
-#define MONGOC_LOG_DOMAIN "PHONGO"
-
-/**
- * Manager abstracts a cluster of Server objects (i.e. socket connections).
- *
- * Typically, users will connect to a cluster using a URI, and the Manager will
- * perform tasks such as replica set discovery and create the necessary Server
- * objects. That said, it is also possible to create a Manager with an arbitrary
- * collection of Server objects using the static factory method (this can be
- * useful for testing or administration).
- *
- * Operation methods do not take socket-level options (e.g. socketTimeoutMS).
- * Those options should be specified during construction.
- */
-zend_class_entry* php_phongo_manager_ce;
-
-/* Checks if driverOptions contains a stream context resource in the "context"
- * key and incorporates any of its SSL options into the base array that did not
- * already exist (i.e. array union). The "context" key is then unset from the
- * base array.
- *
- * This handles the merging of any legacy SSL context options and also makes
- * driverOptions suitable for serialization by removing the resource zval. */
-static bool php_phongo_manager_merge_context_options(zval* zdriverOptions) /* {{{ */
-{
- php_stream_context* context;
- zval * zcontext, *zcontextOptions;
-
- if (!php_array_existsc(zdriverOptions, "context")) {
- return true;
- }
-
- zcontext = php_array_fetchc(zdriverOptions, "context");
- context = php_stream_context_from_zval(zcontext, 1);
-
- if (!context) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "\"context\" driver option is not a valid Stream-Context resource");
- return false;
- }
-
- zcontextOptions = php_array_fetchc_array(&context->options, "ssl");
-
- if (!zcontextOptions) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Stream-Context resource does not contain \"ssl\" options array");
- return false;
- }
-
- /* When running PHP in debug mode, php_error_docref duplicates the current
- * scope, leading to a COW violation in zend_hash_merge and
- * zend_symtable_str_del (called by php_array_unsetc). This macro allows
- * that violation in debug mode and is a NOOP when in non-debug. */
- HT_ALLOW_COW_VIOLATION(Z_ARRVAL_P(zdriverOptions));
-
- php_error_docref(NULL, E_DEPRECATED, "The \"context\" driver option is deprecated.");
-
- /* Perform array union (see: add_function() in zend_operators.c) */
- zend_hash_merge(Z_ARRVAL_P(zdriverOptions), Z_ARRVAL_P(zcontextOptions), zval_add_ref, 0);
-
- php_array_unsetc(zdriverOptions, "context");
-
- return true;
-} /* }}} */
-
-/* Prepare authMechanismProperties for BSON encoding by converting a boolean
- * value for the "CANONICALIZE_HOST_NAME" option to a string.
- *
- * Note: URI options are case-insensitive, so we must iterate through the
- * HashTable in order to detect options. */
-static void php_phongo_manager_prep_authmechanismproperties(zval* properties) /* {{{ */
-{
- HashTable* ht_data;
-
- if (Z_TYPE_P(properties) != IS_ARRAY && Z_TYPE_P(properties) != IS_OBJECT) {
- return;
- }
-
- ht_data = HASH_OF(properties);
-
- {
- zend_string* string_key = NULL;
- zend_ulong num_key = 0;
- zval* property;
-
- ZEND_HASH_FOREACH_KEY_VAL_IND(ht_data, num_key, string_key, property)
- {
- if (!string_key) {
- continue;
- }
-
- /* URI options are case-insensitive */
- if (!strcasecmp(ZSTR_VAL(string_key), "CANONICALIZE_HOST_NAME")) {
- ZVAL_DEREF(property);
- if (Z_TYPE_P(property) != IS_STRING && zend_is_true(property)) {
- SEPARATE_ZVAL_NOREF(property);
- ZVAL_NEW_STR(property, zend_string_init(ZEND_STRL("true"), 0));
- }
- }
- }
- ZEND_HASH_FOREACH_END();
- }
-} /* }}} */
-
-/* Prepare URI options for BSON encoding.
- *
- * Read preference tag sets must be an array of documents. In order to ensure
- * that empty arrays serialize as empty documents, array elements will be
- * converted to objects. php_phongo_read_preference_tags_are_valid() handles
- * actual validation of the tag set structure.
- *
- * Auth mechanism properties must have string values, so a boolean true value
- * for the "CANONICALIZE_HOST_NAME" property will be converted to "true".
- *
- * Note: URI options are case-insensitive, so we must iterate through the
- * HashTable in order to detect options. */
-static void php_phongo_manager_prep_uri_options(zval* options) /* {{{ */
-{
- HashTable* ht_data;
-
- if (Z_TYPE_P(options) != IS_ARRAY) {
- return;
- }
-
- ht_data = HASH_OF(options);
-
- {
- zend_string* string_key = NULL;
- zend_ulong num_key = 0;
- zval* option;
-
- ZEND_HASH_FOREACH_KEY_VAL_IND(ht_data, num_key, string_key, option)
- {
- if (!string_key) {
- continue;
- }
-
- if (!strcasecmp(ZSTR_VAL(string_key), MONGOC_URI_READPREFERENCETAGS)) {
- ZVAL_DEREF(option);
- SEPARATE_ZVAL_NOREF(option);
- php_phongo_read_preference_prep_tagsets(option);
- continue;
- }
-
- if (!strcasecmp(ZSTR_VAL(string_key), MONGOC_URI_AUTHMECHANISMPROPERTIES)) {
- ZVAL_DEREF(option);
- SEPARATE_ZVAL_NOREF(option);
- php_phongo_manager_prep_authmechanismproperties(option);
- continue;
- }
- }
- ZEND_HASH_FOREACH_END();
- }
-} /* }}} */
-
-/* Selects a server for an execute method. If "for_writes" is true, a primary
- * will be selected. Otherwise, a read preference will be used to select the
- * server. If zreadPreference is NULL, the client's read preference will be
- * used. If zsession is a session object in a sharded transaction, the session
- * will be checked whether it is pinned to a server. If so, that server will be
- * selected. Otherwise, server selection
- *
- * On success, server_id will be set and the function will return true;
- * otherwise, false is returned and an exception is thrown. */
-static bool php_phongo_manager_select_server(bool for_writes, bool inherit_read_preference, zval* zreadPreference, zval* zsession, mongoc_client_t* client, uint32_t* server_id) /* {{{ */
-{
- mongoc_server_description_t* selected_server;
- const mongoc_read_prefs_t* read_preference = NULL;
- bson_error_t error = { 0 };
-
- if (zsession) {
- const mongoc_client_session_t* session = Z_SESSION_OBJ_P(zsession)->client_session;
-
- /* Attempt to fetch server pinned to session */
- if (mongoc_client_session_get_server_id(session) > 0) {
- *server_id = mongoc_client_session_get_server_id(session);
-
- return true;
- }
- }
-
- if (!for_writes) {
- if (zreadPreference) {
- read_preference = phongo_read_preference_from_zval(zreadPreference);
- } else if (inherit_read_preference) {
- read_preference = mongoc_client_get_read_prefs(client);
- }
- }
-
- selected_server = mongoc_client_select_server(client, for_writes, read_preference, &error);
-
- if (selected_server) {
- *server_id = mongoc_server_description_id(selected_server);
- mongoc_server_description_destroy(selected_server);
-
- return true;
- }
-
- /* Check for connection related exceptions */
- if (!EG(exception)) {
- phongo_throw_exception_from_bson_error_t(&error);
- }
-
- return false;
-} /* }}} */
-
-/* {{{ proto void MongoDB\Driver\Manager::__construct([string $uri = "mongodb://127.0.0.1/"[, array $options = array()[, array $driverOptions = array()]]])
- Constructs a new Manager */
-static PHP_METHOD(Manager, __construct)
-{
- zend_error_handling error_handling;
- php_phongo_manager_t* intern;
- char* uri_string = NULL;
- size_t uri_string_len = 0;
- zval* options = NULL;
- zval* driverOptions = NULL;
-
- intern = Z_MANAGER_OBJ_P(getThis());
-
- /* Separate the options and driverOptions zvals, since we may end up
- * modifying them in php_phongo_manager_prep_uri_options() and
- * php_phongo_manager_merge_context_options() below, respectively. */
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s!a/!a/!", &uri_string, &uri_string_len, &options, &driverOptions) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- if (options) {
- php_phongo_manager_prep_uri_options(options);
- }
-
- if (driverOptions && !php_phongo_manager_merge_context_options(driverOptions)) {
- /* Exception should already have been thrown */
- return;
- }
-
- phongo_manager_init(intern, uri_string ? uri_string : PHONGO_MANAGER_URI_DEFAULT, options, driverOptions);
-
- if (EG(exception)) {
- return;
- }
-
- /* Update the request-scoped Manager registry */
- if (!php_phongo_manager_register(intern)) {
- phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "Failed to add Manager to internal registry");
- }
-} /* }}} */
-
-/* {{{ proto void MongoDB\Driver\Manager::addSubscriber(MongoDB\Driver\Monitoring\Subscriber $subscriber)
- Registers an event subscriber for this Manager */
-static PHP_METHOD(Manager, addSubscriber)
-{
- php_phongo_manager_t* intern;
- zval* subscriber;
-
- PHONGO_PARSE_PARAMETERS_START(1, 1)
- Z_PARAM_OBJECT_OF_CLASS(subscriber, php_phongo_subscriber_ce)
- PHONGO_PARSE_PARAMETERS_END();
-
- intern = Z_MANAGER_OBJ_P(getThis());
-
- /* Lazily initialize the subscriber HashTable */
- if (!intern->subscribers) {
- ALLOC_HASHTABLE(intern->subscribers);
- zend_hash_init(intern->subscribers, 0, NULL, ZVAL_PTR_DTOR, 0);
- }
-
- phongo_apm_add_subscriber(intern->subscribers, subscriber);
-} /* }}} */
-
-/* {{{ proto MongoDB\Driver\ClientEncryption MongoDB\Driver\Manager::createClientEncryption(array $options)
- Return a ClientEncryption instance */
-static PHP_METHOD(Manager, createClientEncryption)
-{
- zend_error_handling error_handling;
- php_phongo_manager_t* intern;
- php_phongo_clientencryption_t* clientencryption;
- zval* options;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &options) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- intern = Z_MANAGER_OBJ_P(getThis());
-
- object_init_ex(return_value, php_phongo_clientencryption_ce);
- clientencryption = Z_CLIENTENCRYPTION_OBJ_P(return_value);
-
- /* An exception will be thrown on error. */
- phongo_clientencryption_init(clientencryption, getThis(), options);
-} /* }}} */
-
-/* {{{ proto MongoDB\Driver\Cursor MongoDB\Driver\Manager::executeCommand(string $db, MongoDB\Driver\Command $command[, array $options = null])
- Execute a Command */
-static PHP_METHOD(Manager, executeCommand)
-{
- zend_error_handling error_handling;
- php_phongo_manager_t* intern;
- char* db;
- size_t db_len;
- zval* command;
- zval* options = NULL;
- bool free_options = false;
- zval* zreadPreference = NULL;
- zval* zsession = NULL;
- uint32_t server_id = 0;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "sO|z!", &db, &db_len, &command, php_phongo_command_ce, &options) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- intern = Z_MANAGER_OBJ_P(getThis());
-
- options = php_phongo_prep_legacy_option(options, "readPreference", &free_options);
-
- if (!phongo_parse_session(options, intern->client, NULL, &zsession)) {
- /* Exception should already have been thrown */
- goto cleanup;
- }
-
- if (!phongo_parse_read_preference(options, &zreadPreference)) {
- /* Exception should already have been thrown */
- goto cleanup;
- }
-
- if (!php_phongo_manager_select_server(false, false, zreadPreference, zsession, intern->client, &server_id)) {
- /* Exception should already have been thrown */
- goto cleanup;
- }
-
- /* If the Manager was created in a different process, reset the client so
- * that cursors created by this process can be differentiated and its
- * session pool is cleared. */
- PHONGO_RESET_CLIENT_IF_PID_DIFFERS(intern, intern);
-
- phongo_execute_command(getThis(), PHONGO_COMMAND_RAW, db, command, options, server_id, return_value);
-
-cleanup:
- if (free_options) {
- php_phongo_prep_legacy_option_free(options);
- }
-} /* }}} */
-
-/* {{{ proto MongoDB\Driver\Cursor MongoDB\Driver\Manager::executeReadCommand(string $db, MongoDB\Driver\Command $command[, array $options = null])
- Execute a ReadCommand */
-static PHP_METHOD(Manager, executeReadCommand)
-{
- zend_error_handling error_handling;
- php_phongo_manager_t* intern;
- char* db;
- size_t db_len;
- zval* command;
- zval* options = NULL;
- zval* zreadPreference = NULL;
- uint32_t server_id = 0;
- zval* zsession = NULL;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "sO|a!", &db, &db_len, &command, php_phongo_command_ce, &options) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- intern = Z_MANAGER_OBJ_P(getThis());
-
- if (!phongo_parse_session(options, intern->client, NULL, &zsession)) {
- /* Exception should already have been thrown */
- return;
- }
-
- if (!phongo_parse_read_preference(options, &zreadPreference)) {
- /* Exception should already have been thrown */
- return;
- }
-
- if (!php_phongo_manager_select_server(false, true, zreadPreference, zsession, intern->client, &server_id)) {
- /* Exception should already have been thrown */
- return;
- }
-
- /* If the Manager was created in a different process, reset the client so
- * that cursors created by this process can be differentiated and its
- * session pool is cleared. */
- PHONGO_RESET_CLIENT_IF_PID_DIFFERS(intern, intern);
-
- phongo_execute_command(getThis(), PHONGO_COMMAND_READ, db, command, options, server_id, return_value);
-} /* }}} */
-
-/* {{{ proto MongoDB\Driver\Cursor MongoDB\Driver\Manager::executeWriteCommand(string $db, MongoDB\Driver\Command $command[, array $options = null])
- Execute a WriteCommand */
-static PHP_METHOD(Manager, executeWriteCommand)
-{
- zend_error_handling error_handling;
- php_phongo_manager_t* intern;
- char* db;
- size_t db_len;
- zval* command;
- zval* options = NULL;
- uint32_t server_id = 0;
- zval* zsession = NULL;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "sO|a!", &db, &db_len, &command, php_phongo_command_ce, &options) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- intern = Z_MANAGER_OBJ_P(getThis());
-
- if (!phongo_parse_session(options, intern->client, NULL, &zsession)) {
- /* Exception should already have been thrown */
- return;
- }
-
- if (!php_phongo_manager_select_server(true, false, NULL, zsession, intern->client, &server_id)) {
- /* Exception should already have been thrown */
- return;
- }
-
- /* If the Manager was created in a different process, reset the client so
- * that cursors created by this process can be differentiated and its
- * session pool is cleared. */
- PHONGO_RESET_CLIENT_IF_PID_DIFFERS(intern, intern);
-
- phongo_execute_command(getThis(), PHONGO_COMMAND_WRITE, db, command, options, server_id, return_value);
-} /* }}} */
-
-/* {{{ proto MongoDB\Driver\Cursor MongoDB\Driver\Manager::executeReadWriteCommand(string $db, MongoDB\Driver\Command $command[, array $options = null])
- Execute a ReadWriteCommand */
-static PHP_METHOD(Manager, executeReadWriteCommand)
-{
- zend_error_handling error_handling;
- php_phongo_manager_t* intern;
- char* db;
- size_t db_len;
- zval* command;
- zval* options = NULL;
- uint32_t server_id = 0;
- zval* zsession = NULL;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "sO|a!", &db, &db_len, &command, php_phongo_command_ce, &options) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- intern = Z_MANAGER_OBJ_P(getThis());
-
- if (!phongo_parse_session(options, intern->client, NULL, &zsession)) {
- /* Exception should already have been thrown */
- return;
- }
-
- if (!php_phongo_manager_select_server(true, false, NULL, zsession, intern->client, &server_id)) {
- /* Exception should already have been thrown */
- return;
- }
-
- /* If the Manager was created in a different process, reset the client so
- * that cursors created by this process can be differentiated and its
- * session pool is cleared. */
- PHONGO_RESET_CLIENT_IF_PID_DIFFERS(intern, intern);
-
- phongo_execute_command(getThis(), PHONGO_COMMAND_READ_WRITE, db, command, options, server_id, return_value);
-} /* }}} */
-
-/* {{{ proto MongoDB\Driver\Cursor MongoDB\Driver\Manager::executeQuery(string $namespace, MongoDB\Driver\Query $query[, array $options = null])
- Execute a Query */
-static PHP_METHOD(Manager, executeQuery)
-{
- zend_error_handling error_handling;
- php_phongo_manager_t* intern;
- char* namespace;
- size_t namespace_len;
- zval* query;
- zval* options = NULL;
- bool free_options = false;
- zval* zreadPreference = NULL;
- uint32_t server_id = 0;
- zval* zsession = NULL;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "sO|z!", &namespace, &namespace_len, &query, php_phongo_query_ce, &options) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- intern = Z_MANAGER_OBJ_P(getThis());
-
- options = php_phongo_prep_legacy_option(options, "readPreference", &free_options);
-
- if (!phongo_parse_session(options, intern->client, NULL, &zsession)) {
- /* Exception should already have been thrown */
- goto cleanup;
- }
-
- if (!phongo_parse_read_preference(options, &zreadPreference)) {
- /* Exception should already have been thrown */
- goto cleanup;
- }
-
- if (!php_phongo_manager_select_server(false, true, zreadPreference, zsession, intern->client, &server_id)) {
- /* Exception should already have been thrown */
- goto cleanup;
- }
-
- /* If the Manager was created in a different process, reset the client so
- * that cursors created by this process can be differentiated and its
- * session pool is cleared. */
- PHONGO_RESET_CLIENT_IF_PID_DIFFERS(intern, intern);
-
- phongo_execute_query(getThis(), namespace, query, options, server_id, return_value);
-
-cleanup:
- if (free_options) {
- php_phongo_prep_legacy_option_free(options);
- }
-} /* }}} */
-
-/* {{{ proto MongoDB\Driver\WriteResult MongoDB\Driver\Manager::executeBulkWrite(string $namespace, MongoDB\Driver\BulkWrite $zbulk[, array $options = null])
- Executes a BulkWrite (i.e. any number of insert, update, and delete ops) */
-static PHP_METHOD(Manager, executeBulkWrite)
-{
- zend_error_handling error_handling;
- php_phongo_manager_t* intern;
- char* namespace;
- size_t namespace_len;
- zval* zbulk;
- php_phongo_bulkwrite_t* bulk;
- zval* options = NULL;
- bool free_options = false;
- uint32_t server_id = 0;
- zval* zsession = NULL;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "sO|z!", &namespace, &namespace_len, &zbulk, php_phongo_bulkwrite_ce, &options) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- intern = Z_MANAGER_OBJ_P(getThis());
- bulk = Z_BULKWRITE_OBJ_P(zbulk);
-
- options = php_phongo_prep_legacy_option(options, "writeConcern", &free_options);
-
- if (!phongo_parse_session(options, intern->client, NULL, &zsession)) {
- /* Exception should already have been thrown */
- return;
- }
-
- if (!php_phongo_manager_select_server(true, false, NULL, zsession, intern->client, &server_id)) {
- /* Exception should already have been thrown */
- goto cleanup;
- }
-
- /* If the Server was created in a different process, reset the client so
- * that its session pool is cleared. */
- PHONGO_RESET_CLIENT_IF_PID_DIFFERS(intern, intern);
-
- phongo_execute_bulk_write(getThis(), namespace, bulk, options, server_id, return_value);
-
-cleanup:
- if (free_options) {
- php_phongo_prep_legacy_option_free(options);
- }
-} /* }}} */
-
-/* {{{ proto MongoDB\Driver\ReadConcern MongoDB\Driver\Manager::getReadConcern()
- Returns the ReadConcern associated with this Manager */
-static PHP_METHOD(Manager, getReadConcern)
-{
- zend_error_handling error_handling;
- php_phongo_manager_t* intern;
-
- intern = Z_MANAGER_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- phongo_readconcern_init(return_value, mongoc_client_get_read_concern(intern->client));
-} /* }}} */
-
-/* {{{ proto MongoDB\Driver\ReadPreference MongoDB\Driver\Manager::getReadPreference()
- Returns the ReadPreference associated with this Manager */
-static PHP_METHOD(Manager, getReadPreference)
-{
- zend_error_handling error_handling;
- php_phongo_manager_t* intern;
-
- intern = Z_MANAGER_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- phongo_readpreference_init(return_value, mongoc_client_get_read_prefs(intern->client));
-} /* }}} */
-
-/* {{{ proto MongoDB\Driver\Server[] MongoDB\Driver\Manager::getServers()
- Returns the Servers associated with this Manager */
-static PHP_METHOD(Manager, getServers)
-{
- zend_error_handling error_handling;
- php_phongo_manager_t* intern;
- mongoc_server_description_t** sds;
- size_t i, n = 0;
-
- intern = Z_MANAGER_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- sds = mongoc_client_get_server_descriptions(intern->client, &n);
- array_init_size(return_value, n);
-
- for (i = 0; i < n; i++) {
- zval obj;
-
- phongo_server_init(&obj, getThis(), mongoc_server_description_id(sds[i]));
- add_next_index_zval(return_value, &obj);
- }
-
- mongoc_server_descriptions_destroy_all(sds, n);
-} /* }}} */
-
-/* {{{ proto MongoDB\Driver\WriteConcern MongoDB\Driver\Manager::getWriteConcern()
- Returns the WriteConcern associated with this Manager */
-static PHP_METHOD(Manager, getWriteConcern)
-{
- zend_error_handling error_handling;
- php_phongo_manager_t* intern;
-
- intern = Z_MANAGER_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- phongo_writeconcern_init(return_value, mongoc_client_get_write_concern(intern->client));
-} /* }}} */
-
-/* {{{ proto void MongoDB\Driver\Manager::removeSubscriber(MongoDB\Driver\Monitoring\Subscriber $subscriber)
- Unregisters an event subscriber for this Manager */
-static PHP_METHOD(Manager, removeSubscriber)
-{
- php_phongo_manager_t* intern;
- zval* subscriber;
-
- PHONGO_PARSE_PARAMETERS_START(1, 1)
- Z_PARAM_OBJECT_OF_CLASS(subscriber, php_phongo_subscriber_ce)
- PHONGO_PARSE_PARAMETERS_END();
-
- intern = Z_MANAGER_OBJ_P(getThis());
-
- /* NOP if subscribers HashTable was never initialized by addSubscriber */
- if (!intern->subscribers) {
- return;
- }
-
- phongo_apm_remove_subscriber(intern->subscribers, subscriber);
-} /* }}} */
-
-/* {{{ proto MongoDB\Driver\Server MongoDB\Driver\Manager::selectServers([MongoDB\Driver\ReadPreference $readPreference = null])
- Selects a Server for the given ReadPreference (default: primary). */
-static PHP_METHOD(Manager, selectServer)
-{
- php_phongo_manager_t* intern;
- zval* zreadPreference = NULL;
- uint32_t server_id = 0;
-
- PHONGO_PARSE_PARAMETERS_START(0, 1)
- Z_PARAM_OPTIONAL
- Z_PARAM_OBJECT_OF_CLASS_OR_NULL(zreadPreference, php_phongo_readpreference_ce)
- PHONGO_PARSE_PARAMETERS_END();
-
- intern = Z_MANAGER_OBJ_P(getThis());
-
- if (!php_phongo_manager_select_server(false, false, zreadPreference, NULL, intern->client, &server_id)) {
- /* Exception should already have been thrown */
- return;
- }
-
- phongo_server_init(return_value, getThis(), server_id);
-} /* }}} */
-
-/* {{{ proto MongoDB\Driver\Session MongoDB\Driver\Manager::startSession([array $options = null])
- Returns a new client session */
-static PHP_METHOD(Manager, startSession)
-{
- zend_error_handling error_handling;
- php_phongo_manager_t* intern;
- zval* options = NULL;
- mongoc_session_opt_t* cs_opts = NULL;
- mongoc_client_session_t* cs;
- bson_error_t error = { 0 };
- mongoc_transaction_opt_t* txn_opts = NULL;
-
- intern = Z_MANAGER_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "|a!", &options) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- if (options && php_array_existsc(options, "causalConsistency")) {
- cs_opts = mongoc_session_opts_new();
- mongoc_session_opts_set_causal_consistency(cs_opts, php_array_fetchc_bool(options, "causalConsistency"));
- }
-
- if (options && php_array_existsc(options, "defaultTransactionOptions")) {
- zval* txn_options = php_array_fetchc(options, "defaultTransactionOptions");
-
- /* Thrown exception and return if the defaultTransactionOptions is not an array */
- if (Z_TYPE_P(txn_options) != IS_ARRAY) {
- phongo_throw_exception(
- PHONGO_ERROR_INVALID_ARGUMENT,
- "Expected \"defaultTransactionOptions\" option to be an array, %s given",
- PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(txn_options));
- goto cleanup;
- }
-
- /* Parse transaction options */
- txn_opts = php_mongodb_session_parse_transaction_options(txn_options);
-
- /* If an exception is thrown while parsing, the txn_opts struct is also
- * NULL, so no need to free it here */
- if (EG(exception)) {
- goto cleanup;
- }
-
- /* If the options are non-empty, add them to the client session opts struct */
- if (txn_opts) {
- if (!cs_opts) {
- cs_opts = mongoc_session_opts_new();
- }
-
- mongoc_session_opts_set_default_transaction_opts(cs_opts, txn_opts);
- mongoc_transaction_opts_destroy(txn_opts);
- }
- }
-
- if (options && php_array_existsc(options, "snapshot")) {
- if (!cs_opts) {
- cs_opts = mongoc_session_opts_new();
- }
- mongoc_session_opts_set_snapshot(cs_opts, php_array_fetchc_bool(options, "snapshot"));
- }
-
- if (cs_opts && mongoc_session_opts_get_causal_consistency(cs_opts) && mongoc_session_opts_get_snapshot(cs_opts)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Only one of \"causalConsistency\" and \"snapshot\" can be enabled");
- goto cleanup;
- }
-
- /* If the Manager was created in a different process, reset the client so
- * that its session pool is cleared. This will ensure that we do not re-use
- * a server session (i.e. LSID) created by a parent process. */
- PHONGO_RESET_CLIENT_IF_PID_DIFFERS(intern, intern);
-
- cs = mongoc_client_start_session(intern->client, cs_opts, &error);
-
- if (cs) {
- phongo_session_init(return_value, getThis(), cs);
- } else {
- phongo_throw_exception_from_bson_error_t(&error);
- }
-
-cleanup:
- if (cs_opts) {
- mongoc_session_opts_destroy(cs_opts);
- }
-} /* }}} */
-
-/* {{{ MongoDB\Driver\Manager function entries */
-ZEND_BEGIN_ARG_INFO_EX(ai_Manager___construct, 0, 0, 0)
- ZEND_ARG_INFO(0, uri)
- ZEND_ARG_ARRAY_INFO(0, options, 0)
- ZEND_ARG_ARRAY_INFO(0, driverOptions, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_Manager_addSubscriber, 0, 0, 1)
- ZEND_ARG_OBJ_INFO(0, subscriber, MongoDB\\Driver\\Monitoring\\Subscriber, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_Manager_createClientEncryption, 0, 0, 1)
- ZEND_ARG_ARRAY_INFO(0, options, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_Manager_executeCommand, 0, 0, 2)
- ZEND_ARG_INFO(0, db)
- ZEND_ARG_OBJ_INFO(0, command, MongoDB\\Driver\\Command, 0)
- ZEND_ARG_INFO(0, options)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_Manager_executeRWCommand, 0, 0, 2)
- ZEND_ARG_INFO(0, db)
- ZEND_ARG_OBJ_INFO(0, command, MongoDB\\Driver\\Command, 0)
- ZEND_ARG_ARRAY_INFO(0, options, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_Manager_executeQuery, 0, 0, 2)
- ZEND_ARG_INFO(0, namespace)
- ZEND_ARG_OBJ_INFO(0, zquery, MongoDB\\Driver\\Query, 0)
- ZEND_ARG_INFO(0, options)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_Manager_executeBulkWrite, 0, 0, 2)
- ZEND_ARG_INFO(0, namespace)
- ZEND_ARG_OBJ_INFO(0, zbulk, MongoDB\\Driver\\BulkWrite, 0)
- ZEND_ARG_INFO(0, options)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_Manager_removeSubscriber, 0, 0, 1)
- ZEND_ARG_OBJ_INFO(0, subscriber, MongoDB\\Driver\\Monitoring\\Subscriber, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_Manager_selectServer, 0, 0, 0)
- ZEND_ARG_OBJ_INFO(0, readPreference, MongoDB\\Driver\\ReadPreference, 1)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_Manager_startSession, 0, 0, 0)
- ZEND_ARG_ARRAY_INFO(0, options, 1)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_Manager_void, 0, 0, 0)
-ZEND_END_ARG_INFO()
-
-static zend_function_entry php_phongo_manager_me[] = {
- /* clang-format off */
- PHP_ME(Manager, __construct, ai_Manager___construct, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Manager, addSubscriber, ai_Manager_addSubscriber, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Manager, createClientEncryption, ai_Manager_createClientEncryption, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Manager, executeCommand, ai_Manager_executeCommand, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Manager, executeReadCommand, ai_Manager_executeRWCommand, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Manager, executeWriteCommand, ai_Manager_executeRWCommand, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Manager, executeReadWriteCommand, ai_Manager_executeCommand, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Manager, executeQuery, ai_Manager_executeQuery, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Manager, executeBulkWrite, ai_Manager_executeBulkWrite, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Manager, getReadConcern, ai_Manager_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Manager, getReadPreference, ai_Manager_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Manager, getServers, ai_Manager_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Manager, getWriteConcern, ai_Manager_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Manager, removeSubscriber, ai_Manager_removeSubscriber, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Manager, selectServer, ai_Manager_selectServer, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Manager, startSession, ai_Manager_startSession, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- ZEND_NAMED_ME(__wakeup, PHP_FN(MongoDB_disabled___wakeup), ai_Manager_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_FE_END
- /* clang-format on */
-};
-/* }}} */
-
-/* {{{ MongoDB\Driver\Manager object handlers */
-static zend_object_handlers php_phongo_handler_manager;
-
-static void php_phongo_manager_free_object(zend_object* object) /* {{{ */
-{
- php_phongo_manager_t* intern = Z_OBJ_MANAGER(object);
-
- zend_object_std_dtor(&intern->std);
-
- /* Update the request-scoped Manager registry. The return value is ignored
- * because it's possible that the Manager was never registered due to a
- * constructor exception. */
- php_phongo_manager_unregister(intern);
-
- if (intern->client) {
- /* Request-scoped clients will be removed from the registry and
- * destroyed. This is a NOP for persistent clients. The return value is
- * ignored because we can't reasonably report an error here. On the off
- * chance any request-scoped clients are missed, they will ultimately be
- * destroyed in RSHUTDOWN along with the registry HashTable. */
- php_phongo_client_unregister(intern);
- }
-
- if (intern->client_hash) {
- efree(intern->client_hash);
- }
-
- /* Free the keyVaultClient last to ensure that potential non-persistent
- * clients are destroyed in the correct order */
- if (!Z_ISUNDEF(intern->key_vault_client_manager)) {
- zval_ptr_dtor(&intern->key_vault_client_manager);
- }
-
- if (intern->subscribers) {
- zend_hash_destroy(intern->subscribers);
- FREE_HASHTABLE(intern->subscribers);
- }
-} /* }}} */
-
-static zend_object* php_phongo_manager_create_object(zend_class_entry* class_type) /* {{{ */
-{
- php_phongo_manager_t* intern = NULL;
-
- intern = PHONGO_ALLOC_OBJECT_T(php_phongo_manager_t, class_type);
-
- zend_object_std_init(&intern->std, class_type);
- object_properties_init(&intern->std, class_type);
-
- PHONGO_SET_CREATED_BY_PID(intern);
-
- intern->std.handlers = &php_phongo_handler_manager;
-
- return &intern->std;
-} /* }}} */
-
-static HashTable* php_phongo_manager_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
-{
- php_phongo_manager_t* intern;
- mongoc_server_description_t** sds;
- size_t i, n = 0;
- zval retval = ZVAL_STATIC_INIT;
- zval cluster;
-
- *is_temp = 1;
- intern = Z_OBJ_MANAGER(PHONGO_COMPAT_GET_OBJ(object));
-
- array_init_size(&retval, 2);
-
- ADD_ASSOC_STRING(&retval, "uri", mongoc_uri_get_string(mongoc_client_get_uri(intern->client)));
-
- sds = mongoc_client_get_server_descriptions(intern->client, &n);
-
- array_init_size(&cluster, n);
-
- for (i = 0; i < n; i++) {
- zval obj;
-
- if (!php_phongo_server_to_zval(&obj, intern->client, sds[i])) {
- /* Exception already thrown */
- zval_ptr_dtor(&obj);
- zval_ptr_dtor(&cluster);
- goto done;
- }
-
- add_next_index_zval(&cluster, &obj);
- }
-
- ADD_ASSOC_ZVAL_EX(&retval, "cluster", &cluster);
-
-done:
- mongoc_server_descriptions_destroy_all(sds, n);
-
- return Z_ARRVAL(retval);
-} /* }}} */
-/* }}} */
-
-void php_phongo_manager_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver", "Manager", php_phongo_manager_me);
- php_phongo_manager_ce = zend_register_internal_class(&ce);
- php_phongo_manager_ce->create_object = php_phongo_manager_create_object;
- PHONGO_CE_FINAL(php_phongo_manager_ce);
- PHONGO_CE_DISABLE_SERIALIZATION(php_phongo_manager_ce);
-
- memcpy(&php_phongo_handler_manager, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
- php_phongo_handler_manager.get_debug_info = php_phongo_manager_get_debug_info;
- php_phongo_handler_manager.free_obj = php_phongo_manager_free_object;
- php_phongo_handler_manager.offset = XtOffsetOf(php_phongo_manager_t, std);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/MongoDB/Monitoring/CommandFailedEvent.c b/mongodb-1.12.0/src/MongoDB/Monitoring/CommandFailedEvent.c
deleted file mode 100644
index 237715d5..00000000
--- a/mongodb-1.12.0/src/MongoDB/Monitoring/CommandFailedEvent.c
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
- * Copyright 2016-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-#include <Zend/zend_interfaces.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-
-zend_class_entry* php_phongo_commandfailedevent_ce;
-
-/* {{{ proto string CommandFailedEvent::getCommandName()
- Returns the command name for this event */
-PHP_METHOD(CommandFailedEvent, getCommandName)
-{
- zend_error_handling error_handling;
- php_phongo_commandfailedevent_t* intern;
-
- intern = Z_COMMANDFAILEDEVENT_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- RETVAL_STRING(intern->command_name);
-} /* }}} */
-
-/* {{{ proto int CommandFailedEvent::getDurationMicros()
- Returns the event's duration in microseconds */
-PHP_METHOD(CommandFailedEvent, getDurationMicros)
-{
- zend_error_handling error_handling;
- php_phongo_commandfailedevent_t* intern;
-
- intern = Z_COMMANDFAILEDEVENT_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- RETURN_LONG(intern->duration_micros);
-} /* }}} */
-
-/* {{{ proto Exception CommandFailedEvent::getError()
- Returns the error document associated with the event */
-PHP_METHOD(CommandFailedEvent, getError)
-{
- zend_error_handling error_handling;
- php_phongo_commandfailedevent_t* intern;
-
- intern = Z_COMMANDFAILEDEVENT_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- RETURN_ZVAL(&intern->z_error, 1, 0);
-} /* }}} */
-
-/* {{{ proto string CommandFailedEvent::getOperationId()
- Returns the event's operation ID */
-PHP_METHOD(CommandFailedEvent, getOperationId)
-{
- zend_error_handling error_handling;
- php_phongo_commandfailedevent_t* intern;
- char int_as_string[20];
-
- intern = Z_COMMANDFAILEDEVENT_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- sprintf(int_as_string, "%" PRIu64, intern->operation_id);
- RETVAL_STRING(int_as_string);
-} /* }}} */
-
-/* {{{ proto stdClass CommandFailedEvent::getReply()
- Returns the reply document associated with the event */
-PHP_METHOD(CommandFailedEvent, getReply)
-{
- zend_error_handling error_handling;
- php_phongo_commandfailedevent_t* intern;
- php_phongo_bson_state state;
-
- PHONGO_BSON_INIT_STATE(state);
-
- intern = Z_COMMANDFAILEDEVENT_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- if (!php_phongo_bson_to_zval_ex(bson_get_data(intern->reply), intern->reply->len, &state)) {
- zval_ptr_dtor(&state.zchild);
- return;
- }
-
- RETURN_ZVAL(&state.zchild, 0, 1);
-} /* }}} */
-
-/* {{{ proto string CommandFailedEvent::getRequestId()
- Returns the event's request ID */
-PHP_METHOD(CommandFailedEvent, getRequestId)
-{
- zend_error_handling error_handling;
- php_phongo_commandfailedevent_t* intern;
- char int_as_string[20];
-
- intern = Z_COMMANDFAILEDEVENT_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- sprintf(int_as_string, "%" PRIu64, intern->request_id);
- RETVAL_STRING(int_as_string);
-} /* }}} */
-
-/* {{{ proto MongoDB\Driver\Server CommandFailedEvent::getServer()
- Returns the Server from which the event originated */
-PHP_METHOD(CommandFailedEvent, getServer)
-{
- zend_error_handling error_handling;
- php_phongo_commandfailedevent_t* intern;
-
- intern = Z_COMMANDFAILEDEVENT_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- phongo_server_init(return_value, &intern->manager, intern->server_id);
-} /* }}} */
-
-/* {{{ proto MongoDB\BSON\ObjectId|null CommandFailedEvent::getServiceId()
- Returns the event's service ID */
-PHP_METHOD(CommandFailedEvent, getServiceId)
-{
- php_phongo_commandfailedevent_t* intern = Z_COMMANDFAILEDEVENT_OBJ_P(getThis());
-
- PHONGO_PARSE_PARAMETERS_NONE();
-
- if (!intern->has_service_id) {
- RETURN_NULL();
- }
-
- phongo_objectid_init(return_value, &intern->service_id);
-} /* }}} */
-
-/**
- * Event thrown when a command has failed to execute.
- *
- * This class is only constructed internally.
- */
-
-/* {{{ MongoDB\Driver\Monitoring\CommandFailedEvent function entries */
-ZEND_BEGIN_ARG_INFO_EX(ai_CommandFailedEvent_void, 0, 0, 0)
-ZEND_END_ARG_INFO()
-
-static zend_function_entry php_phongo_commandfailedevent_me[] = {
- /* clang-format off */
- ZEND_NAMED_ME(__construct, PHP_FN(MongoDB_disabled___construct), ai_CommandFailedEvent_void, ZEND_ACC_PRIVATE | ZEND_ACC_FINAL)
- PHP_ME(CommandFailedEvent, getCommandName, ai_CommandFailedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(CommandFailedEvent, getError, ai_CommandFailedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(CommandFailedEvent, getDurationMicros, ai_CommandFailedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(CommandFailedEvent, getOperationId, ai_CommandFailedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(CommandFailedEvent, getReply, ai_CommandFailedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(CommandFailedEvent, getRequestId, ai_CommandFailedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(CommandFailedEvent, getServer, ai_CommandFailedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(CommandFailedEvent, getServiceId, ai_CommandFailedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- ZEND_NAMED_ME(__wakeup, PHP_FN(MongoDB_disabled___wakeup), ai_CommandFailedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_FE_END
- /* clang-format on */
-};
-/* }}} */
-
-/* {{{ MongoDB\Driver\Monitoring\CommandFailedEvent object handlers */
-static zend_object_handlers php_phongo_handler_commandfailedevent;
-
-static void php_phongo_commandfailedevent_free_object(zend_object* object) /* {{{ */
-{
- php_phongo_commandfailedevent_t* intern = Z_OBJ_COMMANDFAILEDEVENT(object);
-
- zend_object_std_dtor(&intern->std);
-
- if (!Z_ISUNDEF(intern->z_error)) {
- zval_ptr_dtor(&intern->z_error);
- }
-
- if (!Z_ISUNDEF(intern->manager)) {
- zval_ptr_dtor(&intern->manager);
- }
-
- if (intern->reply) {
- bson_destroy(intern->reply);
- }
-
- if (intern->command_name) {
- efree(intern->command_name);
- }
-} /* }}} */
-
-static zend_object* php_phongo_commandfailedevent_create_object(zend_class_entry* class_type) /* {{{ */
-{
- php_phongo_commandfailedevent_t* intern = NULL;
-
- intern = PHONGO_ALLOC_OBJECT_T(php_phongo_commandfailedevent_t, class_type);
-
- zend_object_std_init(&intern->std, class_type);
- object_properties_init(&intern->std, class_type);
-
- intern->std.handlers = &php_phongo_handler_commandfailedevent;
-
- return &intern->std;
-} /* }}} */
-
-static HashTable* php_phongo_commandfailedevent_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
-{
- php_phongo_commandfailedevent_t* intern;
- zval retval = ZVAL_STATIC_INIT;
- char operation_id[20], request_id[20];
- php_phongo_bson_state reply_state;
-
- PHONGO_BSON_INIT_STATE(reply_state);
-
- intern = Z_OBJ_COMMANDFAILEDEVENT(PHONGO_COMPAT_GET_OBJ(object));
- *is_temp = 1;
- array_init_size(&retval, 6);
-
- ADD_ASSOC_STRING(&retval, "commandName", intern->command_name);
- ADD_ASSOC_INT64(&retval, "durationMicros", (int64_t) intern->duration_micros);
-
- ADD_ASSOC_ZVAL_EX(&retval, "error", &intern->z_error);
- Z_ADDREF(intern->z_error);
-
- sprintf(operation_id, "%" PRIu64, intern->operation_id);
- ADD_ASSOC_STRING(&retval, "operationId", operation_id);
-
- if (!php_phongo_bson_to_zval_ex(bson_get_data(intern->reply), intern->reply->len, &reply_state)) {
- zval_ptr_dtor(&reply_state.zchild);
- goto done;
- }
-
- ADD_ASSOC_ZVAL(&retval, "reply", &reply_state.zchild);
-
- sprintf(request_id, "%" PRIu64, intern->request_id);
- ADD_ASSOC_STRING(&retval, "requestId", request_id);
-
- {
- zval server;
-
- phongo_server_init(&server, &intern->manager, intern->server_id);
- ADD_ASSOC_ZVAL_EX(&retval, "server", &server);
- }
-
- if (intern->has_service_id) {
- zval service_id;
-
- phongo_objectid_init(&service_id, &intern->service_id);
- ADD_ASSOC_ZVAL_EX(&retval, "serviceId", &service_id);
- } else {
- ADD_ASSOC_NULL_EX(&retval, "serviceId");
- }
-
-done:
- return Z_ARRVAL(retval);
-} /* }}} */
-/* }}} */
-
-void php_phongo_commandfailedevent_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
- (void) type;
- (void) module_number;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver\\Monitoring", "CommandFailedEvent", php_phongo_commandfailedevent_me);
- php_phongo_commandfailedevent_ce = zend_register_internal_class(&ce);
- php_phongo_commandfailedevent_ce->create_object = php_phongo_commandfailedevent_create_object;
- PHONGO_CE_FINAL(php_phongo_commandfailedevent_ce);
- PHONGO_CE_DISABLE_SERIALIZATION(php_phongo_commandfailedevent_ce);
-
- memcpy(&php_phongo_handler_commandfailedevent, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
- php_phongo_handler_commandfailedevent.get_debug_info = php_phongo_commandfailedevent_get_debug_info;
- php_phongo_handler_commandfailedevent.free_obj = php_phongo_commandfailedevent_free_object;
- php_phongo_handler_commandfailedevent.offset = XtOffsetOf(php_phongo_commandfailedevent_t, std);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/MongoDB/Monitoring/CommandStartedEvent.c b/mongodb-1.12.0/src/MongoDB/Monitoring/CommandStartedEvent.c
deleted file mode 100644
index 2583ae97..00000000
--- a/mongodb-1.12.0/src/MongoDB/Monitoring/CommandStartedEvent.c
+++ /dev/null
@@ -1,313 +0,0 @@
-/*
- * Copyright 2016-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-#include <Zend/zend_interfaces.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-
-zend_class_entry* php_phongo_commandstartedevent_ce;
-
-/* {{{ proto stdClass CommandStartedEvent::getCommand()
- Returns the command document associated with the event */
-PHP_METHOD(CommandStartedEvent, getCommand)
-{
- zend_error_handling error_handling;
- php_phongo_commandstartedevent_t* intern;
- php_phongo_bson_state state;
-
- PHONGO_BSON_INIT_STATE(state);
-
- intern = Z_COMMANDSTARTEDEVENT_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- if (!php_phongo_bson_to_zval_ex(bson_get_data(intern->command), intern->command->len, &state)) {
- zval_ptr_dtor(&state.zchild);
- return;
- }
-
- RETURN_ZVAL(&state.zchild, 0, 1);
-} /* }}} */
-
-/* {{{ proto string CommandStartedEvent::getCommandName()
- Returns the command name for this event */
-PHP_METHOD(CommandStartedEvent, getCommandName)
-{
- zend_error_handling error_handling;
- php_phongo_commandstartedevent_t* intern;
-
- intern = Z_COMMANDSTARTEDEVENT_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- RETVAL_STRING(intern->command_name);
-} /* }}} */
-
-/* {{{ proto string CommandStartedEvent::getDatabaseName()
- Returns the database name for this event */
-PHP_METHOD(CommandStartedEvent, getDatabaseName)
-{
- zend_error_handling error_handling;
- php_phongo_commandstartedevent_t* intern;
-
- intern = Z_COMMANDSTARTEDEVENT_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- RETVAL_STRING(intern->database_name);
-} /* }}} */
-
-/* {{{ proto string CommandStartedEvent::getOperationId()
- Returns the event's operation ID */
-PHP_METHOD(CommandStartedEvent, getOperationId)
-{
- zend_error_handling error_handling;
- php_phongo_commandstartedevent_t* intern;
- char int_as_string[20];
-
- intern = Z_COMMANDSTARTEDEVENT_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- sprintf(int_as_string, "%" PRIu64, intern->operation_id);
- RETVAL_STRING(int_as_string);
-} /* }}} */
-
-/* {{{ proto string CommandStartedEvent::getRequestId()
- Returns the event's request ID */
-PHP_METHOD(CommandStartedEvent, getRequestId)
-{
- zend_error_handling error_handling;
- php_phongo_commandstartedevent_t* intern;
- char int_as_string[20];
-
- intern = Z_COMMANDSTARTEDEVENT_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- sprintf(int_as_string, "%" PRIu64, intern->request_id);
- RETVAL_STRING(int_as_string);
-} /* }}} */
-
-/* {{{ proto MongoDB\Driver\Server CommandStartedEvent::getServer()
- Returns the Server from which the event originated */
-PHP_METHOD(CommandStartedEvent, getServer)
-{
- zend_error_handling error_handling;
- php_phongo_commandstartedevent_t* intern;
-
- intern = Z_COMMANDSTARTEDEVENT_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- phongo_server_init(return_value, &intern->manager, intern->server_id);
-} /* }}} */
-
-/* {{{ proto MongoDB\BSON\ObjectId|null CommandStartedEvent::getServiceId()
- Returns the event's service ID */
-PHP_METHOD(CommandStartedEvent, getServiceId)
-{
- php_phongo_commandstartedevent_t* intern = Z_COMMANDSTARTEDEVENT_OBJ_P(getThis());
-
- PHONGO_PARSE_PARAMETERS_NONE();
-
- if (!intern->has_service_id) {
- RETURN_NULL();
- }
-
- phongo_objectid_init(return_value, &intern->service_id);
-} /* }}} */
-
-/**
- * Event thrown when a command has started to execute.
- *
- * This class is only constructed internally.
- */
-
-/* {{{ MongoDB\Driver\Monitoring\CommandStartedEvent function entries */
-ZEND_BEGIN_ARG_INFO_EX(ai_CommandStartedEvent_void, 0, 0, 0)
-ZEND_END_ARG_INFO()
-
-static zend_function_entry php_phongo_commandstartedevent_me[] = {
- /* clang-format off */
- ZEND_NAMED_ME(__construct, PHP_FN(MongoDB_disabled___construct), ai_CommandStartedEvent_void, ZEND_ACC_PRIVATE | ZEND_ACC_FINAL)
- PHP_ME(CommandStartedEvent, getCommand, ai_CommandStartedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(CommandStartedEvent, getCommandName, ai_CommandStartedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(CommandStartedEvent, getDatabaseName, ai_CommandStartedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(CommandStartedEvent, getOperationId, ai_CommandStartedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(CommandStartedEvent, getRequestId, ai_CommandStartedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(CommandStartedEvent, getServer, ai_CommandStartedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(CommandStartedEvent, getServiceId, ai_CommandStartedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- ZEND_NAMED_ME(__wakeup, PHP_FN(MongoDB_disabled___wakeup), ai_CommandStartedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_FE_END
- /* clang-format on */
-};
-/* }}} */
-
-/* {{{ MongoDB\Driver\Monitoring\CommandStartedEvent object handlers */
-static zend_object_handlers php_phongo_handler_commandstartedevent;
-
-static void php_phongo_commandstartedevent_free_object(zend_object* object) /* {{{ */
-{
- php_phongo_commandstartedevent_t* intern = Z_OBJ_COMMANDSTARTEDEVENT(object);
-
- zend_object_std_dtor(&intern->std);
-
- if (!Z_ISUNDEF(intern->manager)) {
- zval_ptr_dtor(&intern->manager);
- }
-
- if (intern->command) {
- bson_destroy(intern->command);
- }
-
- if (intern->command_name) {
- efree(intern->command_name);
- }
-
- if (intern->database_name) {
- efree(intern->database_name);
- }
-} /* }}} */
-
-static zend_object* php_phongo_commandstartedevent_create_object(zend_class_entry* class_type) /* {{{ */
-{
- php_phongo_commandstartedevent_t* intern = NULL;
-
- intern = PHONGO_ALLOC_OBJECT_T(php_phongo_commandstartedevent_t, class_type);
-
- zend_object_std_init(&intern->std, class_type);
- object_properties_init(&intern->std, class_type);
-
- intern->std.handlers = &php_phongo_handler_commandstartedevent;
-
- return &intern->std;
-} /* }}} */
-
-static HashTable* php_phongo_commandstartedevent_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
-{
- php_phongo_commandstartedevent_t* intern;
- zval retval = ZVAL_STATIC_INIT;
- char operation_id[20], request_id[20];
- php_phongo_bson_state command_state;
-
- PHONGO_BSON_INIT_STATE(command_state);
-
- intern = Z_OBJ_COMMANDSTARTEDEVENT(PHONGO_COMPAT_GET_OBJ(object));
- *is_temp = 1;
- array_init_size(&retval, 6);
-
- if (!php_phongo_bson_to_zval_ex(bson_get_data(intern->command), intern->command->len, &command_state)) {
- zval_ptr_dtor(&command_state.zchild);
- goto done;
- }
-
- ADD_ASSOC_ZVAL(&retval, "command", &command_state.zchild);
-
- ADD_ASSOC_STRING(&retval, "commandName", intern->command_name);
- ADD_ASSOC_STRING(&retval, "databaseName", intern->database_name);
-
- sprintf(operation_id, "%" PRIu64, intern->operation_id);
- ADD_ASSOC_STRING(&retval, "operationId", operation_id);
-
- sprintf(request_id, "%" PRIu64, intern->request_id);
- ADD_ASSOC_STRING(&retval, "requestId", request_id);
-
- {
- zval server;
-
- phongo_server_init(&server, &intern->manager, intern->server_id);
- ADD_ASSOC_ZVAL_EX(&retval, "server", &server);
- }
-
- if (intern->has_service_id) {
- zval service_id;
-
- phongo_objectid_init(&service_id, &intern->service_id);
- ADD_ASSOC_ZVAL_EX(&retval, "serviceId", &service_id);
- } else {
- ADD_ASSOC_NULL_EX(&retval, "serviceId");
- }
-
-done:
- return Z_ARRVAL(retval);
-} /* }}} */
-/* }}} */
-
-void php_phongo_commandstartedevent_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
- (void) type;
- (void) module_number;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver\\Monitoring", "CommandStartedEvent", php_phongo_commandstartedevent_me);
- php_phongo_commandstartedevent_ce = zend_register_internal_class(&ce);
- php_phongo_commandstartedevent_ce->create_object = php_phongo_commandstartedevent_create_object;
- PHONGO_CE_FINAL(php_phongo_commandstartedevent_ce);
- PHONGO_CE_DISABLE_SERIALIZATION(php_phongo_commandstartedevent_ce);
-
- memcpy(&php_phongo_handler_commandstartedevent, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
- php_phongo_handler_commandstartedevent.get_debug_info = php_phongo_commandstartedevent_get_debug_info;
- php_phongo_handler_commandstartedevent.free_obj = php_phongo_commandstartedevent_free_object;
- php_phongo_handler_commandstartedevent.offset = XtOffsetOf(php_phongo_commandstartedevent_t, std);
-
- return;
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/MongoDB/Monitoring/CommandSubscriber.c b/mongodb-1.12.0/src/MongoDB/Monitoring/CommandSubscriber.c
deleted file mode 100644
index 0de7dee3..00000000
--- a/mongodb-1.12.0/src/MongoDB/Monitoring/CommandSubscriber.c
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright 2016-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-#include <Zend/zend_interfaces.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-
-zend_class_entry* php_phongo_commandsubscriber_ce;
-
-/* {{{ MongoDB\Driver\Monitoring\CommandSubscriber function entries */
-ZEND_BEGIN_ARG_INFO_EX(ai_CommandSubscriber_commandStarted, 0, 0, 1)
- ZEND_ARG_OBJ_INFO(0, event, MongoDB\\Driver\\Monitoring\\CommandStartedEvent, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_CommandSubscriber_commandSucceeded, 0, 0, 1)
- ZEND_ARG_OBJ_INFO(0, event, MongoDB\\Driver\\Monitoring\\CommandSucceededEvent, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_CommandSubscriber_commandFailed, 0, 0, 1)
- ZEND_ARG_OBJ_INFO(0, event, MongoDB\\Driver\\Monitoring\\CommandFailedEvent, 0)
-ZEND_END_ARG_INFO()
-
-static zend_function_entry php_phongo_commandsubscriber_me[] = {
- /* clang-format off */
- ZEND_ABSTRACT_ME(CommandSubscriber, commandStarted, ai_CommandSubscriber_commandStarted)
- ZEND_ABSTRACT_ME(CommandSubscriber, commandSucceeded, ai_CommandSubscriber_commandSucceeded)
- ZEND_ABSTRACT_ME(CommandSubscriber, commandFailed, ai_CommandSubscriber_commandFailed)
- PHP_FE_END
- /* clang-format on */
-};
-/* }}} */
-
-void php_phongo_commandsubscriber_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
- (void) type;
- (void) module_number;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver\\Monitoring", "CommandSubscriber", php_phongo_commandsubscriber_me);
- php_phongo_commandsubscriber_ce = zend_register_internal_interface(&ce);
- zend_class_implements(php_phongo_commandsubscriber_ce, 1, php_phongo_subscriber_ce);
-
- return;
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/MongoDB/Monitoring/CommandSucceededEvent.c b/mongodb-1.12.0/src/MongoDB/Monitoring/CommandSucceededEvent.c
deleted file mode 100644
index 9c2010f6..00000000
--- a/mongodb-1.12.0/src/MongoDB/Monitoring/CommandSucceededEvent.c
+++ /dev/null
@@ -1,309 +0,0 @@
-/*
- * Copyright 2016-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-#include <Zend/zend_interfaces.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-
-zend_class_entry* php_phongo_commandsucceededevent_ce;
-
-/* {{{ proto string CommandSucceededEvent::getCommandName()
- Returns the command name for this event */
-PHP_METHOD(CommandSucceededEvent, getCommandName)
-{
- zend_error_handling error_handling;
- php_phongo_commandsucceededevent_t* intern;
-
- intern = Z_COMMANDSUCCEEDEDEVENT_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- RETVAL_STRING(intern->command_name);
-} /* }}} */
-
-/* {{{ proto int CommandSucceededEvent::getDurationMicros()
- Returns the event's duration in microseconds */
-PHP_METHOD(CommandSucceededEvent, getDurationMicros)
-{
- zend_error_handling error_handling;
- php_phongo_commandsucceededevent_t* intern;
-
- intern = Z_COMMANDSUCCEEDEDEVENT_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- RETURN_LONG(intern->duration_micros);
-} /* }}} */
-
-/* {{{ proto string CommandSucceededEvent::getOperationId()
- Returns the event's operation ID */
-PHP_METHOD(CommandSucceededEvent, getOperationId)
-{
- zend_error_handling error_handling;
- php_phongo_commandsucceededevent_t* intern;
- char int_as_string[20];
-
- intern = Z_COMMANDSUCCEEDEDEVENT_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- sprintf(int_as_string, "%" PRIu64, intern->operation_id);
- RETVAL_STRING(int_as_string);
-} /* }}} */
-
-/* {{{ proto stdClass CommandSucceededEvent::getReply()
- Returns the reply document associated with the event */
-PHP_METHOD(CommandSucceededEvent, getReply)
-{
- zend_error_handling error_handling;
- php_phongo_commandsucceededevent_t* intern;
- php_phongo_bson_state state;
-
- PHONGO_BSON_INIT_STATE(state);
-
- intern = Z_COMMANDSUCCEEDEDEVENT_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- if (!php_phongo_bson_to_zval_ex(bson_get_data(intern->reply), intern->reply->len, &state)) {
- zval_ptr_dtor(&state.zchild);
- return;
- }
-
- RETURN_ZVAL(&state.zchild, 0, 1);
-} /* }}} */
-
-/* {{{ proto string CommandsucceededEvent::getRequestId()
- Returns the event's request ID */
-PHP_METHOD(CommandSucceededEvent, getRequestId)
-{
- zend_error_handling error_handling;
- php_phongo_commandsucceededevent_t* intern;
- char int_as_string[20];
-
- intern = Z_COMMANDSUCCEEDEDEVENT_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- sprintf(int_as_string, "%" PRIu64, intern->request_id);
- RETVAL_STRING(int_as_string);
-} /* }}} */
-
-/* {{{ proto MongoDB\Driver\Server CommandSucceededEvent::getServer()
- Returns the Server from which the event originated */
-PHP_METHOD(CommandSucceededEvent, getServer)
-{
- zend_error_handling error_handling;
- php_phongo_commandsucceededevent_t* intern;
-
- intern = Z_COMMANDSUCCEEDEDEVENT_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- phongo_server_init(return_value, &intern->manager, intern->server_id);
-} /* }}} */
-
-/* {{{ proto MongoDB\BSON\ObjectId|null CommandSucceededEvent::getServiceId()
- Returns the event's service ID */
-PHP_METHOD(CommandSucceededEvent, getServiceId)
-{
- php_phongo_commandsucceededevent_t* intern = Z_COMMANDSUCCEEDEDEVENT_OBJ_P(getThis());
-
- PHONGO_PARSE_PARAMETERS_NONE();
-
- if (!intern->has_service_id) {
- RETURN_NULL();
- }
-
- phongo_objectid_init(return_value, &intern->service_id);
-} /* }}} */
-
-/**
- * Event thrown when a command has succeeded to execute.
- *
- * This class is only constructed internally.
- */
-
-/* {{{ MongoDB\Driver\Monitoring\CommandSucceededEvent function entries */
-ZEND_BEGIN_ARG_INFO_EX(ai_CommandSucceededEvent_void, 0, 0, 0)
-ZEND_END_ARG_INFO()
-
-static zend_function_entry php_phongo_commandsucceededevent_me[] = {
- /* clang-format off */
- ZEND_NAMED_ME(__construct, PHP_FN(MongoDB_disabled___construct), ai_CommandSucceededEvent_void, ZEND_ACC_PRIVATE | ZEND_ACC_FINAL)
- PHP_ME(CommandSucceededEvent, getCommandName, ai_CommandSucceededEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(CommandSucceededEvent, getDurationMicros, ai_CommandSucceededEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(CommandSucceededEvent, getOperationId, ai_CommandSucceededEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(CommandSucceededEvent, getReply, ai_CommandSucceededEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(CommandSucceededEvent, getRequestId, ai_CommandSucceededEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(CommandSucceededEvent, getServer, ai_CommandSucceededEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(CommandSucceededEvent, getServiceId, ai_CommandSucceededEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- ZEND_NAMED_ME(__wakeup, PHP_FN(MongoDB_disabled___wakeup), ai_CommandSucceededEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_FE_END
- /* clang-format on */
-};
-/* }}} */
-
-/* {{{ MongoDB\Driver\Monitoring\CommandSucceededEvent object handlers */
-static zend_object_handlers php_phongo_handler_commandsucceededevent;
-
-static void php_phongo_commandsucceededevent_free_object(zend_object* object) /* {{{ */
-{
- php_phongo_commandsucceededevent_t* intern = Z_OBJ_COMMANDSUCCEEDEDEVENT(object);
-
- zend_object_std_dtor(&intern->std);
-
- if (!Z_ISUNDEF(intern->manager)) {
- zval_ptr_dtor(&intern->manager);
- }
-
- if (intern->reply) {
- bson_destroy(intern->reply);
- }
-
- if (intern->command_name) {
- efree(intern->command_name);
- }
-} /* }}} */
-
-static zend_object* php_phongo_commandsucceededevent_create_object(zend_class_entry* class_type) /* {{{ */
-{
- php_phongo_commandsucceededevent_t* intern = NULL;
-
- intern = PHONGO_ALLOC_OBJECT_T(php_phongo_commandsucceededevent_t, class_type);
-
- zend_object_std_init(&intern->std, class_type);
- object_properties_init(&intern->std, class_type);
-
- intern->std.handlers = &php_phongo_handler_commandsucceededevent;
-
- return &intern->std;
-} /* }}} */
-
-static HashTable* php_phongo_commandsucceededevent_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
-{
- php_phongo_commandsucceededevent_t* intern;
- zval retval = ZVAL_STATIC_INIT;
- char operation_id[20], request_id[20];
- php_phongo_bson_state reply_state;
-
- PHONGO_BSON_INIT_STATE(reply_state);
-
- intern = Z_OBJ_COMMANDSUCCEEDEDEVENT(PHONGO_COMPAT_GET_OBJ(object));
- *is_temp = 1;
- array_init_size(&retval, 6);
-
- ADD_ASSOC_STRING(&retval, "commandName", intern->command_name);
- ADD_ASSOC_INT64(&retval, "durationMicros", (int64_t) intern->duration_micros);
-
- sprintf(operation_id, "%" PRIu64, intern->operation_id);
- ADD_ASSOC_STRING(&retval, "operationId", operation_id);
-
- if (!php_phongo_bson_to_zval_ex(bson_get_data(intern->reply), intern->reply->len, &reply_state)) {
- zval_ptr_dtor(&reply_state.zchild);
- goto done;
- }
-
- ADD_ASSOC_ZVAL(&retval, "reply", &reply_state.zchild);
-
- sprintf(request_id, "%" PRIu64, intern->request_id);
- ADD_ASSOC_STRING(&retval, "requestId", request_id);
-
- {
- zval server;
-
- phongo_server_init(&server, &intern->manager, intern->server_id);
- ADD_ASSOC_ZVAL_EX(&retval, "server", &server);
- }
-
- if (intern->has_service_id) {
- zval service_id;
-
- phongo_objectid_init(&service_id, &intern->service_id);
- ADD_ASSOC_ZVAL_EX(&retval, "serviceId", &service_id);
- } else {
- ADD_ASSOC_NULL_EX(&retval, "serviceId");
- }
-
-done:
- return Z_ARRVAL(retval);
-} /* }}} */
-/* }}} */
-
-void php_phongo_commandsucceededevent_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
- (void) type;
- (void) module_number;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver\\Monitoring", "CommandSucceededEvent", php_phongo_commandsucceededevent_me);
- php_phongo_commandsucceededevent_ce = zend_register_internal_class(&ce);
- php_phongo_commandsucceededevent_ce->create_object = php_phongo_commandsucceededevent_create_object;
- PHONGO_CE_FINAL(php_phongo_commandsucceededevent_ce);
- PHONGO_CE_DISABLE_SERIALIZATION(php_phongo_commandsucceededevent_ce);
-
- memcpy(&php_phongo_handler_commandsucceededevent, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
- php_phongo_handler_commandsucceededevent.get_debug_info = php_phongo_commandsucceededevent_get_debug_info;
- php_phongo_handler_commandsucceededevent.free_obj = php_phongo_commandsucceededevent_free_object;
- php_phongo_handler_commandsucceededevent.offset = XtOffsetOf(php_phongo_commandsucceededevent_t, std);
-
- return;
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/MongoDB/Monitoring/Subscriber.c b/mongodb-1.12.0/src/MongoDB/Monitoring/Subscriber.c
deleted file mode 100644
index ef716e47..00000000
--- a/mongodb-1.12.0/src/MongoDB/Monitoring/Subscriber.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright 2016-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-#include <Zend/zend_interfaces.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-
-zend_class_entry* php_phongo_subscriber_ce;
-
-/* {{{ MongoDB\Driver\Monitoring\Subscriber function entries */
-static zend_function_entry php_phongo_subscriber_me[] = {
- PHP_FE_END
-};
-/* }}} */
-
-void php_phongo_subscriber_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
- (void) type;
- (void) module_number;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver\\Monitoring", "Subscriber", php_phongo_subscriber_me);
- php_phongo_subscriber_ce = zend_register_internal_interface(&ce);
-
- return;
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/MongoDB/Monitoring/functions.c b/mongodb-1.12.0/src/MongoDB/Monitoring/functions.c
deleted file mode 100644
index 8e90602d..00000000
--- a/mongodb-1.12.0/src/MongoDB/Monitoring/functions.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright 2016-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-#include "src/phongo_apm.h"
-
-ZEND_EXTERN_MODULE_GLOBALS(mongodb)
-
-/* {{{ proto void MongoDB\Driver\Monitoring\addSubscriber(MongoDB\Driver\Monitoring\Subscriber $subscriber)
- Registers a global event subscriber */
-PHP_FUNCTION(MongoDB_Driver_Monitoring_addSubscriber)
-{
- zval* subscriber;
-
- PHONGO_PARSE_PARAMETERS_START(1, 1)
- Z_PARAM_OBJECT_OF_CLASS(subscriber, php_phongo_subscriber_ce)
- PHONGO_PARSE_PARAMETERS_END();
-
- phongo_apm_add_subscriber(MONGODB_G(subscribers), subscriber);
-} /* }}} */
-
-/* {{{ proto void MongoDB\Driver\Monitoring\removeSubscriber(MongoDB\Driver\Monitoring\Subscriber $subscriber)
- Unregisters a global event subscriber */
-PHP_FUNCTION(MongoDB_Driver_Monitoring_removeSubscriber)
-{
- zval* subscriber;
-
- PHONGO_PARSE_PARAMETERS_START(1, 1)
- Z_PARAM_OBJECT_OF_CLASS(subscriber, php_phongo_subscriber_ce)
- PHONGO_PARSE_PARAMETERS_END();
-
- phongo_apm_remove_subscriber(MONGODB_G(subscribers), subscriber);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/MongoDB/Monitoring/functions.h b/mongodb-1.12.0/src/MongoDB/Monitoring/functions.h
deleted file mode 100644
index 10790f79..00000000
--- a/mongodb-1.12.0/src/MongoDB/Monitoring/functions.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2016-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef PHONGO_MONITORING_FUNCTIONS_H
-#define PHONGO_MONITORING_FUNCTIONS_H
-
-#include <php.h>
-
-PHP_FUNCTION(MongoDB_Driver_Monitoring_addSubscriber);
-PHP_FUNCTION(MongoDB_Driver_Monitoring_removeSubscriber);
-
-#endif /* PHONGO_MONITORING_FUNCTIONS_H */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/MongoDB/Query.c b/mongodb-1.12.0/src/MongoDB/Query.c
deleted file mode 100644
index 7c590225..00000000
--- a/mongodb-1.12.0/src/MongoDB/Query.c
+++ /dev/null
@@ -1,502 +0,0 @@
-/*
- * Copyright 2014-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-#include <Zend/zend_interfaces.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "php_array_api.h"
-#include "phongo_compat.h"
-#include "php_phongo.h"
-#include "php_bson.h"
-
-zend_class_entry* php_phongo_query_ce;
-
-/* Appends a string field into the BSON options. Returns true on success;
- * otherwise, false is returned and an exception is thrown. */
-static bool php_phongo_query_opts_append_string(bson_t* opts, const char* opts_key, zval* zarr, const char* zarr_key) /* {{{ */
-{
- zval* value = php_array_fetch(zarr, zarr_key);
-
- if (Z_TYPE_P(value) != IS_STRING) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"%s\" %s to be string, %s given", zarr_key, zarr_key[0] == '$' ? "modifier" : "option", PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(value));
- return false;
- }
-
- if (!bson_append_utf8(opts, opts_key, strlen(opts_key), Z_STRVAL_P(value), Z_STRLEN_P(value))) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Error appending \"%s\" option", opts_key);
- return false;
- }
-
- return true;
-} /* }}} */
-
-/* Appends a document field for the given opts document and key. Returns true on
- * success; otherwise, false is returned and an exception is thrown. */
-static bool php_phongo_query_opts_append_document(bson_t* opts, const char* opts_key, zval* zarr, const char* zarr_key) /* {{{ */
-{
- zval* value = php_array_fetch(zarr, zarr_key);
- bson_t b = BSON_INITIALIZER;
-
- if (Z_TYPE_P(value) != IS_OBJECT && Z_TYPE_P(value) != IS_ARRAY) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"%s\" %s to be array or object, %s given", zarr_key, zarr_key[0] == '$' ? "modifier" : "option", PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(value));
- return false;
- }
-
- php_phongo_zval_to_bson(value, PHONGO_BSON_NONE, &b, NULL);
-
- if (EG(exception)) {
- bson_destroy(&b);
- return false;
- }
-
- if (!bson_validate(&b, BSON_VALIDATE_EMPTY_KEYS, NULL)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Cannot use empty keys in \"%s\" %s", zarr_key, zarr_key[0] == '$' ? "modifier" : "option");
- bson_destroy(&b);
- return false;
- }
-
- if (!BSON_APPEND_DOCUMENT(opts, opts_key, &b)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Error appending \"%s\" option", opts_key);
- bson_destroy(&b);
- return false;
- }
-
- bson_destroy(&b);
- return true;
-} /* }}} */
-
-#define PHONGO_QUERY_OPT_BOOL_EX(opt, zarr, key, deprecated) \
- if ((zarr) && php_array_existsc((zarr), (key))) { \
- if ((deprecated)) { \
- php_error_docref(NULL, E_DEPRECATED, "The \"%s\" option is deprecated and will be removed in a future release", key); \
- } \
- if (!BSON_APPEND_BOOL(intern->opts, (opt), php_array_fetchc_bool((zarr), (key)))) { \
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Error appending \"%s\" option", (opt)); \
- return false; \
- } \
- }
-
-#define PHONGO_QUERY_OPT_BOOL(opt, zarr, key) PHONGO_QUERY_OPT_BOOL_EX((opt), (zarr), (key), 0)
-#define PHONGO_QUERY_OPT_BOOL_DEPRECATED(opt, zarr, key) PHONGO_QUERY_OPT_BOOL_EX((opt), (zarr), (key), 1)
-
-#define PHONGO_QUERY_OPT_DOCUMENT(opt, zarr, key) \
- if ((zarr) && php_array_existsc((zarr), (key))) { \
- if (!php_phongo_query_opts_append_document(intern->opts, (opt), (zarr), (key))) { \
- return false; \
- } \
- }
-
-/* Note: handling of integer options will depend on SIZEOF_ZEND_LONG and we
- * are not converting strings to 64-bit integers for 32-bit platforms. */
-
-#define PHONGO_QUERY_OPT_INT64_EX(opt, zarr, key, deprecated) \
- if ((zarr) && php_array_existsc((zarr), (key))) { \
- if ((deprecated)) { \
- php_error_docref(NULL, E_DEPRECATED, "The \"%s\" option is deprecated and will be removed in a future release", key); \
- } \
- if (!BSON_APPEND_INT64(intern->opts, (opt), php_array_fetchc_long((zarr), (key)))) { \
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Error appending \"%s\" option", (opt)); \
- return false; \
- } \
- }
-
-#define PHONGO_QUERY_OPT_INT64(opt, zarr, key) PHONGO_QUERY_OPT_INT64_EX((opt), (zarr), (key), 0)
-#define PHONGO_QUERY_OPT_INT64_DEPRECATED(opt, zarr, key) PHONGO_QUERY_OPT_INT64_EX((opt), (zarr), (key), 1)
-
-#define PHONGO_QUERY_OPT_STRING(opt, zarr, key) \
- if ((zarr) && php_array_existsc((zarr), (key))) { \
- if (!php_phongo_query_opts_append_string(intern->opts, (opt), (zarr), (key))) { \
- return false; \
- } \
- }
-
-/* Initialize the "hint" option. Returns true on success; otherwise, false is
- * returned and an exception is thrown.
- *
- * The "hint" option (or "$hint" modifier) must be a string or document. Check
- * for both types and merge into BSON options accordingly. */
-static bool php_phongo_query_init_hint(php_phongo_query_t* intern, zval* options, zval* modifiers) /* {{{ */
-{
- /* The "hint" option (or "$hint" modifier) must be a string or document.
- * Check for both types and merge into BSON options accordingly. */
- if (php_array_existsc(options, "hint")) {
- zend_uchar type = Z_TYPE_P(php_array_fetchc(options, "hint"));
-
- if (type == IS_STRING) {
- PHONGO_QUERY_OPT_STRING("hint", options, "hint");
- } else if (type == IS_OBJECT || type == IS_ARRAY) {
- PHONGO_QUERY_OPT_DOCUMENT("hint", options, "hint");
- } else {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"hint\" option to be string, array, or object, %s given", zend_get_type_by_const(type));
- return false;
- }
- } else if (modifiers && php_array_existsc(modifiers, "$hint")) {
- zend_uchar type = Z_TYPE_P(php_array_fetchc(modifiers, "$hint"));
-
- if (type == IS_STRING) {
- PHONGO_QUERY_OPT_STRING("hint", modifiers, "$hint");
- } else if (type == IS_OBJECT || type == IS_ARRAY) {
- PHONGO_QUERY_OPT_DOCUMENT("hint", modifiers, "$hint");
- } else {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"$hint\" modifier to be string, array, or object, %s given", zend_get_type_by_const(type));
- return false;
- }
- }
-
- return true;
-} /* }}} */
-
-/* Initialize the "limit" and "singleBatch" options. Returns true on success;
- * otherwise, false is returned and an exception is thrown.
- *
- * mongoc_collection_find_with_opts() requires a non-negative limit. For
- * backwards compatibility, a negative limit should be set as a positive value
- * and default singleBatch to true. */
-static bool php_phongo_query_init_limit_and_singlebatch(php_phongo_query_t* intern, zval* options) /* {{{ */
-{
- if (php_array_fetchc_long(options, "limit") < 0) {
- zend_long limit = php_array_fetchc_long(options, "limit");
-
- if (!BSON_APPEND_INT64(intern->opts, "limit", -limit)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Error appending \"limit\" option");
- return false;
- }
-
- if (php_array_existsc(options, "singleBatch") && !php_array_fetchc_bool(options, "singleBatch")) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Negative \"limit\" option conflicts with false \"singleBatch\" option");
- return false;
- } else {
- if (!BSON_APPEND_BOOL(intern->opts, "singleBatch", true)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Error appending \"singleBatch\" option");
- return false;
- }
- }
- } else {
- PHONGO_QUERY_OPT_INT64("limit", options, "limit");
- PHONGO_QUERY_OPT_BOOL("singleBatch", options, "singleBatch");
- }
-
- return true;
-} /* }}} */
-
-/* Initialize the "readConcern" option. Returns true on success; otherwise,
- * false is returned and an exception is thrown.
- *
- * The "readConcern" option should be a MongoDB\Driver\ReadConcern instance,
- * which must be converted to a mongoc_read_concern_t. */
-static bool php_phongo_query_init_readconcern(php_phongo_query_t* intern, zval* options) /* {{{ */
-{
- zval* read_concern;
-
- if (!php_array_existsc(options, "readConcern")) {
- return true;
- }
-
- read_concern = php_array_fetchc(options, "readConcern");
-
- if (Z_TYPE_P(read_concern) != IS_OBJECT || !instanceof_function(Z_OBJCE_P(read_concern), php_phongo_readconcern_ce)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"readConcern\" option to be %s, %s given", ZSTR_VAL(php_phongo_readconcern_ce->name), PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(read_concern));
- return false;
- }
-
- intern->read_concern = mongoc_read_concern_copy(phongo_read_concern_from_zval(read_concern));
-
- return true;
-} /* }}} */
-
-/* Initialize the "maxAwaitTimeMS" option. Returns true on success; otherwise,
- * false is returned and an exception is thrown.
- *
- * The "maxAwaitTimeMS" option is assigned to the cursor after query execution
- * via mongoc_cursor_set_max_await_time_ms(). */
-static bool php_phongo_query_init_max_await_time_ms(php_phongo_query_t* intern, zval* options) /* {{{ */
-{
- int64_t max_await_time_ms;
-
- if (!php_array_existsc(options, "maxAwaitTimeMS")) {
- return true;
- }
-
- max_await_time_ms = php_array_fetchc_long(options, "maxAwaitTimeMS");
-
- if (max_await_time_ms < 0) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"maxAwaitTimeMS\" option to be >= 0, %" PRId64 " given", max_await_time_ms);
- return false;
- }
-
- if (max_await_time_ms > UINT32_MAX) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"maxAwaitTimeMS\" option to be <= %" PRIu32 ", %" PRId64 " given", UINT32_MAX, max_await_time_ms);
- return false;
- }
-
- intern->max_await_time_ms = (uint32_t) max_await_time_ms;
-
- return true;
-} /* }}} */
-
-/* Initializes the php_phongo_query_t from filter and options arguments. This
- * function will fall back to a modifier in the absence of a top-level option
- * (where applicable). */
-static bool php_phongo_query_init(php_phongo_query_t* intern, zval* filter, zval* options) /* {{{ */
-{
- zval* modifiers = NULL;
-
- intern->filter = bson_new();
- intern->opts = bson_new();
- intern->max_await_time_ms = 0;
-
- php_phongo_zval_to_bson(filter, PHONGO_BSON_NONE, intern->filter, NULL);
-
- /* Note: if any exceptions are thrown, we can simply return as PHP will
- * invoke php_phongo_query_free_object to destruct the object. */
- if (EG(exception)) {
- return false;
- }
-
- if (!bson_validate(intern->filter, BSON_VALIDATE_EMPTY_KEYS, NULL)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Cannot use empty keys in filter document");
- return false;
- }
-
- if (!options) {
- return true;
- }
-
- if (php_array_existsc(options, "modifiers")) {
- modifiers = php_array_fetchc(options, "modifiers");
-
- if (Z_TYPE_P(modifiers) != IS_ARRAY) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"modifiers\" option to be array, %s given", PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(modifiers));
- return false;
- }
- }
-
- PHONGO_QUERY_OPT_BOOL("allowDiskUse", options, "allowDiskUse")
- PHONGO_QUERY_OPT_BOOL("allowPartialResults", options, "allowPartialResults")
- else PHONGO_QUERY_OPT_BOOL("allowPartialResults", options, "partial");
- PHONGO_QUERY_OPT_BOOL("awaitData", options, "awaitData");
- PHONGO_QUERY_OPT_INT64("batchSize", options, "batchSize");
- PHONGO_QUERY_OPT_DOCUMENT("collation", options, "collation");
- PHONGO_QUERY_OPT_STRING("comment", options, "comment")
- else PHONGO_QUERY_OPT_STRING("comment", modifiers, "$comment");
- PHONGO_QUERY_OPT_BOOL("exhaust", options, "exhaust");
- PHONGO_QUERY_OPT_DOCUMENT("max", options, "max")
- else PHONGO_QUERY_OPT_DOCUMENT("max", modifiers, "$max");
- PHONGO_QUERY_OPT_INT64_DEPRECATED("maxScan", options, "maxScan")
- else PHONGO_QUERY_OPT_INT64_DEPRECATED("maxScan", modifiers, "$maxScan");
- PHONGO_QUERY_OPT_INT64("maxTimeMS", options, "maxTimeMS")
- else PHONGO_QUERY_OPT_INT64("maxTimeMS", modifiers, "$maxTimeMS");
- PHONGO_QUERY_OPT_DOCUMENT("min", options, "min")
- else PHONGO_QUERY_OPT_DOCUMENT("min", modifiers, "$min");
- PHONGO_QUERY_OPT_BOOL("noCursorTimeout", options, "noCursorTimeout");
- PHONGO_QUERY_OPT_BOOL_DEPRECATED("oplogReplay", options, "oplogReplay");
- PHONGO_QUERY_OPT_DOCUMENT("projection", options, "projection");
- PHONGO_QUERY_OPT_BOOL("returnKey", options, "returnKey")
- else PHONGO_QUERY_OPT_BOOL("returnKey", modifiers, "$returnKey");
- PHONGO_QUERY_OPT_BOOL("showRecordId", options, "showRecordId")
- else PHONGO_QUERY_OPT_BOOL("showRecordId", modifiers, "$showDiskLoc");
- PHONGO_QUERY_OPT_INT64("skip", options, "skip");
- PHONGO_QUERY_OPT_DOCUMENT("sort", options, "sort")
- else PHONGO_QUERY_OPT_DOCUMENT("sort", modifiers, "$orderby");
- PHONGO_QUERY_OPT_BOOL_DEPRECATED("snapshot", options, "snapshot")
- else PHONGO_QUERY_OPT_BOOL_DEPRECATED("snapshot", modifiers, "$snapshot");
- PHONGO_QUERY_OPT_BOOL("tailable", options, "tailable");
-
- /* The "$explain" modifier should be converted to an "explain" option, which
- * libmongoc will later convert back to a modifier for the OP_QUERY code
- * path. This modifier will be ignored for the find command code path. */
- PHONGO_QUERY_OPT_BOOL("explain", modifiers, "$explain");
-
- if (!php_phongo_query_init_hint(intern, options, modifiers)) {
- return false;
- }
-
- if (!php_phongo_query_init_limit_and_singlebatch(intern, options)) {
- return false;
- }
-
- if (!php_phongo_query_init_readconcern(intern, options)) {
- return false;
- }
-
- if (!php_phongo_query_init_max_await_time_ms(intern, options)) {
- return false;
- }
-
- return true;
-} /* }}} */
-
-#undef PHONGO_QUERY_OPT_BOOL
-#undef PHONGO_QUERY_OPT_DOCUMENT
-#undef PHONGO_QUERY_OPT_INT64
-#undef PHONGO_QUERY_OPT_STRING
-
-/* {{{ proto void MongoDB\Driver\Query::__construct(array|object $filter[, array $options = array()])
- Constructs a new Query */
-static PHP_METHOD(Query, __construct)
-{
- zend_error_handling error_handling;
- php_phongo_query_t* intern;
- zval* filter;
- zval* options = NULL;
-
- intern = Z_QUERY_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "A|a!", &filter, &options) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- php_phongo_query_init(intern, filter, options);
-} /* }}} */
-
-/* {{{ MongoDB\Driver\Query function entries */
-ZEND_BEGIN_ARG_INFO_EX(ai_Query___construct, 0, 0, 1)
- ZEND_ARG_INFO(0, filter)
- ZEND_ARG_ARRAY_INFO(0, options, 1)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_Query_void, 0, 0, 0)
-ZEND_END_ARG_INFO()
-
-static zend_function_entry php_phongo_query_me[] = {
- /* clang-format off */
- PHP_ME(Query, __construct, ai_Query___construct, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- ZEND_NAMED_ME(__wakeup, PHP_FN(MongoDB_disabled___wakeup), ai_Query_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_FE_END
- /* clang-format on */
-};
-/* }}} */
-
-/* {{{ MongoDB\Driver\Query object handlers */
-static zend_object_handlers php_phongo_handler_query;
-
-static void php_phongo_query_free_object(zend_object* object) /* {{{ */
-{
- php_phongo_query_t* intern = Z_OBJ_QUERY(object);
-
- zend_object_std_dtor(&intern->std);
-
- if (intern->filter) {
- bson_clear(&intern->filter);
- }
-
- if (intern->opts) {
- bson_clear(&intern->opts);
- }
-
- if (intern->read_concern) {
- mongoc_read_concern_destroy(intern->read_concern);
- }
-} /* }}} */
-
-static zend_object* php_phongo_query_create_object(zend_class_entry* class_type) /* {{{ */
-{
- php_phongo_query_t* intern = NULL;
-
- intern = PHONGO_ALLOC_OBJECT_T(php_phongo_query_t, class_type);
-
- zend_object_std_init(&intern->std, class_type);
- object_properties_init(&intern->std, class_type);
-
- intern->std.handlers = &php_phongo_handler_query;
-
- return &intern->std;
-} /* }}} */
-
-static HashTable* php_phongo_query_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
-{
- php_phongo_query_t* intern;
- zval retval = ZVAL_STATIC_INIT;
-
- *is_temp = 1;
- intern = Z_OBJ_QUERY(PHONGO_COMPAT_GET_OBJ(object));
-
- array_init_size(&retval, 3);
-
- /* Avoid using PHONGO_TYPEMAP_NATIVE_ARRAY for decoding filter and opts
- * documents so that users can differentiate BSON arrays and documents. */
- if (intern->filter) {
- zval zv;
-
- if (!php_phongo_bson_to_zval(bson_get_data(intern->filter), intern->filter->len, &zv)) {
- zval_ptr_dtor(&zv);
- goto done;
- }
-
- ADD_ASSOC_ZVAL_EX(&retval, "filter", &zv);
- } else {
- ADD_ASSOC_NULL_EX(&retval, "filter");
- }
-
- if (intern->opts) {
- zval zv;
-
- if (!php_phongo_bson_to_zval(bson_get_data(intern->opts), intern->opts->len, &zv)) {
- zval_ptr_dtor(&zv);
- goto done;
- }
-
- ADD_ASSOC_ZVAL_EX(&retval, "options", &zv);
- } else {
- ADD_ASSOC_NULL_EX(&retval, "options");
- }
-
- if (intern->read_concern) {
- zval read_concern;
-
- php_phongo_read_concern_to_zval(&read_concern, intern->read_concern);
- ADD_ASSOC_ZVAL_EX(&retval, "readConcern", &read_concern);
- } else {
- ADD_ASSOC_NULL_EX(&retval, "readConcern");
- }
-
-done:
- return Z_ARRVAL(retval);
-
-} /* }}} */
-/* }}} */
-
-void php_phongo_query_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver", "Query", php_phongo_query_me);
- php_phongo_query_ce = zend_register_internal_class(&ce);
- php_phongo_query_ce->create_object = php_phongo_query_create_object;
- PHONGO_CE_FINAL(php_phongo_query_ce);
- PHONGO_CE_DISABLE_SERIALIZATION(php_phongo_query_ce);
-
- memcpy(&php_phongo_handler_query, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
- php_phongo_handler_query.get_debug_info = php_phongo_query_get_debug_info;
- php_phongo_handler_query.free_obj = php_phongo_query_free_object;
- php_phongo_handler_query.offset = XtOffsetOf(php_phongo_query_t, std);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/MongoDB/ReadConcern.c b/mongodb-1.12.0/src/MongoDB/ReadConcern.c
deleted file mode 100644
index e0ed560d..00000000
--- a/mongodb-1.12.0/src/MongoDB/ReadConcern.c
+++ /dev/null
@@ -1,411 +0,0 @@
-/*
- * Copyright 2015-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-#include <Zend/zend_interfaces.h>
-#include <ext/standard/php_var.h>
-#include <zend_smart_str.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-
-zend_class_entry* php_phongo_readconcern_ce;
-
-/* Initialize the object from a HashTable and return whether it was successful.
- * An exception will be thrown on error. */
-static bool php_phongo_readconcern_init_from_hash(php_phongo_readconcern_t* intern, HashTable* props) /* {{{ */
-{
- zval* level;
-
- intern->read_concern = mongoc_read_concern_new();
-
- if ((level = zend_hash_str_find(props, "level", sizeof("level") - 1))) {
- if (Z_TYPE_P(level) == IS_STRING) {
- mongoc_read_concern_set_level(intern->read_concern, Z_STRVAL_P(level));
- return true;
- }
-
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"level\" string field", ZSTR_VAL(php_phongo_readconcern_ce->name));
- goto failure;
- }
-
- return true;
-
-failure:
- mongoc_read_concern_destroy(intern->read_concern);
- intern->read_concern = NULL;
- return false;
-} /* }}} */
-
-/* {{{ proto void MongoDB\Driver\ReadConcern::__construct([string $level])
- Constructs a new ReadConcern */
-static PHP_METHOD(ReadConcern, __construct)
-{
- zend_error_handling error_handling;
- php_phongo_readconcern_t* intern;
- char* level = NULL;
- size_t level_len = 0;
-
- intern = Z_READCONCERN_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s!", &level, &level_len) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- intern->read_concern = mongoc_read_concern_new();
-
- if (level) {
- mongoc_read_concern_set_level(intern->read_concern, level);
- }
-} /* }}} */
-
-/* {{{ proto MongoDB\Driver\ReadConcern MongoDB\Driver\ReadConcern::__set_state(array $properties)
-*/
-static PHP_METHOD(ReadConcern, __set_state)
-{
- zend_error_handling error_handling;
- php_phongo_readconcern_t* intern;
- HashTable* props;
- zval* array;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &array) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- object_init_ex(return_value, php_phongo_readconcern_ce);
-
- intern = Z_READCONCERN_OBJ_P(return_value);
- props = Z_ARRVAL_P(array);
-
- php_phongo_readconcern_init_from_hash(intern, props);
-} /* }}} */
-
-/* {{{ proto string|null MongoDB\Driver\ReadConcern::getLevel()
- Returns the ReadConcern "level" option */
-static PHP_METHOD(ReadConcern, getLevel)
-{
- zend_error_handling error_handling;
- php_phongo_readconcern_t* intern;
- const char* level;
-
- intern = Z_READCONCERN_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- level = mongoc_read_concern_get_level(intern->read_concern);
-
- if (level) {
- RETURN_STRING(level);
- }
-
- RETURN_NULL();
-} /* }}} */
-
-/* {{{ proto boolean MongoDB\Driver\ReadConcern::isDefault()
- Returns whether the read concern has not been modified (i.e. constructed
- without a level or from a Manager with no read concern URI options). */
-static PHP_METHOD(ReadConcern, isDefault)
-{
- zend_error_handling error_handling;
- php_phongo_readconcern_t* intern;
-
- intern = Z_READCONCERN_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- RETURN_BOOL(mongoc_read_concern_is_default(intern->read_concern));
-} /* }}} */
-
-static HashTable* php_phongo_readconcern_get_properties_hash(phongo_compat_object_handler_type* object, bool is_temp) /* {{{ */
-{
- php_phongo_readconcern_t* intern;
- HashTable* props;
- const char* level;
-
- intern = Z_OBJ_READCONCERN(PHONGO_COMPAT_GET_OBJ(object));
-
- PHONGO_GET_PROPERTY_HASH_INIT_PROPS(is_temp, intern, props, 1);
-
- if (!intern->read_concern) {
- return props;
- }
-
- level = mongoc_read_concern_get_level(intern->read_concern);
-
- if (level) {
- zval z_level;
-
- ZVAL_STRING(&z_level, level);
- zend_hash_str_update(props, "level", sizeof("level") - 1, &z_level);
- }
-
- return props;
-} /* }}} */
-
-/* {{{ proto array MongoDB\Driver\ReadConcern::bsonSerialize()
-*/
-static PHP_METHOD(ReadConcern, bsonSerialize)
-{
- zend_error_handling error_handling;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- ZVAL_ARR(return_value, php_phongo_readconcern_get_properties_hash(PHONGO_COMPAT_OBJ_P(getThis()), true));
- convert_to_object(return_value);
-} /* }}} */
-
-/* {{{ proto string MongoDB\Driver\ReadConcern::serialize()
-*/
-static PHP_METHOD(ReadConcern, serialize)
-{
- zend_error_handling error_handling;
- php_phongo_readconcern_t* intern;
- zval retval;
- php_serialize_data_t var_hash;
- smart_str buf = { 0 };
- const char* level;
-
- intern = Z_READCONCERN_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- if (!intern->read_concern) {
- return;
- }
-
- level = mongoc_read_concern_get_level(intern->read_concern);
-
- if (!level) {
- RETURN_STRING("");
- }
-
- array_init_size(&retval, 1);
- ADD_ASSOC_STRING(&retval, "level", level);
-
- PHP_VAR_SERIALIZE_INIT(var_hash);
- php_var_serialize(&buf, &retval, &var_hash);
- smart_str_0(&buf);
- PHP_VAR_SERIALIZE_DESTROY(var_hash);
-
- PHONGO_RETVAL_SMART_STR(buf);
-
- smart_str_free(&buf);
- zval_ptr_dtor(&retval);
-} /* }}} */
-
-/* {{{ proto void MongoDB\Driver\ReadConcern::unserialize(string $serialized)
-*/
-static PHP_METHOD(ReadConcern, unserialize)
-{
- zend_error_handling error_handling;
- php_phongo_readconcern_t* intern;
- char* serialized;
- size_t serialized_len;
- zval props;
- php_unserialize_data_t var_hash;
-
- intern = Z_READCONCERN_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &serialized, &serialized_len) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- if (!serialized_len) {
- return;
- }
-
- PHP_VAR_UNSERIALIZE_INIT(var_hash);
- if (!php_var_unserialize(&props, (const unsigned char**) &serialized, (unsigned char*) serialized + serialized_len, &var_hash)) {
- zval_ptr_dtor(&props);
- phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "%s unserialization failed", ZSTR_VAL(php_phongo_readconcern_ce->name));
-
- PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
- return;
- }
- PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
-
- php_phongo_readconcern_init_from_hash(intern, HASH_OF(&props));
- zval_ptr_dtor(&props);
-} /* }}} */
-
-/* {{{ proto array MongoDB\Driver\ReadConcern::__serialize()
-*/
-static PHP_METHOD(ReadConcern, __serialize)
-{
- PHONGO_PARSE_PARAMETERS_NONE();
-
- RETURN_ARR(php_phongo_readconcern_get_properties_hash(PHONGO_COMPAT_OBJ_P(getThis()), true));
-} /* }}} */
-
-/* {{{ proto void MongoDB\Driver\ReadConcern::__unserialize(array $data)
-*/
-static PHP_METHOD(ReadConcern, __unserialize)
-{
- zval* data;
-
- PHONGO_PARSE_PARAMETERS_START(1, 1)
- Z_PARAM_ARRAY(data)
- PHONGO_PARSE_PARAMETERS_END();
-
- php_phongo_readconcern_init_from_hash(Z_READCONCERN_OBJ_P(getThis()), Z_ARRVAL_P(data));
-} /* }}} */
-
-/* {{{ MongoDB\Driver\ReadConcern function entries */
-ZEND_BEGIN_ARG_INFO_EX(ai_ReadConcern___construct, 0, 0, 0)
- ZEND_ARG_INFO(0, level)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_ReadConcern___set_state, 0, 0, 1)
- ZEND_ARG_ARRAY_INFO(0, properties, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_ReadConcern___unserialize, 0, 0, 1)
- ZEND_ARG_ARRAY_INFO(0, data, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_ReadConcern_unserialize, 0, 0, 1)
- ZEND_ARG_INFO(0, serialized)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_ReadConcern_void, 0, 0, 0)
-ZEND_END_ARG_INFO()
-
-static zend_function_entry php_phongo_readconcern_me[] = {
- /* clang-format off */
- PHP_ME(ReadConcern, __construct, ai_ReadConcern___construct, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(ReadConcern, __serialize, ai_ReadConcern_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(ReadConcern, __set_state, ai_ReadConcern___set_state, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
- PHP_ME(ReadConcern, __unserialize, ai_ReadConcern___unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(ReadConcern, getLevel, ai_ReadConcern_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(ReadConcern, isDefault, ai_ReadConcern_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(ReadConcern, bsonSerialize, ai_ReadConcern_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(ReadConcern, serialize, ai_ReadConcern_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(ReadConcern, unserialize, ai_ReadConcern_unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_FE_END
- /* clang-format on */
-};
-/* }}} */
-
-/* {{{ MongoDB\Driver\ReadConcern object handlers */
-static zend_object_handlers php_phongo_handler_readconcern;
-
-static void php_phongo_readconcern_free_object(zend_object* object) /* {{{ */
-{
- php_phongo_readconcern_t* intern = Z_OBJ_READCONCERN(object);
-
- zend_object_std_dtor(&intern->std);
-
- if (intern->properties) {
- zend_hash_destroy(intern->properties);
- FREE_HASHTABLE(intern->properties);
- }
-
- if (intern->read_concern) {
- mongoc_read_concern_destroy(intern->read_concern);
- }
-}
-
-static zend_object* php_phongo_readconcern_create_object(zend_class_entry* class_type) /* {{{ */
-{
- php_phongo_readconcern_t* intern = NULL;
-
- intern = PHONGO_ALLOC_OBJECT_T(php_phongo_readconcern_t, class_type);
-
- zend_object_std_init(&intern->std, class_type);
- object_properties_init(&intern->std, class_type);
-
- intern->std.handlers = &php_phongo_handler_readconcern;
-
- return &intern->std;
-} /* }}} */
-
-static HashTable* php_phongo_readconcern_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
-{
- *is_temp = 1;
- return php_phongo_readconcern_get_properties_hash(object, true);
-} /* }}} */
-
-static HashTable* php_phongo_readconcern_get_properties(phongo_compat_object_handler_type* object) /* {{{ */
-{
- return php_phongo_readconcern_get_properties_hash(object, false);
-} /* }}} */
-
-void php_phongo_readconcern_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver", "ReadConcern", php_phongo_readconcern_me);
- php_phongo_readconcern_ce = zend_register_internal_class(&ce);
- php_phongo_readconcern_ce->create_object = php_phongo_readconcern_create_object;
- PHONGO_CE_FINAL(php_phongo_readconcern_ce);
-
- zend_class_implements(php_phongo_readconcern_ce, 1, php_phongo_serializable_ce);
- zend_class_implements(php_phongo_readconcern_ce, 1, zend_ce_serializable);
-
- memcpy(&php_phongo_handler_readconcern, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
- php_phongo_handler_readconcern.get_debug_info = php_phongo_readconcern_get_debug_info;
- php_phongo_handler_readconcern.get_properties = php_phongo_readconcern_get_properties;
- php_phongo_handler_readconcern.free_obj = php_phongo_readconcern_free_object;
- php_phongo_handler_readconcern.offset = XtOffsetOf(php_phongo_readconcern_t, std);
-
- zend_declare_class_constant_stringl(php_phongo_readconcern_ce, ZEND_STRL("LOCAL"), ZEND_STRL(MONGOC_READ_CONCERN_LEVEL_LOCAL));
- zend_declare_class_constant_stringl(php_phongo_readconcern_ce, ZEND_STRL("MAJORITY"), ZEND_STRL(MONGOC_READ_CONCERN_LEVEL_MAJORITY));
- zend_declare_class_constant_stringl(php_phongo_readconcern_ce, ZEND_STRL("LINEARIZABLE"), ZEND_STRL(MONGOC_READ_CONCERN_LEVEL_LINEARIZABLE));
- zend_declare_class_constant_stringl(php_phongo_readconcern_ce, ZEND_STRL("AVAILABLE"), ZEND_STRL(MONGOC_READ_CONCERN_LEVEL_AVAILABLE));
- zend_declare_class_constant_stringl(php_phongo_readconcern_ce, ZEND_STRL("SNAPSHOT"), ZEND_STRL(MONGOC_READ_CONCERN_LEVEL_SNAPSHOT));
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/MongoDB/ReadPreference.c b/mongodb-1.12.0/src/MongoDB/ReadPreference.c
deleted file mode 100644
index 7060b880..00000000
--- a/mongodb-1.12.0/src/MongoDB/ReadPreference.c
+++ /dev/null
@@ -1,828 +0,0 @@
-/*
- * Copyright 2014-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-#include <Zend/zend_interfaces.h>
-#include <ext/standard/php_var.h>
-#include <zend_smart_str.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "php_array_api.h"
-#include "phongo_compat.h"
-#include "php_phongo.h"
-#include "php_bson.h"
-
-zend_class_entry* php_phongo_readpreference_ce;
-
-#define PHONGO_READ_PRIMARY "primary"
-#define PHONGO_READ_PRIMARY_PREFERRED "primaryPreferred"
-#define PHONGO_READ_SECONDARY "secondary"
-#define PHONGO_READ_SECONDARY_PREFERRED "secondaryPreferred"
-#define PHONGO_READ_NEAREST "nearest"
-
-/* Initialize the object from a HashTable and return whether it was successful.
- * An exception will be thrown on error. */
-static bool php_phongo_readpreference_init_from_hash(php_phongo_readpreference_t* intern, HashTable* props) /* {{{ */
-{
- zval *mode, *tagSets, *maxStalenessSeconds, *hedge;
-
- if ((mode = zend_hash_str_find(props, "mode", sizeof("mode") - 1)) && Z_TYPE_P(mode) == IS_STRING) {
- if (strcasecmp(Z_STRVAL_P(mode), PHONGO_READ_PRIMARY) == 0) {
- intern->read_preference = mongoc_read_prefs_new(MONGOC_READ_PRIMARY);
- } else if (strcasecmp(Z_STRVAL_P(mode), PHONGO_READ_PRIMARY_PREFERRED) == 0) {
- intern->read_preference = mongoc_read_prefs_new(MONGOC_READ_PRIMARY_PREFERRED);
- } else if (strcasecmp(Z_STRVAL_P(mode), PHONGO_READ_SECONDARY) == 0) {
- intern->read_preference = mongoc_read_prefs_new(MONGOC_READ_SECONDARY);
- } else if (strcasecmp(Z_STRVAL_P(mode), PHONGO_READ_SECONDARY_PREFERRED) == 0) {
- intern->read_preference = mongoc_read_prefs_new(MONGOC_READ_SECONDARY_PREFERRED);
- } else if (strcasecmp(Z_STRVAL_P(mode), PHONGO_READ_NEAREST) == 0) {
- intern->read_preference = mongoc_read_prefs_new(MONGOC_READ_NEAREST);
- } else {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires specific values for \"mode\" string field", ZSTR_VAL(php_phongo_readpreference_ce->name));
- return false;
- }
- } else {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"mode\" field to be string", ZSTR_VAL(php_phongo_readpreference_ce->name));
- return false;
- }
-
- if ((tagSets = zend_hash_str_find(props, "tags", sizeof("tags") - 1))) {
- ZVAL_DEREF(tagSets);
- if (Z_TYPE_P(tagSets) == IS_ARRAY) {
- bson_t* tags = bson_new();
-
- /* Separate tagSets as php_phongo_read_preference_prep_tagsets may
- * modify these tags. */
- SEPARATE_ZVAL_NOREF(tagSets);
-
- php_phongo_read_preference_prep_tagsets(tagSets);
- php_phongo_zval_to_bson(tagSets, PHONGO_BSON_NONE, (bson_t*) tags, NULL);
-
- if (!php_phongo_read_preference_tags_are_valid(tags)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"tags\" array field to have zero or more documents", ZSTR_VAL(php_phongo_readpreference_ce->name));
- bson_destroy(tags);
- goto failure;
- }
-
- if (!bson_empty(tags) && (mongoc_read_prefs_get_mode(intern->read_preference) == MONGOC_READ_PRIMARY)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"tags\" array field to not be present with \"primary\" mode", ZSTR_VAL(php_phongo_readpreference_ce->name));
- bson_destroy(tags);
- goto failure;
- }
-
- mongoc_read_prefs_set_tags(intern->read_preference, tags);
- bson_destroy(tags);
- } else {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"tags\" field to be array", ZSTR_VAL(php_phongo_readpreference_ce->name));
- goto failure;
- }
- }
-
- if ((maxStalenessSeconds = zend_hash_str_find(props, "maxStalenessSeconds", sizeof("maxStalenessSeconds") - 1))) {
- if (Z_TYPE_P(maxStalenessSeconds) == IS_LONG) {
- if (Z_LVAL_P(maxStalenessSeconds) != MONGOC_NO_MAX_STALENESS) {
- if (mongoc_read_prefs_get_mode(intern->read_preference) == MONGOC_READ_PRIMARY) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"maxStalenessSeconds\" field to not be present with \"primary\" mode", ZSTR_VAL(php_phongo_readpreference_ce->name));
- goto failure;
- }
- if (Z_LVAL_P(maxStalenessSeconds) < MONGOC_SMALLEST_MAX_STALENESS_SECONDS) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"maxStalenessSeconds\" integer field to be >= %d", ZSTR_VAL(php_phongo_readpreference_ce->name), MONGOC_SMALLEST_MAX_STALENESS_SECONDS);
- goto failure;
- }
- if (Z_LVAL_P(maxStalenessSeconds) > INT32_MAX) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"maxStalenessSeconds\" integer field to be <= %" PRId32, ZSTR_VAL(php_phongo_readpreference_ce->name), INT32_MAX);
- goto failure;
- }
- }
-
- mongoc_read_prefs_set_max_staleness_seconds(intern->read_preference, Z_LVAL_P(maxStalenessSeconds));
- } else {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"maxStalenessSeconds\" field to be integer", ZSTR_VAL(php_phongo_readpreference_ce->name));
- goto failure;
- }
- }
-
- if ((hedge = zend_hash_str_find(props, "hedge", sizeof("hedge") - 1))) {
- if (Z_TYPE_P(hedge) == IS_ARRAY || Z_TYPE_P(hedge) == IS_OBJECT) {
- bson_t* hedge_doc = bson_new();
-
- if (mongoc_read_prefs_get_mode(intern->read_preference) == MONGOC_READ_PRIMARY) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"hedge\" field to not be present with \"primary\" mode", ZSTR_VAL(php_phongo_readpreference_ce->name));
- bson_destroy(hedge_doc);
- goto failure;
- }
-
- php_phongo_zval_to_bson(hedge, PHONGO_BSON_NONE, hedge_doc, NULL);
-
- if (EG(exception)) {
- bson_destroy(hedge_doc);
- goto failure;
- }
-
- mongoc_read_prefs_set_hedge(intern->read_preference, hedge_doc);
- bson_destroy(hedge_doc);
- } else {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"hedge\" field to be an array or object", ZSTR_VAL(php_phongo_readpreference_ce->name));
- goto failure;
- }
- }
-
- if (!mongoc_read_prefs_is_valid(intern->read_preference)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Read preference is not valid");
- goto failure;
- }
-
- return true;
-
-failure:
- mongoc_read_prefs_destroy(intern->read_preference);
- intern->read_preference = NULL;
- return false;
-} /* }}} */
-
-static const char* php_phongo_readpreference_get_mode_string(mongoc_read_mode_t mode) /* {{{ */
-{
- switch (mode) {
- case MONGOC_READ_PRIMARY:
- return PHONGO_READ_PRIMARY;
- case MONGOC_READ_PRIMARY_PREFERRED:
- return PHONGO_READ_PRIMARY_PREFERRED;
- case MONGOC_READ_SECONDARY:
- return PHONGO_READ_SECONDARY;
- case MONGOC_READ_SECONDARY_PREFERRED:
- return PHONGO_READ_SECONDARY_PREFERRED;
- case MONGOC_READ_NEAREST:
- return PHONGO_READ_NEAREST;
- default:
- /* Should never happen, but if it does: exception */
- phongo_throw_exception(PHONGO_ERROR_LOGIC, "Mode '%d' should never have been passed to php_phongo_readpreference_get_mode_string, please file a bug report", mode);
- break;
- }
-
- return NULL;
-} /* }}} */
-
-/* {{{ proto void MongoDB\Driver\ReadPreference::__construct(int|string $mode[, array $tagSets = array()[, array $options = array()]])
- Constructs a new ReadPreference */
-static PHP_METHOD(ReadPreference, __construct)
-{
- zend_error_handling error_handling;
- php_phongo_readpreference_t* intern;
- zval* mode;
- zval* tagSets = NULL;
- zval* options = NULL;
-
- intern = Z_READPREFERENCE_OBJ_P(getThis());
-
- /* Separate the tagSets zval, since we may end up modifying it in
- * php_phongo_read_preference_prep_tagsets() below. */
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|a/!a!", &mode, &tagSets, &options) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- if (Z_TYPE_P(mode) == IS_LONG) {
- switch (Z_LVAL_P(mode)) {
- case MONGOC_READ_PRIMARY:
- case MONGOC_READ_SECONDARY:
- case MONGOC_READ_PRIMARY_PREFERRED:
- case MONGOC_READ_SECONDARY_PREFERRED:
- case MONGOC_READ_NEAREST:
- intern->read_preference = mongoc_read_prefs_new(Z_LVAL_P(mode));
- break;
- default:
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Invalid mode: %" PHONGO_LONG_FORMAT, Z_LVAL_P(mode));
- return;
- }
- } else if (Z_TYPE_P(mode) == IS_STRING) {
- if (strcasecmp(Z_STRVAL_P(mode), PHONGO_READ_PRIMARY) == 0) {
- intern->read_preference = mongoc_read_prefs_new(MONGOC_READ_PRIMARY);
- } else if (strcasecmp(Z_STRVAL_P(mode), PHONGO_READ_PRIMARY_PREFERRED) == 0) {
- intern->read_preference = mongoc_read_prefs_new(MONGOC_READ_PRIMARY_PREFERRED);
- } else if (strcasecmp(Z_STRVAL_P(mode), PHONGO_READ_SECONDARY) == 0) {
- intern->read_preference = mongoc_read_prefs_new(MONGOC_READ_SECONDARY);
- } else if (strcasecmp(Z_STRVAL_P(mode), PHONGO_READ_SECONDARY_PREFERRED) == 0) {
- intern->read_preference = mongoc_read_prefs_new(MONGOC_READ_SECONDARY_PREFERRED);
- } else if (strcasecmp(Z_STRVAL_P(mode), PHONGO_READ_NEAREST) == 0) {
- intern->read_preference = mongoc_read_prefs_new(MONGOC_READ_NEAREST);
- } else {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Invalid mode: '%s'", Z_STRVAL_P(mode));
- return;
- }
- } else {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected mode to be integer or string, %s given", PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(mode));
- return;
- }
-
- if (tagSets) {
- bson_t* tags = bson_new();
-
- php_phongo_read_preference_prep_tagsets(tagSets);
- php_phongo_zval_to_bson(tagSets, PHONGO_BSON_NONE, (bson_t*) tags, NULL);
-
- if (!php_phongo_read_preference_tags_are_valid(tags)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "tagSets must be an array of zero or more documents");
- bson_destroy(tags);
- return;
- }
-
- if (!bson_empty(tags) && (mongoc_read_prefs_get_mode(intern->read_preference) == MONGOC_READ_PRIMARY)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "tagSets may not be used with primary mode");
- bson_destroy(tags);
- return;
- }
-
- mongoc_read_prefs_set_tags(intern->read_preference, tags);
- bson_destroy(tags);
- }
-
- if (options && php_array_exists(options, "maxStalenessSeconds")) {
- zend_long maxStalenessSeconds = php_array_fetchc_long(options, "maxStalenessSeconds");
-
- if (maxStalenessSeconds != MONGOC_NO_MAX_STALENESS) {
- if (maxStalenessSeconds < MONGOC_SMALLEST_MAX_STALENESS_SECONDS) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected maxStalenessSeconds to be >= %d, %" PHONGO_LONG_FORMAT " given", MONGOC_SMALLEST_MAX_STALENESS_SECONDS, maxStalenessSeconds);
- return;
- }
- if (maxStalenessSeconds > INT32_MAX) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected maxStalenessSeconds to be <= %" PRId32 ", %" PHONGO_LONG_FORMAT " given", INT32_MAX, maxStalenessSeconds);
- return;
- }
- if (mongoc_read_prefs_get_mode(intern->read_preference) == MONGOC_READ_PRIMARY) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "maxStalenessSeconds may not be used with primary mode");
- return;
- }
- }
-
- mongoc_read_prefs_set_max_staleness_seconds(intern->read_preference, maxStalenessSeconds);
- }
-
- if (options && php_array_exists(options, "hedge")) {
- zval* hedge = php_array_fetchc(options, "hedge");
-
- if (Z_TYPE_P(hedge) == IS_ARRAY || Z_TYPE_P(hedge) == IS_OBJECT) {
- bson_t* hedge_doc = bson_new();
-
- if (mongoc_read_prefs_get_mode(intern->read_preference) == MONGOC_READ_PRIMARY) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "hedge may not be used with primary mode");
- bson_destroy(hedge_doc);
- return;
- }
-
- php_phongo_zval_to_bson(hedge, PHONGO_BSON_NONE, hedge_doc, NULL);
-
- if (EG(exception)) {
- bson_destroy(hedge_doc);
- return;
- }
-
- mongoc_read_prefs_set_hedge(intern->read_preference, hedge_doc);
- bson_destroy(hedge_doc);
- } else {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"hedge\" field to be an array or object", ZSTR_VAL(php_phongo_readpreference_ce->name));
- return;
- }
- }
-
- if (!mongoc_read_prefs_is_valid(intern->read_preference)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Read preference is not valid");
- return;
- }
-} /* }}} */
-
-/* {{{ proto MongoDB\Driver\ReadPreference MongoDB\Driver\ReadPreference::__set_state(array $properties)
-*/
-static PHP_METHOD(ReadPreference, __set_state)
-{
- zend_error_handling error_handling;
- php_phongo_readpreference_t* intern;
- HashTable* props;
- zval* array;
-
- /* Separate the zval, since we may end up modifying the "tags" element in
- * php_phongo_read_preference_prep_tagsets(), which is called from
- * php_phongo_readpreference_init_from_hash. */
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/", &array) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- object_init_ex(return_value, php_phongo_readpreference_ce);
-
- intern = Z_READPREFERENCE_OBJ_P(return_value);
- props = Z_ARRVAL_P(array);
-
- php_phongo_readpreference_init_from_hash(intern, props);
-} /* }}} */
-
-/* {{{ proto array|null MongoDB\Driver\ReadPreference::getHedge()
- Returns the ReadPreference hedge document */
-static PHP_METHOD(ReadPreference, getHedge)
-{
- zend_error_handling error_handling;
- php_phongo_readpreference_t* intern;
- const bson_t* hedge;
-
- intern = Z_READPREFERENCE_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- hedge = mongoc_read_prefs_get_hedge(intern->read_preference);
-
- if (!bson_empty0(hedge)) {
- php_phongo_bson_state state;
-
- PHONGO_BSON_INIT_STATE(state);
-
- if (!php_phongo_bson_to_zval_ex(bson_get_data(hedge), hedge->len, &state)) {
- zval_ptr_dtor(&state.zchild);
- return;
- }
-
- RETURN_ZVAL(&state.zchild, 0, 1);
- } else {
- RETURN_NULL();
- }
-} /* }}} */
-
-/* {{{ proto integer MongoDB\Driver\ReadPreference::getMaxStalenessSeconds()
- Returns the ReadPreference maxStalenessSeconds value */
-static PHP_METHOD(ReadPreference, getMaxStalenessSeconds)
-{
- zend_error_handling error_handling;
- php_phongo_readpreference_t* intern;
-
- intern = Z_READPREFERENCE_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- RETURN_LONG(mongoc_read_prefs_get_max_staleness_seconds(intern->read_preference));
-} /* }}} */
-
-/* {{{ proto integer MongoDB\Driver\ReadPreference::getMode()
- Returns the ReadPreference mode */
-static PHP_METHOD(ReadPreference, getMode)
-{
- zend_error_handling error_handling;
- php_phongo_readpreference_t* intern;
-
- intern = Z_READPREFERENCE_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- RETURN_LONG(mongoc_read_prefs_get_mode(intern->read_preference));
-} /* }}} */
-
-/* {{{ proto string MongoDB\Driver\ReadPreference::getModeString()
- Returns the ReadPreference mode as string */
-static PHP_METHOD(ReadPreference, getModeString)
-{
- zend_error_handling error_handling;
- php_phongo_readpreference_t* intern;
- const char* mode_string;
-
- intern = Z_READPREFERENCE_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- mode_string = php_phongo_readpreference_get_mode_string(mongoc_read_prefs_get_mode(intern->read_preference));
- if (!mode_string) {
- /* Exception already thrown */
- return;
- }
-
- RETURN_STRING(mode_string);
-} /* }}} */
-
-/* {{{ proto array MongoDB\Driver\ReadPreference::getTagSets()
- Returns the ReadPreference tag sets */
-static PHP_METHOD(ReadPreference, getTagSets)
-{
- zend_error_handling error_handling;
- php_phongo_readpreference_t* intern;
- const bson_t* tags;
-
- intern = Z_READPREFERENCE_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- tags = mongoc_read_prefs_get_tags(intern->read_preference);
-
- if (tags->len) {
- php_phongo_bson_state state;
-
- PHONGO_BSON_INIT_DEBUG_STATE(state);
-
- if (!php_phongo_bson_to_zval_ex(bson_get_data(tags), tags->len, &state)) {
- zval_ptr_dtor(&state.zchild);
- return;
- }
-
- RETURN_ZVAL(&state.zchild, 0, 1);
- } else {
- RETURN_NULL();
- }
-} /* }}} */
-
-static HashTable* php_phongo_readpreference_get_properties_hash(phongo_compat_object_handler_type* object, bool is_temp) /* {{{ */
-{
- php_phongo_readpreference_t* intern;
- HashTable* props;
- const char* modeString = NULL;
- const bson_t* tags;
- const bson_t* hedge;
- mongoc_read_mode_t mode;
-
- intern = Z_OBJ_READPREFERENCE(PHONGO_COMPAT_GET_OBJ(object));
-
- PHONGO_GET_PROPERTY_HASH_INIT_PROPS(is_temp, intern, props, 4);
-
- if (!intern->read_preference) {
- return props;
- }
-
- tags = mongoc_read_prefs_get_tags(intern->read_preference);
- mode = mongoc_read_prefs_get_mode(intern->read_preference);
- modeString = php_phongo_readpreference_get_mode_string(mode);
- hedge = mongoc_read_prefs_get_hedge(intern->read_preference);
-
- if (modeString) {
- zval z_mode;
-
- ZVAL_STRING(&z_mode, modeString);
- zend_hash_str_update(props, "mode", sizeof("mode") - 1, &z_mode);
- }
-
- if (!bson_empty0(tags)) {
- php_phongo_bson_state state;
-
- /* Use PHONGO_TYPEMAP_NATIVE_ARRAY for the root type since tags is an
- * array; however, inner documents and arrays can use the default. */
- PHONGO_BSON_INIT_STATE(state);
- state.map.root_type = PHONGO_TYPEMAP_NATIVE_ARRAY;
-
- if (!php_phongo_bson_to_zval_ex(bson_get_data(tags), tags->len, &state)) {
- zval_ptr_dtor(&state.zchild);
- goto done;
- }
-
- zend_hash_str_update(props, "tags", sizeof("tags") - 1, &state.zchild);
- }
-
- if (mongoc_read_prefs_get_max_staleness_seconds(intern->read_preference) != MONGOC_NO_MAX_STALENESS) {
- /* Note: valid values for maxStalesnessSeconds will not exceed the range
- * of 32-bit signed integers, so conditional encoding is not necessary. */
- long maxStalenessSeconds = mongoc_read_prefs_get_max_staleness_seconds(intern->read_preference);
- zval z_max_ss;
-
- ZVAL_LONG(&z_max_ss, maxStalenessSeconds);
- zend_hash_str_update(props, "maxStalenessSeconds", sizeof("maxStalenessSeconds") - 1, &z_max_ss);
- }
-
- if (!bson_empty0(hedge)) {
- php_phongo_bson_state state;
-
- PHONGO_BSON_INIT_STATE(state);
-
- if (!php_phongo_bson_to_zval_ex(bson_get_data(hedge), hedge->len, &state)) {
- zval_ptr_dtor(&state.zchild);
- goto done;
- }
-
- zend_hash_str_update(props, "hedge", sizeof("hedge") - 1, &state.zchild);
- }
-
-done:
- return props;
-} /* }}} */
-
-/* {{{ proto array MongoDB\Driver\ReadPreference::bsonSerialize()
-*/
-static PHP_METHOD(ReadPreference, bsonSerialize)
-{
- zend_error_handling error_handling;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- ZVAL_ARR(return_value, php_phongo_readpreference_get_properties_hash(PHONGO_COMPAT_OBJ_P(getThis()), true));
- convert_to_object(return_value);
-} /* }}} */
-
-/* {{{ proto string MongoDB\Driver\ReadPreference::serialize()
-*/
-static PHP_METHOD(ReadPreference, serialize)
-{
- zend_error_handling error_handling;
- php_phongo_readpreference_t* intern;
- zval retval;
- php_serialize_data_t var_hash;
- smart_str buf = { 0 };
- const char* modeString = NULL;
- const bson_t* tags;
- const bson_t* hedge;
- int64_t maxStalenessSeconds;
- mongoc_read_mode_t mode;
-
- intern = Z_READPREFERENCE_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- if (!intern->read_preference) {
- return;
- }
-
- tags = mongoc_read_prefs_get_tags(intern->read_preference);
- mode = mongoc_read_prefs_get_mode(intern->read_preference);
- modeString = php_phongo_readpreference_get_mode_string(mode);
- maxStalenessSeconds = mongoc_read_prefs_get_max_staleness_seconds(intern->read_preference);
- hedge = mongoc_read_prefs_get_hedge(intern->read_preference);
-
- array_init_size(&retval, 4);
-
- if (modeString) {
- ADD_ASSOC_STRING(&retval, "mode", modeString);
- }
-
- if (!bson_empty0(tags)) {
- php_phongo_bson_state state;
-
- PHONGO_BSON_INIT_DEBUG_STATE(state);
-
- if (!php_phongo_bson_to_zval_ex(bson_get_data(tags), tags->len, &state)) {
- zval_ptr_dtor(&state.zchild);
- return;
- }
-
- ADD_ASSOC_ZVAL_EX(&retval, "tags", &state.zchild);
- }
-
- if (maxStalenessSeconds != MONGOC_NO_MAX_STALENESS) {
- ADD_ASSOC_LONG_EX(&retval, "maxStalenessSeconds", maxStalenessSeconds);
- }
-
- if (!bson_empty0(hedge)) {
- php_phongo_bson_state state;
-
- PHONGO_BSON_INIT_STATE(state);
-
- if (!php_phongo_bson_to_zval_ex(bson_get_data(hedge), hedge->len, &state)) {
- zval_ptr_dtor(&state.zchild);
- return;
- }
-
- ADD_ASSOC_ZVAL_EX(&retval, "hedge", &state.zchild);
- }
-
- PHP_VAR_SERIALIZE_INIT(var_hash);
- php_var_serialize(&buf, &retval, &var_hash);
- smart_str_0(&buf);
- PHP_VAR_SERIALIZE_DESTROY(var_hash);
-
- PHONGO_RETVAL_SMART_STR(buf);
-
- smart_str_free(&buf);
- zval_ptr_dtor(&retval);
-} /* }}} */
-
-/* {{{ proto void MongoDB\Driver\ReadPreference::unserialize(string $serialized)
-*/
-static PHP_METHOD(ReadPreference, unserialize)
-{
- zend_error_handling error_handling;
- php_phongo_readpreference_t* intern;
- char* serialized;
- size_t serialized_len;
- zval props;
- php_unserialize_data_t var_hash;
-
- intern = Z_READPREFERENCE_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &serialized, &serialized_len) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- if (!serialized_len) {
- return;
- }
-
- PHP_VAR_UNSERIALIZE_INIT(var_hash);
- if (!php_var_unserialize(&props, (const unsigned char**) &serialized, (unsigned char*) serialized + serialized_len, &var_hash)) {
- zval_ptr_dtor(&props);
- phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "%s unserialization failed", ZSTR_VAL(php_phongo_readpreference_ce->name));
-
- PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
- return;
- }
- PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
-
- php_phongo_readpreference_init_from_hash(intern, HASH_OF(&props));
- zval_ptr_dtor(&props);
-} /* }}} */
-
-/* {{{ proto array MongoDB\Driver\ReadPreference::__serialize()
-*/
-static PHP_METHOD(ReadPreference, __serialize)
-{
- PHONGO_PARSE_PARAMETERS_NONE();
-
- RETURN_ARR(php_phongo_readpreference_get_properties_hash(PHONGO_COMPAT_OBJ_P(getThis()), true));
-} /* }}} */
-
-/* {{{ proto void MongoDB\Driver\ReadPreference::__unserialize(array $data)
-*/
-static PHP_METHOD(ReadPreference, __unserialize)
-{
- zval* data;
-
- PHONGO_PARSE_PARAMETERS_START(1, 1)
- Z_PARAM_ARRAY(data)
- PHONGO_PARSE_PARAMETERS_END();
-
- php_phongo_readpreference_init_from_hash(Z_READPREFERENCE_OBJ_P(getThis()), Z_ARRVAL_P(data));
-} /* }}} */
-
-/* {{{ MongoDB\Driver\ReadPreference function entries */
-ZEND_BEGIN_ARG_INFO_EX(ai_ReadPreference___construct, 0, 0, 1)
- ZEND_ARG_INFO(0, mode)
- ZEND_ARG_ARRAY_INFO(0, tagSets, 1)
- ZEND_ARG_ARRAY_INFO(0, options, 1)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_ReadPreference___set_state, 0, 0, 1)
- ZEND_ARG_ARRAY_INFO(0, properties, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_ReadPreference___unserialize, 0, 0, 1)
- ZEND_ARG_ARRAY_INFO(0, data, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_ReadPreference_unserialize, 0, 0, 1)
- ZEND_ARG_INFO(0, serialized)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_ReadPreference_void, 0, 0, 0)
-ZEND_END_ARG_INFO()
-
-static zend_function_entry php_phongo_readpreference_me[] = {
- /* clang-format off */
- PHP_ME(ReadPreference, __construct, ai_ReadPreference___construct, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(ReadPreference, __serialize, ai_ReadPreference_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(ReadPreference, __set_state, ai_ReadPreference___set_state, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
- PHP_ME(ReadPreference, __unserialize, ai_ReadPreference___unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(ReadPreference, getHedge, ai_ReadPreference_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(ReadPreference, getMaxStalenessSeconds, ai_ReadPreference_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(ReadPreference, getMode, ai_ReadPreference_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(ReadPreference, getModeString, ai_ReadPreference_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(ReadPreference, getTagSets, ai_ReadPreference_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(ReadPreference, bsonSerialize, ai_ReadPreference_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(ReadPreference, serialize, ai_ReadPreference_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(ReadPreference, unserialize, ai_ReadPreference_unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_FE_END
- /* clang-format on */
-};
-/* }}} */
-
-/* {{{ MongoDB\Driver\ReadPreference object handlers */
-static zend_object_handlers php_phongo_handler_readpreference;
-
-static void php_phongo_readpreference_free_object(zend_object* object) /* {{{ */
-{
- php_phongo_readpreference_t* intern = Z_OBJ_READPREFERENCE(object);
-
- zend_object_std_dtor(&intern->std);
-
- if (intern->properties) {
- zend_hash_destroy(intern->properties);
- FREE_HASHTABLE(intern->properties);
- }
-
- if (intern->read_preference) {
- mongoc_read_prefs_destroy(intern->read_preference);
- }
-} /* }}} */
-
-static zend_object* php_phongo_readpreference_create_object(zend_class_entry* class_type) /* {{{ */
-{
- php_phongo_readpreference_t* intern = NULL;
-
- intern = PHONGO_ALLOC_OBJECT_T(php_phongo_readpreference_t, class_type);
-
- zend_object_std_init(&intern->std, class_type);
- object_properties_init(&intern->std, class_type);
-
- intern->std.handlers = &php_phongo_handler_readpreference;
-
- return &intern->std;
-} /* }}} */
-
-static HashTable* php_phongo_readpreference_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
-{
- *is_temp = 1;
- return php_phongo_readpreference_get_properties_hash(object, true);
-} /* }}} */
-
-static HashTable* php_phongo_readpreference_get_properties(phongo_compat_object_handler_type* object) /* {{{ */
-{
- return php_phongo_readpreference_get_properties_hash(object, false);
-} /* }}} */
-/* }}} */
-
-void php_phongo_readpreference_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver", "ReadPreference", php_phongo_readpreference_me);
- php_phongo_readpreference_ce = zend_register_internal_class(&ce);
- php_phongo_readpreference_ce->create_object = php_phongo_readpreference_create_object;
- PHONGO_CE_FINAL(php_phongo_readpreference_ce);
-
- zend_class_implements(php_phongo_readpreference_ce, 1, php_phongo_serializable_ce);
- zend_class_implements(php_phongo_readpreference_ce, 1, zend_ce_serializable);
-
- memcpy(&php_phongo_handler_readpreference, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
- php_phongo_handler_readpreference.get_debug_info = php_phongo_readpreference_get_debug_info;
- php_phongo_handler_readpreference.get_properties = php_phongo_readpreference_get_properties;
- php_phongo_handler_readpreference.free_obj = php_phongo_readpreference_free_object;
- php_phongo_handler_readpreference.offset = XtOffsetOf(php_phongo_readpreference_t, std);
-
- zend_declare_class_constant_long(php_phongo_readpreference_ce, ZEND_STRL("RP_PRIMARY"), MONGOC_READ_PRIMARY);
- zend_declare_class_constant_long(php_phongo_readpreference_ce, ZEND_STRL("RP_PRIMARY_PREFERRED"), MONGOC_READ_PRIMARY_PREFERRED);
- zend_declare_class_constant_long(php_phongo_readpreference_ce, ZEND_STRL("RP_SECONDARY"), MONGOC_READ_SECONDARY);
- zend_declare_class_constant_long(php_phongo_readpreference_ce, ZEND_STRL("RP_SECONDARY_PREFERRED"), MONGOC_READ_SECONDARY_PREFERRED);
- zend_declare_class_constant_long(php_phongo_readpreference_ce, ZEND_STRL("RP_NEAREST"), MONGOC_READ_NEAREST);
- zend_declare_class_constant_long(php_phongo_readpreference_ce, ZEND_STRL("NO_MAX_STALENESS"), MONGOC_NO_MAX_STALENESS);
- zend_declare_class_constant_long(php_phongo_readpreference_ce, ZEND_STRL("SMALLEST_MAX_STALENESS_SECONDS"), MONGOC_SMALLEST_MAX_STALENESS_SECONDS);
-
- zend_declare_class_constant_string(php_phongo_readpreference_ce, ZEND_STRL("PRIMARY"), PHONGO_READ_PRIMARY);
- zend_declare_class_constant_string(php_phongo_readpreference_ce, ZEND_STRL("PRIMARY_PREFERRED"), PHONGO_READ_PRIMARY_PREFERRED);
- zend_declare_class_constant_string(php_phongo_readpreference_ce, ZEND_STRL("SECONDARY"), PHONGO_READ_SECONDARY);
- zend_declare_class_constant_string(php_phongo_readpreference_ce, ZEND_STRL("SECONDARY_PREFERRED"), PHONGO_READ_SECONDARY_PREFERRED);
- zend_declare_class_constant_string(php_phongo_readpreference_ce, ZEND_STRL("NEAREST"), PHONGO_READ_NEAREST);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/MongoDB/Server.c b/mongodb-1.12.0/src/MongoDB/Server.c
deleted file mode 100644
index 4bc3ab1e..00000000
--- a/mongodb-1.12.0/src/MongoDB/Server.c
+++ /dev/null
@@ -1,740 +0,0 @@
-/*
- * Copyright 2014-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-#include <Zend/zend_interfaces.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-#include "php_bson.h"
-
-zend_class_entry* php_phongo_server_ce;
-
-/* {{{ proto MongoDB\Driver\Cursor MongoDB\Driver\Server::executeCommand(string $db, MongoDB\Driver\Command $command[, array $options = null]))
- Executes a Command on this Server */
-static PHP_METHOD(Server, executeCommand)
-{
- zend_error_handling error_handling;
- php_phongo_server_t* intern;
- char* db;
- size_t db_len;
- zval* command;
- zval* options = NULL;
- bool free_options = false;
-
- intern = Z_SERVER_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "sO|z!", &db, &db_len, &command, php_phongo_command_ce, &options) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- options = php_phongo_prep_legacy_option(options, "readPreference", &free_options);
-
- /* If the Server was created in a different process, reset the client so
- * that cursors created by this process can be differentiated and its
- * session pool is cleared. */
- PHONGO_RESET_CLIENT_IF_PID_DIFFERS(intern, Z_MANAGER_OBJ_P(&intern->manager));
-
- phongo_execute_command(&intern->manager, PHONGO_COMMAND_RAW, db, command, options, intern->server_id, return_value);
-
- if (free_options) {
- php_phongo_prep_legacy_option_free(options);
- }
-} /* }}} */
-
-/* {{{ proto MongoDB\Driver\Cursor MongoDB\Driver\Server::executeReadCommand(string $db, MongoDB\Driver\Command $command[, array $options = null]))
- Executes a ReadCommand on this Server */
-static PHP_METHOD(Server, executeReadCommand)
-{
- zend_error_handling error_handling;
- php_phongo_server_t* intern;
- char* db;
- size_t db_len;
- zval* command;
- zval* options = NULL;
-
- intern = Z_SERVER_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "sO|a!", &db, &db_len, &command, php_phongo_command_ce, &options) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- /* If the Server was created in a different process, reset the client so
- * that cursors created by this process can be differentiated and its
- * session pool is cleared. */
- PHONGO_RESET_CLIENT_IF_PID_DIFFERS(intern, Z_MANAGER_OBJ_P(&intern->manager));
-
- phongo_execute_command(&intern->manager, PHONGO_COMMAND_READ, db, command, options, intern->server_id, return_value);
-} /* }}} */
-
-/* {{{ proto MongoDB\Driver\Cursor MongoDB\Driver\Server::executeWriteCommand(string $db, MongoDB\Driver\Command $command[, array $options = null]))
- Executes a WriteCommand on this Server */
-static PHP_METHOD(Server, executeWriteCommand)
-{
- zend_error_handling error_handling;
- php_phongo_server_t* intern;
- char* db;
- size_t db_len;
- zval* command;
- zval* options = NULL;
-
- intern = Z_SERVER_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "sO|a!", &db, &db_len, &command, php_phongo_command_ce, &options) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- /* If the Server was created in a different process, reset the client so
- * that cursors created by this process can be differentiated. and its
- * session pool is cleared. */
- PHONGO_RESET_CLIENT_IF_PID_DIFFERS(intern, Z_MANAGER_OBJ_P(&intern->manager));
-
- phongo_execute_command(&intern->manager, PHONGO_COMMAND_WRITE, db, command, options, intern->server_id, return_value);
-} /* }}} */
-
-/* {{{ proto MongoDB\Driver\Cursor MongoDB\Driver\Server::executeReadWriteCommand(string $db, MongoDB\Driver\Command $command[, array $options = null]))
- Executes a ReadWriteCommand on this Server */
-static PHP_METHOD(Server, executeReadWriteCommand)
-{
- zend_error_handling error_handling;
- php_phongo_server_t* intern;
- char* db;
- size_t db_len;
- zval* command;
- zval* options = NULL;
-
- intern = Z_SERVER_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "sO|a!", &db, &db_len, &command, php_phongo_command_ce, &options) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- /* If the Server was created in a different process, reset the client so
- * that cursors created by this process can be differentiated and its
- * session pool is cleared. */
- PHONGO_RESET_CLIENT_IF_PID_DIFFERS(intern, Z_MANAGER_OBJ_P(&intern->manager));
-
- phongo_execute_command(&intern->manager, PHONGO_COMMAND_READ_WRITE, db, command, options, intern->server_id, return_value);
-} /* }}} */
-
-/* {{{ proto MongoDB\Driver\Cursor MongoDB\Driver\Server::executeQuery(string $namespace, MongoDB\Driver\Query $query[, array $options = null]))
- Executes a Query on this Server */
-static PHP_METHOD(Server, executeQuery)
-{
- zend_error_handling error_handling;
- php_phongo_server_t* intern;
- char* namespace;
- size_t namespace_len;
- zval* query;
- zval* options = NULL;
- bool free_options = false;
-
- intern = Z_SERVER_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "sO|z!", &namespace, &namespace_len, &query, php_phongo_query_ce, &options) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- options = php_phongo_prep_legacy_option(options, "readPreference", &free_options);
-
- /* If the Server was created in a different process, reset the client so
- * that cursors created by this process can be differentiated and its
- * session pool is cleared. */
- PHONGO_RESET_CLIENT_IF_PID_DIFFERS(intern, Z_MANAGER_OBJ_P(&intern->manager));
-
- phongo_execute_query(&intern->manager, namespace, query, options, intern->server_id, return_value);
-
- if (free_options) {
- php_phongo_prep_legacy_option_free(options);
- }
-} /* }}} */
-
-/* {{{ proto MongoDB\Driver\WriteResult MongoDB\Driver\Server::executeBulkWrite(string $namespace, MongoDB\Driver\BulkWrite $zbulk[, array $options = null])
- Executes a BulkWrite (i.e. any number of insert, update, and delete ops) on
- this Server */
-static PHP_METHOD(Server, executeBulkWrite)
-{
- zend_error_handling error_handling;
- php_phongo_server_t* intern;
- char* namespace;
- size_t namespace_len;
- zval* zbulk;
- php_phongo_bulkwrite_t* bulk;
- zval* options = NULL;
- bool free_options = false;
-
- intern = Z_SERVER_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "sO|z!", &namespace, &namespace_len, &zbulk, php_phongo_bulkwrite_ce, &options, php_phongo_writeconcern_ce) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- bulk = Z_BULKWRITE_OBJ_P(zbulk);
-
- options = php_phongo_prep_legacy_option(options, "writeConcern", &free_options);
-
- /* If the Server was created in a different process, reset the client so
- * that its session pool is cleared. */
- PHONGO_RESET_CLIENT_IF_PID_DIFFERS(intern, Z_MANAGER_OBJ_P(&intern->manager));
-
- phongo_execute_bulk_write(&intern->manager, namespace, bulk, options, intern->server_id, return_value);
-
- if (free_options) {
- php_phongo_prep_legacy_option_free(options);
- }
-} /* }}} */
-
-/* {{{ proto string MongoDB\Driver\Server::getHost()
- Returns the hostname for this Server */
-static PHP_METHOD(Server, getHost)
-{
- zend_error_handling error_handling;
- php_phongo_server_t* intern;
- mongoc_server_description_t* sd;
-
- intern = Z_SERVER_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- if ((sd = mongoc_client_get_server_description(Z_MANAGER_OBJ_P(&intern->manager)->client, intern->server_id))) {
- RETVAL_STRING(mongoc_server_description_host(sd)->host);
- mongoc_server_description_destroy(sd);
- return;
- }
-
- phongo_throw_exception(PHONGO_ERROR_RUNTIME, "Failed to get server description");
-} /* }}} */
-
-/* {{{ proto array MongoDB\Driver\Server::getTags()
- Returns the currently configured tags for this Server */
-static PHP_METHOD(Server, getTags)
-{
- zend_error_handling error_handling;
- php_phongo_server_t* intern;
- mongoc_server_description_t* sd;
-
- intern = Z_SERVER_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- if ((sd = mongoc_client_get_server_description(Z_MANAGER_OBJ_P(&intern->manager)->client, intern->server_id))) {
- const bson_t* hello_response = mongoc_server_description_hello_response(sd);
- bson_iter_t iter;
-
- if (bson_iter_init_find(&iter, hello_response, "tags") && BSON_ITER_HOLDS_DOCUMENT(&iter)) {
- const uint8_t* bytes;
- uint32_t len;
- php_phongo_bson_state state;
-
- PHONGO_BSON_INIT_DEBUG_STATE(state);
- bson_iter_document(&iter, &len, &bytes);
-
- if (!php_phongo_bson_to_zval_ex(bytes, len, &state)) {
- /* Exception should already have been thrown */
- zval_ptr_dtor(&state.zchild);
- mongoc_server_description_destroy(sd);
- return;
- }
-
- mongoc_server_description_destroy(sd);
-
- RETURN_ZVAL(&state.zchild, 0, 1);
- }
-
- array_init(return_value);
- mongoc_server_description_destroy(sd);
- return;
- }
-
- phongo_throw_exception(PHONGO_ERROR_RUNTIME, "Failed to get server description");
-} /* }}} */
-
-/* {{{ proto array MongoDB\Driver\Server::getInfo()
- Returns the last hello response for this Server or, in the case of a load
- balancer, the initial handshake response. */
-static PHP_METHOD(Server, getInfo)
-{
- php_phongo_server_t* intern;
- mongoc_client_t* client;
- mongoc_server_description_t* sd;
- mongoc_server_description_t* handshake_sd = NULL;
- const bson_t* hello_response;
- php_phongo_bson_state state;
-
- PHONGO_PARSE_PARAMETERS_NONE();
-
- intern = Z_SERVER_OBJ_P(getThis());
- client = Z_MANAGER_OBJ_P(&intern->manager)->client;
-
- if (!(sd = mongoc_client_get_server_description(client, intern->server_id))) {
- phongo_throw_exception(PHONGO_ERROR_RUNTIME, "Failed to get server description");
- return;
- }
-
- hello_response = mongoc_server_description_hello_response(sd);
-
- /* If the server description is a load balancer, its hello_response will be
- * empty. Instead, report the hello_response from the handshake description
- * (i.e. backing server). */
- if (!strcmp(mongoc_server_description_type(sd), php_phongo_server_description_type_map[PHONGO_SERVER_LOAD_BALANCER].name)) {
- bson_error_t error = { 0 };
-
- if (!(handshake_sd = mongoc_client_get_handshake_description(client, intern->server_id, NULL, &error))) {
- phongo_throw_exception(PHONGO_ERROR_RUNTIME, "Failed to get handshake server description: %s", error.message);
- goto cleanup;
- }
-
- hello_response = mongoc_server_description_hello_response(handshake_sd);
- }
-
- PHONGO_BSON_INIT_DEBUG_STATE(state);
-
- if (!php_phongo_bson_to_zval_ex(bson_get_data(hello_response), hello_response->len, &state)) {
- /* Exception should already have been thrown */
- zval_ptr_dtor(&state.zchild);
- goto cleanup;
- }
-
- RETVAL_ZVAL(&state.zchild, 0, 1);
-
-cleanup:
- if (handshake_sd) {
- mongoc_server_description_destroy(handshake_sd);
- }
-
- mongoc_server_description_destroy(sd);
-} /* }}} */
-
-/* {{{ proto integer|null MongoDB\Driver\Server::getLatency()
- Returns the measured latency (i.e. round trip time in milliseconds) for
- this Server, or null if unset. */
-static PHP_METHOD(Server, getLatency)
-{
- php_phongo_server_t* intern;
- mongoc_server_description_t* sd;
-
- PHONGO_PARSE_PARAMETERS_NONE();
-
- intern = Z_SERVER_OBJ_P(getThis());
-
- if (!(sd = mongoc_client_get_server_description(Z_MANAGER_OBJ_P(&intern->manager)->client, intern->server_id))) {
- phongo_throw_exception(PHONGO_ERROR_RUNTIME, "Failed to get server description");
- return;
- }
-
- /* TODO: Use MONGOC_RTT_UNSET once it is added to libmongoc's public API (CDRIVER-4176) */
- if (mongoc_server_description_round_trip_time(sd) == -1) {
- RETVAL_NULL();
- } else {
- RETVAL_LONG((zend_long) mongoc_server_description_round_trip_time(sd));
- }
-
- mongoc_server_description_destroy(sd);
-} /* }}} */
-
-/* {{{ proto integer MongoDB\Driver\Server::getPort()
- Returns the port for this Server */
-static PHP_METHOD(Server, getPort)
-{
- zend_error_handling error_handling;
- php_phongo_server_t* intern;
- mongoc_server_description_t* sd;
-
- intern = Z_SERVER_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- if ((sd = mongoc_client_get_server_description(Z_MANAGER_OBJ_P(&intern->manager)->client, intern->server_id))) {
- RETVAL_LONG(mongoc_server_description_host(sd)->port);
- mongoc_server_description_destroy(sd);
- return;
- }
-
- phongo_throw_exception(PHONGO_ERROR_RUNTIME, "Failed to get server description");
-} /* }}} */
-
-/* {{{ proto integer MongoDB\Driver\Server::getType()
- Returns the node type of this Server */
-static PHP_METHOD(Server, getType)
-{
- zend_error_handling error_handling;
- php_phongo_server_t* intern;
- mongoc_server_description_t* sd;
-
- intern = Z_SERVER_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- if ((sd = mongoc_client_get_server_description(Z_MANAGER_OBJ_P(&intern->manager)->client, intern->server_id))) {
- RETVAL_LONG(php_phongo_server_description_type(sd));
- mongoc_server_description_destroy(sd);
- return;
- }
-
- phongo_throw_exception(PHONGO_ERROR_RUNTIME, "Failed to get server description");
-} /* }}} */
-
-/* {{{ proto boolean MongoDB\Driver\Server::isPrimary()
- Returns whether this Server is a primary member of a replica set */
-static PHP_METHOD(Server, isPrimary)
-{
- zend_error_handling error_handling;
- php_phongo_server_t* intern;
- mongoc_server_description_t* sd;
-
- intern = Z_SERVER_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- if ((sd = mongoc_client_get_server_description(Z_MANAGER_OBJ_P(&intern->manager)->client, intern->server_id))) {
- RETVAL_BOOL(!strcmp(mongoc_server_description_type(sd), php_phongo_server_description_type_map[PHONGO_SERVER_RS_PRIMARY].name));
- mongoc_server_description_destroy(sd);
- return;
- }
-
- phongo_throw_exception(PHONGO_ERROR_RUNTIME, "Failed to get server description");
-} /* }}} */
-
-/* {{{ proto boolean MongoDB\Driver\Server::isSecondary()
- Returns whether this Server is a secondary member of a replica set */
-static PHP_METHOD(Server, isSecondary)
-{
- zend_error_handling error_handling;
- php_phongo_server_t* intern;
- mongoc_server_description_t* sd;
-
- intern = Z_SERVER_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- if ((sd = mongoc_client_get_server_description(Z_MANAGER_OBJ_P(&intern->manager)->client, intern->server_id))) {
- RETVAL_BOOL(!strcmp(mongoc_server_description_type(sd), php_phongo_server_description_type_map[PHONGO_SERVER_RS_SECONDARY].name));
- mongoc_server_description_destroy(sd);
- return;
- }
-
- phongo_throw_exception(PHONGO_ERROR_RUNTIME, "Failed to get server description");
-} /* }}} */
-
-/* {{{ proto boolean MongoDB\Driver\Server::isArbiter()
- Returns whether this Server is an arbiter member of a replica set */
-static PHP_METHOD(Server, isArbiter)
-{
- zend_error_handling error_handling;
- php_phongo_server_t* intern;
- mongoc_server_description_t* sd;
-
- intern = Z_SERVER_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- if ((sd = mongoc_client_get_server_description(Z_MANAGER_OBJ_P(&intern->manager)->client, intern->server_id))) {
- RETVAL_BOOL(!strcmp(mongoc_server_description_type(sd), php_phongo_server_description_type_map[PHONGO_SERVER_RS_ARBITER].name));
- mongoc_server_description_destroy(sd);
- return;
- }
-
- phongo_throw_exception(PHONGO_ERROR_RUNTIME, "Failed to get server description");
-} /* }}} */
-
-/* {{{ proto boolean MongoDB\Driver\Server::isHidden()
- Returns whether this Server is a hidden member of a replica set */
-static PHP_METHOD(Server, isHidden)
-{
- zend_error_handling error_handling;
- php_phongo_server_t* intern;
- mongoc_server_description_t* sd;
-
- intern = Z_SERVER_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- if ((sd = mongoc_client_get_server_description(Z_MANAGER_OBJ_P(&intern->manager)->client, intern->server_id))) {
- bson_iter_t iter;
-
- RETVAL_BOOL(bson_iter_init_find_case(&iter, mongoc_server_description_hello_response(sd), "hidden") && bson_iter_as_bool(&iter));
- mongoc_server_description_destroy(sd);
- return;
- }
-
- phongo_throw_exception(PHONGO_ERROR_RUNTIME, "Failed to get server description");
-} /* }}} */
-
-/* {{{ proto boolean MongoDB\Driver\Server::isPassive()
- Returns whether this Server is a passive member of a replica set */
-static PHP_METHOD(Server, isPassive)
-{
- zend_error_handling error_handling;
- php_phongo_server_t* intern;
- mongoc_server_description_t* sd;
-
- intern = Z_SERVER_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- if ((sd = mongoc_client_get_server_description(Z_MANAGER_OBJ_P(&intern->manager)->client, intern->server_id))) {
- bson_iter_t iter;
-
- RETVAL_BOOL(bson_iter_init_find_case(&iter, mongoc_server_description_hello_response(sd), "passive") && bson_iter_as_bool(&iter));
- mongoc_server_description_destroy(sd);
- return;
- }
-
- phongo_throw_exception(PHONGO_ERROR_RUNTIME, "Failed to get server description");
-} /* }}} */
-
-/* {{{ MongoDB\Driver\Server function entries */
-ZEND_BEGIN_ARG_INFO_EX(ai_Server_executeCommand, 0, 0, 2)
- ZEND_ARG_INFO(0, db)
- ZEND_ARG_OBJ_INFO(0, command, MongoDB\\Driver\\Command, 0)
- ZEND_ARG_INFO(0, options)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_Server_executeRWCommand, 0, 0, 2)
- ZEND_ARG_INFO(0, db)
- ZEND_ARG_OBJ_INFO(0, command, MongoDB\\Driver\\Command, 0)
- ZEND_ARG_ARRAY_INFO(0, options, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_Server_executeQuery, 0, 0, 2)
- ZEND_ARG_INFO(0, namespace)
- ZEND_ARG_OBJ_INFO(0, zquery, MongoDB\\Driver\\Query, 0)
- ZEND_ARG_INFO(0, options)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_Server_executeBulkWrite, 0, 0, 2)
- ZEND_ARG_INFO(0, namespace)
- ZEND_ARG_OBJ_INFO(0, zbulk, MongoDB\\Driver\\BulkWrite, 0)
- ZEND_ARG_INFO(0, options)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_Server_void, 0, 0, 0)
-ZEND_END_ARG_INFO()
-
-static zend_function_entry php_phongo_server_me[] = {
- /* clang-format off */
- PHP_ME(Server, executeCommand, ai_Server_executeCommand, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Server, executeReadCommand, ai_Server_executeRWCommand, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Server, executeWriteCommand, ai_Server_executeRWCommand, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Server, executeReadWriteCommand, ai_Server_executeRWCommand, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Server, executeQuery, ai_Server_executeQuery, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Server, executeBulkWrite, ai_Server_executeBulkWrite, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Server, getHost, ai_Server_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Server, getTags, ai_Server_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Server, getInfo, ai_Server_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Server, getLatency, ai_Server_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Server, getPort, ai_Server_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Server, getType, ai_Server_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Server, isPrimary, ai_Server_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Server, isSecondary, ai_Server_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Server, isArbiter, ai_Server_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Server, isHidden, ai_Server_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Server, isPassive, ai_Server_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- ZEND_NAMED_ME(__construct, PHP_FN(MongoDB_disabled___construct), ai_Server_void, ZEND_ACC_PRIVATE | ZEND_ACC_FINAL)
- ZEND_NAMED_ME(__wakeup, PHP_FN(MongoDB_disabled___wakeup), ai_Server_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_FE_END
- /* clang-format on */
-};
-/* }}} */
-
-/* {{{ MongoDB\Driver\Server object handlers */
-static zend_object_handlers php_phongo_handler_server;
-
-static int php_phongo_server_compare_objects(zval* o1, zval* o2) /* {{{ */
-{
- php_phongo_server_t* intern1;
- php_phongo_server_t* intern2;
- mongoc_server_description_t *sd1, *sd2;
- int retval = 0;
-
- ZEND_COMPARE_OBJECTS_FALLBACK(o1, o2);
-
- intern1 = Z_SERVER_OBJ_P(o1);
- intern2 = Z_SERVER_OBJ_P(o2);
-
- sd1 = mongoc_client_get_server_description(Z_MANAGER_OBJ_P(&intern1->manager)->client, intern1->server_id);
- sd2 = mongoc_client_get_server_description(Z_MANAGER_OBJ_P(&intern2->manager)->client, intern2->server_id);
-
- if (sd1 && sd2) {
- retval = strcasecmp(mongoc_server_description_host(sd1)->host_and_port, mongoc_server_description_host(sd2)->host_and_port);
- } else {
- phongo_throw_exception(PHONGO_ERROR_RUNTIME, "Failed to get server description(s)");
- }
-
- if (sd1) {
- mongoc_server_description_destroy(sd1);
- }
-
- if (sd2) {
- mongoc_server_description_destroy(sd2);
- }
-
- return retval;
-} /* }}} */
-
-static void php_phongo_server_free_object(zend_object* object) /* {{{ */
-{
- php_phongo_server_t* intern = Z_OBJ_SERVER(object);
-
- zend_object_std_dtor(&intern->std);
-
- if (!Z_ISUNDEF(intern->manager)) {
- zval_ptr_dtor(&intern->manager);
- }
-} /* }}} */
-
-static zend_object* php_phongo_server_create_object(zend_class_entry* class_type) /* {{{ */
-{
- php_phongo_server_t* intern = NULL;
-
- intern = PHONGO_ALLOC_OBJECT_T(php_phongo_server_t, class_type);
-
- zend_object_std_init(&intern->std, class_type);
- object_properties_init(&intern->std, class_type);
-
- PHONGO_SET_CREATED_BY_PID(intern);
-
- intern->std.handlers = &php_phongo_handler_server;
-
- return &intern->std;
-} /* }}} */
-
-static HashTable* php_phongo_server_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
-{
- php_phongo_server_t* intern = NULL;
- zval retval = ZVAL_STATIC_INIT;
- mongoc_client_t* client;
- mongoc_server_description_t* sd;
-
- *is_temp = 1;
- intern = Z_OBJ_SERVER(PHONGO_COMPAT_GET_OBJ(object));
- client = Z_MANAGER_OBJ_P(&intern->manager)->client;
-
- if (!(sd = mongoc_client_get_server_description(client, intern->server_id))) {
- phongo_throw_exception(PHONGO_ERROR_RUNTIME, "Failed to get server description");
- return NULL;
- }
-
- php_phongo_server_to_zval(&retval, client, sd);
- mongoc_server_description_destroy(sd);
-
- return Z_ARRVAL(retval);
-} /* }}} */
-/* }}} */
-
-void php_phongo_server_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver", "Server", php_phongo_server_me);
- php_phongo_server_ce = zend_register_internal_class(&ce);
- php_phongo_server_ce->create_object = php_phongo_server_create_object;
- PHONGO_CE_FINAL(php_phongo_server_ce);
- PHONGO_CE_DISABLE_SERIALIZATION(php_phongo_server_ce);
-
- memcpy(&php_phongo_handler_server, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
- PHONGO_COMPAT_SET_COMPARE_OBJECTS_HANDLER(server);
- php_phongo_handler_server.get_debug_info = php_phongo_server_get_debug_info;
- php_phongo_handler_server.free_obj = php_phongo_server_free_object;
- php_phongo_handler_server.offset = XtOffsetOf(php_phongo_server_t, std);
-
- zend_declare_class_constant_long(php_phongo_server_ce, ZEND_STRL("TYPE_UNKNOWN"), PHONGO_SERVER_UNKNOWN);
- zend_declare_class_constant_long(php_phongo_server_ce, ZEND_STRL("TYPE_STANDALONE"), PHONGO_SERVER_STANDALONE);
- zend_declare_class_constant_long(php_phongo_server_ce, ZEND_STRL("TYPE_MONGOS"), PHONGO_SERVER_MONGOS);
- zend_declare_class_constant_long(php_phongo_server_ce, ZEND_STRL("TYPE_POSSIBLE_PRIMARY"), PHONGO_SERVER_POSSIBLE_PRIMARY);
- zend_declare_class_constant_long(php_phongo_server_ce, ZEND_STRL("TYPE_RS_PRIMARY"), PHONGO_SERVER_RS_PRIMARY);
- zend_declare_class_constant_long(php_phongo_server_ce, ZEND_STRL("TYPE_RS_SECONDARY"), PHONGO_SERVER_RS_SECONDARY);
- zend_declare_class_constant_long(php_phongo_server_ce, ZEND_STRL("TYPE_RS_ARBITER"), PHONGO_SERVER_RS_ARBITER);
- zend_declare_class_constant_long(php_phongo_server_ce, ZEND_STRL("TYPE_RS_OTHER"), PHONGO_SERVER_RS_OTHER);
- zend_declare_class_constant_long(php_phongo_server_ce, ZEND_STRL("TYPE_RS_GHOST"), PHONGO_SERVER_RS_GHOST);
- zend_declare_class_constant_long(php_phongo_server_ce, ZEND_STRL("TYPE_LOAD_BALANCER"), PHONGO_SERVER_LOAD_BALANCER);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/MongoDB/ServerApi.c b/mongodb-1.12.0/src/MongoDB/ServerApi.c
deleted file mode 100644
index 6357cabc..00000000
--- a/mongodb-1.12.0/src/MongoDB/ServerApi.c
+++ /dev/null
@@ -1,403 +0,0 @@
-/*
- * Copyright 2021-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-#include <Zend/zend_interfaces.h>
-#include <ext/standard/php_var.h>
-#include <zend_smart_str.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-
-zend_class_entry* php_phongo_serverapi_ce;
-
-static bool php_phongo_serverapi_create_libmongoc_object(mongoc_server_api_t** server_api, zend_string* version, bool strict_set, bool strict, bool deprecation_errors_set, bool deprecation_errors) /* {{{ */
-{
- mongoc_server_api_version_t server_api_version;
-
- if (!mongoc_server_api_version_from_string(ZSTR_VAL(version), &server_api_version)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Server API version \"%s\" is not supported in this driver version", ZSTR_VAL(version));
- return false;
- }
-
- if (*server_api) {
- phongo_throw_exception(PHONGO_ERROR_LOGIC, "Server API object already initialized. Please file a bug report as this should not happen.");
- return false;
- }
-
- *server_api = mongoc_server_api_new(server_api_version);
-
- if (strict_set) {
- mongoc_server_api_strict(*server_api, strict);
- }
-
- if (deprecation_errors_set) {
- mongoc_server_api_deprecation_errors(*server_api, deprecation_errors);
- }
-
- return true;
-} /* }}} */
-
-/* Initialize the object from a HashTable and return whether it was successful.
- * An exception will be thrown on error. */
-static bool php_phongo_serverapi_init_from_hash(php_phongo_serverapi_t* intern, HashTable* props) /* {{{ */
-{
- zval* version;
- zval* strict;
- zval* deprecation_errors;
-
- version = zend_hash_str_find(props, ZEND_STRL("version"));
- if (!version || Z_TYPE_P(version) != IS_STRING) {
- // Exception
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"version\" field to be string", ZSTR_VAL(php_phongo_serverapi_ce->name));
- return false;
- }
-
- if ((strict = zend_hash_str_find(props, ZEND_STRL("strict"))) && !ZVAL_IS_NULL(strict)) {
- if (Z_TYPE_P(strict) != IS_TRUE && Z_TYPE_P(strict) != IS_FALSE) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"strict\" field to be bool or null", ZSTR_VAL(php_phongo_serverapi_ce->name));
- return false;
- }
- }
-
- if ((deprecation_errors = zend_hash_str_find(props, ZEND_STRL("deprecationErrors"))) && !ZVAL_IS_NULL(deprecation_errors)) {
- if (Z_TYPE_P(deprecation_errors) != IS_TRUE && Z_TYPE_P(deprecation_errors) != IS_FALSE) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"deprecationErrors\" field to be bool or null", ZSTR_VAL(php_phongo_serverapi_ce->name));
- return false;
- }
- }
-
- return php_phongo_serverapi_create_libmongoc_object(
- &intern->server_api,
- Z_STR_P(version),
- strict && !ZVAL_IS_NULL(strict),
- strict && zval_is_true(strict),
- deprecation_errors && !ZVAL_IS_NULL(deprecation_errors),
- deprecation_errors && zval_is_true(deprecation_errors));
-} /* }}} */
-
-/* {{{ proto void MongoDB\Driver\ServerApi::__construct(string $version, [?bool $strict], [?bool $deprecationErrors])
- Constructs a new ServerApi object */
-static PHP_METHOD(ServerApi, __construct)
-{
- php_phongo_serverapi_t* intern;
- zend_string* version;
- zend_bool strict = 0;
- zend_bool strict_null = 1;
- zend_bool deprecation_errors = 0;
- zend_bool deprecation_errors_null = 1;
-
- intern = Z_SERVERAPI_OBJ_P(getThis());
-
- PHONGO_PARSE_PARAMETERS_START(1, 3)
- Z_PARAM_STR(version)
- Z_PARAM_OPTIONAL
- Z_PARAM_BOOL_EX(strict, strict_null, 1, 0)
- Z_PARAM_BOOL_EX(deprecation_errors, deprecation_errors_null, 1, 0)
- PHONGO_PARSE_PARAMETERS_END();
-
- // Will throw on failure
- php_phongo_serverapi_create_libmongoc_object(
- &intern->server_api,
- version,
- (bool) !strict_null,
- (bool) strict,
- (bool) !deprecation_errors_null,
- (bool) deprecation_errors);
-} /* }}} */
-
-/* {{{ proto MongoDB\Driver\ServerApi MongoDB\Driver\ServerApi::__set_state(array $properties)
-*/
-static PHP_METHOD(ServerApi, __set_state)
-{
- php_phongo_serverapi_t* intern;
- HashTable* props;
- zval* array;
-
- PHONGO_PARSE_PARAMETERS_START(1, 1)
- Z_PARAM_ARRAY(array)
- PHONGO_PARSE_PARAMETERS_END();
-
- object_init_ex(return_value, php_phongo_serverapi_ce);
-
- intern = Z_SERVERAPI_OBJ_P(return_value);
- props = Z_ARRVAL_P(array);
-
- php_phongo_serverapi_init_from_hash(intern, props);
-} /* }}} */
-
-static HashTable* php_phongo_serverapi_get_properties_hash(phongo_compat_object_handler_type* object, bool is_temp, bool include_null) /* {{{ */
-{
- php_phongo_serverapi_t* intern;
- HashTable* props;
- zval version, strict, deprecation_errors;
- bool is_set;
-
- intern = Z_OBJ_SERVERAPI(PHONGO_COMPAT_GET_OBJ(object));
-
- PHONGO_GET_PROPERTY_HASH_INIT_PROPS(is_temp, intern, props, 1);
-
- ZVAL_STRING(&version, mongoc_server_api_version_to_string(mongoc_server_api_get_version(intern->server_api)));
- zend_hash_str_add(props, "version", sizeof("version") - 1, &version);
-
- is_set = mongoc_optional_is_set(mongoc_server_api_get_strict(intern->server_api));
- if (is_set) {
- ZVAL_BOOL(&strict, mongoc_optional_value(mongoc_server_api_get_strict(intern->server_api)));
- } else {
- ZVAL_NULL(&strict);
- }
-
- if (include_null || is_set) {
- zend_hash_str_add(props, "strict", sizeof("strict") - 1, &strict);
- }
-
- is_set = mongoc_optional_is_set(mongoc_server_api_get_deprecation_errors(intern->server_api));
- if (is_set) {
- ZVAL_BOOL(&deprecation_errors, mongoc_optional_value(mongoc_server_api_get_deprecation_errors(intern->server_api)));
- } else {
- ZVAL_NULL(&deprecation_errors);
- }
-
- if (include_null || is_set) {
- zend_hash_str_add(props, "deprecationErrors", sizeof("deprecationErrors") - 1, &deprecation_errors);
- }
-
- return props;
-} /* }}} */
-
-/* {{{ proto array MongoDB\Driver\ServerApi::bsonSerialize()
-*/
-static PHP_METHOD(ServerApi, bsonSerialize)
-{
- PHONGO_PARSE_PARAMETERS_NONE();
-
- ZVAL_ARR(return_value, php_phongo_serverapi_get_properties_hash(PHONGO_COMPAT_OBJ_P(getThis()), true, false));
- convert_to_object(return_value);
-} /* }}} */
-
-/* {{{ proto string MongoDB\Driver\ServerApi::serialize()
-*/
-static PHP_METHOD(ServerApi, serialize)
-{
- php_phongo_serverapi_t* intern;
- zval retval;
- php_serialize_data_t var_hash;
- smart_str buf = { 0 };
-
- intern = Z_SERVERAPI_OBJ_P(getThis());
-
- PHONGO_PARSE_PARAMETERS_NONE();
-
- array_init_size(&retval, 3);
-
- ADD_ASSOC_STRING(&retval, "version", mongoc_server_api_version_to_string(mongoc_server_api_get_version(intern->server_api)));
-
- if (mongoc_optional_is_set(mongoc_server_api_get_strict(intern->server_api))) {
- ADD_ASSOC_BOOL_EX(&retval, "strict", mongoc_optional_value(mongoc_server_api_get_strict(intern->server_api)));
- } else {
- ADD_ASSOC_NULL_EX(&retval, "strict");
- }
-
- if (mongoc_optional_is_set(mongoc_server_api_get_deprecation_errors(intern->server_api))) {
- ADD_ASSOC_BOOL_EX(&retval, "deprecationErrors", mongoc_optional_value(mongoc_server_api_get_deprecation_errors(intern->server_api)));
- } else {
- ADD_ASSOC_NULL_EX(&retval, "deprecationErrors");
- }
-
- PHP_VAR_SERIALIZE_INIT(var_hash);
- php_var_serialize(&buf, &retval, &var_hash);
- smart_str_0(&buf);
- PHP_VAR_SERIALIZE_DESTROY(var_hash);
-
- PHONGO_RETVAL_SMART_STR(buf);
-
- smart_str_free(&buf);
- zval_ptr_dtor(&retval);
-} /* }}} */
-
-/* {{{ proto void MongoDB\Driver\ServerApi::unserialize(string $serialized)
-*/
-static PHP_METHOD(ServerApi, unserialize)
-{
- php_phongo_serverapi_t* intern;
- char* serialized;
- size_t serialized_len;
- zval props;
- php_unserialize_data_t var_hash;
-
- intern = Z_SERVERAPI_OBJ_P(getThis());
-
- PHONGO_PARSE_PARAMETERS_START(1, 1)
- Z_PARAM_STRING(serialized, serialized_len)
- PHONGO_PARSE_PARAMETERS_END();
-
- if (!serialized_len) {
- return;
- }
-
- PHP_VAR_UNSERIALIZE_INIT(var_hash);
- if (!php_var_unserialize(&props, (const unsigned char**) &serialized, (unsigned char*) serialized + serialized_len, &var_hash)) {
- zval_ptr_dtor(&props);
- phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "%s unserialization failed", ZSTR_VAL(php_phongo_serverapi_ce->name));
-
- PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
- return;
- }
- PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
-
- php_phongo_serverapi_init_from_hash(intern, HASH_OF(&props));
- zval_ptr_dtor(&props);
-} /* }}} */
-
-/* {{{ proto array MongoDB\Driver\ServerApi::__serialize()
-*/
-static PHP_METHOD(ServerApi, __serialize)
-{
- PHONGO_PARSE_PARAMETERS_NONE();
-
- RETURN_ARR(php_phongo_serverapi_get_properties_hash(PHONGO_COMPAT_OBJ_P(getThis()), true, true));
-} /* }}} */
-
-/* {{{ proto void MongoDB\Driver\ServerApi::__unserialize(array $data)
-*/
-static PHP_METHOD(ServerApi, __unserialize)
-{
- zval* data;
-
- PHONGO_PARSE_PARAMETERS_START(1, 1)
- Z_PARAM_ARRAY(data)
- PHONGO_PARSE_PARAMETERS_END();
-
- php_phongo_serverapi_init_from_hash(Z_SERVERAPI_OBJ_P(getThis()), Z_ARRVAL_P(data));
-} /* }}} */
-
-/* {{{ MongoDB\Driver\ServerApi function entries */
-ZEND_BEGIN_ARG_INFO_EX(ai_ServerApi___construct, 0, 0, 1)
- ZEND_ARG_TYPE_INFO(0, version, IS_STRING, 0)
- ZEND_ARG_TYPE_INFO(0, strict, _IS_BOOL, 1)
- ZEND_ARG_TYPE_INFO(0, deprecationErrors, _IS_BOOL, 1)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_ServerApi___set_state, 0, 0, 1)
- ZEND_ARG_ARRAY_INFO(0, properties, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_ServerApi___unserialize, 0, 0, 1)
- ZEND_ARG_ARRAY_INFO(0, data, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_ServerApi_unserialize, 0, 0, 1)
-#if PHP_VERSION_ID >= 80000
- ZEND_ARG_TYPE_INFO(0, serialized, IS_STRING, 0)
-#else
- ZEND_ARG_INFO(0, serialized)
-#endif
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_ServerApi_void, 0, 0, 0)
-ZEND_END_ARG_INFO()
-
-static zend_function_entry php_phongo_serverapi_me[] = {
- /* clang-format off */
- PHP_ME(ServerApi, __construct, ai_ServerApi___construct, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(ServerApi, __serialize, ai_ServerApi_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(ServerApi, __set_state, ai_ServerApi___set_state, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
- PHP_ME(ServerApi, __unserialize, ai_ServerApi___unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(ServerApi, bsonSerialize, ai_ServerApi_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(ServerApi, serialize, ai_ServerApi_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(ServerApi, unserialize, ai_ServerApi_unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_FE_END
- /* clang-format on */
-};
-/* }}} */
-
-/* {{{ MongoDB\Driver\ServerApi object handlers */
-static zend_object_handlers php_phongo_handler_serverapi;
-
-static void php_phongo_serverapi_free_object(zend_object* object) /* {{{ */
-{
- php_phongo_serverapi_t* intern = Z_OBJ_SERVERAPI(object);
-
- zend_object_std_dtor(&intern->std);
-
- if (intern->properties) {
- zend_hash_destroy(intern->properties);
- FREE_HASHTABLE(intern->properties);
- }
-
- if (intern->server_api) {
- mongoc_server_api_destroy(intern->server_api);
- }
-}
-
-static zend_object* php_phongo_serverapi_create_object(zend_class_entry* class_type) /* {{{ */
-{
- php_phongo_serverapi_t* intern = NULL;
-
- intern = PHONGO_ALLOC_OBJECT_T(php_phongo_serverapi_t, class_type);
-
- zend_object_std_init(&intern->std, class_type);
- object_properties_init(&intern->std, class_type);
-
- intern->std.handlers = &php_phongo_handler_serverapi;
-
- return &intern->std;
-} /* }}} */
-
-static HashTable* php_phongo_serverapi_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
-{
- *is_temp = 1;
- return php_phongo_serverapi_get_properties_hash(object, true, true);
-} /* }}} */
-
-static HashTable* php_phongo_serverapi_get_properties(phongo_compat_object_handler_type* object) /* {{{ */
-{
- return php_phongo_serverapi_get_properties_hash(object, false, true);
-} /* }}} */
-
-void php_phongo_serverapi_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver", "ServerApi", php_phongo_serverapi_me);
- php_phongo_serverapi_ce = zend_register_internal_class(&ce);
- php_phongo_serverapi_ce->create_object = php_phongo_serverapi_create_object;
- PHONGO_CE_FINAL(php_phongo_serverapi_ce);
-
- zend_class_implements(php_phongo_serverapi_ce, 1, php_phongo_serializable_ce);
- zend_class_implements(php_phongo_serverapi_ce, 1, zend_ce_serializable);
-
- memcpy(&php_phongo_handler_serverapi, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
- php_phongo_handler_serverapi.get_debug_info = php_phongo_serverapi_get_debug_info;
- php_phongo_handler_serverapi.get_properties = php_phongo_serverapi_get_properties;
- php_phongo_handler_serverapi.free_obj = php_phongo_serverapi_free_object;
- php_phongo_handler_serverapi.offset = XtOffsetOf(php_phongo_serverapi_t, std);
-
- zend_declare_class_constant_stringl(php_phongo_serverapi_ce, ZEND_STRL("V1"), ZEND_STRL("1"));
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/MongoDB/Session.c b/mongodb-1.12.0/src/MongoDB/Session.c
deleted file mode 100644
index 4144bb19..00000000
--- a/mongodb-1.12.0/src/MongoDB/Session.c
+++ /dev/null
@@ -1,843 +0,0 @@
-/*
- * Copyright 2017-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-#include <Zend/zend_interfaces.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-#include "php_bson.h"
-#include "php_array_api.h"
-#include "Session.h"
-
-zend_class_entry* php_phongo_session_ce;
-
-#define PHONGO_TRANSACTION_NONE "none"
-#define PHONGO_TRANSACTION_STARTING "starting"
-#define PHONGO_TRANSACTION_IN_PROGRESS "in_progress"
-#define PHONGO_TRANSACTION_COMMITTED "committed"
-#define PHONGO_TRANSACTION_ABORTED "aborted"
-
-#define SESSION_CHECK_LIVELINESS(i, m) \
- if (!(i)->client_session) { \
- phongo_throw_exception( \
- PHONGO_ERROR_LOGIC, \
- "Cannot call '%s', as the session has already been ended.", \
- (m)); \
- return; \
- }
-
-static bool php_phongo_session_get_timestamp_parts(zval* obj, uint32_t* timestamp, uint32_t* increment)
-{
- bool retval = false;
- zval ztimestamp = ZVAL_STATIC_INIT;
- zval zincrement = ZVAL_STATIC_INIT;
-
- zend_call_method_with_0_params(PHONGO_COMPAT_OBJ_P(obj), NULL, NULL, "getTimestamp", &ztimestamp);
-
- if (Z_ISUNDEF(ztimestamp) || EG(exception)) {
- goto cleanup;
- }
-
- zend_call_method_with_0_params(PHONGO_COMPAT_OBJ_P(obj), NULL, NULL, "getIncrement", &zincrement);
-
- if (Z_ISUNDEF(zincrement) || EG(exception)) {
- goto cleanup;
- }
-
- *timestamp = Z_LVAL(ztimestamp);
- *increment = Z_LVAL(zincrement);
-
- retval = true;
-
-cleanup:
- if (!Z_ISUNDEF(ztimestamp)) {
- zval_ptr_dtor(&ztimestamp);
- }
-
- if (!Z_ISUNDEF(zincrement)) {
- zval_ptr_dtor(&zincrement);
- }
-
- return retval;
-}
-
-static const char* php_phongo_get_transaction_state_string(mongoc_transaction_state_t state)
-{
- switch (state) {
- case MONGOC_TRANSACTION_NONE:
- return PHONGO_TRANSACTION_NONE;
- case MONGOC_TRANSACTION_STARTING:
- return PHONGO_TRANSACTION_STARTING;
- case MONGOC_TRANSACTION_IN_PROGRESS:
- return PHONGO_TRANSACTION_IN_PROGRESS;
- case MONGOC_TRANSACTION_COMMITTED:
- return PHONGO_TRANSACTION_COMMITTED;
- case MONGOC_TRANSACTION_ABORTED:
- return PHONGO_TRANSACTION_ABORTED;
- default:
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Invalid transaction state %d given", (int) state);
- return NULL;
- }
-}
-
-static void php_phongo_transaction_options_to_zval(mongoc_client_session_t* cs, zval* retval)
-{
- mongoc_transaction_opt_t* opts;
- int64_t max_commit_time_ms;
- const mongoc_read_concern_t* read_concern;
- const mongoc_read_prefs_t* read_preference;
- const mongoc_write_concern_t* write_concern;
-
- if (!cs) {
- ZVAL_NULL(retval);
- return;
- }
-
- opts = mongoc_session_opts_get_transaction_opts(cs);
-
- if (!opts) {
- ZVAL_NULL(retval);
- return;
- }
-
- max_commit_time_ms = mongoc_transaction_opts_get_max_commit_time_ms(opts);
- read_concern = mongoc_transaction_opts_get_read_concern(opts);
- read_preference = mongoc_transaction_opts_get_read_prefs(opts);
- write_concern = mongoc_transaction_opts_get_write_concern(opts);
-
- array_init_size(retval, 4);
-
- if (max_commit_time_ms) {
- ADD_ASSOC_LONG_EX(retval, "maxCommitTimeMS", max_commit_time_ms);
- }
-
- if (!mongoc_read_concern_is_default(read_concern)) {
- zval zread_concern;
-
- phongo_readconcern_init(&zread_concern, read_concern);
- ADD_ASSOC_ZVAL_EX(retval, "readConcern", &zread_concern);
- }
-
- if (read_preference) {
- zval zread_preference;
-
- phongo_readpreference_init(&zread_preference, read_preference);
- ADD_ASSOC_ZVAL_EX(retval, "readPreference", &zread_preference);
- }
-
- if (!mongoc_write_concern_is_default(write_concern)) {
- zval zwrite_concern;
-
- phongo_writeconcern_init(&zwrite_concern, write_concern);
- ADD_ASSOC_ZVAL_EX(retval, "writeConcern", &zwrite_concern);
- }
-
- mongoc_transaction_opts_destroy(opts);
-}
-
-/* {{{ proto void MongoDB\Driver\Session::advanceClusterTime(array|object $clusterTime)
- Advances the cluster time for this Session */
-static PHP_METHOD(Session, advanceClusterTime)
-{
- zend_error_handling error_handling;
- php_phongo_session_t* intern;
- zval* zcluster_time;
- bson_t cluster_time = BSON_INITIALIZER;
-
- intern = Z_SESSION_OBJ_P(getThis());
- SESSION_CHECK_LIVELINESS(intern, "advanceClusterTime")
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "A", &zcluster_time) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- php_phongo_zval_to_bson(zcluster_time, PHONGO_BSON_NONE, &cluster_time, NULL);
-
- /* An exception may be thrown during BSON conversion */
- if (EG(exception)) {
- goto cleanup;
- }
-
- mongoc_client_session_advance_cluster_time(intern->client_session, &cluster_time);
-
-cleanup:
- bson_destroy(&cluster_time);
-} /* }}} */
-
-/* {{{ proto void MongoDB\Driver\Session::advanceOperationTime(MongoDB\BSON\TimestampInterface $timestamp)
- Advances the operation time for this Session */
-static PHP_METHOD(Session, advanceOperationTime)
-{
- zend_error_handling error_handling;
- php_phongo_session_t* intern;
- zval* ztimestamp;
- uint32_t timestamp = 0;
- uint32_t increment = 0;
-
- intern = Z_SESSION_OBJ_P(getThis());
- SESSION_CHECK_LIVELINESS(intern, "advanceOperationTime")
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &ztimestamp, php_phongo_timestamp_interface_ce) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- if (!php_phongo_session_get_timestamp_parts(ztimestamp, &timestamp, &increment)) {
- return;
- }
-
- mongoc_client_session_advance_operation_time(intern->client_session, timestamp, increment);
-} /* }}} */
-
-/* {{{ proto object|null MongoDB\Driver\Session::getClusterTime()
- Returns the cluster time for this Session */
-static PHP_METHOD(Session, getClusterTime)
-{
- zend_error_handling error_handling;
- php_phongo_session_t* intern;
- const bson_t* cluster_time;
- php_phongo_bson_state state;
-
- PHONGO_BSON_INIT_STATE(state);
-
- intern = Z_SESSION_OBJ_P(getThis());
- SESSION_CHECK_LIVELINESS(intern, "getClusterTime")
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- cluster_time = mongoc_client_session_get_cluster_time(intern->client_session);
-
- if (!cluster_time) {
- RETURN_NULL();
- }
-
- if (!php_phongo_bson_to_zval_ex(bson_get_data(cluster_time), cluster_time->len, &state)) {
- /* Exception should already have been thrown */
- zval_ptr_dtor(&state.zchild);
- return;
- }
-
- RETURN_ZVAL(&state.zchild, 0, 1);
-} /* }}} */
-
-/* {{{ proto object MongoDB\Driver\Session::getLogicalSessionId()
- Returns the logical session ID for this Session */
-static PHP_METHOD(Session, getLogicalSessionId)
-{
- zend_error_handling error_handling;
- php_phongo_session_t* intern;
- const bson_t* lsid;
- php_phongo_bson_state state;
-
- PHONGO_BSON_INIT_STATE(state);
-
- intern = Z_SESSION_OBJ_P(getThis());
- SESSION_CHECK_LIVELINESS(intern, "getLogicalSessionId")
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- lsid = mongoc_client_session_get_lsid(intern->client_session);
-
- if (!php_phongo_bson_to_zval_ex(bson_get_data(lsid), lsid->len, &state)) {
- /* Exception should already have been thrown */
- zval_ptr_dtor(&state.zchild);
- return;
- }
-
- RETURN_ZVAL(&state.zchild, 0, 1);
-} /* }}} */
-
-/* {{{ proto MongoDB\BSON\Timestamp|null MongoDB\Driver\Session::getOperationTime()
- Returns the operation time for this Session */
-static PHP_METHOD(Session, getOperationTime)
-{
- zend_error_handling error_handling;
- php_phongo_session_t* intern;
- uint32_t timestamp, increment;
-
- intern = Z_SESSION_OBJ_P(getThis());
- SESSION_CHECK_LIVELINESS(intern, "getOperationTime")
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- mongoc_client_session_get_operation_time(intern->client_session, &timestamp, &increment);
-
- /* mongoc_client_session_get_operation_time() returns 0 for both parts if
- * the session has not been used. According to the causal consistency spec,
- * the operation time for an unused session is null. */
- if (timestamp == 0 && increment == 0) {
- RETURN_NULL();
- }
-
- php_phongo_bson_new_timestamp_from_increment_and_timestamp(return_value, increment, timestamp);
-} /* }}} */
-
-/* {{{ proto MongoDB\Driver\Server|null MongoDB\Driver\Session::getServer()
- Returns the server this session is pinned to */
-static PHP_METHOD(Session, getServer)
-{
- zend_error_handling error_handling;
- php_phongo_session_t* intern;
- uint32_t server_id = 0;
-
- intern = Z_SESSION_OBJ_P(getThis());
- SESSION_CHECK_LIVELINESS(intern, "getServer")
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- server_id = mongoc_client_session_get_server_id(intern->client_session);
-
- /* For sessions without a pinned server, 0 is returned. */
- if (!server_id) {
- RETURN_NULL();
- }
-
- phongo_server_init(return_value, &intern->manager, server_id);
-} /* }}} */
-
-/* {{{ proto array|null MongoDB\Driver\Session::getTransactionOptions()
- Returns options for the currently running transaction */
-static PHP_METHOD(Session, getTransactionOptions)
-{
- zend_error_handling error_handling;
- php_phongo_session_t* intern;
-
- intern = Z_SESSION_OBJ_P(getThis());
- SESSION_CHECK_LIVELINESS(intern, "getTransactionOptions")
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- php_phongo_transaction_options_to_zval(intern->client_session, return_value);
-} /* }}} */
-
-/* {{{ proto string MongoDB\Driver\Session::getTransactionState()
- Returns the current transaction state for this session */
-static PHP_METHOD(Session, getTransactionState)
-{
- zend_error_handling error_handling;
- php_phongo_session_t* intern;
- const char* state;
-
- intern = Z_SESSION_OBJ_P(getThis());
- SESSION_CHECK_LIVELINESS(intern, "getTransactionState")
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- state = php_phongo_get_transaction_state_string(mongoc_client_session_get_transaction_state(intern->client_session));
- if (!state) {
- /* Exception already thrown */
- return;
- }
-
- RETURN_STRING(state);
-} /* }}} */
-
-/* Creates a opts structure from an array optionally containing an RP, RC,
- * WC object, and/or maxCommitTimeMS int. Returns NULL if no options were found,
- * or there was an invalid option. If there was an invalid option or structure,
- * an exception will be thrown too. */
-mongoc_transaction_opt_t* php_mongodb_session_parse_transaction_options(zval* options)
-{
- mongoc_transaction_opt_t* opts = NULL;
-
- if (php_array_existsc(options, "maxCommitTimeMS")) {
- int64_t max_commit_time_ms = php_array_fetchc_long(options, "maxCommitTimeMS");
-
- if (max_commit_time_ms < 0) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"maxCommitTimeMS\" option to be >= 0, %" PRId64 " given", max_commit_time_ms);
- /* Freeing opts is not needed here, as it can't be set yet. The
- * code is here to keep it consistent with the others in case more
- * options are added before this one. */
- if (opts) {
- mongoc_transaction_opts_destroy(opts);
- }
- return NULL;
- }
-
- if (max_commit_time_ms > UINT32_MAX) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"maxCommitTimeMS\" option to be <= %" PRIu32 ", %" PRId64 " given", UINT32_MAX, max_commit_time_ms);
- /* Freeing opts is not needed here, as it can't be set yet. The
- * code is here to keep it consistent with the others in case more
- * options are added before this one. */
- if (opts) {
- mongoc_transaction_opts_destroy(opts);
- }
- return NULL;
- }
-
- if (!opts) {
- opts = mongoc_transaction_opts_new();
- }
-
- mongoc_transaction_opts_set_max_commit_time_ms(opts, max_commit_time_ms);
- }
-
- if (php_array_existsc(options, "readConcern")) {
- zval* read_concern = php_array_fetchc(options, "readConcern");
-
- if (Z_TYPE_P(read_concern) != IS_OBJECT || !instanceof_function(Z_OBJCE_P(read_concern), php_phongo_readconcern_ce)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"readConcern\" option to be %s, %s given", ZSTR_VAL(php_phongo_readconcern_ce->name), PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(read_concern));
- if (opts) {
- mongoc_transaction_opts_destroy(opts);
- }
- return NULL;
- }
-
- if (!opts) {
- opts = mongoc_transaction_opts_new();
- }
-
- mongoc_transaction_opts_set_read_concern(opts, phongo_read_concern_from_zval(read_concern));
- }
-
- if (php_array_existsc(options, "readPreference")) {
- zval* read_preference = php_array_fetchc(options, "readPreference");
-
- if (Z_TYPE_P(read_preference) != IS_OBJECT || !instanceof_function(Z_OBJCE_P(read_preference), php_phongo_readpreference_ce)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"readPreference\" option to be %s, %s given", ZSTR_VAL(php_phongo_readpreference_ce->name), PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(read_preference));
- if (opts) {
- mongoc_transaction_opts_destroy(opts);
- }
- return NULL;
- }
-
- if (!opts) {
- opts = mongoc_transaction_opts_new();
- }
-
- mongoc_transaction_opts_set_read_prefs(opts, phongo_read_preference_from_zval(read_preference));
- }
-
- if (php_array_existsc(options, "writeConcern")) {
- zval* write_concern = php_array_fetchc(options, "writeConcern");
-
- if (Z_TYPE_P(write_concern) != IS_OBJECT || !instanceof_function(Z_OBJCE_P(write_concern), php_phongo_writeconcern_ce)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"writeConcern\" option to be %s, %s given", ZSTR_VAL(php_phongo_writeconcern_ce->name), PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(write_concern));
- if (opts) {
- mongoc_transaction_opts_destroy(opts);
- }
- return NULL;
- }
-
- if (!opts) {
- opts = mongoc_transaction_opts_new();
- }
-
- mongoc_transaction_opts_set_write_concern(opts, phongo_write_concern_from_zval(write_concern));
- }
-
- return opts;
-}
-
-/* {{{ proto void MongoDB\Driver\Session::startTransaction([array $options = null])
- Starts a new transaction */
-static PHP_METHOD(Session, startTransaction)
-{
- zend_error_handling error_handling;
- php_phongo_session_t* intern;
- zval* options = NULL;
- mongoc_transaction_opt_t* txn_options = NULL;
- bson_error_t error;
-
- intern = Z_SESSION_OBJ_P(getThis());
- SESSION_CHECK_LIVELINESS(intern, "startTransaction")
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "|a!", &options) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- if (options) {
- txn_options = php_mongodb_session_parse_transaction_options(options);
- }
- if (EG(exception)) {
- return;
- }
-
- if (!mongoc_client_session_start_transaction(intern->client_session, txn_options, &error)) {
- phongo_throw_exception_from_bson_error_t(&error);
- }
-
- if (txn_options) {
- mongoc_transaction_opts_destroy(txn_options);
- }
-} /* }}} */
-
-/* {{{ proto void MongoDB\Driver\Session::commitTransaction(void)
- Commits an existing transaction */
-static PHP_METHOD(Session, commitTransaction)
-{
- zend_error_handling error_handling;
- php_phongo_session_t* intern;
- bson_error_t error;
- bson_t reply;
-
- intern = Z_SESSION_OBJ_P(getThis());
- SESSION_CHECK_LIVELINESS(intern, "commitTransaction")
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- if (!mongoc_client_session_commit_transaction(intern->client_session, &reply, &error)) {
- phongo_throw_exception_from_bson_error_t_and_reply(&error, &reply);
- }
-
- bson_destroy(&reply);
-} /* }}} */
-
-/* {{{ proto void MongoDB\Driver\Session::abortTransaction(void)
- Aborts (rolls back) an existing transaction */
-static PHP_METHOD(Session, abortTransaction)
-{
- zend_error_handling error_handling;
- php_phongo_session_t* intern;
- bson_error_t error;
-
- intern = Z_SESSION_OBJ_P(getThis());
- SESSION_CHECK_LIVELINESS(intern, "abortTransaction")
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- if (!mongoc_client_session_abort_transaction(intern->client_session, &error)) {
- phongo_throw_exception_from_bson_error_t(&error);
- }
-} /* }}} */
-
-/* {{{ proto void MongoDB\Driver\Session::endSession(void)
- Ends the session, and a running transaction if active */
-static PHP_METHOD(Session, endSession)
-{
- zend_error_handling error_handling;
- php_phongo_session_t* intern;
-
- intern = Z_SESSION_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- mongoc_client_session_destroy(intern->client_session);
- intern->client_session = NULL;
-} /* }}} */
-
-/* {{{ proto void MongoDB\Driver\Session::isInTransaction(void)
- Returns whether a multi-document transaction is in progress */
-static PHP_METHOD(Session, isInTransaction)
-{
- zend_error_handling error_handling;
- php_phongo_session_t* intern;
-
- intern = Z_SESSION_OBJ_P(getThis());
- SESSION_CHECK_LIVELINESS(intern, "isInTransaction")
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- RETURN_BOOL(mongoc_client_session_in_transaction(intern->client_session));
-} /* }}} */
-
-/* {{{ MongoDB\Driver\Session function entries */
-ZEND_BEGIN_ARG_INFO_EX(ai_Session_advanceClusterTime, 0, 0, 1)
- ZEND_ARG_INFO(0, clusterTime)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_Session_advanceOperationTime, 0, 0, 1)
- ZEND_ARG_INFO(0, timestamp)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_Session_startTransaction, 0, 0, 0)
- ZEND_ARG_ARRAY_INFO(0, options, 1)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_Session_void, 0, 0, 0)
-ZEND_END_ARG_INFO()
-
-static zend_function_entry php_phongo_session_me[] = {
- /* clang-format off */
- PHP_ME(Session, abortTransaction, ai_Session_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Session, advanceClusterTime, ai_Session_advanceClusterTime, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Session, advanceOperationTime, ai_Session_advanceOperationTime, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Session, commitTransaction, ai_Session_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Session, endSession, ai_Session_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Session, getClusterTime, ai_Session_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Session, getLogicalSessionId, ai_Session_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Session, getOperationTime, ai_Session_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Session, getServer, ai_Session_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Session, getTransactionOptions, ai_Session_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Session, getTransactionState, ai_Session_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Session, isInTransaction, ai_Session_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(Session, startTransaction, ai_Session_startTransaction, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- ZEND_NAMED_ME(__construct, PHP_FN(MongoDB_disabled___construct), ai_Session_void, ZEND_ACC_PRIVATE | ZEND_ACC_FINAL)
- ZEND_NAMED_ME(__wakeup, PHP_FN(MongoDB_disabled___wakeup), ai_Session_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_FE_END
- /* clang-format on */
-};
-/* }}} */
-
-/* {{{ MongoDB\Driver\Session object handlers */
-static zend_object_handlers php_phongo_handler_session;
-
-static void php_phongo_session_free_object(zend_object* object) /* {{{ */
-{
- php_phongo_session_t* intern = Z_OBJ_SESSION(object);
-
- zend_object_std_dtor(&intern->std);
-
- /* If this Session was created in a different process, reset the client so
- * that its session pool is cleared and mongoc_client_session_destroy will
- * destroy the corresponding server session rather than return it to the
- * now-empty pool. This will ensure that we do not re-use a server session
- * (i.e. LSID) created by a parent process. */
- PHONGO_RESET_CLIENT_IF_PID_DIFFERS(intern, Z_MANAGER_OBJ_P(&intern->manager));
-
- if (intern->client_session) {
- mongoc_client_session_destroy(intern->client_session);
- }
-
- if (!Z_ISUNDEF(intern->manager)) {
- zval_ptr_dtor(&intern->manager);
- }
-} /* }}} */
-
-static zend_object* php_phongo_session_create_object(zend_class_entry* class_type) /* {{{ */
-{
- php_phongo_session_t* intern = NULL;
-
- intern = PHONGO_ALLOC_OBJECT_T(php_phongo_session_t, class_type);
-
- zend_object_std_init(&intern->std, class_type);
- object_properties_init(&intern->std, class_type);
-
- PHONGO_SET_CREATED_BY_PID(intern);
-
- intern->std.handlers = &php_phongo_handler_session;
-
- return &intern->std;
-} /* }}} */
-
-static HashTable* php_phongo_session_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
-{
- php_phongo_session_t* intern = NULL;
- zval retval = ZVAL_STATIC_INIT;
-
- *is_temp = 1;
- intern = Z_OBJ_SESSION(PHONGO_COMPAT_GET_OBJ(object));
-
- array_init(&retval);
-
- if (intern->client_session) {
- const bson_t* lsid;
- php_phongo_bson_state state;
-
- PHONGO_BSON_INIT_DEBUG_STATE(state);
-
- lsid = mongoc_client_session_get_lsid(intern->client_session);
-
- if (!php_phongo_bson_to_zval_ex(bson_get_data(lsid), lsid->len, &state)) {
- zval_ptr_dtor(&state.zchild);
- goto done;
- }
-
- ADD_ASSOC_ZVAL_EX(&retval, "logicalSessionId", &state.zchild);
- } else {
- ADD_ASSOC_NULL_EX(&retval, "logicalSessionId");
- }
-
- if (intern->client_session) {
- const bson_t* cluster_time;
-
- cluster_time = mongoc_client_session_get_cluster_time(intern->client_session);
-
- if (cluster_time) {
- php_phongo_bson_state state;
-
- PHONGO_BSON_INIT_DEBUG_STATE(state);
-
- if (!php_phongo_bson_to_zval_ex(bson_get_data(cluster_time), cluster_time->len, &state)) {
- zval_ptr_dtor(&state.zchild);
- goto done;
- }
-
- ADD_ASSOC_ZVAL_EX(&retval, "clusterTime", &state.zchild);
- } else {
- ADD_ASSOC_NULL_EX(&retval, "clusterTime");
- }
- } else {
- ADD_ASSOC_NULL_EX(&retval, "clusterTime");
- }
-
- if (intern->client_session) {
- const mongoc_session_opt_t* cs_opts = mongoc_client_session_get_opts(intern->client_session);
- ADD_ASSOC_BOOL_EX(&retval, "causalConsistency", mongoc_session_opts_get_causal_consistency(cs_opts));
- ADD_ASSOC_BOOL_EX(&retval, "snapshot", mongoc_session_opts_get_snapshot(cs_opts));
- } else {
- ADD_ASSOC_NULL_EX(&retval, "causalConsistency");
- ADD_ASSOC_NULL_EX(&retval, "snapshot");
- }
-
- if (intern->client_session) {
- uint32_t timestamp, increment;
-
- mongoc_client_session_get_operation_time(intern->client_session, &timestamp, &increment);
-
- if (timestamp && increment) {
- zval ztimestamp;
-
- php_phongo_bson_new_timestamp_from_increment_and_timestamp(&ztimestamp, increment, timestamp);
- ADD_ASSOC_ZVAL_EX(&retval, "operationTime", &ztimestamp);
- } else {
- ADD_ASSOC_NULL_EX(&retval, "operationTime");
- }
- } else {
- ADD_ASSOC_NULL_EX(&retval, "operationTime");
- }
-
- if (intern->client_session) {
- uint32_t server_id = mongoc_client_session_get_server_id(intern->client_session);
-
- if (server_id) {
-
- zval server;
-
- phongo_server_init(&server, &intern->manager, server_id);
- ADD_ASSOC_ZVAL_EX(&retval, "server", &server);
- } else {
- ADD_ASSOC_NULL_EX(&retval, "server");
- }
- } else {
- ADD_ASSOC_NULL_EX(&retval, "server");
- }
-
- if (intern->client_session) {
- ADD_ASSOC_BOOL_EX(&retval, "inTransaction", mongoc_client_session_in_transaction(intern->client_session));
- } else {
- ADD_ASSOC_NULL_EX(&retval, "inTransaction");
- }
-
- if (intern->client_session) {
- const char* state = php_phongo_get_transaction_state_string(mongoc_client_session_get_transaction_state(intern->client_session));
-
- if (!state) {
- /* Exception should already have been thrown */
- goto done;
- }
-
- ADD_ASSOC_STRING(&retval, "transactionState", state);
- } else {
- ADD_ASSOC_NULL_EX(&retval, "transactionState");
- }
-
- if (intern->client_session) {
- zval txn_opts;
- php_phongo_transaction_options_to_zval(intern->client_session, &txn_opts);
- ADD_ASSOC_ZVAL_EX(&retval, "transactionOptions", &txn_opts);
- } else {
- ADD_ASSOC_NULL_EX(&retval, "transactionOptions");
- }
-
-done:
- return Z_ARRVAL(retval);
-} /* }}} */
-/* }}} */
-
-void php_phongo_session_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver", "Session", php_phongo_session_me);
- php_phongo_session_ce = zend_register_internal_class(&ce);
- php_phongo_session_ce->create_object = php_phongo_session_create_object;
- PHONGO_CE_FINAL(php_phongo_session_ce);
- PHONGO_CE_DISABLE_SERIALIZATION(php_phongo_session_ce);
-
- memcpy(&php_phongo_handler_session, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
- php_phongo_handler_session.get_debug_info = php_phongo_session_get_debug_info;
- php_phongo_handler_session.free_obj = php_phongo_session_free_object;
- php_phongo_handler_session.offset = XtOffsetOf(php_phongo_session_t, std);
-
- zend_declare_class_constant_string(php_phongo_session_ce, ZEND_STRL("TRANSACTION_NONE"), PHONGO_TRANSACTION_NONE);
- zend_declare_class_constant_string(php_phongo_session_ce, ZEND_STRL("TRANSACTION_STARTING"), PHONGO_TRANSACTION_STARTING);
- zend_declare_class_constant_string(php_phongo_session_ce, ZEND_STRL("TRANSACTION_IN_PROGRESS"), PHONGO_TRANSACTION_IN_PROGRESS);
- zend_declare_class_constant_string(php_phongo_session_ce, ZEND_STRL("TRANSACTION_COMMITTED"), PHONGO_TRANSACTION_COMMITTED);
- zend_declare_class_constant_string(php_phongo_session_ce, ZEND_STRL("TRANSACTION_ABORTED"), PHONGO_TRANSACTION_ABORTED);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/MongoDB/Session.h b/mongodb-1.12.0/src/MongoDB/Session.h
deleted file mode 100644
index b4bd00ad..00000000
--- a/mongodb-1.12.0/src/MongoDB/Session.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright 2017-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef PHP_MONGODB_DRIVER_SESSION_H
-#define PHP_MONGODB_DRIVER_SESSION_H
-
-mongoc_transaction_opt_t* php_mongodb_session_parse_transaction_options(zval* txnOptions);
-
-#endif /* PHP_MONGODB_DRIVER_SESSION_H */
diff --git a/mongodb-1.12.0/src/MongoDB/WriteConcern.c b/mongodb-1.12.0/src/MongoDB/WriteConcern.c
deleted file mode 100644
index c9800435..00000000
--- a/mongodb-1.12.0/src/MongoDB/WriteConcern.c
+++ /dev/null
@@ -1,624 +0,0 @@
-/*
- * Copyright 2014-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-#include <Zend/zend_interfaces.h>
-#include <ext/standard/php_var.h>
-#include <zend_smart_str.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-
-zend_class_entry* php_phongo_writeconcern_ce;
-
-/* Initialize the object from a HashTable and return whether it was successful.
- * An exception will be thrown on error. */
-static bool php_phongo_writeconcern_init_from_hash(php_phongo_writeconcern_t* intern, HashTable* props) /* {{{ */
-{
- zval *w, *wtimeout, *j;
-
- intern->write_concern = mongoc_write_concern_new();
-
- if ((w = zend_hash_str_find(props, "w", sizeof("w") - 1))) {
- if (Z_TYPE_P(w) == IS_LONG) {
- if (Z_LVAL_P(w) < -3) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"w\" integer field to be >= -3", ZSTR_VAL(php_phongo_writeconcern_ce->name));
- goto failure;
- }
- mongoc_write_concern_set_w(intern->write_concern, Z_LVAL_P(w));
- } else if (Z_TYPE_P(w) == IS_STRING) {
- if (strcmp(Z_STRVAL_P(w), PHONGO_WRITE_CONCERN_W_MAJORITY) == 0) {
- mongoc_write_concern_set_w(intern->write_concern, MONGOC_WRITE_CONCERN_W_MAJORITY);
- } else {
- mongoc_write_concern_set_wtag(intern->write_concern, Z_STRVAL_P(w));
- }
- } else {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"w\" field to be integer or string", ZSTR_VAL(php_phongo_writeconcern_ce->name));
- goto failure;
- }
- }
-
- if ((wtimeout = zend_hash_str_find(props, "wtimeout", sizeof("wtimeout") - 1))) {
- if (Z_TYPE_P(wtimeout) == IS_LONG) {
- if (Z_LVAL_P(wtimeout) < 0) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"wtimeout\" integer field to be >= 0", ZSTR_VAL(php_phongo_writeconcern_ce->name));
- goto failure;
- }
-
- mongoc_write_concern_set_wtimeout_int64(intern->write_concern, (int64_t) Z_LVAL_P(wtimeout));
- } else if (Z_TYPE_P(wtimeout) == IS_STRING) {
- int64_t timeout;
-
- if (!php_phongo_parse_int64(&timeout, Z_STRVAL_P(wtimeout), Z_STRLEN_P(wtimeout))) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Error parsing \"%s\" as 64-bit value for %s initialization", Z_STRVAL_P(wtimeout), ZSTR_VAL(php_phongo_writeconcern_ce->name));
- return false;
- }
-
- mongoc_write_concern_set_wtimeout_int64(intern->write_concern, timeout);
- } else {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"wtimeout\" field to be integer or string", ZSTR_VAL(php_phongo_writeconcern_ce->name));
- goto failure;
- }
- }
-
- if ((j = zend_hash_str_find(props, "j", sizeof("j") - 1))) {
- if (Z_TYPE_P(j) == IS_TRUE || Z_TYPE_P(j) == IS_FALSE) {
- if (zend_is_true(j) && (mongoc_write_concern_get_w(intern->write_concern) == MONGOC_WRITE_CONCERN_W_UNACKNOWLEDGED || mongoc_write_concern_get_w(intern->write_concern) == MONGOC_WRITE_CONCERN_W_ERRORS_IGNORED)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Cannot enable journaling when using w = 0");
- goto failure;
- }
-
- mongoc_write_concern_set_journal(intern->write_concern, zend_is_true(j));
- } else {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"j\" field to be boolean", ZSTR_VAL(php_phongo_writeconcern_ce->name));
- goto failure;
- }
- }
-
- if (!mongoc_write_concern_is_valid(intern->write_concern)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Write concern is not valid");
- goto failure;
- }
-
- return true;
-
-failure:
- mongoc_write_concern_destroy(intern->write_concern);
- intern->write_concern = NULL;
- return false;
-} /* }}} */
-
-/* {{{ proto void MongoDB\Driver\WriteConcern::__construct(integer|string $w[, integer $wtimeout[, boolean $journal]])
- Constructs a new WriteConcern */
-static PHP_METHOD(WriteConcern, __construct)
-{
- zend_error_handling error_handling;
- php_phongo_writeconcern_t* intern;
- zval * w, *journal;
- zend_long wtimeout = 0;
-
- intern = Z_WRITECONCERN_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|lz", &w, &wtimeout, &journal) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- intern->write_concern = mongoc_write_concern_new();
-
- if (Z_TYPE_P(w) == IS_LONG) {
- if (Z_LVAL_P(w) < -3) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected w to be >= -3, %ld given", Z_LVAL_P(w));
- return;
- }
- mongoc_write_concern_set_w(intern->write_concern, Z_LVAL_P(w));
- } else if (Z_TYPE_P(w) == IS_STRING) {
- if (strcmp(Z_STRVAL_P(w), PHONGO_WRITE_CONCERN_W_MAJORITY) == 0) {
- mongoc_write_concern_set_w(intern->write_concern, MONGOC_WRITE_CONCERN_W_MAJORITY);
- } else {
- mongoc_write_concern_set_wtag(intern->write_concern, Z_STRVAL_P(w));
- }
- } else {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected w to be integer or string, %s given", PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(w));
- return;
- }
-
- switch (ZEND_NUM_ARGS()) {
- case 3:
- if (Z_TYPE_P(journal) != IS_NULL) {
- if (zend_is_true(journal) && (mongoc_write_concern_get_w(intern->write_concern) == MONGOC_WRITE_CONCERN_W_UNACKNOWLEDGED || mongoc_write_concern_get_w(intern->write_concern) == MONGOC_WRITE_CONCERN_W_ERRORS_IGNORED)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Cannot enable journaling when using w = 0");
- return;
- }
-
- mongoc_write_concern_set_journal(intern->write_concern, zend_is_true(journal));
- }
- PHONGO_BREAK_INTENTIONALLY_MISSING
-
- case 2:
- if (wtimeout < 0) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected wtimeout to be >= 0, %" PHONGO_LONG_FORMAT " given", wtimeout);
- return;
- }
-
- mongoc_write_concern_set_wtimeout_int64(intern->write_concern, (int64_t) wtimeout);
- }
-
- if (!mongoc_write_concern_is_valid(intern->write_concern)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Write concern is not valid");
- return;
- }
-} /* }}} */
-
-/* {{{ proto MongoDB\Driver\WriteConcern MongoDB\Driver\WriteConcern::__set_state(array $properties)
-*/
-static PHP_METHOD(WriteConcern, __set_state)
-{
- zend_error_handling error_handling;
- php_phongo_writeconcern_t* intern;
- HashTable* props;
- zval* array;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &array) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- object_init_ex(return_value, php_phongo_writeconcern_ce);
-
- intern = Z_WRITECONCERN_OBJ_P(return_value);
- props = Z_ARRVAL_P(array);
-
- php_phongo_writeconcern_init_from_hash(intern, props);
-} /* }}} */
-
-/* {{{ proto string|integer|null MongoDB\Driver\WriteConcern::getW()
- Returns the WriteConcern "w" option */
-static PHP_METHOD(WriteConcern, getW)
-{
- zend_error_handling error_handling;
- php_phongo_writeconcern_t* intern;
- const char* wtag;
-
- intern = Z_WRITECONCERN_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- wtag = mongoc_write_concern_get_wtag(intern->write_concern);
-
- if (wtag) {
- RETURN_STRING(wtag);
- }
-
- if (mongoc_write_concern_get_wmajority(intern->write_concern)) {
- RETURN_STRING(PHONGO_WRITE_CONCERN_W_MAJORITY);
- }
-
- if (mongoc_write_concern_get_w(intern->write_concern) != MONGOC_WRITE_CONCERN_W_DEFAULT) {
- RETURN_LONG(mongoc_write_concern_get_w(intern->write_concern));
- }
-
- RETURN_NULL();
-} /* }}} */
-
-/* {{{ proto integer MongoDB\Driver\WriteConcern::getWtimeout()
- Returns the WriteConcern "wtimeout" option */
-static PHP_METHOD(WriteConcern, getWtimeout)
-{
- zend_error_handling error_handling;
- php_phongo_writeconcern_t* intern;
- int64_t wtimeout;
-
- intern = Z_WRITECONCERN_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- wtimeout = mongoc_write_concern_get_wtimeout_int64(intern->write_concern);
-
-#if SIZEOF_ZEND_LONG == 4
- if (wtimeout > INT32_MAX || wtimeout < INT32_MIN) {
- zend_error(E_WARNING, "Truncating 64-bit value for wTimeoutMS");
- }
-#endif
-
- RETURN_LONG(wtimeout);
-} /* }}} */
-
-/* {{{ proto null|boolean MongoDB\Driver\WriteConcern::getJournal()
- Returns the WriteConcern "journal" option */
-static PHP_METHOD(WriteConcern, getJournal)
-{
- zend_error_handling error_handling;
- php_phongo_writeconcern_t* intern;
-
- intern = Z_WRITECONCERN_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- if (mongoc_write_concern_journal_is_set(intern->write_concern)) {
- RETURN_BOOL(mongoc_write_concern_get_journal(intern->write_concern));
- }
-
- RETURN_NULL();
-} /* }}} */
-
-/* {{{ proto boolean MongoDB\Driver\WriteConcern::isDefault()
- Returns whether the write concern has not been modified (i.e. from a Manager
- with no write concern URI options). */
-static PHP_METHOD(WriteConcern, isDefault)
-{
- zend_error_handling error_handling;
- php_phongo_writeconcern_t* intern;
-
- intern = Z_WRITECONCERN_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- RETURN_BOOL(mongoc_write_concern_is_default(intern->write_concern));
-} /* }}} */
-
-static HashTable* php_phongo_writeconcern_get_properties_hash(phongo_compat_object_handler_type* object, bool is_temp, bool is_bson, bool is_serialize) /* {{{ */
-{
- php_phongo_writeconcern_t* intern;
- HashTable* props;
- const char* wtag;
- int32_t w;
- int64_t wtimeout;
-
- intern = Z_OBJ_WRITECONCERN(PHONGO_COMPAT_GET_OBJ(object));
-
- PHONGO_GET_PROPERTY_HASH_INIT_PROPS(is_temp, intern, props, 4);
-
- if (!intern->write_concern) {
- return props;
- }
-
- wtag = mongoc_write_concern_get_wtag(intern->write_concern);
- w = mongoc_write_concern_get_w(intern->write_concern);
- wtimeout = mongoc_write_concern_get_wtimeout_int64(intern->write_concern);
-
- {
- zval z_w;
-
- if (wtag) {
- ZVAL_STRING(&z_w, wtag);
- zend_hash_str_update(props, "w", sizeof("w") - 1, &z_w);
- } else if (mongoc_write_concern_get_wmajority(intern->write_concern)) {
- ZVAL_STRING(&z_w, PHONGO_WRITE_CONCERN_W_MAJORITY);
- zend_hash_str_update(props, "w", sizeof("w") - 1, &z_w);
- } else if (w != MONGOC_WRITE_CONCERN_W_DEFAULT) {
- ZVAL_LONG(&z_w, w);
- zend_hash_str_update(props, "w", sizeof("w") - 1, &z_w);
- }
-
- if (mongoc_write_concern_journal_is_set(intern->write_concern)) {
- zval z_j;
-
- ZVAL_BOOL(&z_j, mongoc_write_concern_get_journal(intern->write_concern));
- zend_hash_str_update(props, "j", sizeof("j") - 1, &z_j);
- }
-
- if (wtimeout != 0) {
- zval z_wtimeout;
-
- if (is_bson) {
- ZVAL_INT64(&z_wtimeout, wtimeout);
- } else if (is_serialize) {
- if (wtimeout > INT32_MAX || wtimeout < INT32_MIN) {
- ZVAL_INT64_STRING(&z_wtimeout, wtimeout);
- } else {
- ZVAL_LONG(&z_wtimeout, wtimeout);
- }
- } else {
-#if SIZEOF_ZEND_LONG == 4
- if (wtimeout > INT32_MAX || wtimeout < INT32_MIN) {
- ZVAL_INT64_STRING(&z_wtimeout, wtimeout);
- } else {
- ZVAL_LONG(&z_wtimeout, wtimeout);
- }
-#else
- ZVAL_LONG(&z_wtimeout, wtimeout);
-#endif
- }
-
- zend_hash_str_update(props, "wtimeout", sizeof("wtimeout") - 1, &z_wtimeout);
- }
- }
-
- return props;
-} /* }}} */
-
-/* {{{ proto array MongoDB\Driver\WriteConcern::bsonSerialize()
-*/
-static PHP_METHOD(WriteConcern, bsonSerialize)
-{
- zend_error_handling error_handling;
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- ZVAL_ARR(return_value, php_phongo_writeconcern_get_properties_hash(PHONGO_COMPAT_OBJ_P(getThis()), true, true, false));
- convert_to_object(return_value);
-} /* }}} */
-
-/* {{{ proto string MongoDB\Driver\WriteConcern::serialize()
-*/
-static PHP_METHOD(WriteConcern, serialize)
-{
- zend_error_handling error_handling;
- php_phongo_writeconcern_t* intern;
- zval retval;
- php_serialize_data_t var_hash;
- smart_str buf = { 0 };
- const char* wtag;
- int32_t w;
- int64_t wtimeout;
-
- intern = Z_WRITECONCERN_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- if (!intern->write_concern) {
- return;
- }
-
- wtag = mongoc_write_concern_get_wtag(intern->write_concern);
- w = mongoc_write_concern_get_w(intern->write_concern);
- wtimeout = mongoc_write_concern_get_wtimeout_int64(intern->write_concern);
-
- array_init_size(&retval, 3);
-
- if (wtag) {
- ADD_ASSOC_STRING(&retval, "w", wtag);
- } else if (mongoc_write_concern_get_wmajority(intern->write_concern)) {
- ADD_ASSOC_STRING(&retval, "w", PHONGO_WRITE_CONCERN_W_MAJORITY);
- } else if (w != MONGOC_WRITE_CONCERN_W_DEFAULT) {
- ADD_ASSOC_LONG_EX(&retval, "w", w);
- }
-
- if (mongoc_write_concern_journal_is_set(intern->write_concern)) {
- ADD_ASSOC_BOOL_EX(&retval, "j", mongoc_write_concern_get_journal(intern->write_concern));
- }
-
- if (wtimeout != 0) {
- if (wtimeout > INT32_MAX || wtimeout < INT32_MIN) {
- ADD_ASSOC_INT64_AS_STRING(&retval, "wtimeout", wtimeout);
- } else {
- ADD_ASSOC_LONG_EX(&retval, "wtimeout", wtimeout);
- }
- }
-
- PHP_VAR_SERIALIZE_INIT(var_hash);
- php_var_serialize(&buf, &retval, &var_hash);
- smart_str_0(&buf);
- PHP_VAR_SERIALIZE_DESTROY(var_hash);
-
- PHONGO_RETVAL_SMART_STR(buf);
-
- smart_str_free(&buf);
- zval_ptr_dtor(&retval);
-} /* }}} */
-
-/* {{{ proto void MongoDB\Driver\WriteConcern::unserialize(string $serialized)
-*/
-static PHP_METHOD(WriteConcern, unserialize)
-{
- zend_error_handling error_handling;
- php_phongo_writeconcern_t* intern;
- char* serialized;
- size_t serialized_len;
- zval props;
- php_unserialize_data_t var_hash;
-
- intern = Z_WRITECONCERN_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &serialized, &serialized_len) == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- if (!serialized_len) {
- return;
- }
-
- PHP_VAR_UNSERIALIZE_INIT(var_hash);
- if (!php_var_unserialize(&props, (const unsigned char**) &serialized, (unsigned char*) serialized + serialized_len, &var_hash)) {
- zval_ptr_dtor(&props);
- phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "%s unserialization failed", ZSTR_VAL(php_phongo_writeconcern_ce->name));
-
- PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
- return;
- }
- PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
-
- php_phongo_writeconcern_init_from_hash(intern, HASH_OF(&props));
- zval_ptr_dtor(&props);
-} /* }}} */
-
-/* {{{ proto array MongoDB\Driver\WriteConcern::__serialize()
-*/
-static PHP_METHOD(WriteConcern, __serialize)
-{
- PHONGO_PARSE_PARAMETERS_NONE();
-
- RETURN_ARR(php_phongo_writeconcern_get_properties_hash(PHONGO_COMPAT_OBJ_P(getThis()), true, false, true));
-} /* }}} */
-
-/* {{{ proto void MongoDB\Driver\WriteConcern::__unserialize(array $data)
-*/
-static PHP_METHOD(WriteConcern, __unserialize)
-{
- zval* data;
-
- PHONGO_PARSE_PARAMETERS_START(1, 1)
- Z_PARAM_ARRAY(data)
- PHONGO_PARSE_PARAMETERS_END();
-
- php_phongo_writeconcern_init_from_hash(Z_WRITECONCERN_OBJ_P(getThis()), Z_ARRVAL_P(data));
-} /* }}} */
-
-/* {{{ MongoDB\Driver\WriteConcern function entries */
-ZEND_BEGIN_ARG_INFO_EX(ai_WriteConcern___construct, 0, 0, 1)
- ZEND_ARG_INFO(0, w)
- ZEND_ARG_INFO(0, wtimeout)
- ZEND_ARG_INFO(0, journal)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_WriteConcern___set_state, 0, 0, 1)
- ZEND_ARG_ARRAY_INFO(0, properties, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_WriteConcern___unserialize, 0, 0, 1)
- ZEND_ARG_ARRAY_INFO(0, data, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_WriteConcern_unserialize, 0, 0, 1)
- ZEND_ARG_INFO(0, serialized)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(ai_WriteConcern_void, 0, 0, 0)
-ZEND_END_ARG_INFO()
-
-static zend_function_entry php_phongo_writeconcern_me[] = {
- /* clang-format off */
- PHP_ME(WriteConcern, __construct, ai_WriteConcern___construct, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(WriteConcern, __serialize, ai_WriteConcern_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(WriteConcern, __set_state, ai_WriteConcern___set_state, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
- PHP_ME(WriteConcern, __unserialize, ai_WriteConcern___unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(WriteConcern, getW, ai_WriteConcern_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(WriteConcern, getWtimeout, ai_WriteConcern_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(WriteConcern, getJournal, ai_WriteConcern_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(WriteConcern, isDefault, ai_WriteConcern_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(WriteConcern, bsonSerialize, ai_WriteConcern_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(WriteConcern, serialize, ai_WriteConcern_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(WriteConcern, unserialize, ai_WriteConcern_unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_FE_END
- /* clang-format on */
-};
-/* }}} */
-
-/* {{{ MongoDB\Driver\WriteConcern object handlers */
-static zend_object_handlers php_phongo_handler_writeconcern;
-
-static void php_phongo_writeconcern_free_object(zend_object* object) /* {{{ */
-{
- php_phongo_writeconcern_t* intern = Z_OBJ_WRITECONCERN(object);
-
- zend_object_std_dtor(&intern->std);
-
- if (intern->properties) {
- zend_hash_destroy(intern->properties);
- FREE_HASHTABLE(intern->properties);
- }
-
- if (intern->write_concern) {
- mongoc_write_concern_destroy(intern->write_concern);
- }
-} /* }}} */
-
-static zend_object* php_phongo_writeconcern_create_object(zend_class_entry* class_type) /* {{{ */
-{
- php_phongo_writeconcern_t* intern = NULL;
-
- intern = PHONGO_ALLOC_OBJECT_T(php_phongo_writeconcern_t, class_type);
-
- zend_object_std_init(&intern->std, class_type);
- object_properties_init(&intern->std, class_type);
-
- intern->std.handlers = &php_phongo_handler_writeconcern;
-
- return &intern->std;
-} /* }}} */
-
-static HashTable* php_phongo_writeconcern_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
-{
- *is_temp = 1;
- return php_phongo_writeconcern_get_properties_hash(object, true, false, false);
-} /* }}} */
-
-static HashTable* php_phongo_writeconcern_get_properties(phongo_compat_object_handler_type* object) /* {{{ */
-{
- return php_phongo_writeconcern_get_properties_hash(object, false, false, false);
-} /* }}} */
-
-void php_phongo_writeconcern_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver", "WriteConcern", php_phongo_writeconcern_me);
- php_phongo_writeconcern_ce = zend_register_internal_class(&ce);
- php_phongo_writeconcern_ce->create_object = php_phongo_writeconcern_create_object;
- PHONGO_CE_FINAL(php_phongo_writeconcern_ce);
-
- zend_class_implements(php_phongo_writeconcern_ce, 1, php_phongo_serializable_ce);
- zend_class_implements(php_phongo_writeconcern_ce, 1, zend_ce_serializable);
-
- memcpy(&php_phongo_handler_writeconcern, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
- php_phongo_handler_writeconcern.get_debug_info = php_phongo_writeconcern_get_debug_info;
- php_phongo_handler_writeconcern.get_properties = php_phongo_writeconcern_get_properties;
- php_phongo_handler_writeconcern.free_obj = php_phongo_writeconcern_free_object;
- php_phongo_handler_writeconcern.offset = XtOffsetOf(php_phongo_writeconcern_t, std);
-
- zend_declare_class_constant_stringl(php_phongo_writeconcern_ce, ZEND_STRL("MAJORITY"), ZEND_STRL(PHONGO_WRITE_CONCERN_W_MAJORITY));
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/MongoDB/WriteConcernError.c b/mongodb-1.12.0/src/MongoDB/WriteConcernError.c
deleted file mode 100644
index 74681a47..00000000
--- a/mongodb-1.12.0/src/MongoDB/WriteConcernError.c
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Copyright 2014-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-#include <Zend/zend_interfaces.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-
-zend_class_entry* php_phongo_writeconcernerror_ce;
-
-/* {{{ proto integer MongoDB\Driver\WriteConcernError::getCode()
- Returns the MongoDB error code */
-static PHP_METHOD(WriteConcernError, getCode)
-{
- zend_error_handling error_handling;
- php_phongo_writeconcernerror_t* intern;
-
- intern = Z_WRITECONCERNERROR_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- RETURN_LONG(intern->code);
-} /* }}} */
-
-/* {{{ proto object|null MongoDB\Driver\WriteConcernError::getInfo()
- Returns additional metadata for the error */
-static PHP_METHOD(WriteConcernError, getInfo)
-{
- zend_error_handling error_handling;
- php_phongo_writeconcernerror_t* intern;
-
- intern = Z_WRITECONCERNERROR_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- if (!Z_ISUNDEF(intern->info)) {
- RETURN_ZVAL(&intern->info, 1, 0);
- }
-} /* }}} */
-
-/* {{{ proto string MongoDB\Driver\WriteConcernError::getMessage()
- Returns the actual error message from the server */
-static PHP_METHOD(WriteConcernError, getMessage)
-{
- zend_error_handling error_handling;
- php_phongo_writeconcernerror_t* intern;
-
- intern = Z_WRITECONCERNERROR_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- RETURN_STRING(intern->message);
-} /* }}} */
-
-/* {{{ MongoDB\Driver\WriteConcernError function entries */
-ZEND_BEGIN_ARG_INFO_EX(ai_WriteConcernError_void, 0, 0, 0)
-ZEND_END_ARG_INFO()
-
-static zend_function_entry php_phongo_writeconcernerror_me[] = {
- /* clang-format off */
- PHP_ME(WriteConcernError, getCode, ai_WriteConcernError_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(WriteConcernError, getInfo, ai_WriteConcernError_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(WriteConcernError, getMessage, ai_WriteConcernError_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- ZEND_NAMED_ME(__construct, PHP_FN(MongoDB_disabled___construct), ai_WriteConcernError_void, ZEND_ACC_PRIVATE | ZEND_ACC_FINAL)
- ZEND_NAMED_ME(__wakeup, PHP_FN(MongoDB_disabled___wakeup), ai_WriteConcernError_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_FE_END
- /* clang-format on */
-};
-/* }}} */
-
-/* {{{ MongoDB\Driver\WriteConcernError object handlers */
-static zend_object_handlers php_phongo_handler_writeconcernerror;
-
-static void php_phongo_writeconcernerror_free_object(zend_object* object) /* {{{ */
-{
- php_phongo_writeconcernerror_t* intern = Z_OBJ_WRITECONCERNERROR(object);
-
- zend_object_std_dtor(&intern->std);
-
- if (intern->message) {
- efree(intern->message);
- }
-
- if (!Z_ISUNDEF(intern->info)) {
- zval_ptr_dtor(&intern->info);
- }
-} /* }}} */
-
-static zend_object* php_phongo_writeconcernerror_create_object(zend_class_entry* class_type) /* {{{ */
-{
- php_phongo_writeconcernerror_t* intern = NULL;
-
- intern = PHONGO_ALLOC_OBJECT_T(php_phongo_writeconcernerror_t, class_type);
-
- zend_object_std_init(&intern->std, class_type);
- object_properties_init(&intern->std, class_type);
-
- intern->std.handlers = &php_phongo_handler_writeconcernerror;
-
- return &intern->std;
-} /* }}} */
-
-static HashTable* php_phongo_writeconcernerror_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
-{
- php_phongo_writeconcernerror_t* intern;
- zval retval = ZVAL_STATIC_INIT;
-
- *is_temp = 1;
- intern = Z_OBJ_WRITECONCERNERROR(PHONGO_COMPAT_GET_OBJ(object));
-
- array_init_size(&retval, 3);
- ADD_ASSOC_STRING(&retval, "message", intern->message);
- ADD_ASSOC_LONG_EX(&retval, "code", intern->code);
- if (!Z_ISUNDEF(intern->info)) {
- Z_ADDREF(intern->info);
- ADD_ASSOC_ZVAL_EX(&retval, "info", &intern->info);
- } else {
- ADD_ASSOC_NULL_EX(&retval, "info");
- }
-
- return Z_ARRVAL(retval);
-} /* }}} */
-/* }}} */
-
-void php_phongo_writeconcernerror_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver", "WriteConcernError", php_phongo_writeconcernerror_me);
- php_phongo_writeconcernerror_ce = zend_register_internal_class(&ce);
- php_phongo_writeconcernerror_ce->create_object = php_phongo_writeconcernerror_create_object;
- PHONGO_CE_FINAL(php_phongo_writeconcernerror_ce);
- PHONGO_CE_DISABLE_SERIALIZATION(php_phongo_writeconcernerror_ce);
-
- memcpy(&php_phongo_handler_writeconcernerror, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
- php_phongo_handler_writeconcernerror.get_debug_info = php_phongo_writeconcernerror_get_debug_info;
- php_phongo_handler_writeconcernerror.free_obj = php_phongo_writeconcernerror_free_object;
- php_phongo_handler_writeconcernerror.offset = XtOffsetOf(php_phongo_writeconcernerror_t, std);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/MongoDB/WriteError.c b/mongodb-1.12.0/src/MongoDB/WriteError.c
deleted file mode 100644
index 7d282e7b..00000000
--- a/mongodb-1.12.0/src/MongoDB/WriteError.c
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Copyright 2014-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-#include <Zend/zend_interfaces.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-
-zend_class_entry* php_phongo_writeerror_ce;
-
-/* {{{ proto integer MongoDB\Driver\WriteError::getCode()
- Returns the MongoDB error code */
-static PHP_METHOD(WriteError, getCode)
-{
- zend_error_handling error_handling;
- php_phongo_writeerror_t* intern;
-
- intern = Z_WRITEERROR_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- RETURN_LONG(intern->code);
-} /* }}} */
-
-/* {{{ proto integer MongoDB\Driver\WriteError::getIndex()
- Returns the index of the operation in the BulkWrite to which this WriteError
- corresponds. */
-static PHP_METHOD(WriteError, getIndex)
-{
- zend_error_handling error_handling;
- php_phongo_writeerror_t* intern;
-
- intern = Z_WRITEERROR_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- RETURN_LONG(intern->index);
-} /* }}} */
-
-/* {{{ proto string MongoDB\Driver\WriteError::getMessage()
- Returns the actual error message from the server */
-static PHP_METHOD(WriteError, getMessage)
-{
- zend_error_handling error_handling;
- php_phongo_writeerror_t* intern;
-
- intern = Z_WRITEERROR_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- RETURN_STRING(intern->message);
-} /* }}} */
-
-/* {{{ proto object|null MongoDB\Driver\WriteError::getInfo()
- Returns additional metadata for the error */
-static PHP_METHOD(WriteError, getInfo)
-{
- zend_error_handling error_handling;
- php_phongo_writeerror_t* intern;
-
- intern = Z_WRITEERROR_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- if (!Z_ISUNDEF(intern->info)) {
- RETURN_ZVAL(&intern->info, 1, 0);
- }
-} /* }}} */
-
-/* {{{ MongoDB\Driver\WriteError function entries */
-ZEND_BEGIN_ARG_INFO_EX(ai_WriteError_void, 0, 0, 0)
-ZEND_END_ARG_INFO()
-
-static zend_function_entry php_phongo_writeerror_me[] = {
- /* clang-format off */
- PHP_ME(WriteError, getCode, ai_WriteError_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(WriteError, getIndex, ai_WriteError_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(WriteError, getMessage, ai_WriteError_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(WriteError, getInfo, ai_WriteError_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- ZEND_NAMED_ME(__construct, PHP_FN(MongoDB_disabled___construct), ai_WriteError_void, ZEND_ACC_PRIVATE | ZEND_ACC_FINAL)
- ZEND_NAMED_ME(__wakeup, PHP_FN(MongoDB_disabled___wakeup), ai_WriteError_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_FE_END
- /* clang-format on */
-};
-/* }}} */
-
-/* {{{ MongoDB\Driver\WriteError object handlers */
-static zend_object_handlers php_phongo_handler_writeerror;
-
-static void php_phongo_writeerror_free_object(zend_object* object) /* {{{ */
-{
- php_phongo_writeerror_t* intern = Z_OBJ_WRITEERROR(object);
-
- zend_object_std_dtor(&intern->std);
-
- if (intern->message) {
- efree(intern->message);
- }
-
- if (!Z_ISUNDEF(intern->info)) {
- zval_ptr_dtor(&intern->info);
- }
-} /* }}} */
-
-static zend_object* php_phongo_writeerror_create_object(zend_class_entry* class_type) /* {{{ */
-{
- php_phongo_writeerror_t* intern = NULL;
-
- intern = PHONGO_ALLOC_OBJECT_T(php_phongo_writeerror_t, class_type);
-
- zend_object_std_init(&intern->std, class_type);
- object_properties_init(&intern->std, class_type);
-
- intern->std.handlers = &php_phongo_handler_writeerror;
-
- return &intern->std;
-} /* }}} */
-
-static HashTable* php_phongo_writeerror_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
-{
- php_phongo_writeerror_t* intern;
- zval retval = ZVAL_STATIC_INIT;
-
- *is_temp = 1;
- intern = Z_OBJ_WRITEERROR(PHONGO_COMPAT_GET_OBJ(object));
-
- array_init_size(&retval, 3);
- ADD_ASSOC_STRING(&retval, "message", intern->message);
- ADD_ASSOC_LONG_EX(&retval, "code", intern->code);
- ADD_ASSOC_LONG_EX(&retval, "index", intern->index);
- if (!Z_ISUNDEF(intern->info)) {
- Z_ADDREF(intern->info);
- ADD_ASSOC_ZVAL_EX(&retval, "info", &intern->info);
- } else {
- ADD_ASSOC_NULL_EX(&retval, "info");
- }
-
- return Z_ARRVAL(retval);
-} /* }}} */
-/* }}} */
-
-void php_phongo_writeerror_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver", "WriteError", php_phongo_writeerror_me);
- php_phongo_writeerror_ce = zend_register_internal_class(&ce);
- php_phongo_writeerror_ce->create_object = php_phongo_writeerror_create_object;
- PHONGO_CE_FINAL(php_phongo_writeerror_ce);
- PHONGO_CE_DISABLE_SERIALIZATION(php_phongo_writeerror_ce);
-
- memcpy(&php_phongo_handler_writeerror, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
- php_phongo_handler_writeerror.get_debug_info = php_phongo_writeerror_get_debug_info;
- php_phongo_handler_writeerror.free_obj = php_phongo_writeerror_free_object;
- php_phongo_handler_writeerror.offset = XtOffsetOf(php_phongo_writeerror_t, std);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/MongoDB/WriteResult.c b/mongodb-1.12.0/src/MongoDB/WriteResult.c
deleted file mode 100644
index fc28abc2..00000000
--- a/mongodb-1.12.0/src/MongoDB/WriteResult.c
+++ /dev/null
@@ -1,485 +0,0 @@
-/*
- * Copyright 2014-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <php.h>
-#include <Zend/zend_interfaces.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "php_array_api.h"
-#include "phongo_compat.h"
-#include "php_phongo.h"
-#include "php_bson.h"
-
-#define PHONGO_WRITERESULT_RETURN_LONG_FROM_BSON_INT32(iter, bson, key) \
- if (bson_iter_init_find((iter), (bson), (key)) && BSON_ITER_HOLDS_INT32((iter))) { \
- RETURN_LONG(bson_iter_int32((iter))); \
- }
-
-zend_class_entry* php_phongo_writeresult_ce;
-
-static bool php_phongo_writeresult_get_writeconcernerror(php_phongo_writeresult_t* intern, zval* return_value) /* {{{ */
-{
- bson_iter_t iter, child;
- zval writeconcernerror;
-
- ZVAL_NULL(return_value);
-
- if (bson_iter_init_find(&iter, intern->reply, "writeConcernErrors") && BSON_ITER_HOLDS_ARRAY(&iter) && bson_iter_recurse(&iter, &child)) {
- while (bson_iter_next(&child)) {
- bson_t cbson;
- uint32_t len;
- const uint8_t* data;
-
- if (!BSON_ITER_HOLDS_DOCUMENT(&child)) {
- continue;
- }
-
- bson_iter_document(&child, &len, &data);
-
- if (!bson_init_static(&cbson, data, len)) {
- continue;
- }
-
- if (!phongo_writeconcernerror_init(&writeconcernerror, &cbson)) {
- zval_ptr_dtor(&writeconcernerror);
- return false;
- }
-
- ZVAL_ZVAL(return_value, &writeconcernerror, 1, 1);
-
- return true;
- }
- }
-
- return true;
-} /* }}} */
-
-static bool php_phongo_writeresult_get_writeerrors(php_phongo_writeresult_t* intern, zval* return_value) /* {{{ */
-{
- bson_iter_t iter, child;
-
- array_init(return_value);
-
- if (bson_iter_init_find(&iter, intern->reply, "writeErrors") && BSON_ITER_HOLDS_ARRAY(&iter) && bson_iter_recurse(&iter, &child)) {
- while (bson_iter_next(&child)) {
- bson_t cbson;
- uint32_t len;
- const uint8_t* data;
- zval writeerror;
-
- if (!BSON_ITER_HOLDS_DOCUMENT(&child)) {
- continue;
- }
-
- bson_iter_document(&child, &len, &data);
-
- if (!bson_init_static(&cbson, data, len)) {
- continue;
- }
-
- if (!phongo_writeerror_init(&writeerror, &cbson)) {
- zval_ptr_dtor(&writeerror);
- continue;
- }
-
- add_next_index_zval(return_value, &writeerror);
- }
- }
-
- return true;
-} /* }}} */
-
-/* {{{ proto integer|null MongoDB\Driver\WriteResult::getInsertedCount()
- Returns the number of documents that were inserted */
-static PHP_METHOD(WriteResult, getInsertedCount)
-{
- zend_error_handling error_handling;
- bson_iter_t iter;
- php_phongo_writeresult_t* intern;
-
- intern = Z_WRITERESULT_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- PHONGO_WRITERESULT_RETURN_LONG_FROM_BSON_INT32(&iter, intern->reply, "nInserted");
-} /* }}} */
-
-/* {{{ proto integer|null MongoDB\Driver\WriteResult::getMatchedCount()
- Returns the number of documents that matched the update criteria */
-static PHP_METHOD(WriteResult, getMatchedCount)
-{
- zend_error_handling error_handling;
- bson_iter_t iter;
- php_phongo_writeresult_t* intern;
-
- intern = Z_WRITERESULT_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- PHONGO_WRITERESULT_RETURN_LONG_FROM_BSON_INT32(&iter, intern->reply, "nMatched");
-} /* }}} */
-
-/* {{{ proto integer|null MongoDB\Driver\WriteResult::getModifiedCount()
- Returns the number of documents that were actually modified by an update */
-static PHP_METHOD(WriteResult, getModifiedCount)
-{
- zend_error_handling error_handling;
- bson_iter_t iter;
- php_phongo_writeresult_t* intern;
-
- intern = Z_WRITERESULT_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- PHONGO_WRITERESULT_RETURN_LONG_FROM_BSON_INT32(&iter, intern->reply, "nModified");
-} /* }}} */
-
-/* {{{ proto integer|null MongoDB\Driver\WriteResult::getDeletedCount()
- Returns the number of documents that were deleted */
-static PHP_METHOD(WriteResult, getDeletedCount)
-{
- zend_error_handling error_handling;
- bson_iter_t iter;
- php_phongo_writeresult_t* intern;
-
- intern = Z_WRITERESULT_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- PHONGO_WRITERESULT_RETURN_LONG_FROM_BSON_INT32(&iter, intern->reply, "nRemoved");
-} /* }}} */
-
-/* {{{ proto integer|null MongoDB\Driver\WriteResult::getUpsertedCount()
- Returns the number of documents that were upserted */
-static PHP_METHOD(WriteResult, getUpsertedCount)
-{
- zend_error_handling error_handling;
- bson_iter_t iter;
- php_phongo_writeresult_t* intern;
-
- intern = Z_WRITERESULT_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- PHONGO_WRITERESULT_RETURN_LONG_FROM_BSON_INT32(&iter, intern->reply, "nUpserted");
-} /* }}} */
-
-/* {{{ proto MongoDB\Driver\Server MongoDB\Driver\WriteResult::getServer()
- Returns the Server from which the result originated */
-static PHP_METHOD(WriteResult, getServer)
-{
- zend_error_handling error_handling;
- php_phongo_writeresult_t* intern;
-
- intern = Z_WRITERESULT_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- phongo_server_init(return_value, &intern->manager, intern->server_id);
-} /* }}} */
-
-/* {{{ proto array MongoDB\Driver\WriteResult::getUpsertedIds()
- Returns the identifiers generated by the server for upsert operations. */
-static PHP_METHOD(WriteResult, getUpsertedIds)
-{
- zend_error_handling error_handling;
- bson_iter_t iter, child;
- php_phongo_writeresult_t* intern;
-
- intern = Z_WRITERESULT_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- array_init(return_value);
-
- if (bson_iter_init_find(&iter, intern->reply, "upserted") && BSON_ITER_HOLDS_ARRAY(&iter) && bson_iter_recurse(&iter, &child)) {
- while (bson_iter_next(&child)) {
- uint32_t data_len;
- const uint8_t* data = NULL;
- php_phongo_bson_state state;
-
- /* Use PHONGO_TYPEMAP_NATIVE_ARRAY for the root type so we can
- * easily access the "index" and "_id" fields. */
- PHONGO_BSON_INIT_STATE(state);
- state.map.root_type = PHONGO_TYPEMAP_NATIVE_ARRAY;
-
- if (!BSON_ITER_HOLDS_DOCUMENT(&child)) {
- continue;
- }
-
- bson_iter_document(&child, &data_len, &data);
-
- if (php_phongo_bson_to_zval_ex(data, data_len, &state)) {
- zval* zid = php_array_fetchc(&state.zchild, "_id");
- add_index_zval(return_value, php_array_fetchc_long(&state.zchild, "index"), zid);
- zval_add_ref(zid);
- }
-
- zval_ptr_dtor(&state.zchild);
- }
- }
-} /* }}} */
-
-/* {{{ proto WriteConcernError MongoDB\Driver\WriteResult::getWriteConcernError()
- Return any write concern error that occurred */
-static PHP_METHOD(WriteResult, getWriteConcernError)
-{
- zend_error_handling error_handling;
- php_phongo_writeresult_t* intern;
-
- intern = Z_WRITERESULT_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- php_phongo_writeresult_get_writeconcernerror(intern, return_value);
-} /* }}} */
-
-/* {{{ proto WriteError[] MongoDB\Driver\WriteResult::getWriteErrors()
- Returns any write errors that occurred */
-static PHP_METHOD(WriteResult, getWriteErrors)
-{
- zend_error_handling error_handling;
- php_phongo_writeresult_t* intern;
-
- intern = Z_WRITERESULT_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- php_phongo_writeresult_get_writeerrors(intern, return_value);
-} /* }}} */
-
-/* {{{ proto boolean MongoDB\Driver\WriteResult::isAcknowledged()
- Returns whether the write operation was acknowledged (based on the write
- concern). */
-static PHP_METHOD(WriteResult, isAcknowledged)
-{
- zend_error_handling error_handling;
- php_phongo_writeresult_t* intern;
-
- intern = Z_WRITERESULT_OBJ_P(getThis());
-
- zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
- if (zend_parse_parameters_none() == FAILURE) {
- zend_restore_error_handling(&error_handling);
- return;
- }
- zend_restore_error_handling(&error_handling);
-
- RETURN_BOOL(mongoc_write_concern_is_acknowledged(intern->write_concern));
-} /* }}} */
-
-/* {{{ MongoDB\Driver\WriteResult function entries */
-ZEND_BEGIN_ARG_INFO_EX(ai_WriteResult_void, 0, 0, 0)
-ZEND_END_ARG_INFO()
-
-static zend_function_entry php_phongo_writeresult_me[] = {
- /* clang-format off */
- PHP_ME(WriteResult, getInsertedCount, ai_WriteResult_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(WriteResult, getMatchedCount, ai_WriteResult_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(WriteResult, getModifiedCount, ai_WriteResult_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(WriteResult, getDeletedCount, ai_WriteResult_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(WriteResult, getUpsertedCount, ai_WriteResult_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(WriteResult, getServer, ai_WriteResult_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(WriteResult, getUpsertedIds, ai_WriteResult_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(WriteResult, getWriteConcernError, ai_WriteResult_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(WriteResult, getWriteErrors, ai_WriteResult_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_ME(WriteResult, isAcknowledged, ai_WriteResult_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- ZEND_NAMED_ME(__construct, PHP_FN(MongoDB_disabled___construct), ai_WriteResult_void, ZEND_ACC_PRIVATE | ZEND_ACC_FINAL)
- ZEND_NAMED_ME(__wakeup, PHP_FN(MongoDB_disabled___wakeup), ai_WriteResult_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
- PHP_FE_END
- /* clang-format on */
-};
-/* }}} */
-
-/* {{{ MongoDB\Driver\WriteResult object handlers */
-static zend_object_handlers php_phongo_handler_writeresult;
-
-static void php_phongo_writeresult_free_object(zend_object* object) /* {{{ */
-{
- php_phongo_writeresult_t* intern = Z_OBJ_WRITERESULT(object);
-
- zend_object_std_dtor(&intern->std);
-
- if (intern->reply) {
- bson_destroy(intern->reply);
- }
-
- if (intern->write_concern) {
- mongoc_write_concern_destroy(intern->write_concern);
- }
-
- if (!Z_ISUNDEF(intern->manager)) {
- zval_ptr_dtor(&intern->manager);
- }
-} /* }}} */
-
-static zend_object* php_phongo_writeresult_create_object(zend_class_entry* class_type) /* {{{ */
-{
- php_phongo_writeresult_t* intern = NULL;
-
- intern = PHONGO_ALLOC_OBJECT_T(php_phongo_writeresult_t, class_type);
-
- zend_object_std_init(&intern->std, class_type);
- object_properties_init(&intern->std, class_type);
-
- intern->std.handlers = &php_phongo_handler_writeresult;
-
- return &intern->std;
-} /* }}} */
-
-static HashTable* php_phongo_writeresult_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
-{
- php_phongo_writeresult_t* intern;
- zval retval = ZVAL_STATIC_INIT;
- bson_iter_t iter;
-
- intern = Z_OBJ_WRITERESULT(PHONGO_COMPAT_GET_OBJ(object));
- *is_temp = 1;
- array_init_size(&retval, 9);
-
-#define PHONGO_WRITERESULT_SCP(field) \
- if (bson_iter_init_find(&iter, intern->reply, (field)) && BSON_ITER_HOLDS_INT32(&iter)) { \
- ADD_ASSOC_LONG_EX(&retval, (field), bson_iter_int32(&iter)); \
- } else { \
- ADD_ASSOC_NULL_EX(&retval, (field)); \
- }
-
- PHONGO_WRITERESULT_SCP("nInserted");
- PHONGO_WRITERESULT_SCP("nMatched");
- PHONGO_WRITERESULT_SCP("nModified");
- PHONGO_WRITERESULT_SCP("nRemoved");
- PHONGO_WRITERESULT_SCP("nUpserted");
-#undef PHONGO_WRITERESULT_SCP
-
- if (bson_iter_init_find(&iter, intern->reply, "upserted") && BSON_ITER_HOLDS_ARRAY(&iter)) {
- uint32_t len;
- const uint8_t* data;
- php_phongo_bson_state state;
-
- PHONGO_BSON_INIT_DEBUG_STATE(state);
- bson_iter_array(&iter, &len, &data);
- if (!php_phongo_bson_to_zval_ex(data, len, &state)) {
- zval_ptr_dtor(&state.zchild);
- goto done;
- }
-
- ADD_ASSOC_ZVAL_EX(&retval, "upsertedIds", &state.zchild);
- } else {
- zval upsertedIds;
- array_init(&upsertedIds);
- ADD_ASSOC_ZVAL_EX(&retval, "upsertedIds", &upsertedIds);
- }
-
- {
- zval writeerrors;
-
- php_phongo_writeresult_get_writeerrors(intern, &writeerrors);
- ADD_ASSOC_ZVAL_EX(&retval, "writeErrors", &writeerrors);
- }
-
- {
- zval writeconcernerror;
-
- php_phongo_writeresult_get_writeconcernerror(intern, &writeconcernerror);
- ADD_ASSOC_ZVAL_EX(&retval, "writeConcernError", &writeconcernerror);
- }
-
- if (intern->write_concern) {
- zval write_concern;
-
- phongo_writeconcern_init(&write_concern, intern->write_concern);
- ADD_ASSOC_ZVAL_EX(&retval, "writeConcern", &write_concern);
- } else {
- ADD_ASSOC_NULL_EX(&retval, "writeConcern");
- }
-
-done:
- return Z_ARRVAL(retval);
-} /* }}} */
-/* }}} */
-
-void php_phongo_writeresult_init_ce(INIT_FUNC_ARGS) /* {{{ */
-{
- zend_class_entry ce;
-
- INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver", "WriteResult", php_phongo_writeresult_me);
- php_phongo_writeresult_ce = zend_register_internal_class(&ce);
- php_phongo_writeresult_ce->create_object = php_phongo_writeresult_create_object;
- PHONGO_CE_FINAL(php_phongo_writeresult_ce);
- PHONGO_CE_DISABLE_SERIALIZATION(php_phongo_writeresult_ce);
-
- memcpy(&php_phongo_handler_writeresult, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
- php_phongo_handler_writeresult.get_debug_info = php_phongo_writeresult_get_debug_info;
- php_phongo_handler_writeresult.free_obj = php_phongo_writeresult_free_object;
- php_phongo_handler_writeresult.offset = XtOffsetOf(php_phongo_writeresult_t, std);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/bson-encode.c b/mongodb-1.12.0/src/bson-encode.c
deleted file mode 100644
index 86b2e864..00000000
--- a/mongodb-1.12.0/src/bson-encode.c
+++ /dev/null
@@ -1,530 +0,0 @@
-/*
- * Copyright 2014-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <bson/bson.h>
-
-#include <php.h>
-#include <Zend/zend_hash.h>
-#include <Zend/zend_interfaces.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "php_phongo.h"
-#include "php_bson.h"
-#include "phongo_compat.h"
-
-#if SIZEOF_ZEND_LONG == 8
-#define BSON_APPEND_INT(b, key, keylen, val) \
- if (val > INT32_MAX || val < INT32_MIN) { \
- bson_append_int64(b, key, keylen, val); \
- } else { \
- bson_append_int32(b, key, keylen, val); \
- }
-#elif SIZEOF_ZEND_LONG == 4
-#define BSON_APPEND_INT(b, key, keylen, val) \
- bson_append_int32(b, key, keylen, val)
-#else
-#error Unsupported architecture (integers are neither 32-bit nor 64-bit)
-#endif
-
-#undef MONGOC_LOG_DOMAIN
-#define MONGOC_LOG_DOMAIN "PHONGO-BSON"
-
-/* Forwards declarations */
-static void php_phongo_zval_to_bson_internal(zval* data, php_phongo_field_path* field_path, php_phongo_bson_flags_t flags, bson_t* bson, bson_t** bson_out);
-
-/* Determines whether the argument should be serialized as a BSON array or
- * document. IS_ARRAY is returned if the argument's keys are a sequence of
- * integers starting at zero; otherwise, IS_OBJECT is returned. */
-static int php_phongo_is_array_or_document(zval* val) /* {{{ */
-{
- HashTable* ht_data = HASH_OF(val);
- int count;
-
- if (Z_TYPE_P(val) != IS_ARRAY) {
- return IS_OBJECT;
- }
-
- count = ht_data ? zend_hash_num_elements(ht_data) : 0;
- if (count > 0) {
- zend_string* key;
- zend_ulong index, idx;
-
- idx = 0;
- ZEND_HASH_FOREACH_KEY(ht_data, index, key)
- {
- if (key) {
- return IS_OBJECT;
- } else {
- if (index != idx) {
- return IS_OBJECT;
- }
- }
- idx++;
- }
- ZEND_HASH_FOREACH_END();
- } else {
- return Z_TYPE_P(val);
- }
-
- return IS_ARRAY;
-} /* }}} */
-
-/* Appends the array or object argument to the BSON document. If the object is
- * an instance of MongoDB\BSON\Serializable, the return value of bsonSerialize()
- * will be appended as an embedded document. Other MongoDB\BSON\Type instances
- * will be appended as the appropriate BSON type. Other array or object values
- * will be appended as an embedded document. */
-static void php_phongo_bson_append_object(bson_t* bson, php_phongo_field_path* field_path, php_phongo_bson_flags_t flags, const char* key, long key_len, zval* object) /* {{{ */
-{
- if (Z_TYPE_P(object) == IS_OBJECT && instanceof_function(Z_OBJCE_P(object), php_phongo_cursorid_ce)) {
- bson_append_int64(bson, key, key_len, Z_CURSORID_OBJ_P(object)->id);
- return;
- }
-
- if (Z_TYPE_P(object) == IS_OBJECT && instanceof_function(Z_OBJCE_P(object), php_phongo_type_ce)) {
- if (instanceof_function(Z_OBJCE_P(object), php_phongo_serializable_ce)) {
- zval obj_data;
- bson_t child;
-
- zend_call_method_with_0_params(PHONGO_COMPAT_OBJ_P(object), NULL, NULL, BSON_SERIALIZE_FUNC_NAME, &obj_data);
-
- if (Z_ISUNDEF(obj_data)) {
- /* zend_call_method() failed or bsonSerialize() threw an
- * exception. Either way, there is nothing else to do. */
- return;
- }
-
- if (Z_TYPE(obj_data) != IS_ARRAY && !(Z_TYPE(obj_data) == IS_OBJECT && instanceof_function(Z_OBJCE(obj_data), zend_standard_class_def))) {
- phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE,
- "Expected %s::%s() to return an array or stdClass, %s given",
- ZSTR_VAL(Z_OBJCE_P(object)->name),
- BSON_SERIALIZE_FUNC_NAME,
- PHONGO_ZVAL_CLASS_OR_TYPE_NAME(obj_data));
- zval_ptr_dtor(&obj_data);
-
- return;
- }
-
- /* Persistable objects must always be serialized as BSON documents;
- * otherwise, infer based on bsonSerialize()'s return value. */
- if (instanceof_function(Z_OBJCE_P(object), php_phongo_persistable_ce) || php_phongo_is_array_or_document(&obj_data) == IS_OBJECT) {
- bson_append_document_begin(bson, key, key_len, &child);
- if (instanceof_function(Z_OBJCE_P(object), php_phongo_persistable_ce)) {
- bson_append_binary(&child, PHONGO_ODM_FIELD_NAME, -1, 0x80, (const uint8_t*) Z_OBJCE_P(object)->name->val, Z_OBJCE_P(object)->name->len);
- }
- php_phongo_zval_to_bson_internal(&obj_data, field_path, flags, &child, NULL);
- bson_append_document_end(bson, &child);
- } else {
- bson_append_array_begin(bson, key, key_len, &child);
- php_phongo_zval_to_bson_internal(&obj_data, field_path, flags, &child, NULL);
- bson_append_array_end(bson, &child);
- }
-
- zval_ptr_dtor(&obj_data);
- return;
- }
-
- if (instanceof_function(Z_OBJCE_P(object), php_phongo_objectid_ce)) {
- bson_oid_t oid;
- php_phongo_objectid_t* intern = Z_OBJECTID_OBJ_P(object);
-
- mongoc_log(MONGOC_LOG_LEVEL_TRACE, MONGOC_LOG_DOMAIN, "encoding ObjectId");
- bson_oid_init_from_string(&oid, intern->oid);
- bson_append_oid(bson, key, key_len, &oid);
- return;
- }
- if (instanceof_function(Z_OBJCE_P(object), php_phongo_utcdatetime_ce)) {
- php_phongo_utcdatetime_t* intern = Z_UTCDATETIME_OBJ_P(object);
-
- mongoc_log(MONGOC_LOG_LEVEL_TRACE, MONGOC_LOG_DOMAIN, "encoding UTCDateTime");
- bson_append_date_time(bson, key, key_len, intern->milliseconds);
- return;
- }
- if (instanceof_function(Z_OBJCE_P(object), php_phongo_binary_ce)) {
- php_phongo_binary_t* intern = Z_BINARY_OBJ_P(object);
-
- mongoc_log(MONGOC_LOG_LEVEL_TRACE, MONGOC_LOG_DOMAIN, "encoding Binary");
- bson_append_binary(bson, key, key_len, intern->type, (const uint8_t*) intern->data, (uint32_t) intern->data_len);
- return;
- }
- if (instanceof_function(Z_OBJCE_P(object), php_phongo_decimal128_ce)) {
- php_phongo_decimal128_t* intern = Z_DECIMAL128_OBJ_P(object);
-
- mongoc_log(MONGOC_LOG_LEVEL_TRACE, MONGOC_LOG_DOMAIN, "encoding Decimal128");
- bson_append_decimal128(bson, key, key_len, &intern->decimal);
- return;
- }
- if (instanceof_function(Z_OBJCE_P(object), php_phongo_int64_ce)) {
- php_phongo_int64_t* intern = Z_INT64_OBJ_P(object);
-
- mongoc_log(MONGOC_LOG_LEVEL_TRACE, MONGOC_LOG_DOMAIN, "encoding Int64");
- bson_append_int64(bson, key, key_len, intern->integer);
- return;
- }
- if (instanceof_function(Z_OBJCE_P(object), php_phongo_regex_ce)) {
- php_phongo_regex_t* intern = Z_REGEX_OBJ_P(object);
-
- mongoc_log(MONGOC_LOG_LEVEL_TRACE, MONGOC_LOG_DOMAIN, "encoding Regex");
- bson_append_regex(bson, key, key_len, intern->pattern, intern->flags);
- return;
- }
- if (instanceof_function(Z_OBJCE_P(object), php_phongo_javascript_ce)) {
- php_phongo_javascript_t* intern = Z_JAVASCRIPT_OBJ_P(object);
-
- if (intern->scope) {
- mongoc_log(MONGOC_LOG_LEVEL_TRACE, MONGOC_LOG_DOMAIN, "encoding Javascript with scope");
- bson_append_code_with_scope(bson, key, key_len, intern->code, intern->scope);
- } else {
- mongoc_log(MONGOC_LOG_LEVEL_TRACE, MONGOC_LOG_DOMAIN, "encoding Javascript without scope");
- bson_append_code(bson, key, key_len, intern->code);
- }
- return;
- }
- if (instanceof_function(Z_OBJCE_P(object), php_phongo_timestamp_ce)) {
- php_phongo_timestamp_t* intern = Z_TIMESTAMP_OBJ_P(object);
-
- mongoc_log(MONGOC_LOG_LEVEL_TRACE, MONGOC_LOG_DOMAIN, "encoding Timestamp");
- bson_append_timestamp(bson, key, key_len, intern->timestamp, intern->increment);
- return;
- }
- if (instanceof_function(Z_OBJCE_P(object), php_phongo_maxkey_ce)) {
- mongoc_log(MONGOC_LOG_LEVEL_TRACE, MONGOC_LOG_DOMAIN, "encoding MaxKey");
- bson_append_maxkey(bson, key, key_len);
- return;
- }
- if (instanceof_function(Z_OBJCE_P(object), php_phongo_minkey_ce)) {
- mongoc_log(MONGOC_LOG_LEVEL_TRACE, MONGOC_LOG_DOMAIN, "encoding MinKey");
- bson_append_minkey(bson, key, key_len);
- return;
- }
-
- /* Deprecated types */
- if (instanceof_function(Z_OBJCE_P(object), php_phongo_dbpointer_ce)) {
- bson_oid_t oid;
- php_phongo_dbpointer_t* intern = Z_DBPOINTER_OBJ_P(object);
-
- mongoc_log(MONGOC_LOG_LEVEL_TRACE, MONGOC_LOG_DOMAIN, "encoding DBPointer");
- bson_oid_init_from_string(&oid, intern->id);
- bson_append_dbpointer(bson, key, key_len, intern->ref, &oid);
- return;
- }
- if (instanceof_function(Z_OBJCE_P(object), php_phongo_symbol_ce)) {
- php_phongo_symbol_t* intern = Z_SYMBOL_OBJ_P(object);
-
- mongoc_log(MONGOC_LOG_LEVEL_TRACE, MONGOC_LOG_DOMAIN, "encoding Symbol");
- bson_append_symbol(bson, key, key_len, intern->symbol, intern->symbol_len);
- return;
- }
- if (instanceof_function(Z_OBJCE_P(object), php_phongo_undefined_ce)) {
- mongoc_log(MONGOC_LOG_LEVEL_TRACE, MONGOC_LOG_DOMAIN, "encoding Undefined");
- bson_append_undefined(bson, key, key_len);
- return;
- }
-
- phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "Unexpected %s instance: %s", ZSTR_VAL(php_phongo_type_ce->name), ZSTR_VAL(Z_OBJCE_P(object)->name));
- return;
- } else {
- bson_t child;
-
- mongoc_log(MONGOC_LOG_LEVEL_TRACE, MONGOC_LOG_DOMAIN, "encoding document");
- bson_append_document_begin(bson, key, key_len, &child);
- php_phongo_zval_to_bson_internal(object, field_path, flags, &child, NULL);
- bson_append_document_end(bson, &child);
- }
-} /* }}} */
-
-/* Appends the zval argument to the BSON document. If the argument is an object,
- * or an array that should be serialized as an embedded document, this function
- * will defer to php_phongo_bson_append_object(). */
-static void php_phongo_bson_append(bson_t* bson, php_phongo_field_path* field_path, php_phongo_bson_flags_t flags, const char* key, long key_len, zval* entry) /* {{{ */
-{
- php_phongo_field_path_write_item_at_current_level(field_path, key);
-
-try_again:
- switch (Z_TYPE_P(entry)) {
- case IS_NULL:
- bson_append_null(bson, key, key_len);
- break;
- case IS_TRUE:
- bson_append_bool(bson, key, key_len, true);
- break;
-
- case IS_FALSE:
- bson_append_bool(bson, key, key_len, false);
- break;
-
- case IS_LONG:
- BSON_APPEND_INT(bson, key, key_len, Z_LVAL_P(entry));
- break;
-
- case IS_DOUBLE:
- bson_append_double(bson, key, key_len, Z_DVAL_P(entry));
- break;
-
- case IS_STRING:
- if (bson_utf8_validate(Z_STRVAL_P(entry), Z_STRLEN_P(entry), true)) {
- bson_append_utf8(bson, key, key_len, Z_STRVAL_P(entry), Z_STRLEN_P(entry));
- } else {
- char* path_string = php_phongo_field_path_as_string(field_path);
- phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "Detected invalid UTF-8 for field path \"%s\": %s", path_string, Z_STRVAL_P(entry));
- efree(path_string);
- }
- break;
-
- case IS_ARRAY:
- if (php_phongo_is_array_or_document(entry) == IS_ARRAY) {
- bson_t child;
- HashTable* tmp_ht = HASH_OF(entry);
-
- if (!php_phongo_zend_hash_apply_protection_begin(tmp_ht)) {
- char* path_string = php_phongo_field_path_as_string(field_path);
- phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "Detected recursion for field path \"%s\"", path_string);
- efree(path_string);
- break;
- }
-
- bson_append_array_begin(bson, key, key_len, &child);
- php_phongo_field_path_write_type_at_current_level(field_path, PHONGO_FIELD_PATH_ITEM_ARRAY);
- field_path->size++;
- php_phongo_zval_to_bson_internal(entry, field_path, flags, &child, NULL);
- field_path->size--;
- bson_append_array_end(bson, &child);
-
- php_phongo_zend_hash_apply_protection_end(tmp_ht);
- break;
- }
- PHONGO_BREAK_INTENTIONALLY_MISSING
-
- case IS_OBJECT: {
- HashTable* tmp_ht = HASH_OF(entry);
-
- if (!php_phongo_zend_hash_apply_protection_begin(tmp_ht)) {
- char* path_string = php_phongo_field_path_as_string(field_path);
- phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "Detected recursion for field path \"%s\"", path_string);
- efree(path_string);
- break;
- }
-
- php_phongo_field_path_write_type_at_current_level(field_path, PHONGO_FIELD_PATH_ITEM_DOCUMENT);
- field_path->size++;
- php_phongo_bson_append_object(bson, field_path, flags, key, key_len, entry);
- field_path->size--;
-
- php_phongo_zend_hash_apply_protection_end(tmp_ht);
- break;
- }
-
- case IS_REFERENCE:
- ZVAL_DEREF(entry);
- goto try_again;
-
- default: {
- char* path_string = php_phongo_field_path_as_string(field_path);
- phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "Detected unsupported PHP type for field path \"%s\": %d (%s)", path_string, Z_TYPE_P(entry), zend_get_type_by_const(Z_TYPE_P(entry)));
- efree(path_string);
- }
- }
-} /* }}} */
-
-static void php_phongo_zval_to_bson_internal(zval* data, php_phongo_field_path* field_path, php_phongo_bson_flags_t flags, bson_t* bson, bson_t** bson_out) /* {{{ */
-{
- HashTable* ht_data = NULL;
- zval obj_data;
-
- /* If we will be encoding a class that may contain protected and private
- * properties, we'll need to filter them out later. */
- bool ht_data_from_properties = false;
-
- /* If the object is an instance of MongoDB\BSON\Persistable, we will need to
- * inject the PHP class name as a BSON key and ignore any existing key in
- * the return value of bsonSerialize(). */
- bool skip_odm_field = false;
-
- ZVAL_UNDEF(&obj_data);
-
- switch (Z_TYPE_P(data)) {
- case IS_OBJECT:
- if (instanceof_function(Z_OBJCE_P(data), php_phongo_serializable_ce)) {
- zend_call_method_with_0_params(PHONGO_COMPAT_OBJ_P(data), NULL, NULL, BSON_SERIALIZE_FUNC_NAME, &obj_data);
-
- if (Z_ISUNDEF(obj_data)) {
- /* zend_call_method() failed or bsonSerialize() threw an
- * exception. Either way, there is nothing else to do. */
- return;
- }
-
- if (Z_TYPE(obj_data) != IS_ARRAY && !(Z_TYPE(obj_data) == IS_OBJECT && instanceof_function(Z_OBJCE(obj_data), zend_standard_class_def))) {
- phongo_throw_exception(
- PHONGO_ERROR_UNEXPECTED_VALUE,
- "Expected %s::%s() to return an array or stdClass, %s given",
- ZSTR_VAL(Z_OBJCE_P(data)->name),
- BSON_SERIALIZE_FUNC_NAME,
- PHONGO_ZVAL_CLASS_OR_TYPE_NAME(obj_data));
-
- goto cleanup;
- }
-
- ht_data = HASH_OF(&obj_data);
-
- if (instanceof_function(Z_OBJCE_P(data), php_phongo_persistable_ce)) {
- bson_append_binary(bson, PHONGO_ODM_FIELD_NAME, -1, 0x80, (const uint8_t*) Z_OBJCE_P(data)->name->val, Z_OBJCE_P(data)->name->len);
- /* Ensure that we ignore an existing key with the same name
- * if one exists in the bsonSerialize() return value. */
- skip_odm_field = true;
- }
-
- break;
- }
-
- if (instanceof_function(Z_OBJCE_P(data), php_phongo_type_ce)) {
- phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "%s instance %s cannot be serialized as a root element", ZSTR_VAL(php_phongo_type_ce->name), ZSTR_VAL(Z_OBJCE_P(data)->name));
- return;
- }
-
- ht_data = Z_OBJ_HT_P(data)->get_properties(PHONGO_COMPAT_OBJ_P(data));
- ht_data_from_properties = true;
- break;
-
- case IS_ARRAY:
- ht_data = HASH_OF(data);
- break;
-
- default:
- return;
- }
-
- {
- zend_string* string_key = NULL;
- zend_ulong num_key = 0;
- zval* value;
-
- ZEND_HASH_FOREACH_KEY_VAL_IND(ht_data, num_key, string_key, value)
- {
- if (string_key) {
- if (ht_data_from_properties) {
- /* Skip protected and private properties */
- if (ZSTR_VAL(string_key)[0] == '\0' && ZSTR_LEN(string_key) > 0) {
- continue;
- }
- }
-
- if (strlen(ZSTR_VAL(string_key)) != ZSTR_LEN(string_key)) {
- phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "BSON keys cannot contain null bytes. Unexpected null byte after \"%s\".", ZSTR_VAL(string_key));
-
- goto cleanup;
- }
-
- if (skip_odm_field && !strcmp(ZSTR_VAL(string_key), PHONGO_ODM_FIELD_NAME)) {
- continue;
- }
-
- if (flags & PHONGO_BSON_ADD_ID) {
- if (!strcmp(ZSTR_VAL(string_key), "_id")) {
- flags &= ~PHONGO_BSON_ADD_ID;
- }
- }
- }
-
- /* Ensure we're working with a string key */
- if (!string_key) {
- string_key = zend_long_to_str(num_key);
- } else {
- zend_string_addref(string_key);
- }
-
- php_phongo_bson_append(bson, field_path, flags & ~PHONGO_BSON_ADD_ID, ZSTR_VAL(string_key), strlen(ZSTR_VAL(string_key)), value);
-
- zend_string_release(string_key);
- }
- ZEND_HASH_FOREACH_END();
- }
-
- if (flags & PHONGO_BSON_ADD_ID) {
- bson_oid_t oid;
-
- bson_oid_init(&oid, NULL);
- bson_append_oid(bson, "_id", strlen("_id"), &oid);
- mongoc_log(MONGOC_LOG_LEVEL_TRACE, MONGOC_LOG_DOMAIN, "Added new _id");
- }
-
- if (flags & PHONGO_BSON_RETURN_ID && bson_out) {
- bson_iter_t iter;
-
- *bson_out = bson_new();
-
- if (bson_iter_init_find(&iter, bson, "_id") && !bson_append_iter(*bson_out, NULL, 0, &iter)) {
- /* This should not be able to happen since we are copying from
- * within a valid bson_t. */
- phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "Error copying \"_id\" field from encoded document");
-
- goto cleanup;
- }
- }
-
-cleanup:
- if (!Z_ISUNDEF(obj_data)) {
- zval_ptr_dtor(&obj_data);
- }
-} /* }}} */
-
-/* Converts the array or object argument to a BSON document. If the object is an
- * instance of MongoDB\BSON\Serializable, the return value of bsonSerialize()
- * will be used. */
-void php_phongo_zval_to_bson(zval* data, php_phongo_bson_flags_t flags, bson_t* bson, bson_t** bson_out) /* {{{ */
-{
- php_phongo_field_path* field_path = php_phongo_field_path_alloc(false);
-
- php_phongo_zval_to_bson_internal(data, field_path, flags, bson, bson_out);
-
- php_phongo_field_path_free(field_path);
-} /* }}} */
-
-/* Converts the argument to a bson_value_t. If the object is an instance of
- * MongoDB\BSON\Serializable, the return value of bsonSerialize() will be
- * used. */
-void php_phongo_zval_to_bson_value(zval* data, php_phongo_bson_flags_t flags, bson_value_t* value) /* {{{ */
-{
- bson_iter_t iter;
- bson_t bson = BSON_INITIALIZER;
-
- zval* data_object = ecalloc(1, sizeof(zval));
-
- array_init_size(data_object, 1);
- add_assoc_zval(data_object, "data", data);
-
- Z_TRY_ADDREF_P(data);
-
- php_phongo_zval_to_bson(data_object, flags, &bson, NULL);
-
- if (bson_iter_init_find(&iter, &bson, "data")) {
- bson_value_copy(bson_iter_value(&iter), value);
- }
-
- zval_ptr_dtor(data_object);
- efree(data_object);
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/bson.c b/mongodb-1.12.0/src/bson.c
deleted file mode 100644
index 2ee42843..00000000
--- a/mongodb-1.12.0/src/bson.c
+++ /dev/null
@@ -1,1378 +0,0 @@
-/*
- * Copyright 2014-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <bson/bson.h>
-
-#include <php.h>
-#include <Zend/zend_hash.h>
-#include <Zend/zend_interfaces.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "php_phongo.h"
-#include "php_bson.h"
-#include "phongo_compat.h"
-#include "php_array_api.h"
-
-#define DEBUG 0
-
-#undef MONGOC_LOG_DOMAIN
-#define MONGOC_LOG_DOMAIN "PHONGO-BSON"
-
-#define PHONGO_IS_CLASS_INSTANTIATABLE(ce) \
- (!(ce->ce_flags & (ZEND_ACC_INTERFACE | ZEND_ACC_IMPLICIT_ABSTRACT_CLASS | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)))
-
-#define PHONGO_BSON_STATE_ZCHILD(state) (&((php_phongo_bson_state*) (state))->zchild)
-
-#define PHONGO_FIELD_PATH_EXPANSION 8
-
-/* Forward declarations */
-static bool php_phongo_bson_visit_document(const bson_iter_t* iter ARG_UNUSED, const char* key, const bson_t* v_document, void* data);
-static bool php_phongo_bson_visit_array(const bson_iter_t* iter ARG_UNUSED, const char* key, const bson_t* v_document, void* data);
-
-/* Path builder */
-char* php_phongo_field_path_as_string(php_phongo_field_path* field_path)
-{
- size_t length = 1; /* NULL character */
- size_t i;
- char* path;
- char* ptr;
-
- if (!field_path) {
- return estrdup("");
- }
- if (!field_path->elements) {
- return estrdup("");
- }
-
- for (i = 0; i <= field_path->size; i++) {
- if (!field_path->elements[i]) {
- continue;
- }
- length += (1 + strlen(field_path->elements[i]));
- }
-
- path = emalloc(length);
- ptr = path;
-
- for (i = 0; i <= field_path->size; i++) {
- if (!field_path->elements[i]) {
- continue;
- }
- strcpy(ptr, field_path->elements[i]);
- ptr += strlen(field_path->elements[i]);
- ptr[0] = '.';
- ptr++;
- }
- ptr[-1] = '\0';
-
- return path;
-}
-
-php_phongo_field_path* php_phongo_field_path_alloc(bool owns_elements)
-{
- php_phongo_field_path* tmp = ecalloc(1, sizeof(php_phongo_field_path));
- tmp->ref_count = 1;
- tmp->owns_elements = owns_elements;
-
- return tmp;
-}
-
-void php_phongo_field_path_free(php_phongo_field_path* field_path)
-{
- if (field_path->owns_elements) {
- size_t i;
-
- for (i = 0; i < field_path->size; i++) {
- efree(field_path->elements[i]);
- }
- }
- if (field_path->elements) {
- efree(field_path->elements);
- }
- if (field_path->element_types) {
- efree(field_path->element_types);
- }
- efree(field_path);
-}
-
-static void php_phongo_field_path_ensure_allocation(php_phongo_field_path* field_path, size_t level)
-{
- if (level >= field_path->allocated_size) {
- size_t i;
-
- field_path->allocated_size = field_path->size + PHONGO_FIELD_PATH_EXPANSION;
- field_path->elements = erealloc(field_path->elements, sizeof(char*) * field_path->allocated_size);
- field_path->element_types = erealloc(field_path->element_types, sizeof(php_phongo_bson_field_path_item_types) * field_path->allocated_size);
-
- for (i = level; i < field_path->allocated_size; i++) {
- field_path->elements[i] = NULL;
- field_path->element_types[i] = PHONGO_FIELD_PATH_ITEM_NONE;
- }
- }
-}
-
-void php_phongo_field_path_write_item_at_current_level(php_phongo_field_path* field_path, const char* element)
-{
- php_phongo_field_path_ensure_allocation(field_path, field_path->size);
-
- if (field_path->owns_elements) {
- field_path->elements[field_path->size] = estrdup(element);
- } else {
- field_path->elements[field_path->size] = (char*) element;
- }
-}
-
-void php_phongo_field_path_write_type_at_current_level(php_phongo_field_path* field_path, php_phongo_bson_field_path_item_types element_type)
-{
- php_phongo_field_path_ensure_allocation(field_path, field_path->size);
-
- field_path->element_types[field_path->size] = element_type;
-}
-
-bool php_phongo_field_path_push(php_phongo_field_path* field_path, const char* element, php_phongo_bson_field_path_item_types element_type)
-{
- php_phongo_field_path_write_item_at_current_level(field_path, element);
- php_phongo_field_path_write_type_at_current_level(field_path, element_type);
-
- field_path->size++;
-
- return true;
-}
-
-bool php_phongo_field_path_pop(php_phongo_field_path* field_path)
-{
- php_phongo_field_path_ensure_allocation(field_path, field_path->size);
-
- field_path->elements[field_path->size] = NULL;
- field_path->element_types[field_path->size] = PHONGO_FIELD_PATH_ITEM_NONE;
-
- field_path->size--;
-
- field_path->elements[field_path->size] = NULL;
- field_path->element_types[field_path->size] = PHONGO_FIELD_PATH_ITEM_NONE;
-
- return true;
-}
-
-inline static bool php_phongo_bson_state_is_initialized(php_phongo_bson_state* state)
-{
- return state->field_path != NULL;
-}
-
-void php_phongo_bson_state_ctor(php_phongo_bson_state* state)
-{
- state->field_path = php_phongo_field_path_alloc(false);
-}
-
-void php_phongo_bson_state_copy_ctor(php_phongo_bson_state* dst, php_phongo_bson_state* src)
-{
- dst->map = src->map;
- if (src->field_path) {
- src->field_path->ref_count++;
- }
- dst->field_path = src->field_path;
-}
-
-void php_phongo_bson_state_dtor(php_phongo_bson_state* state)
-{
- if (state->field_path) {
- state->field_path->ref_count--;
-
- if (state->field_path->ref_count < 1) {
- php_phongo_field_path_free(state->field_path);
- }
- state->field_path = NULL;
- }
-} /* }}} */
-
-static void php_phongo_bson_visit_corrupt(const bson_iter_t* iter ARG_UNUSED, void* data ARG_UNUSED) /* {{{ */
-{
- mongoc_log(MONGOC_LOG_LEVEL_WARNING, MONGOC_LOG_DOMAIN, "Corrupt BSON data detected!");
-} /* }}} */
-
-static void php_phongo_bson_visit_unsupported_type(const bson_iter_t* iter ARG_UNUSED, const char* key, uint32_t v_type_code, void* data ARG_UNUSED) /* {{{ */
-{
- php_phongo_bson_state* state = (php_phongo_bson_state*) data;
- char* path_string;
-
- php_phongo_field_path_write_item_at_current_level(state->field_path, key);
- path_string = php_phongo_field_path_as_string(state->field_path);
-
- phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "Detected unknown BSON type 0x%02hhx for field path \"%s\". Are you using the latest driver?", (unsigned char) v_type_code, path_string);
-
- efree(path_string);
-} /* }}} */
-
-static bool php_phongo_bson_visit_double(const bson_iter_t* iter ARG_UNUSED, const char* key, double v_double, void* data) /* {{{ */
-{
- zval* retval = PHONGO_BSON_STATE_ZCHILD(data);
- php_phongo_bson_state* state = (php_phongo_bson_state*) data;
-
- if (state->is_visiting_array) {
- add_next_index_double(retval, v_double);
- } else {
- add_assoc_double(retval, key, v_double);
- }
-
- php_phongo_field_path_write_item_at_current_level(state->field_path, key);
-
- return false;
-} /* }}} */
-
-static bool php_phongo_bson_visit_utf8(const bson_iter_t* iter ARG_UNUSED, const char* key, size_t v_utf8_len, const char* v_utf8, void* data) /* {{{ */
-{
- zval* retval = PHONGO_BSON_STATE_ZCHILD(data);
- php_phongo_bson_state* state = (php_phongo_bson_state*) data;
-
- if (state->is_visiting_array) {
- ADD_NEXT_INDEX_STRINGL(retval, v_utf8, v_utf8_len);
- } else {
- ADD_ASSOC_STRING_EX(retval, key, strlen(key), v_utf8, v_utf8_len);
- }
-
- php_phongo_field_path_write_item_at_current_level(state->field_path, key);
-
- return false;
-} /* }}} */
-
-static void php_phongo_bson_new_binary_from_binary_and_type(zval* object, const char* data, size_t data_len, bson_subtype_t type) /* {{{ */
-{
- php_phongo_binary_t* intern;
-
- object_init_ex(object, php_phongo_binary_ce);
-
- intern = Z_BINARY_OBJ_P(object);
- intern->data = estrndup(data, data_len);
- intern->data_len = data_len;
- intern->type = (uint8_t) type;
-} /* }}} */
-
-static bool php_phongo_bson_visit_binary(const bson_iter_t* iter ARG_UNUSED, const char* key, bson_subtype_t v_subtype, size_t v_binary_len, const uint8_t* v_binary, void* data) /* {{{ */
-{
- zval* retval = PHONGO_BSON_STATE_ZCHILD(data);
- php_phongo_bson_state* state = (php_phongo_bson_state*) data;
-
- if (v_subtype == 0x80 && strcmp(key, PHONGO_ODM_FIELD_NAME) == 0) {
- zend_string* zs_classname = zend_string_init((const char*) v_binary, v_binary_len, 0);
- zend_class_entry* found_ce = zend_fetch_class(zs_classname, ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_SILENT);
- zend_string_release(zs_classname);
-
- if (found_ce && PHONGO_IS_CLASS_INSTANTIATABLE(found_ce) && instanceof_function(found_ce, php_phongo_persistable_ce)) {
- ((php_phongo_bson_state*) data)->odm = found_ce;
- }
- }
-
- {
- zval zchild;
-
- php_phongo_bson_new_binary_from_binary_and_type(&zchild, (const char*) v_binary, v_binary_len, v_subtype);
-
- if (state->is_visiting_array) {
- add_next_index_zval(retval, &zchild);
- } else {
- ADD_ASSOC_ZVAL(retval, key, &zchild);
- }
- }
-
- php_phongo_field_path_write_item_at_current_level(state->field_path, key);
-
- return false;
-} /* }}} */
-
-static bool php_phongo_bson_visit_undefined(const bson_iter_t* iter, const char* key, void* data) /* {{{ */
-{
- zval* retval = PHONGO_BSON_STATE_ZCHILD(data);
- php_phongo_bson_state* state = (php_phongo_bson_state*) data;
- zval zchild;
-
- object_init_ex(&zchild, php_phongo_undefined_ce);
-
- if (state->is_visiting_array) {
- add_next_index_zval(retval, &zchild);
- } else {
- ADD_ASSOC_ZVAL(retval, key, &zchild);
- }
-
- php_phongo_field_path_write_item_at_current_level(state->field_path, key);
-
- return false;
-} /* }}} */
-
-static void php_phongo_objectid_new_from_oid(zval* object, const bson_oid_t* oid) /* {{{ */
-{
- php_phongo_objectid_t* intern;
-
- object_init_ex(object, php_phongo_objectid_ce);
-
- intern = Z_OBJECTID_OBJ_P(object);
- bson_oid_to_string(oid, intern->oid);
- intern->initialized = true;
-} /* }}} */
-
-static bool php_phongo_bson_visit_oid(const bson_iter_t* iter ARG_UNUSED, const char* key, const bson_oid_t* v_oid, void* data) /* {{{ */
-{
- zval* retval = PHONGO_BSON_STATE_ZCHILD(data);
- php_phongo_bson_state* state = (php_phongo_bson_state*) data;
- zval zchild;
-
- php_phongo_objectid_new_from_oid(&zchild, v_oid);
-
- if (state->is_visiting_array) {
- add_next_index_zval(retval, &zchild);
- } else {
- ADD_ASSOC_ZVAL(retval, key, &zchild);
- }
-
- php_phongo_field_path_write_item_at_current_level(state->field_path, key);
-
- return false;
-} /* }}} */
-
-static bool php_phongo_bson_visit_bool(const bson_iter_t* iter ARG_UNUSED, const char* key, bool v_bool, void* data) /* {{{ */
-{
- zval* retval = PHONGO_BSON_STATE_ZCHILD(data);
- php_phongo_bson_state* state = (php_phongo_bson_state*) data;
-
- if (state->is_visiting_array) {
- add_next_index_bool(retval, v_bool);
- } else {
- add_assoc_bool(retval, key, v_bool);
- }
-
- php_phongo_field_path_write_item_at_current_level(state->field_path, key);
-
- return false;
-} /* }}} */
-
-static void php_phongo_bson_new_utcdatetime_from_epoch(zval* object, int64_t msec_since_epoch) /* {{{ */
-{
- php_phongo_utcdatetime_t* intern;
-
- object_init_ex(object, php_phongo_utcdatetime_ce);
-
- intern = Z_UTCDATETIME_OBJ_P(object);
- intern->milliseconds = msec_since_epoch;
- intern->initialized = true;
-} /* }}} */
-
-static bool php_phongo_bson_visit_date_time(const bson_iter_t* iter ARG_UNUSED, const char* key, int64_t msec_since_epoch, void* data) /* {{{ */
-{
- zval* retval = PHONGO_BSON_STATE_ZCHILD(data);
- php_phongo_bson_state* state = (php_phongo_bson_state*) data;
- zval zchild;
-
- php_phongo_bson_new_utcdatetime_from_epoch(&zchild, msec_since_epoch);
-
- if (state->is_visiting_array) {
- add_next_index_zval(retval, &zchild);
- } else {
- ADD_ASSOC_ZVAL(retval, key, &zchild);
- }
-
- php_phongo_field_path_write_item_at_current_level(state->field_path, key);
-
- return false;
-} /* }}} */
-
-static void php_phongo_bson_new_decimal128(zval* object, const bson_decimal128_t* decimal) /* {{{ */
-{
- php_phongo_decimal128_t* intern;
-
- object_init_ex(object, php_phongo_decimal128_ce);
-
- intern = Z_DECIMAL128_OBJ_P(object);
- memcpy(&intern->decimal, decimal, sizeof(bson_decimal128_t));
- intern->initialized = true;
-} /* }}} */
-
-static bool php_phongo_bson_visit_decimal128(const bson_iter_t* iter ARG_UNUSED, const char* key, const bson_decimal128_t* decimal, void* data) /* {{{ */
-{
- zval* retval = PHONGO_BSON_STATE_ZCHILD(data);
- php_phongo_bson_state* state = (php_phongo_bson_state*) data;
- zval zchild;
-
- php_phongo_bson_new_decimal128(&zchild, decimal);
-
- if (state->is_visiting_array) {
- add_next_index_zval(retval, &zchild);
- } else {
- ADD_ASSOC_ZVAL(retval, key, &zchild);
- }
-
- php_phongo_field_path_write_item_at_current_level(state->field_path, key);
-
- return false;
-} /* }}} */
-
-static bool php_phongo_bson_visit_null(const bson_iter_t* iter ARG_UNUSED, const char* key, void* data) /* {{{ */
-{
- zval* retval = PHONGO_BSON_STATE_ZCHILD(data);
- php_phongo_bson_state* state = (php_phongo_bson_state*) data;
-
- if (state->is_visiting_array) {
- add_next_index_null(retval);
- } else {
- add_assoc_null(retval, key);
- }
-
- php_phongo_field_path_write_item_at_current_level(state->field_path, key);
-
- return false;
-} /* }}} */
-
-static void php_phongo_bson_new_regex_from_regex_and_options(zval* object, const char* pattern, const char* flags) /* {{{ */
-{
- php_phongo_regex_t* intern;
-
- object_init_ex(object, php_phongo_regex_ce);
-
- intern = Z_REGEX_OBJ_P(object);
- intern->pattern_len = strlen(pattern);
- intern->pattern = estrndup(pattern, intern->pattern_len);
- intern->flags_len = strlen(flags);
- intern->flags = estrndup(flags, intern->flags_len);
-} /* }}} */
-
-static bool php_phongo_bson_visit_regex(const bson_iter_t* iter ARG_UNUSED, const char* key, const char* v_regex, const char* v_options, void* data) /* {{{ */
-{
- zval* retval = PHONGO_BSON_STATE_ZCHILD(data);
- php_phongo_bson_state* state = (php_phongo_bson_state*) data;
- zval zchild;
-
- php_phongo_bson_new_regex_from_regex_and_options(&zchild, v_regex, v_options);
-
- if (state->is_visiting_array) {
- add_next_index_zval(retval, &zchild);
- } else {
- ADD_ASSOC_ZVAL(retval, key, &zchild);
- }
-
- php_phongo_field_path_write_item_at_current_level(state->field_path, key);
-
- return false;
-} /* }}} */
-
-static void php_phongo_bson_new_symbol(zval* object, const char* symbol, size_t symbol_len) /* {{{ */
-{
- php_phongo_symbol_t* intern;
-
- object_init_ex(object, php_phongo_symbol_ce);
-
- intern = Z_SYMBOL_OBJ_P(object);
- intern->symbol = estrndup(symbol, symbol_len);
- intern->symbol_len = symbol_len;
-} /* }}} */
-
-static bool php_phongo_bson_visit_symbol(const bson_iter_t* iter, const char* key, size_t v_symbol_len, const char* v_symbol, void* data) /* {{{ */
-{
- zval* retval = PHONGO_BSON_STATE_ZCHILD(data);
- php_phongo_bson_state* state = (php_phongo_bson_state*) data;
- zval zchild;
-
- php_phongo_bson_new_symbol(&zchild, v_symbol, v_symbol_len);
-
- if (state->is_visiting_array) {
- add_next_index_zval(retval, &zchild);
- } else {
- ADD_ASSOC_ZVAL(retval, key, &zchild);
- }
-
- php_phongo_field_path_write_item_at_current_level(state->field_path, key);
-
- return false;
-} /* }}} */
-
-static bool php_phongo_bson_new_javascript_from_javascript_and_scope(zval* object, const char* code, size_t code_len, const bson_t* scope) /* {{{ */
-{
- php_phongo_javascript_t* intern;
-
- if (scope) {
- php_phongo_bson_state state;
- bool valid_scope;
-
- PHONGO_BSON_INIT_STATE(state);
-
- valid_scope = php_phongo_bson_to_zval_ex(bson_get_data(scope), scope->len, &state);
- zval_ptr_dtor(&state.zchild);
-
- if (!valid_scope) {
- return false;
- }
- }
-
- object_init_ex(object, php_phongo_javascript_ce);
-
- intern = Z_JAVASCRIPT_OBJ_P(object);
- intern->code = estrndup(code, code_len);
- intern->code_len = code_len;
- intern->scope = scope ? bson_copy(scope) : NULL;
-
- return true;
-} /* }}} */
-
-static bool php_phongo_bson_new_javascript_from_javascript(zval* object, const char* code, size_t code_len) /* {{{ */
-{
- return php_phongo_bson_new_javascript_from_javascript_and_scope(object, code, code_len, NULL);
-} /* }}} */
-
-static bool php_phongo_bson_visit_code(const bson_iter_t* iter ARG_UNUSED, const char* key, size_t v_code_len, const char* v_code, void* data) /* {{{ */
-{
- zval* retval = PHONGO_BSON_STATE_ZCHILD(data);
- php_phongo_bson_state* state = (php_phongo_bson_state*) data;
- zval zchild;
-
- if (!php_phongo_bson_new_javascript_from_javascript(&zchild, v_code, v_code_len)) {
- return true;
- }
-
- if (state->is_visiting_array) {
- add_next_index_zval(retval, &zchild);
- } else {
- ADD_ASSOC_ZVAL(retval, key, &zchild);
- }
-
- php_phongo_field_path_write_item_at_current_level(state->field_path, key);
-
- return false;
-} /* }}} */
-
-static void php_phongo_bson_new_dbpointer(zval* object, const char* ref, size_t ref_len, const bson_oid_t* oid) /* {{{ */
-{
- php_phongo_dbpointer_t* intern;
-
- object_init_ex(object, php_phongo_dbpointer_ce);
-
- intern = Z_DBPOINTER_OBJ_P(object);
- intern->ref = estrndup(ref, ref_len);
- intern->ref_len = ref_len;
- bson_oid_to_string(oid, intern->id);
-} /* }}} */
-
-static bool php_phongo_bson_visit_dbpointer(const bson_iter_t* iter, const char* key, size_t namespace_len, const char* namespace, const bson_oid_t* oid, void* data) /* {{{ */
-{
- zval* retval = PHONGO_BSON_STATE_ZCHILD(data);
- php_phongo_bson_state* state = (php_phongo_bson_state*) data;
- zval zchild;
-
- php_phongo_bson_new_dbpointer(&zchild, namespace, namespace_len, oid);
-
- if (state->is_visiting_array) {
- add_next_index_zval(retval, &zchild);
- } else {
- ADD_ASSOC_ZVAL(retval, key, &zchild);
- }
-
- php_phongo_field_path_write_item_at_current_level(state->field_path, key);
-
- return false;
-} /* }}} */
-
-static bool php_phongo_bson_visit_codewscope(const bson_iter_t* iter ARG_UNUSED, const char* key, size_t v_code_len, const char* v_code, const bson_t* v_scope, void* data) /* {{{ */
-{
- zval* retval = PHONGO_BSON_STATE_ZCHILD(data);
- php_phongo_bson_state* state = (php_phongo_bson_state*) data;
- zval zchild;
-
- if (!php_phongo_bson_new_javascript_from_javascript_and_scope(&zchild, v_code, v_code_len, v_scope)) {
- return true;
- }
-
- if (state->is_visiting_array) {
- add_next_index_zval(retval, &zchild);
- } else {
- ADD_ASSOC_ZVAL(retval, key, &zchild);
- }
-
- php_phongo_field_path_write_item_at_current_level(state->field_path, key);
-
- return false;
-} /* }}} */
-
-static bool php_phongo_bson_visit_int32(const bson_iter_t* iter ARG_UNUSED, const char* key, int32_t v_int32, void* data) /* {{{ */
-{
- zval* retval = PHONGO_BSON_STATE_ZCHILD(data);
- php_phongo_bson_state* state = (php_phongo_bson_state*) data;
-
- if (state->is_visiting_array) {
- add_next_index_long(retval, v_int32);
- } else {
- add_assoc_long(retval, key, v_int32);
- }
-
- php_phongo_field_path_write_item_at_current_level(state->field_path, key);
-
- return false;
-} /* }}} */
-
-static bool php_phongo_bson_visit_timestamp(const bson_iter_t* iter ARG_UNUSED, const char* key, uint32_t v_timestamp, uint32_t v_increment, void* data) /* {{{ */
-{
- zval* retval = PHONGO_BSON_STATE_ZCHILD(data);
- php_phongo_bson_state* state = (php_phongo_bson_state*) data;
- zval zchild;
-
- php_phongo_bson_new_timestamp_from_increment_and_timestamp(&zchild, v_increment, v_timestamp);
-
- if (state->is_visiting_array) {
- add_next_index_zval(retval, &zchild);
- } else {
- ADD_ASSOC_ZVAL(retval, key, &zchild);
- }
-
- php_phongo_field_path_write_item_at_current_level(state->field_path, key);
-
- return false;
-} /* }}} */
-
-static bool php_phongo_bson_visit_int64(const bson_iter_t* iter ARG_UNUSED, const char* key, int64_t v_int64, void* data) /* {{{ */
-{
- zval* retval = PHONGO_BSON_STATE_ZCHILD(data);
- php_phongo_bson_state* state = (php_phongo_bson_state*) data;
-
- php_phongo_field_path_write_item_at_current_level(state->field_path, key);
-
- if (state->is_visiting_array) {
- ADD_NEXT_INDEX_INT64(retval, v_int64);
- } else {
- ADD_ASSOC_INT64(retval, key, v_int64);
- }
-
- return false;
-} /* }}} */
-
-static bool php_phongo_bson_visit_maxkey(const bson_iter_t* iter ARG_UNUSED, const char* key, void* data) /* {{{ */
-{
- zval* retval = PHONGO_BSON_STATE_ZCHILD(data);
- php_phongo_bson_state* state = (php_phongo_bson_state*) data;
- zval zchild;
-
- object_init_ex(&zchild, php_phongo_maxkey_ce);
-
- if (state->is_visiting_array) {
- add_next_index_zval(retval, &zchild);
- } else {
- ADD_ASSOC_ZVAL(retval, key, &zchild);
- }
-
- php_phongo_field_path_write_item_at_current_level(state->field_path, key);
-
- return false;
-} /* }}} */
-
-static bool php_phongo_bson_visit_minkey(const bson_iter_t* iter ARG_UNUSED, const char* key, void* data) /* {{{ */
-{
- zval* retval = PHONGO_BSON_STATE_ZCHILD(data);
- php_phongo_bson_state* state = (php_phongo_bson_state*) data;
- zval zchild;
-
- object_init_ex(&zchild, php_phongo_minkey_ce);
-
- if (state->is_visiting_array) {
- add_next_index_zval(retval, &zchild);
- } else {
- ADD_ASSOC_ZVAL(retval, key, &zchild);
- }
-
- php_phongo_field_path_write_item_at_current_level(state->field_path, key);
-
- return false;
-} /* }}} */
-
-static const bson_visitor_t php_bson_visitors = {
- NULL /* php_phongo_bson_visit_before*/,
- NULL /*php_phongo_bson_visit_after*/,
- php_phongo_bson_visit_corrupt,
- php_phongo_bson_visit_double,
- php_phongo_bson_visit_utf8,
- php_phongo_bson_visit_document,
- php_phongo_bson_visit_array,
- php_phongo_bson_visit_binary,
- php_phongo_bson_visit_undefined,
- php_phongo_bson_visit_oid,
- php_phongo_bson_visit_bool,
- php_phongo_bson_visit_date_time,
- php_phongo_bson_visit_null,
- php_phongo_bson_visit_regex,
- php_phongo_bson_visit_dbpointer,
- php_phongo_bson_visit_code,
- php_phongo_bson_visit_symbol,
- php_phongo_bson_visit_codewscope,
- php_phongo_bson_visit_int32,
- php_phongo_bson_visit_timestamp,
- php_phongo_bson_visit_int64,
- php_phongo_bson_visit_maxkey,
- php_phongo_bson_visit_minkey,
- php_phongo_bson_visit_unsupported_type,
- php_phongo_bson_visit_decimal128,
- { NULL }
-};
-
-static inline bool map_element_matches_field_path(php_phongo_field_path_map_element* map_element, php_phongo_field_path* current)
-{
- size_t i;
-
- if (map_element->entry->size != current->size) {
- return false;
- }
- for (i = 0; i < current->size; i++) {
- if (strcmp(map_element->entry->elements[i], "$") == 0) {
- continue;
- }
- if (strcmp(map_element->entry->elements[i], current->elements[i]) != 0) {
- return false;
- }
- }
- return true;
-}
-
-static php_phongo_field_path_map_element* map_find_field_path_entry(php_phongo_bson_state* state)
-{
- size_t i;
-
- /* Loop over all field path mappings, and for each, try to see whether it matches the current path */
- for (i = 0; i < state->map.field_paths.size; i++) {
- if (map_element_matches_field_path(state->map.field_paths.map[i], state->field_path)) {
- return state->map.field_paths.map[i];
- }
- }
- return NULL;
-}
-
-static void php_phongo_handle_field_path_entry_for_compound_type(php_phongo_bson_state* state, php_phongo_bson_typemap_types* type, zend_class_entry** ce)
-{
- php_phongo_field_path_map_element* entry = map_find_field_path_entry(state);
-
- if (entry) {
- switch (entry->node_type) {
- case PHONGO_TYPEMAP_NATIVE_ARRAY:
- case PHONGO_TYPEMAP_NATIVE_OBJECT:
- *type = entry->node_type;
- break;
- case PHONGO_TYPEMAP_CLASS:
- *type = entry->node_type;
- *ce = entry->node_ce;
- break;
- default:
- /* Do nothing - pacify compiler */
- break;
- }
- }
-}
-
-static bool php_phongo_bson_visit_document(const bson_iter_t* iter ARG_UNUSED, const char* key, const bson_t* v_document, void* data) /* {{{ */
-{
- zval* retval = PHONGO_BSON_STATE_ZCHILD(data);
- bson_iter_t child;
- php_phongo_bson_state* parent_state = (php_phongo_bson_state*) data;
-
- php_phongo_field_path_push(parent_state->field_path, key, PHONGO_FIELD_PATH_ITEM_DOCUMENT);
-
- if (bson_iter_init(&child, v_document)) {
- php_phongo_bson_state state;
-
- PHONGO_BSON_INIT_STATE(state);
- php_phongo_bson_state_copy_ctor(&state, parent_state);
-
- array_init(&state.zchild);
-
- if (!bson_iter_visit_all(&child, &php_bson_visitors, &state) && !child.err_off) {
- /* Check for entries in the fieldPath type map key, and use them to
- * override the default ones for this type */
- php_phongo_handle_field_path_entry_for_compound_type(&state, &state.map.document_type, &state.map.document);
-
- /* If php_phongo_bson_visit_binary() finds an ODM class, it should
- * supersede a default type map and named document class. */
- if (state.odm && state.map.document_type == PHONGO_TYPEMAP_NONE) {
- state.map.document_type = PHONGO_TYPEMAP_CLASS;
- }
-
- switch (state.map.document_type) {
- case PHONGO_TYPEMAP_NATIVE_ARRAY:
- if (((php_phongo_bson_state*) data)->is_visiting_array) {
- add_next_index_zval(retval, &state.zchild);
- } else {
- ADD_ASSOC_ZVAL(retval, key, &state.zchild);
- }
- break;
-
- case PHONGO_TYPEMAP_CLASS: {
- zval obj;
-
- object_init_ex(&obj, state.odm ? state.odm : state.map.document);
- zend_call_method_with_1_params(PHONGO_COMPAT_OBJ_P(&obj), NULL, NULL, BSON_UNSERIALIZE_FUNC_NAME, NULL, &state.zchild);
- if (((php_phongo_bson_state*) data)->is_visiting_array) {
- add_next_index_zval(retval, &obj);
- } else {
- ADD_ASSOC_ZVAL(retval, key, &obj);
- }
- zval_ptr_dtor(&state.zchild);
- break;
- }
-
- case PHONGO_TYPEMAP_NATIVE_OBJECT:
- default:
- convert_to_object(&state.zchild);
- if (((php_phongo_bson_state*) data)->is_visiting_array) {
- add_next_index_zval(retval, &state.zchild);
- } else {
- ADD_ASSOC_ZVAL(retval, key, &state.zchild);
- }
- }
- } else {
- /* Iteration stopped prematurely due to corruption or a failed
- * visitor. Free state.zchild, which we just initialized, and return
- * true to stop iteration for our parent context. */
- zval_ptr_dtor(&state.zchild);
- php_phongo_bson_state_dtor(&state);
- return true;
- }
-
- php_phongo_bson_state_dtor(&state);
- php_phongo_field_path_pop(parent_state->field_path);
- }
-
- return false;
-} /* }}} */
-
-static bool php_phongo_bson_visit_array(const bson_iter_t* iter ARG_UNUSED, const char* key, const bson_t* v_array, void* data) /* {{{ */
-{
- zval* retval = PHONGO_BSON_STATE_ZCHILD(data);
- bson_iter_t child;
- php_phongo_bson_state* parent_state = (php_phongo_bson_state*) data;
-
- php_phongo_field_path_push(parent_state->field_path, key, PHONGO_FIELD_PATH_ITEM_ARRAY);
-
- if (bson_iter_init(&child, v_array)) {
- php_phongo_bson_state state;
-
- PHONGO_BSON_INIT_STATE(state);
- php_phongo_bson_state_copy_ctor(&state, parent_state);
-
- /* Note that we are visiting an array, so element visitors know to use
- * add_next_index() (i.e. disregard BSON keys) instead of add_assoc()
- * when building the PHP array.
- */
- state.is_visiting_array = true;
-
- array_init(&state.zchild);
-
- if (!bson_iter_visit_all(&child, &php_bson_visitors, &state) && !child.err_off) {
- /* Check for entries in the fieldPath type map key, and use them to
- * override the default ones for this type */
- php_phongo_handle_field_path_entry_for_compound_type(&state, &state.map.array_type, &state.map.array);
-
- switch (state.map.array_type) {
- case PHONGO_TYPEMAP_CLASS: {
- zval obj;
-
- object_init_ex(&obj, state.map.array);
- zend_call_method_with_1_params(PHONGO_COMPAT_OBJ_P(&obj), NULL, NULL, BSON_UNSERIALIZE_FUNC_NAME, NULL, &state.zchild);
- if (((php_phongo_bson_state*) data)->is_visiting_array) {
- add_next_index_zval(retval, &obj);
- } else {
- ADD_ASSOC_ZVAL(retval, key, &obj);
- }
- zval_ptr_dtor(&state.zchild);
- break;
- }
-
- case PHONGO_TYPEMAP_NATIVE_OBJECT:
- convert_to_object(&state.zchild);
- if (((php_phongo_bson_state*) data)->is_visiting_array) {
- add_next_index_zval(retval, &state.zchild);
- } else {
- ADD_ASSOC_ZVAL(retval, key, &state.zchild);
- }
- break;
-
- case PHONGO_TYPEMAP_NATIVE_ARRAY:
- default:
- if (((php_phongo_bson_state*) data)->is_visiting_array) {
- add_next_index_zval(retval, &state.zchild);
- } else {
- ADD_ASSOC_ZVAL(retval, key, &state.zchild);
- }
- break;
- }
- } else {
- /* Iteration stopped prematurely due to corruption or a failed
- * visitor. Free state.zchild, which we just initialized, and return
- * true to stop iteration for our parent context. */
- zval_ptr_dtor(&state.zchild);
- php_phongo_bson_state_dtor(&state);
- return true;
- }
-
- php_phongo_bson_state_dtor(&state);
- php_phongo_field_path_pop(parent_state->field_path);
- }
-
- return false;
-} /* }}} */
-
-/* Converts a BSON document to a PHP value using the default typemap. */
-bool php_phongo_bson_to_zval(const unsigned char* data, int data_len, zval* zv) /* {{{ */
-{
- bool retval;
- php_phongo_bson_state state;
-
- PHONGO_BSON_INIT_STATE(state);
-
- retval = php_phongo_bson_to_zval_ex(data, data_len, &state);
- ZVAL_ZVAL(zv, &state.zchild, 1, 1);
-
- return retval;
-} /* }}} */
-
-/* Converts a BSON value to a ZVAL. */
-bool php_phongo_bson_value_to_zval(const bson_value_t* value, zval* zv) /* {{{ */
-{
- bson_t bson = BSON_INITIALIZER;
- php_phongo_bson_state state;
- zval* return_value;
- bool retval = false;
-
- PHONGO_BSON_INIT_STATE(state);
- state.map.root_type = PHONGO_TYPEMAP_NATIVE_ARRAY;
-
- bson_append_value(&bson, "data", 4, value);
- if (!php_phongo_bson_to_zval_ex(bson_get_data(&bson), bson.len, &state)) {
- /* Exception already thrown */
- goto cleanup;
- }
-
- retval = true;
-
- return_value = php_array_fetchc(&state.zchild, "data");
-
- if (return_value) {
- ZVAL_ZVAL(zv, return_value, 1, 0);
- }
-
-cleanup:
- zval_ptr_dtor(&state.zchild);
- return retval;
-} /* }}} */
-
-/* Converts a BSON document to a PHP value according to the typemap specified in
- * the state argument.
- *
- * On success, the result will be set on the state argument and true will be
- * returned. On error, an exception will have been thrown and false will be
- * returned.
- *
- * Note: the result zval in the state argument will always be initialized for
- * PHP 5.x so that the caller may always zval_ptr_dtor() it. The zval is left
- * as-is on PHP 7; however, it should have the type undefined if the state
- * was initialized to zero.
- */
-bool php_phongo_bson_to_zval_ex(const unsigned char* data, int data_len, php_phongo_bson_state* state) /* {{{ */
-{
- bson_reader_t* reader = NULL;
- bson_iter_t iter;
- const bson_t* b;
- bool eof = false;
- bool retval = false;
- bool must_dtor_state = false;
-
- if (!php_phongo_bson_state_is_initialized(state)) {
- php_phongo_bson_state_ctor(state);
- must_dtor_state = true;
- }
-
- reader = bson_reader_new_from_data(data, data_len);
-
- if (!(b = bson_reader_read(reader, NULL))) {
- phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "Could not read document from BSON reader");
-
- goto cleanup;
- }
-
- if (!bson_iter_init(&iter, b)) {
- phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "Could not initialize BSON iterator");
-
- goto cleanup;
- }
-
- /* We initialize an array because it will either be returned as-is (native
- * array in type map), passed to bsonUnserialize() (ODM class), or used to
- * initialize a stdClass object (native object in type map). */
- array_init(&state->zchild);
-
- if (bson_iter_visit_all(&iter, &php_bson_visitors, state) || iter.err_off) {
- /* Iteration stopped prematurely due to corruption or a failed visitor.
- * While we free the reader, state->zchild should be left as-is, since
- * the calling code may want to zval_ptr_dtor() it. If an exception has
- * been thrown already (due to an unsupported BSON type for example,
- * don't overwrite with a generic exception message. */
- if (!EG(exception)) {
- char* path = php_phongo_field_path_as_string(state->field_path);
- phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "Detected corrupt BSON data for field path '%s' at offset %d", path, iter.err_off);
- efree(path);
- }
-
- goto cleanup;
- }
-
- /* If php_phongo_bson_visit_binary() finds an ODM class, it should supersede
- * a default type map and named root class. */
- if (state->odm && state->map.root_type == PHONGO_TYPEMAP_NONE) {
- state->map.root_type = PHONGO_TYPEMAP_CLASS;
- }
-
- switch (state->map.root_type) {
- case PHONGO_TYPEMAP_NATIVE_ARRAY:
- /* Nothing to do here */
- break;
-
- case PHONGO_TYPEMAP_CLASS: {
- zval obj;
-
- object_init_ex(&obj, state->odm ? state->odm : state->map.root);
- zend_call_method_with_1_params(PHONGO_COMPAT_OBJ_P(&obj), NULL, NULL, BSON_UNSERIALIZE_FUNC_NAME, NULL, &state->zchild);
- zval_ptr_dtor(&state->zchild);
- ZVAL_COPY_VALUE(&state->zchild, &obj);
-
- break;
- }
-
- case PHONGO_TYPEMAP_NATIVE_OBJECT:
- default:
- convert_to_object(&state->zchild);
- }
-
- if (bson_reader_read(reader, &eof) || !eof) {
- phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "Reading document did not exhaust input buffer");
-
- goto cleanup;
- }
-
- retval = true;
-
-cleanup:
- if (reader) {
- bson_reader_destroy(reader);
- }
- if (must_dtor_state) {
- php_phongo_bson_state_dtor(state);
- }
-
- return retval;
-} /* }}} */
-
-/* Fetches a zend_class_entry for the given class name and checks that it is
- * also instantiatable and implements a specified interface. Returns the class
- * on success; otherwise, NULL is returned and an exception is thrown. */
-static zend_class_entry* php_phongo_bson_state_fetch_class(const char* classname, int classname_len, zend_class_entry* interface_ce) /* {{{ */
-{
- zend_string* zs_classname = zend_string_init(classname, classname_len, 0);
- zend_class_entry* found_ce = zend_fetch_class(zs_classname, ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_SILENT);
- zend_string_release(zs_classname);
-
- if (!found_ce) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Class %s does not exist", classname);
- } else if (!PHONGO_IS_CLASS_INSTANTIATABLE(found_ce)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Class %s is not instantiatable", classname);
- } else if (!instanceof_function(found_ce, interface_ce)) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Class %s does not implement %s", classname, ZSTR_VAL(interface_ce->name));
- } else {
- return found_ce;
- }
-
- return NULL;
-} /* }}} */
-
-/* Parses a BSON type (i.e. array, document, or root). On success, the type and
- * type_ce output arguments will be assigned and true will be returned;
- * otherwise, false is returned and an exception is thrown. */
-static bool php_phongo_bson_state_parse_type(zval* options, const char* name, php_phongo_bson_typemap_types* type, zend_class_entry** type_ce) /* {{{ */
-{
- char* classname;
- int classname_len;
- zend_bool classname_free = 0;
- bool retval = true;
-
- classname = php_array_fetch_string(options, name, &classname_len, &classname_free);
-
- if (!classname_len) {
- goto cleanup;
- }
-
- if (!strcasecmp(classname, "array")) {
- *type = PHONGO_TYPEMAP_NATIVE_ARRAY;
- *type_ce = NULL;
- } else if (!strcasecmp(classname, "stdclass") || !strcasecmp(classname, "object")) {
- *type = PHONGO_TYPEMAP_NATIVE_OBJECT;
- *type_ce = NULL;
- } else {
- if ((*type_ce = php_phongo_bson_state_fetch_class(classname, classname_len, php_phongo_unserializable_ce))) {
- *type = PHONGO_TYPEMAP_CLASS;
- } else {
- retval = false;
- }
- }
-
-cleanup:
- if (classname_free) {
- efree(classname);
- }
-
- return retval;
-} /* }}} */
-
-static void field_path_map_element_set_info(php_phongo_field_path_map_element* element, php_phongo_bson_typemap_types type, zend_class_entry* ce)
-{
- element->node_type = type;
- element->node_ce = ce;
-}
-
-static void map_add_field_path_element(php_phongo_bson_typemap* map, php_phongo_field_path_map_element* element)
-{
- /* Make sure we have allocated enough */
- if (map->field_paths.allocated_size < map->field_paths.size + 1) {
- map->field_paths.allocated_size += PHONGO_FIELD_PATH_EXPANSION;
- map->field_paths.map = erealloc(map->field_paths.map, sizeof(php_phongo_field_path_map_element) * map->field_paths.allocated_size);
- }
-
- map->field_paths.map[map->field_paths.size] = element;
- map->field_paths.size++;
-}
-
-static php_phongo_field_path_map_element* field_path_map_element_alloc(void)
-{
- php_phongo_field_path_map_element* tmp = ecalloc(1, sizeof(php_phongo_field_path_map_element));
-
- tmp->entry = php_phongo_field_path_alloc(true);
-
- return tmp;
-}
-
-static void field_path_map_element_dtor(php_phongo_field_path_map_element* element)
-{
- php_phongo_field_path_free(element->entry);
- efree(element);
-}
-
-bool php_phongo_bson_state_add_field_path(php_phongo_bson_typemap* map, char* field_path_original, php_phongo_bson_typemap_types type, zend_class_entry* ce)
-{
- char* ptr = NULL;
- char* segment_end = NULL;
- php_phongo_field_path_map_element* field_path_map_element;
-
- if (field_path_original[0] == '.') {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "A 'fieldPaths' key may not start with a '.'");
- return false;
- }
-
- if (field_path_original[strlen(field_path_original) - 1] == '.') {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "A 'fieldPaths' key may not end with a '.'");
- return false;
- }
-
- field_path_map_element = field_path_map_element_alloc();
- ptr = field_path_original;
-
- /* Loop over all the segments. A segment is delimited by a "." */
- while ((segment_end = strchr(ptr, '.')) != NULL) {
- char* tmp = NULL;
-
- /* Bail out if we have an empty segment */
- if (ptr == segment_end) {
- field_path_map_element_dtor(field_path_map_element);
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "A 'fieldPaths' key may not have an empty segment");
- return false;
- }
-
- tmp = calloc(1, segment_end - ptr + 1);
- memcpy(tmp, ptr, segment_end - ptr);
- php_phongo_field_path_push(field_path_map_element->entry, tmp, PHONGO_FIELD_PATH_ITEM_NONE);
- free(tmp);
-
- ptr = segment_end + 1;
- }
-
- /* Add the last (or single) element */
- php_phongo_field_path_push(field_path_map_element->entry, ptr, PHONGO_FIELD_PATH_ITEM_NONE);
-
- field_path_map_element_set_info(field_path_map_element, type, ce);
- map_add_field_path_element(map, field_path_map_element);
-
- return true;
-}
-
-void php_phongo_bson_typemap_dtor(php_phongo_bson_typemap* map)
-{
- size_t i;
-
- if (map->field_paths.map) {
- for (i = 0; i < map->field_paths.size; i++) {
- field_path_map_element_dtor(map->field_paths.map[i]);
- }
- efree(map->field_paths.map);
- }
-
- map->field_paths.map = NULL;
-}
-
-/* Loops over each element in the fieldPaths array (if exists, and is an
- * array), and then checks whether each element is a valid type mapping */
-bool php_phongo_bson_state_parse_fieldpaths(zval* typemap, php_phongo_bson_typemap* map) /* {{{ */
-{
- zval* fieldpaths = NULL;
- HashTable* ht_data;
-
- if (!php_array_existsc(typemap, "fieldPaths")) {
- return true;
- }
-
- fieldpaths = php_array_fetchc_array(typemap, "fieldPaths");
-
- if (!fieldpaths) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "The 'fieldPaths' element is not an array");
- return false;
- }
-
- ht_data = HASH_OF(fieldpaths);
-
- {
- zend_string* string_key = NULL;
- zend_ulong num_key = 0;
- zval* property;
-
- ZEND_HASH_FOREACH_KEY_VAL(ht_data, num_key, string_key, property)
- {
- zend_class_entry* map_ce = NULL;
- php_phongo_bson_typemap_types map_type;
-
- if (!string_key) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "The 'fieldPaths' element is not an associative array");
- return false;
- }
-
- if (strcmp(ZSTR_VAL(string_key), "") == 0) {
- phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "The 'fieldPaths' element may not be an empty string");
- return false;
- }
-
- if (!php_phongo_bson_state_parse_type(fieldpaths, ZSTR_VAL(string_key), &map_type, &map_ce)) {
- return false;
- }
-
- if (!php_phongo_bson_state_add_field_path(map, ZSTR_VAL(string_key), map_type, map_ce)) {
- return false;
- }
- }
- ZEND_HASH_FOREACH_END();
- }
-
- return true;
-} /* }}} */
-
-#if DEBUG
-static void print_node_info(php_phongo_field_path_node* ptr, int level)
-{
- printf("%*sNAME: %s\n", level * 4, "", ptr->name);
- printf("%*s- type:", level * 4, "");
- switch (ptr->node_type) {
- case PHONGO_TYPEMAP_NONE:
- printf(" none (unset)\n");
- break;
- case PHONGO_TYPEMAP_CLASS:
- printf(" class (%s)\n", ZSTR_VAL(ptr->node_ce->name));
- break;
- case PHONGO_TYPEMAP_NATIVE_ARRAY:
- printf(" array\n");
- break;
- case PHONGO_TYPEMAP_NATIVE_OBJECT:
- printf(" stdClass\n");
- break;
- }
-}
-
-static void print_map_list(php_phongo_field_path_node* node, int level)
-{
- php_phongo_field_path_node* ptr = node->children;
-
- if (!ptr) {
- return;
- }
-
- do {
- print_node_info(ptr, level);
- if (ptr->children) {
- printf("%*s- children:\n", level * 4, "");
- print_map_list(ptr, level + 1);
- }
- ptr = ptr->next;
- } while (ptr);
-}
-#endif
-
-/* Applies the array argument to a typemap struct. Returns true on success;
- * otherwise, false is returned an an exception is thrown. */
-bool php_phongo_bson_typemap_to_state(zval* typemap, php_phongo_bson_typemap* map) /* {{{ */
-{
- if (!typemap) {
- return true;
- }
-
- if (!php_phongo_bson_state_parse_type(typemap, "array", &map->array_type, &map->array) ||
- !php_phongo_bson_state_parse_type(typemap, "document", &map->document_type, &map->document) ||
- !php_phongo_bson_state_parse_type(typemap, "root", &map->root_type, &map->root) ||
- !php_phongo_bson_state_parse_fieldpaths(typemap, map)) {
-
- /* Exception should already have been thrown */
- return false;
- }
-#if DEBUG
- print_map_list(&map->field_path_map, 0);
-#endif
- return true;
-} /* }}} */
-
-void php_phongo_bson_new_timestamp_from_increment_and_timestamp(zval* object, uint32_t increment, uint32_t timestamp) /* {{{ */
-{
- php_phongo_timestamp_t* intern;
-
- object_init_ex(object, php_phongo_timestamp_ce);
-
- intern = Z_TIMESTAMP_OBJ_P(object);
- intern->increment = increment;
- intern->timestamp = timestamp;
- intern->initialized = true;
-} /* }}} */
-
-void php_phongo_bson_new_int64(zval* object, int64_t integer) /* {{{ */
-{
- php_phongo_int64_t* intern;
-
- object_init_ex(object, php_phongo_int64_ce);
-
- intern = Z_INT64_OBJ_P(object);
- intern->integer = integer;
- intern->initialized = true;
-} /* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/libmongoc/src/common/common-thread-private.h b/mongodb-1.12.0/src/libmongoc/src/common/common-thread-private.h
deleted file mode 100644
index 8d560f28..00000000
--- a/mongodb-1.12.0/src/libmongoc/src/common/common-thread-private.h
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Copyright 2013-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "common-prelude.h"
-#include "common-config.h"
-#include "common-macros-private.h"
-
-#ifndef COMMON_THREAD_PRIVATE_H
-#define COMMON_THREAD_PRIVATE_H
-
-#define BSON_INSIDE
-#include "bson/bson-compat.h"
-#include "bson/bson-config.h"
-#include "bson/bson-macros.h"
-#undef BSON_INSIDE
-
-BSON_BEGIN_DECLS
-
-#if defined(BSON_OS_UNIX)
-#include <pthread.h>
-
-#define BSON_ONCE_FUN(n) void n (void)
-#define BSON_ONCE_RETURN return
-#define BSON_ONCE_INIT PTHREAD_ONCE_INIT
-#define bson_once pthread_once
-#define bson_once_t pthread_once_t
-#define bson_thread_t pthread_t
-#define BSON_THREAD_FUN(_function_name, _arg_name) \
- void *(_function_name) (void *(_arg_name))
-#define BSON_THREAD_FUN_TYPE(_function_name) void *(*(_function_name)) (void *)
-#define BSON_THREAD_RETURN return NULL
-
-/* this macro can be defined as a as a build configuration option
- * with -DENABLE_DEBUG_ASSERTIONS=ON. its purpose is to allow for functions
- * that require a mutex to be locked on entry to assert that the mutex
- * is actually locked.
- * this can prevent bugs where a caller forgets to lock the mutex. */
-
-#ifndef MONGOC_ENABLE_DEBUG_ASSERTIONS
-
-#define bson_mutex_destroy pthread_mutex_destroy
-#define bson_mutex_init(_n) pthread_mutex_init ((_n), NULL)
-#define bson_mutex_lock pthread_mutex_lock
-#define bson_mutex_t pthread_mutex_t
-#define bson_mutex_unlock pthread_mutex_unlock
-
-#else
-typedef struct {
- pthread_t lock_owner;
- pthread_mutex_t wrapped_mutex;
- bool valid_tid;
-} bson_mutex_t;
-
-#define bson_mutex_destroy(mutex) \
- do { \
- pthread_mutex_destroy (&(mutex)->wrapped_mutex); \
- } while (0);
-
-#define bson_mutex_init(mutex) \
- do { \
- pthread_mutex_init (&(mutex)->wrapped_mutex, NULL); \
- (mutex)->valid_tid = false; \
- } while (0);
-
-#define bson_mutex_lock(mutex) \
- do { \
- pthread_mutex_lock (&(mutex)->wrapped_mutex); \
- (mutex)->lock_owner = pthread_self (); \
- (mutex)->valid_tid = true; \
- } while (0);
-
-#define bson_mutex_unlock(mutex) \
- do { \
- (mutex)->valid_tid = false; \
- pthread_mutex_unlock (&(mutex)->wrapped_mutex); \
- } while (0);
-
-#endif
-
-#else
-#include <process.h>
-#define BSON_ONCE_FUN(n) \
- BOOL CALLBACK n (PINIT_ONCE _ignored_a, PVOID _ignored_b, PVOID *_ignored_c)
-#define BSON_ONCE_INIT INIT_ONCE_STATIC_INIT
-#define BSON_ONCE_RETURN return true
-#define bson_mutex_destroy DeleteCriticalSection
-#define bson_mutex_init InitializeCriticalSection
-#define bson_mutex_lock EnterCriticalSection
-#define bson_mutex_t CRITICAL_SECTION
-#define bson_mutex_unlock LeaveCriticalSection
-#define bson_once(o, c) InitOnceExecuteOnce (o, c, NULL, NULL)
-#define bson_once_t INIT_ONCE
-#define bson_thread_t HANDLE
-#define BSON_THREAD_FUN(_function_name, _arg_name) \
- unsigned (__stdcall _function_name) (void *(_arg_name))
-#define BSON_THREAD_FUN_TYPE(_function_name) \
- unsigned (__stdcall * _function_name) (void *)
-#define BSON_THREAD_RETURN return 0
-#endif
-
-/* Functions that require definitions get the common prefix (_mongoc for
- * libmongoc or _bson for libbson) to avoid duplicate symbols when linking both
- * libbson and libmongoc statically. */
-int COMMON_PREFIX (thread_join) (bson_thread_t thread);
-int COMMON_PREFIX (thread_create) (bson_thread_t *thread,
- BSON_THREAD_FUN_TYPE (func),
- void *arg);
-
-#if defined(MONGOC_ENABLE_DEBUG_ASSERTIONS) && defined(BSON_OS_UNIX)
-bool COMMON_PREFIX (mutex_is_locked) (bson_mutex_t *mutex);
-#endif
-
-/**
- * @brief A shared mutex (a read-write lock)
- *
- * A shared mutex can be locked in 'shared' mode or 'exclusive' mode. Only one
- * thread may hold exclusive mode at a time. Any number of threads may hold
- * the lock in shared mode simultaneously. No thread can hold in exclusive mode
- * while another thread holds in shared mode, and vice-versa.
- */
-typedef struct bson_shared_mutex_t {
- BSON_IF_WINDOWS (SRWLOCK native;)
- BSON_IF_POSIX (pthread_rwlock_t native;)
-} bson_shared_mutex_t;
-
-static BSON_INLINE void
-bson_shared_mutex_init (bson_shared_mutex_t *mtx)
-{
- BSON_IF_WINDOWS (InitializeSRWLock (&mtx->native));
- BSON_IF_POSIX (pthread_rwlock_init (&mtx->native, NULL));
-}
-
-static BSON_INLINE void
-bson_shared_mutex_destroy (bson_shared_mutex_t *mtx)
-{
- BSON_IF_WINDOWS ((void) mtx;)
- BSON_IF_POSIX (pthread_rwlock_destroy (&mtx->native);)
-}
-
-static BSON_INLINE void
-bson_shared_mutex_lock_shared (bson_shared_mutex_t *mtx)
-{
- BSON_IF_WINDOWS (AcquireSRWLockShared (&mtx->native);)
- BSON_IF_POSIX (pthread_rwlock_rdlock (&mtx->native);)
-}
-
-static BSON_INLINE void
-bson_shared_mutex_lock (bson_shared_mutex_t *mtx)
-{
- BSON_IF_WINDOWS (AcquireSRWLockExclusive (&mtx->native);)
- BSON_IF_POSIX (pthread_rwlock_wrlock (&mtx->native);)
-}
-
-static BSON_INLINE void
-bson_shared_mutex_unlock (bson_shared_mutex_t *mtx)
-{
- BSON_IF_WINDOWS (ReleaseSRWLockExclusive (&mtx->native);)
- BSON_IF_POSIX (pthread_rwlock_unlock (&mtx->native);)
-}
-
-static BSON_INLINE void
-bson_shared_mutex_unlock_shared (bson_shared_mutex_t *mtx)
-{
- BSON_IF_WINDOWS (ReleaseSRWLockShared (&mtx->native);)
- BSON_IF_POSIX (pthread_rwlock_unlock (&mtx->native);)
-}
-
-BSON_END_DECLS
-
-#endif /* COMMON_THREAD_PRIVATE_H */
diff --git a/mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_port.c b/mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_port.c
deleted file mode 100644
index 58f7e39e..00000000
--- a/mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_port.c
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2020-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "kms_port.h"
-#if defined(_WIN32)
-char * kms_strndup (const char *src, size_t len)
-{
- char *dst = (char *) malloc (len + 1);
- if (!dst) {
- return 0;
- }
-
- memcpy (dst, src, len);
- dst[len] = '\0';
-
- return dst;
-}
-#endif
\ No newline at end of file
diff --git a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-atomic.c b/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-atomic.c
deleted file mode 100644
index b89aaf16..00000000
--- a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-atomic.c
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- * Copyright 2014 MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-#include "bson-atomic.h"
-
-#ifdef BSON_OS_UNIX
-/* For sched_yield() */
-#include <sched.h>
-#endif
-
-int32_t
-bson_atomic_int_add (volatile int32_t *p, int32_t n)
-{
- return n + bson_atomic_int32_fetch_add (p, n, bson_memory_order_seq_cst);
-}
-
-int64_t
-bson_atomic_int64_add (volatile int64_t *p, int64_t n)
-{
- return n + bson_atomic_int64_fetch_add (p, n, bson_memory_order_seq_cst);
-}
-
-void
-bson_thrd_yield (void)
-{
- BSON_IF_WINDOWS (SwitchToThread ();)
- BSON_IF_POSIX (sched_yield ();)
-}
-
-void
-bson_memory_barrier (void)
-{
- bson_atomic_thread_fence ();
-}
-
-/**
- * Some platforms do not support compiler intrinsics for atomic operations.
- * We emulate that here using a spin lock and regular arithmetic operations
- */
-static int8_t gEmulAtomicLock = 0;
-
-static void
-_lock_emul_atomic ()
-{
- int i;
- if (bson_atomic_int8_compare_exchange_weak (
- &gEmulAtomicLock, 0, 1, bson_memory_order_acquire) == 0) {
- /* Successfully took the spinlock */
- return;
- }
- /* Failed. Try taking ten more times, then begin sleeping. */
- for (i = 0; i < 10; ++i) {
- if (bson_atomic_int8_compare_exchange_weak (
- &gEmulAtomicLock, 0, 1, bson_memory_order_acquire) == 0) {
- /* Succeeded in taking the lock */
- return;
- }
- }
- /* Still don't have the lock. Spin and yield */
- while (bson_atomic_int8_compare_exchange_weak (
- &gEmulAtomicLock, 0, 1, bson_memory_order_acquire) != 0) {
- bson_thrd_yield ();
- }
-}
-
-static void
-_unlock_emul_atomic ()
-{
- int64_t rv = bson_atomic_int8_exchange (
- &gEmulAtomicLock, 0, bson_memory_order_release);
- BSON_ASSERT (rv == 1 && "Released atomic lock while not holding it");
-}
-
-int64_t
-_bson_emul_atomic_int64_fetch_add (volatile int64_t *p,
- int64_t n,
- enum bson_memory_order _unused)
-{
- int64_t ret;
- _lock_emul_atomic ();
- ret = *p;
- *p += n;
- _unlock_emul_atomic ();
- return ret;
-}
-
-int64_t
-_bson_emul_atomic_int64_exchange (volatile int64_t *p,
- int64_t n,
- enum bson_memory_order _unused)
-{
- int64_t ret;
- _lock_emul_atomic ();
- ret = *p;
- *p = n;
- _unlock_emul_atomic ();
- return ret;
-}
-
-int64_t
-_bson_emul_atomic_int64_compare_exchange_strong (volatile int64_t *p,
- int64_t expect_value,
- int64_t new_value,
- enum bson_memory_order _unused)
-{
- int64_t ret;
- _lock_emul_atomic ();
- ret = *p;
- if (ret == expect_value) {
- *p = new_value;
- }
- _unlock_emul_atomic ();
- return ret;
-}
-
-int64_t
-_bson_emul_atomic_int64_compare_exchange_weak (volatile int64_t *p,
- int64_t expect_value,
- int64_t new_value,
- enum bson_memory_order order)
-{
- /* We're emulating. We can't do a weak version. */
- return _bson_emul_atomic_int64_compare_exchange_strong (
- p, expect_value, new_value, order);
-}
-
-
-int32_t
-_bson_emul_atomic_int32_fetch_add (volatile int32_t *p,
- int32_t n,
- enum bson_memory_order _unused)
-{
- int32_t ret;
- _lock_emul_atomic ();
- ret = *p;
- *p += n;
- _unlock_emul_atomic ();
- return ret;
-}
-
-int32_t
-_bson_emul_atomic_int32_exchange (volatile int32_t *p,
- int32_t n,
- enum bson_memory_order _unused)
-{
- int32_t ret;
- _lock_emul_atomic ();
- ret = *p;
- *p = n;
- _unlock_emul_atomic ();
- return ret;
-}
-
-int32_t
-_bson_emul_atomic_int32_compare_exchange_strong (volatile int32_t *p,
- int32_t expect_value,
- int32_t new_value,
- enum bson_memory_order _unused)
-{
- int32_t ret;
- _lock_emul_atomic ();
- ret = *p;
- if (ret == expect_value) {
- *p = new_value;
- }
- _unlock_emul_atomic ();
- return ret;
-}
-
-int32_t
-_bson_emul_atomic_int32_compare_exchange_weak (volatile int32_t *p,
- int32_t expect_value,
- int32_t new_value,
- enum bson_memory_order order)
-{
- /* We're emulating. We can't do a weak version. */
- return _bson_emul_atomic_int32_compare_exchange_strong (
- p, expect_value, new_value, order);
-}
-
-
-int
-_bson_emul_atomic_int_fetch_add (volatile int *p,
- int n,
- enum bson_memory_order _unused)
-{
- int ret;
- _lock_emul_atomic ();
- ret = *p;
- *p += n;
- _unlock_emul_atomic ();
- return ret;
-}
-
-int
-_bson_emul_atomic_int_exchange (volatile int *p,
- int n,
- enum bson_memory_order _unused)
-{
- int ret;
- _lock_emul_atomic ();
- ret = *p;
- *p = n;
- _unlock_emul_atomic ();
- return ret;
-}
-
-int
-_bson_emul_atomic_int_compare_exchange_strong (volatile int *p,
- int expect_value,
- int new_value,
- enum bson_memory_order _unused)
-{
- int ret;
- _lock_emul_atomic ();
- ret = *p;
- if (ret == expect_value) {
- *p = new_value;
- }
- _unlock_emul_atomic ();
- return ret;
-}
-
-int
-_bson_emul_atomic_int_compare_exchange_weak (volatile int *p,
- int expect_value,
- int new_value,
- enum bson_memory_order order)
-{
- /* We're emulating. We can't do a weak version. */
- return _bson_emul_atomic_int_compare_exchange_strong (
- p, expect_value, new_value, order);
-}
diff --git a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-atomic.h b/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-atomic.h
deleted file mode 100644
index 190283b3..00000000
--- a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-atomic.h
+++ /dev/null
@@ -1,754 +0,0 @@
-/*
- * Copyright 2013-2014 MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "bson-prelude.h"
-
-
-#ifndef BSON_ATOMIC_H
-#define BSON_ATOMIC_H
-
-
-#include "bson-config.h"
-#include "bson-compat.h"
-#include "bson-macros.h"
-
-#ifdef _MSC_VER
-#include <intrin.h>
-#endif
-
-
-BSON_BEGIN_DECLS
-
-enum bson_memory_order {
- bson_memory_order_seq_cst,
- bson_memory_order_acquire,
- bson_memory_order_release,
- bson_memory_order_relaxed,
- bson_memory_order_acq_rel,
- bson_memory_order_consume,
-};
-
-#if defined(_M_ARM) /* MSVC memorder atomics are only avail on ARM */
-#define MSVC_MEMORDER_SUFFIX(X) X
-#else
-#define MSVC_MEMORDER_SUFFIX(X)
-#endif
-
-#if defined(USE_LEGACY_GCC_ATOMICS) || \
- (!defined(__clang__) && __GNUC__ == 4)
-#define BSON_USE_LEGACY_GCC_ATOMICS
-#else
-#undef BSON_USE_LEGACY_GCC_ATOMICS
-#endif
-
-/* Not all GCC-like compilers support the current __atomic built-ins. Older
- * GCC (pre-5) used different built-ins named with the __sync prefix. When
- * compiling with such older GCC versions, it is necessary to use the applicable
- * functions, which requires redefining BSON_IF_GNU_LIKE and defining the
- * additional BSON_IF_GNU_LEGACY_ATOMICS macro here. */
-#ifdef BSON_USE_LEGACY_GCC_ATOMICS
-#undef BSON_IF_GNU_LIKE
-#define BSON_IF_GNU_LIKE(...)
-#define BSON_IF_GNU_LEGACY_ATOMICS(...) __VA_ARGS__
-#else
-#define BSON_IF_GNU_LEGACY_ATOMICS(...)
-#endif
-
-/* CDRIVER-4229 zSeries with gcc 4.8.4 produces illegal instructions for int and
- * int32 atomic intrinsics. */
-#if defined(__s390__) || defined(__s390x__) || defined(__zarch__)
-#define BSON_EMULATE_INT32
-#define BSON_EMULATE_INT
-#endif
-
-#define DEF_ATOMIC_OP(MSVC_Intrinsic, GNU_Intrinsic, GNU_Legacy_Intrinsic, Order, ...) \
- do { \
- switch (Order) { \
- case bson_memory_order_acq_rel: \
- BSON_IF_MSVC (return MSVC_Intrinsic (__VA_ARGS__);) \
- BSON_IF_GNU_LIKE ( \
- return GNU_Intrinsic (__VA_ARGS__, __ATOMIC_ACQ_REL);) \
- BSON_IF_GNU_LEGACY_ATOMICS ( \
- return GNU_Legacy_Intrinsic (__VA_ARGS__);) \
- case bson_memory_order_seq_cst: \
- BSON_IF_MSVC (return MSVC_Intrinsic (__VA_ARGS__);) \
- BSON_IF_GNU_LIKE ( \
- return GNU_Intrinsic (__VA_ARGS__, __ATOMIC_SEQ_CST);) \
- BSON_IF_GNU_LEGACY_ATOMICS ( \
- return GNU_Legacy_Intrinsic (__VA_ARGS__);) \
- case bson_memory_order_acquire: \
- BSON_IF_MSVC ( \
- return BSON_CONCAT (MSVC_Intrinsic, \
- MSVC_MEMORDER_SUFFIX (_acq)) (__VA_ARGS__);) \
- BSON_IF_GNU_LIKE ( \
- return GNU_Intrinsic (__VA_ARGS__, __ATOMIC_ACQUIRE);) \
- BSON_IF_GNU_LEGACY_ATOMICS ( \
- return GNU_Legacy_Intrinsic (__VA_ARGS__);) \
- case bson_memory_order_consume: \
- BSON_IF_MSVC ( \
- return BSON_CONCAT (MSVC_Intrinsic, \
- MSVC_MEMORDER_SUFFIX (_acq)) (__VA_ARGS__);) \
- BSON_IF_GNU_LIKE ( \
- return GNU_Intrinsic (__VA_ARGS__, __ATOMIC_CONSUME);) \
- BSON_IF_GNU_LEGACY_ATOMICS ( \
- return GNU_Legacy_Intrinsic (__VA_ARGS__);) \
- case bson_memory_order_release: \
- BSON_IF_MSVC ( \
- return BSON_CONCAT (MSVC_Intrinsic, \
- MSVC_MEMORDER_SUFFIX (_rel)) (__VA_ARGS__);) \
- BSON_IF_GNU_LIKE ( \
- return GNU_Intrinsic (__VA_ARGS__, __ATOMIC_RELEASE);) \
- BSON_IF_GNU_LEGACY_ATOMICS ( \
- return GNU_Legacy_Intrinsic (__VA_ARGS__);) \
- case bson_memory_order_relaxed: \
- BSON_IF_MSVC ( \
- return BSON_CONCAT (MSVC_Intrinsic, \
- MSVC_MEMORDER_SUFFIX (_nf)) (__VA_ARGS__);) \
- BSON_IF_GNU_LIKE ( \
- return GNU_Intrinsic (__VA_ARGS__, __ATOMIC_RELAXED);) \
- BSON_IF_GNU_LEGACY_ATOMICS ( \
- return GNU_Legacy_Intrinsic (__VA_ARGS__);) \
- default: \
- BSON_UNREACHABLE ("Invalid bson_memory_order value"); \
- } \
- } while (0)
-
-
-#define DEF_ATOMIC_CMPEXCH_STRONG( \
- VCSuffix1, VCSuffix2, GNU_MemOrder, Ptr, ExpectActualVar, NewValue) \
- do { \
- BSON_IF_MSVC (ExpectActualVar = BSON_CONCAT3 ( \
- _InterlockedCompareExchange, VCSuffix1, VCSuffix2) ( \
- Ptr, NewValue, ExpectActualVar);) \
- BSON_IF_GNU_LIKE ( \
- (void) __atomic_compare_exchange_n (Ptr, \
- &ExpectActualVar, \
- NewValue, \
- false, /* Not weak */ \
- GNU_MemOrder, \
- GNU_MemOrder);) \
- BSON_IF_GNU_LEGACY_ATOMICS ( \
- __typeof__ (ExpectActualVar) _val; \
- _val = __sync_val_compare_and_swap (Ptr, \
- ExpectActualVar, \
- NewValue); \
- ExpectActualVar = _val;) \
- } while (0)
-
-
-#define DEF_ATOMIC_CMPEXCH_WEAK( \
- VCSuffix1, VCSuffix2, GNU_MemOrder, Ptr, ExpectActualVar, NewValue) \
- do { \
- BSON_IF_MSVC (ExpectActualVar = BSON_CONCAT3 ( \
- _InterlockedCompareExchange, VCSuffix1, VCSuffix2) ( \
- Ptr, NewValue, ExpectActualVar);) \
- BSON_IF_GNU_LIKE ( \
- (void) __atomic_compare_exchange_n (Ptr, \
- &ExpectActualVar, \
- NewValue, \
- true, /* Yes weak */ \
- GNU_MemOrder, \
- GNU_MemOrder);) \
- BSON_IF_GNU_LEGACY_ATOMICS ( \
- __typeof__ (ExpectActualVar) _val; \
- _val = __sync_val_compare_and_swap (Ptr, \
- ExpectActualVar, \
- NewValue); \
- ExpectActualVar = _val;) \
- } while (0)
-
-
-#define DECL_ATOMIC_INTEGRAL(NamePart, Type, VCIntrinSuffix) \
- static BSON_INLINE Type bson_atomic_##NamePart##_fetch_add ( \
- Type volatile *a, Type addend, enum bson_memory_order ord) \
- { \
- DEF_ATOMIC_OP (BSON_CONCAT (_InterlockedExchangeAdd, VCIntrinSuffix), \
- __atomic_fetch_add, \
- __sync_fetch_and_add, \
- ord, \
- a, \
- addend); \
- } \
- \
- static BSON_INLINE Type bson_atomic_##NamePart##_fetch_sub ( \
- Type volatile *a, Type subtrahend, enum bson_memory_order ord) \
- { \
- /* MSVC doesn't have a subtract intrinsic, so just reuse addition */ \
- BSON_IF_MSVC ( \
- return bson_atomic_##NamePart##_fetch_add (a, -subtrahend, ord);) \
- BSON_IF_GNU_LIKE ( \
- DEF_ATOMIC_OP (~, __atomic_fetch_sub, ~, ord, a, subtrahend);) \
- BSON_IF_GNU_LEGACY_ATOMICS ( \
- DEF_ATOMIC_OP (~, ~, __sync_fetch_and_sub, ord, a, subtrahend);) \
- } \
- \
- static BSON_INLINE Type bson_atomic_##NamePart##_fetch ( \
- Type volatile const *a, enum bson_memory_order order) \
- { \
- /* MSVC doesn't have a load intrinsic, so just add zero */ \
- BSON_IF_MSVC (return bson_atomic_##NamePart##_fetch_add ( \
- (Type volatile *) a, 0, order);) \
- /* GNU doesn't want RELEASE order for the fetch operation, so we can't \
- * just use DEF_ATOMIC_OP. */ \
- BSON_IF_GNU_LIKE (switch (order) { \
- case bson_memory_order_release: /* Fall back to seqcst */ \
- case bson_memory_order_acq_rel: /* Fall back to seqcst */ \
- case bson_memory_order_seq_cst: \
- return __atomic_load_n (a, __ATOMIC_SEQ_CST); \
- case bson_memory_order_acquire: \
- return __atomic_load_n (a, __ATOMIC_ACQUIRE); \
- case bson_memory_order_consume: \
- return __atomic_load_n (a, __ATOMIC_CONSUME); \
- case bson_memory_order_relaxed: \
- return __atomic_load_n (a, __ATOMIC_RELAXED); \
- default: \
- BSON_UNREACHABLE ("Invalid bson_memory_order value"); \
- }) \
- BSON_IF_GNU_LEGACY_ATOMICS ({ __sync_synchronize (); return *a; }) \
- } \
- \
- static BSON_INLINE Type bson_atomic_##NamePart##_exchange ( \
- Type volatile *a, Type value, enum bson_memory_order ord) \
- { \
- BSON_IF_MSVC ( \
- DEF_ATOMIC_OP (BSON_CONCAT (_InterlockedExchange, VCIntrinSuffix), \
- ~, \
- ~, \
- ord, \
- a, \
- value);) \
- /* GNU doesn't want CONSUME order for the exchange operation, so we \
- * cannot use DEF_ATOMIC_OP. */ \
- BSON_IF_GNU_LIKE (switch (ord) { \
- case bson_memory_order_acq_rel: \
- return __atomic_exchange_n (a, value, __ATOMIC_ACQ_REL); \
- case bson_memory_order_release: \
- return __atomic_exchange_n (a, value, __ATOMIC_RELEASE); \
- case bson_memory_order_seq_cst: \
- return __atomic_exchange_n (a, value, __ATOMIC_SEQ_CST); \
- case bson_memory_order_consume: /* Fall back to acquire */ \
- case bson_memory_order_acquire: \
- return __atomic_exchange_n (a, value, __ATOMIC_ACQUIRE); \
- case bson_memory_order_relaxed: \
- return __atomic_exchange_n (a, value, __ATOMIC_RELAXED); \
- default: \
- BSON_UNREACHABLE ("Invalid bson_memory_order value"); \
- }) \
- BSON_IF_GNU_LEGACY_ATOMICS ( \
- return __sync_val_compare_and_swap (a, *a, value);) \
- } \
- \
- static BSON_INLINE Type bson_atomic_##NamePart##_compare_exchange_strong ( \
- Type volatile *a, \
- Type expect, \
- Type new_value, \
- enum bson_memory_order ord) \
- { \
- Type actual = expect; \
- switch (ord) { \
- case bson_memory_order_release: \
- case bson_memory_order_acq_rel: \
- case bson_memory_order_seq_cst: \
- DEF_ATOMIC_CMPEXCH_STRONG ( \
- VCIntrinSuffix, , __ATOMIC_SEQ_CST, a, actual, new_value); \
- break; \
- case bson_memory_order_acquire: \
- DEF_ATOMIC_CMPEXCH_STRONG (VCIntrinSuffix, \
- MSVC_MEMORDER_SUFFIX (_acq), \
- __ATOMIC_ACQUIRE, \
- a, \
- actual, \
- new_value); \
- break; \
- case bson_memory_order_consume: \
- DEF_ATOMIC_CMPEXCH_STRONG (VCIntrinSuffix, \
- MSVC_MEMORDER_SUFFIX (_acq), \
- __ATOMIC_CONSUME, \
- a, \
- actual, \
- new_value); \
- break; \
- case bson_memory_order_relaxed: \
- DEF_ATOMIC_CMPEXCH_STRONG (VCIntrinSuffix, \
- MSVC_MEMORDER_SUFFIX (_nf), \
- __ATOMIC_RELAXED, \
- a, \
- actual, \
- new_value); \
- break; \
- default: \
- BSON_UNREACHABLE ("Invalid bson_memory_order value"); \
- } \
- return actual; \
- } \
- \
- static BSON_INLINE Type bson_atomic_##NamePart##_compare_exchange_weak ( \
- Type volatile *a, \
- Type expect, \
- Type new_value, \
- enum bson_memory_order ord) \
- { \
- Type actual = expect; \
- switch (ord) { \
- case bson_memory_order_release: \
- case bson_memory_order_acq_rel: \
- case bson_memory_order_seq_cst: \
- DEF_ATOMIC_CMPEXCH_WEAK ( \
- VCIntrinSuffix, , __ATOMIC_SEQ_CST, a, actual, new_value); \
- break; \
- case bson_memory_order_acquire: \
- DEF_ATOMIC_CMPEXCH_WEAK (VCIntrinSuffix, \
- MSVC_MEMORDER_SUFFIX (_acq), \
- __ATOMIC_ACQUIRE, \
- a, \
- actual, \
- new_value); \
- break; \
- case bson_memory_order_consume: \
- DEF_ATOMIC_CMPEXCH_WEAK (VCIntrinSuffix, \
- MSVC_MEMORDER_SUFFIX (_acq), \
- __ATOMIC_CONSUME, \
- a, \
- actual, \
- new_value); \
- break; \
- case bson_memory_order_relaxed: \
- DEF_ATOMIC_CMPEXCH_WEAK (VCIntrinSuffix, \
- MSVC_MEMORDER_SUFFIX (_nf), \
- __ATOMIC_RELAXED, \
- a, \
- actual, \
- new_value); \
- break; \
- default: \
- BSON_UNREACHABLE ("Invalid bson_memory_order value"); \
- } \
- return actual; \
- }
-
-#define DECL_ATOMIC_STDINT(Name, VCSuffix) \
- DECL_ATOMIC_INTEGRAL (Name, Name##_t, VCSuffix)
-
-#if defined(_MSC_VER) || defined (BSON_USE_LEGACY_GCC_ATOMICS)
-/* MSVC expects precise types for their atomic intrinsics. */
-DECL_ATOMIC_INTEGRAL (int8, char, 8);
-DECL_ATOMIC_INTEGRAL (int16, short, 16)
-#if !defined (BSON_EMULATE_INT32)
-DECL_ATOMIC_INTEGRAL (int32, long, )
-#endif
-#if !defined (BSON_EMULATE_INT)
-DECL_ATOMIC_INTEGRAL (int, long, )
-#endif
-#else
-/* Other compilers that we support provide generic intrinsics */
-DECL_ATOMIC_STDINT (int8, 8)
-DECL_ATOMIC_STDINT (int16, 16)
-#if !defined (BSON_EMULATE_INT32)
-DECL_ATOMIC_STDINT (int32, )
-#endif
-#if !defined (BSON_EMULATE_INT)
-DECL_ATOMIC_INTEGRAL (int, int, )
-#endif
-#endif
-
-BSON_EXPORT (int64_t)
-_bson_emul_atomic_int64_fetch_add (int64_t volatile *val,
- int64_t v,
- enum bson_memory_order);
-BSON_EXPORT (int64_t)
-_bson_emul_atomic_int64_exchange (int64_t volatile *val,
- int64_t v,
- enum bson_memory_order);
-BSON_EXPORT (int64_t)
-_bson_emul_atomic_int64_compare_exchange_strong (int64_t volatile *val,
- int64_t expect_value,
- int64_t new_value,
- enum bson_memory_order);
-
-BSON_EXPORT (int64_t)
-_bson_emul_atomic_int64_compare_exchange_weak (int64_t volatile *val,
- int64_t expect_value,
- int64_t new_value,
- enum bson_memory_order);
-
-BSON_EXPORT (int32_t)
-_bson_emul_atomic_int32_fetch_add (int32_t volatile *val,
- int32_t v,
- enum bson_memory_order);
-BSON_EXPORT (int32_t)
-_bson_emul_atomic_int32_exchange (int32_t volatile *val,
- int32_t v,
- enum bson_memory_order);
-BSON_EXPORT (int32_t)
-_bson_emul_atomic_int32_compare_exchange_strong (int32_t volatile *val,
- int32_t expect_value,
- int32_t new_value,
- enum bson_memory_order);
-
-BSON_EXPORT (int32_t)
-_bson_emul_atomic_int32_compare_exchange_weak (int32_t volatile *val,
- int32_t expect_value,
- int32_t new_value,
- enum bson_memory_order);
-
-BSON_EXPORT (int)
-_bson_emul_atomic_int_fetch_add (int volatile *val,
- int v,
- enum bson_memory_order);
-BSON_EXPORT (int)
-_bson_emul_atomic_int_exchange (int volatile *val,
- int v,
- enum bson_memory_order);
-BSON_EXPORT (int)
-_bson_emul_atomic_int_compare_exchange_strong (int volatile *val,
- int expect_value,
- int new_value,
- enum bson_memory_order);
-
-BSON_EXPORT (int)
-_bson_emul_atomic_int_compare_exchange_weak (int volatile *val,
- int expect_value,
- int new_value,
- enum bson_memory_order);
-
-BSON_EXPORT (void)
-bson_thrd_yield (void);
-
-#if (defined(_MSC_VER) && !defined(_M_IX86)) || (defined(__LP64__) && __LP64__)
-/* (64-bit intrinsics are only available in x64) */
-#ifdef _MSC_VER
-DECL_ATOMIC_INTEGRAL (int64, __int64, 64)
-#else
-DECL_ATOMIC_STDINT (int64, 64)
-#endif
-#else
-static BSON_INLINE int64_t
-bson_atomic_int64_fetch (const int64_t volatile *val,
- enum bson_memory_order order)
-{
- return _bson_emul_atomic_int64_fetch_add (
- (int64_t volatile *) val, 0, order);
-}
-
-static BSON_INLINE int64_t
-bson_atomic_int64_fetch_add (int64_t volatile *val,
- int64_t v,
- enum bson_memory_order order)
-{
- return _bson_emul_atomic_int64_fetch_add (val, v, order);
-}
-
-static BSON_INLINE int64_t
-bson_atomic_int64_fetch_sub (int64_t volatile *val,
- int64_t v,
- enum bson_memory_order order)
-{
- return _bson_emul_atomic_int64_fetch_add (val, -v, order);
-}
-
-static BSON_INLINE int64_t
-bson_atomic_int64_exchange (int64_t volatile *val,
- int64_t v,
- enum bson_memory_order order)
-{
- return _bson_emul_atomic_int64_exchange (val, v, order);
-}
-
-static BSON_INLINE int64_t
-bson_atomic_int64_compare_exchange_strong (int64_t volatile *val,
- int64_t expect_value,
- int64_t new_value,
- enum bson_memory_order order)
-{
- return _bson_emul_atomic_int64_compare_exchange_strong (
- val, expect_value, new_value, order);
-}
-
-static BSON_INLINE int64_t
-bson_atomic_int64_compare_exchange_weak (int64_t volatile *val,
- int64_t expect_value,
- int64_t new_value,
- enum bson_memory_order order)
-{
- return _bson_emul_atomic_int64_compare_exchange_weak (
- val, expect_value, new_value, order);
-}
-#endif
-
-#if defined(BSON_EMULATE_INT32)
-static BSON_INLINE int32_t
-bson_atomic_int32_fetch (const int32_t volatile *val,
- enum bson_memory_order order)
-{
- return _bson_emul_atomic_int32_fetch_add (
- (int32_t volatile *) val, 0, order);
-}
-
-static BSON_INLINE int32_t
-bson_atomic_int32_fetch_add (int32_t volatile *val,
- int32_t v,
- enum bson_memory_order order)
-{
- return _bson_emul_atomic_int32_fetch_add (val, v, order);
-}
-
-static BSON_INLINE int32_t
-bson_atomic_int32_fetch_sub (int32_t volatile *val,
- int32_t v,
- enum bson_memory_order order)
-{
- return _bson_emul_atomic_int32_fetch_add (val, -v, order);
-}
-
-static BSON_INLINE int32_t
-bson_atomic_int32_exchange (int32_t volatile *val,
- int32_t v,
- enum bson_memory_order order)
-{
- return _bson_emul_atomic_int32_exchange (val, v, order);
-}
-
-static BSON_INLINE int32_t
-bson_atomic_int32_compare_exchange_strong (int32_t volatile *val,
- int32_t expect_value,
- int32_t new_value,
- enum bson_memory_order order)
-{
- return _bson_emul_atomic_int32_compare_exchange_strong (
- val, expect_value, new_value, order);
-}
-
-static BSON_INLINE int32_t
-bson_atomic_int32_compare_exchange_weak (int32_t volatile *val,
- int32_t expect_value,
- int32_t new_value,
- enum bson_memory_order order)
-{
- return _bson_emul_atomic_int32_compare_exchange_weak (
- val, expect_value, new_value, order);
-}
-#endif /* BSON_EMULATE_INT32 */
-
-#if defined(BSON_EMULATE_INT)
-static BSON_INLINE int
-bson_atomic_int_fetch (const int volatile *val, enum bson_memory_order order)
-{
- return _bson_emul_atomic_int_fetch_add ((int volatile *) val, 0, order);
-}
-
-static BSON_INLINE int
-bson_atomic_int_fetch_add (int volatile *val,
- int v,
- enum bson_memory_order order)
-{
- return _bson_emul_atomic_int_fetch_add (val, v, order);
-}
-
-static BSON_INLINE int
-bson_atomic_int_fetch_sub (int volatile *val,
- int v,
- enum bson_memory_order order)
-{
- return _bson_emul_atomic_int_fetch_add (val, -v, order);
-}
-
-static BSON_INLINE int
-bson_atomic_int_exchange (int volatile *val,
- int v,
- enum bson_memory_order order)
-{
- return _bson_emul_atomic_int_exchange (val, v, order);
-}
-
-static BSON_INLINE int
-bson_atomic_int_compare_exchange_strong (int volatile *val,
- int expect_value,
- int new_value,
- enum bson_memory_order order)
-{
- return _bson_emul_atomic_int_compare_exchange_strong (
- val, expect_value, new_value, order);
-}
-
-static BSON_INLINE int
-bson_atomic_int_compare_exchange_weak (int volatile *val,
- int expect_value,
- int new_value,
- enum bson_memory_order order)
-{
- return _bson_emul_atomic_int_compare_exchange_weak (
- val, expect_value, new_value, order);
-}
-#endif /* BSON_EMULATE_INT */
-
-static BSON_INLINE void *
-bson_atomic_ptr_exchange (void *volatile *ptr,
- void *new_value,
- enum bson_memory_order ord)
-{
- /* The older __sync_val_compare_and_swap also takes oldval */
-#if defined(BSON_USE_LEGACY_GCC_ATOMICS)
- DEF_ATOMIC_OP (_InterlockedExchangePointer,
- ,
- __sync_val_compare_and_swap,
- ord,
- ptr,
- *ptr,
- new_value);
-#else
- DEF_ATOMIC_OP (_InterlockedExchangePointer,
- __atomic_exchange_n,
- ,
- ord,
- ptr,
- new_value);
-#endif
-}
-
-static BSON_INLINE void *
-bson_atomic_ptr_compare_exchange_strong (void *volatile *ptr,
- void *expect,
- void *new_value,
- enum bson_memory_order ord)
-{
- switch (ord) {
- case bson_memory_order_release:
- case bson_memory_order_acq_rel:
- case bson_memory_order_seq_cst:
- DEF_ATOMIC_CMPEXCH_STRONG (
- Pointer, , __ATOMIC_SEQ_CST, ptr, expect, new_value);
- return expect;
- case bson_memory_order_relaxed:
- DEF_ATOMIC_CMPEXCH_STRONG (Pointer,
- MSVC_MEMORDER_SUFFIX (_nf),
- __ATOMIC_RELAXED,
- ptr,
- expect,
- new_value);
- return expect;
- case bson_memory_order_consume:
- DEF_ATOMIC_CMPEXCH_STRONG (Pointer,
- MSVC_MEMORDER_SUFFIX (_acq),
- __ATOMIC_CONSUME,
- ptr,
- expect,
- new_value);
- return expect;
- case bson_memory_order_acquire:
- DEF_ATOMIC_CMPEXCH_STRONG (Pointer,
- MSVC_MEMORDER_SUFFIX (_acq),
- __ATOMIC_ACQUIRE,
- ptr,
- expect,
- new_value);
- return expect;
- default:
- BSON_UNREACHABLE ("Invalid bson_memory_order value");
- }
-}
-
-
-static BSON_INLINE void *
-bson_atomic_ptr_compare_exchange_weak (void *volatile *ptr,
- void *expect,
- void *new_value,
- enum bson_memory_order ord)
-{
- switch (ord) {
- case bson_memory_order_release:
- case bson_memory_order_acq_rel:
- case bson_memory_order_seq_cst:
- DEF_ATOMIC_CMPEXCH_WEAK (
- Pointer, , __ATOMIC_SEQ_CST, ptr, expect, new_value);
- return expect;
- case bson_memory_order_relaxed:
- DEF_ATOMIC_CMPEXCH_WEAK (Pointer,
- MSVC_MEMORDER_SUFFIX (_nf),
- __ATOMIC_RELAXED,
- ptr,
- expect,
- new_value);
- return expect;
- case bson_memory_order_consume:
- DEF_ATOMIC_CMPEXCH_WEAK (Pointer,
- MSVC_MEMORDER_SUFFIX (_acq),
- __ATOMIC_CONSUME,
- ptr,
- expect,
- new_value);
- return expect;
- case bson_memory_order_acquire:
- DEF_ATOMIC_CMPEXCH_WEAK (Pointer,
- MSVC_MEMORDER_SUFFIX (_acq),
- __ATOMIC_ACQUIRE,
- ptr,
- expect,
- new_value);
- return expect;
- default:
- BSON_UNREACHABLE ("Invalid bson_memory_order value");
- }
-}
-
-
-static BSON_INLINE void *
-bson_atomic_ptr_fetch (void *volatile const *ptr, enum bson_memory_order ord)
-{
- return bson_atomic_ptr_compare_exchange_strong (
- (void *volatile *) ptr, NULL, NULL, ord);
-}
-
-#undef DECL_ATOMIC_STDINT
-#undef DECL_ATOMIC_INTEGRAL
-#undef DEF_ATOMIC_OP
-#undef DEF_ATOMIC_CMPEXCH_STRONG
-#undef DEF_ATOMIC_CMPEXCH_WEAK
-#undef MSVC_MEMORDER_SUFFIX
-
-/**
- * @brief Generate a full-fence memory barrier at the call site.
- */
-static BSON_INLINE void
-bson_atomic_thread_fence ()
-{
- BSON_IF_MSVC (MemoryBarrier ();)
- BSON_IF_GNU_LIKE (__sync_synchronize ();)
- BSON_IF_GNU_LEGACY_ATOMICS (__sync_synchronize ();)
-}
-
-#ifdef BSON_USE_LEGACY_GCC_ATOMICS
-#undef BSON_IF_GNU_LIKE
-#define BSON_IF_GNU_LIKE(...) __VA_ARGS__
-#endif
-#undef BSON_IF_GNU_LEGACY_ATOMICS
-#undef BSON_USE_LEGACY_GCC_ATOMICS
-
-BSON_GNUC_DEPRECATED_FOR ("bson_atomic_thread_fence")
-BSON_EXPORT (void) bson_memory_barrier (void);
-
-BSON_GNUC_DEPRECATED_FOR ("bson_atomic_int_fetch_add")
-BSON_EXPORT (int32_t) bson_atomic_int_add (volatile int32_t *p, int32_t n);
-
-BSON_GNUC_DEPRECATED_FOR ("bson_atomic_int64_fetch_add")
-BSON_EXPORT (int64_t) bson_atomic_int64_add (volatile int64_t *p, int64_t n);
-
-#undef BSON_EMULATE_INT32
-#undef BSON_EMULATE_INT
-
-BSON_END_DECLS
-
-
-#endif /* BSON_ATOMIC_H */
diff --git a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-config.h b/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-config.h
deleted file mode 100644
index 31a90bc8..00000000
--- a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-config.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright 2018-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#if !defined(BSON_INSIDE) && !defined(BSON_COMPILATION)
-#error "Only <bson/bson.h> can be included directly."
-#endif
-
-#ifndef BSON_CONFIG_H
-#define BSON_CONFIG_H
-
-/*
- * Define to 1234 for Little Endian, 4321 for Big Endian.
- */
-#define BSON_BYTE_ORDER 1234
-
-
-/*
- * Define to 1 if you have stdbool.h
- */
-#define BSON_HAVE_STDBOOL_H 1
-#if BSON_HAVE_STDBOOL_H != 1
-# undef BSON_HAVE_STDBOOL_H
-#endif
-
-
-/*
- * Define to 1 for POSIX-like systems, 2 for Windows.
- */
-#define BSON_OS 1
-
-
-/*
- * Define to 1 if you have clock_gettime() available.
- */
-#define BSON_HAVE_CLOCK_GETTIME 1
-#if BSON_HAVE_CLOCK_GETTIME != 1
-# undef BSON_HAVE_CLOCK_GETTIME
-#endif
-
-
-/*
- * Define to 1 if you have strings.h available on your platform.
- */
-#define BSON_HAVE_STRINGS_H 1
-#if BSON_HAVE_STRINGS_H != 1
-# undef BSON_HAVE_STRINGS_H
-#endif
-
-
-/*
- * Define to 1 if you have strnlen available on your platform.
- */
-#define BSON_HAVE_STRNLEN 1
-#if BSON_HAVE_STRNLEN != 1
-# undef BSON_HAVE_STRNLEN
-#endif
-
-
-/*
- * Define to 1 if you have snprintf available on your platform.
- */
-#define BSON_HAVE_SNPRINTF 1
-#if BSON_HAVE_SNPRINTF != 1
-# undef BSON_HAVE_SNPRINTF
-#endif
-
-
-/*
- * Define to 1 if you have gmtime_r available on your platform.
- */
-#define BSON_HAVE_GMTIME_R 1
-#if BSON_HAVE_GMTIME_R != 1
-# undef BSON_HAVE_GMTIME_R
-#endif
-
-
-/*
- * Define to 1 if you have struct timespec available on your platform.
- */
-#define BSON_HAVE_TIMESPEC 1
-#if BSON_HAVE_TIMESPEC != 1
-# undef BSON_HAVE_TIMESPEC
-#endif
-
-
-/*
- * Define to 1 if you want extra aligned types in libbson
- */
-#define BSON_EXTRA_ALIGN 0
-#if BSON_EXTRA_ALIGN != 1
-# undef BSON_EXTRA_ALIGN
-#endif
-
-
-/*
- * Define to 1 if you have SYS_gettid syscall
- */
-#define BSON_HAVE_SYSCALL_TID 1
-#if BSON_HAVE_SYSCALL_TID != 1
-# undef BSON_HAVE_SYSCALL_TID
-#endif
-
-#define BSON_HAVE_RAND_R 1
-#if BSON_HAVE_RAND_R != 1
-# undef BSON_HAVE_RAND_R
-#endif
-
-#define BSON_HAVE_STRLCPY 0
-#if BSON_HAVE_STRLCPY != 1
-# undef BSON_HAVE_STRLCPY
-#endif
-
-#endif /* BSON_CONFIG_H */
diff --git a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-config.h.in b/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-config.h.in
deleted file mode 100644
index 4fb59df4..00000000
--- a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-config.h.in
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright 2018-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#if !defined(BSON_INSIDE) && !defined(BSON_COMPILATION)
-#error "Only <bson/bson.h> can be included directly."
-#endif
-
-#ifndef BSON_CONFIG_H
-#define BSON_CONFIG_H
-
-/*
- * Define to 1234 for Little Endian, 4321 for Big Endian.
- */
-#define BSON_BYTE_ORDER @BSON_BYTE_ORDER@
-
-
-/*
- * Define to 1 if you have stdbool.h
- */
-#define BSON_HAVE_STDBOOL_H @BSON_HAVE_STDBOOL_H@
-#if BSON_HAVE_STDBOOL_H != 1
-# undef BSON_HAVE_STDBOOL_H
-#endif
-
-
-/*
- * Define to 1 for POSIX-like systems, 2 for Windows.
- */
-#define BSON_OS @BSON_OS@
-
-
-/*
- * Define to 1 if you have clock_gettime() available.
- */
-#define BSON_HAVE_CLOCK_GETTIME @BSON_HAVE_CLOCK_GETTIME@
-#if BSON_HAVE_CLOCK_GETTIME != 1
-# undef BSON_HAVE_CLOCK_GETTIME
-#endif
-
-
-/*
- * Define to 1 if you have strings.h available on your platform.
- */
-#define BSON_HAVE_STRINGS_H @BSON_HAVE_STRINGS_H@
-#if BSON_HAVE_STRINGS_H != 1
-# undef BSON_HAVE_STRINGS_H
-#endif
-
-
-/*
- * Define to 1 if you have strnlen available on your platform.
- */
-#define BSON_HAVE_STRNLEN @BSON_HAVE_STRNLEN@
-#if BSON_HAVE_STRNLEN != 1
-# undef BSON_HAVE_STRNLEN
-#endif
-
-
-/*
- * Define to 1 if you have snprintf available on your platform.
- */
-#define BSON_HAVE_SNPRINTF @BSON_HAVE_SNPRINTF@
-#if BSON_HAVE_SNPRINTF != 1
-# undef BSON_HAVE_SNPRINTF
-#endif
-
-
-/*
- * Define to 1 if you have gmtime_r available on your platform.
- */
-#define BSON_HAVE_GMTIME_R @BSON_HAVE_GMTIME_R@
-#if BSON_HAVE_GMTIME_R != 1
-# undef BSON_HAVE_GMTIME_R
-#endif
-
-
-/*
- * Define to 1 if you have struct timespec available on your platform.
- */
-#define BSON_HAVE_TIMESPEC @BSON_HAVE_TIMESPEC@
-#if BSON_HAVE_TIMESPEC != 1
-# undef BSON_HAVE_TIMESPEC
-#endif
-
-
-/*
- * Define to 1 if you want extra aligned types in libbson
- */
-#define BSON_EXTRA_ALIGN @BSON_EXTRA_ALIGN@
-#if BSON_EXTRA_ALIGN != 1
-# undef BSON_EXTRA_ALIGN
-#endif
-
-
-/*
- * Define to 1 if you have SYS_gettid syscall
- */
-#define BSON_HAVE_SYSCALL_TID @BSON_HAVE_SYSCALL_TID@
-#if BSON_HAVE_SYSCALL_TID != 1
-# undef BSON_HAVE_SYSCALL_TID
-#endif
-
-#define BSON_HAVE_RAND_R @BSON_HAVE_RAND_R@
-#if BSON_HAVE_RAND_R != 1
-# undef BSON_HAVE_RAND_R
-#endif
-
-#define BSON_HAVE_STRLCPY @BSON_HAVE_STRLCPY@
-#if BSON_HAVE_STRLCPY != 1
-# undef BSON_HAVE_STRLCPY
-#endif
-
-#endif /* BSON_CONFIG_H */
diff --git a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-context-private.h b/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-context-private.h
deleted file mode 100644
index 5b0d4446..00000000
--- a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-context-private.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 2014 MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "bson-prelude.h"
-
-
-#ifndef BSON_CONTEXT_PRIVATE_H
-#define BSON_CONTEXT_PRIVATE_H
-
-
-#include "bson-context.h"
-#include "common-thread-private.h"
-
-
-BSON_BEGIN_DECLS
-
-
-struct _bson_context_t {
- /* flags are defined in bson_context_flags_t */
- int flags;
- int32_t seq32;
- int64_t seq64;
- uint8_t rand[5];
- uint16_t pid;
-
- void (*oid_set_seq32) (bson_context_t *context, bson_oid_t *oid);
- void (*oid_set_seq64) (bson_context_t *context, bson_oid_t *oid);
-
- /* this function pointer allows us to mock gethostname for testing. */
- void (*gethostname) (char *out);
-};
-
-void
-_bson_context_set_oid_rand (bson_context_t *context, bson_oid_t *oid);
-
-
-BSON_END_DECLS
-
-
-#endif /* BSON_CONTEXT_PRIVATE_H */
diff --git a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-context.c b/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-context.c
deleted file mode 100644
index a8f5e124..00000000
--- a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-context.c
+++ /dev/null
@@ -1,445 +0,0 @@
-/*
- * Copyright 2013 MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "bson-compat.h"
-
-#include <limits.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#include "bson-atomic.h"
-#include "bson-clock.h"
-#include "bson-context.h"
-#include "bson-context-private.h"
-#include "bson-memory.h"
-#include "common-thread-private.h"
-
-#ifdef BSON_HAVE_SYSCALL_TID
-#include <sys/syscall.h>
-#endif
-
-
-#ifndef HOST_NAME_MAX
-#define HOST_NAME_MAX 256
-#endif
-
-
-/*
- * Globals.
- */
-static bson_context_t gContextDefault;
-
-static BSON_INLINE uint16_t
-_bson_getpid (void)
-{
- uint16_t pid;
-#ifdef BSON_OS_WIN32
- DWORD real_pid;
-
- real_pid = GetCurrentProcessId ();
- pid = (real_pid & 0xFFFF) ^ ((real_pid >> 16) & 0xFFFF);
-#else
- pid = getpid ();
-#endif
-
- return pid;
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * _bson_context_set_oid_seq32 --
- *
- * 32-bit sequence generator, non-thread-safe version.
- *
- * Returns:
- * None.
- *
- * Side effects:
- * @oid is modified.
- *
- *--------------------------------------------------------------------------
- */
-
-static void
-_bson_context_set_oid_seq32 (bson_context_t *context, /* IN */
- bson_oid_t *oid) /* OUT */
-{
- uint32_t seq = context->seq32++;
-
- seq = BSON_UINT32_TO_BE (seq);
- memcpy (&oid->bytes[9], ((uint8_t *) &seq) + 1, 3);
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * _bson_context_set_oid_seq32_threadsafe --
- *
- * Thread-safe version of 32-bit sequence generator.
- *
- * Returns:
- * None.
- *
- * Side effects:
- * @oid is modified.
- *
- *--------------------------------------------------------------------------
- */
-
-static void
-_bson_context_set_oid_seq32_threadsafe (bson_context_t *context, /* IN */
- bson_oid_t *oid) /* OUT */
-{
- int32_t seq = 1 + bson_atomic_int32_fetch_add (
- &context->seq32, 1, bson_memory_order_seq_cst);
- seq = BSON_UINT32_TO_BE (seq);
- memcpy (&oid->bytes[9], ((uint8_t *) &seq) + 1, 3);
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * _bson_context_set_oid_seq64 --
- *
- * 64-bit oid sequence generator, non-thread-safe version.
- *
- * Returns:
- * None.
- *
- * Side effects:
- * @oid is modified.
- *
- *--------------------------------------------------------------------------
- */
-
-static void
-_bson_context_set_oid_seq64 (bson_context_t *context, /* IN */
- bson_oid_t *oid) /* OUT */
-{
- uint64_t seq;
-
- BSON_ASSERT (context);
- BSON_ASSERT (oid);
-
- seq = BSON_UINT64_TO_BE (context->seq64++);
- memcpy (&oid->bytes[4], &seq, sizeof (seq));
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * _bson_context_set_oid_seq64_threadsafe --
- *
- * Thread-safe 64-bit sequence generator.
- *
- * Returns:
- * None.
- *
- * Side effects:
- * @oid is modified.
- *
- *--------------------------------------------------------------------------
- */
-
-static void
-_bson_context_set_oid_seq64_threadsafe (bson_context_t *context, /* IN */
- bson_oid_t *oid) /* OUT */
-{
- int64_t seq = 1 + bson_atomic_int64_fetch_add (
- &context->seq64, 1, bson_memory_order_seq_cst);
-
- seq = BSON_UINT64_TO_BE (seq);
- memcpy (&oid->bytes[4], &seq, sizeof (seq));
-}
-
-
-static void
-_bson_context_init_random (bson_context_t *context, bool init_sequence);
-
-/*
- *--------------------------------------------------------------------------
- *
- * _bson_context_set_oid_rand --
- *
- * Sets the process specific five byte random sequence in an oid.
- *
- * Returns:
- * None.
- *
- * Side effects:
- * @oid is modified.
- *
- *--------------------------------------------------------------------------
- */
-void
-_bson_context_set_oid_rand (bson_context_t *context, bson_oid_t *oid)
-{
- BSON_ASSERT (context);
- BSON_ASSERT (oid);
-
- if (context->flags & BSON_CONTEXT_DISABLE_PID_CACHE) {
- uint16_t pid = _bson_getpid ();
-
- if (pid != context->pid) {
- context->pid = pid;
- /* randomize the random bytes, not the sequence. */
- _bson_context_init_random (context, false);
- }
- }
- memcpy (&oid->bytes[4], &context->rand, sizeof (context->rand));
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * _get_rand --
- *
- * Gets a random four byte integer. Callers that will use the "rand"
- * function must call "srand" prior.
- *
- * Returns:
- * A random int32_t.
- *
- *--------------------------------------------------------------------------
- */
-static int32_t
-_get_rand (unsigned int *pseed)
-{
- int32_t result = 0;
-#ifndef BSON_HAVE_RAND_R
- /* ms's runtime is multithreaded by default, so no rand_r */
- /* no rand_r on android either */
- result = rand ();
-#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || \
- defined(__OpenBSD__) || defined(__APPLE__)
- arc4random_buf (&result, sizeof (result));
-#else
- result = rand_r (pseed);
-#endif
- return result;
-}
-
-
-/*
- * --------------------------------------------------------------------------
- *
- * _bson_context_get_hostname
- *
- * Gets the hostname of the machine, logs a warning on failure. "out"
- * must be an array of HOST_NAME_MAX bytes.
- *
- * --------------------------------------------------------------------------
- */
-static void
-_bson_context_get_hostname (char *out)
-{
- if (gethostname (out, HOST_NAME_MAX) != 0) {
- if (errno == ENAMETOOLONG) {
- fprintf (stderr,
- "hostname exceeds %d characters, truncating.",
- HOST_NAME_MAX);
- } else {
- fprintf (stderr, "unable to get hostname: %d", errno);
- }
- }
- out[HOST_NAME_MAX - 1] = '\0';
-}
-
-
-static void
-_bson_context_init_random (bson_context_t *context, bool init_sequence)
-{
- int64_t rand_bytes;
- struct timeval tv;
- unsigned int seed = 0;
- char hostname[HOST_NAME_MAX];
- char *ptr;
- int hostname_chars_left;
-
- /*
- * The seed consists of the following xor'd together:
- * - current time in seconds
- * - current time in milliseconds
- * - current pid
- * - current hostname
- */
- bson_gettimeofday (&tv);
- seed ^= (unsigned int) tv.tv_sec;
- seed ^= (unsigned int) tv.tv_usec;
- seed ^= (unsigned int) context->pid;
-
- context->gethostname (hostname);
- hostname_chars_left = strlen (hostname);
- ptr = hostname;
- while (hostname_chars_left) {
- uint32_t hostname_chunk = 0;
- uint32_t to_copy = hostname_chars_left > 4 ? 4 : hostname_chars_left;
-
- memcpy (&hostname_chunk, ptr, to_copy);
- seed ^= (unsigned int) hostname_chunk;
- hostname_chars_left -= to_copy;
- ptr += to_copy;
- }
-
-#ifndef BSON_HAVE_RAND_R
- srand (seed);
-#endif
-
- /* Generate a seed for the random starting position of our increment
- * bytes and the five byte random number. */
- if (init_sequence) {
- /* We mask off the last nibble so that the last digit of the OID will
- * start at zero. Just to be nice. */
- context->seq32 = _get_rand (&seed) & 0x007FFFF0;
- }
-
- rand_bytes = _get_rand (&seed);
- rand_bytes <<= 32;
- rand_bytes |= _get_rand (&seed);
-
- /* Copy five random bytes, endianness does not matter. */
- memcpy (&context->rand, (char *) &rand_bytes, sizeof (context->rand));
-}
-
-static void
-_bson_context_init (bson_context_t *context, bson_context_flags_t flags)
-{
- context->flags = (int) flags;
- context->oid_set_seq32 = _bson_context_set_oid_seq32;
- context->oid_set_seq64 = _bson_context_set_oid_seq64;
- context->gethostname = _bson_context_get_hostname;
-
- if ((flags & BSON_CONTEXT_THREAD_SAFE)) {
- context->oid_set_seq32 = _bson_context_set_oid_seq32_threadsafe;
- context->oid_set_seq64 = _bson_context_set_oid_seq64_threadsafe;
- }
-
- context->pid = _bson_getpid ();
- _bson_context_init_random (context, true);
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * bson_context_new --
- *
- * Initializes a new context with the flags specified.
- *
- * In most cases, you want to call this with @flags set to
- * BSON_CONTEXT_NONE.
- *
- * If you are running on Linux, %BSON_CONTEXT_USE_TASK_ID can result
- * in a healthy speedup for multi-threaded scenarios.
- *
- * If you absolutely must have a single context for your application
- * and use more than one thread, then %BSON_CONTEXT_THREAD_SAFE should
- * be bitwise-or'd with your flags. This requires synchronization
- * between threads.
- *
- * If you expect your pid to change without notice, such as from an
- * unexpected call to fork(), then specify
- * %BSON_CONTEXT_DISABLE_PID_CACHE.
- *
- * Returns:
- * A newly allocated bson_context_t that should be freed with
- * bson_context_destroy().
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-bson_context_t *
-bson_context_new (bson_context_flags_t flags)
-{
- bson_context_t *context;
-
- context = bson_malloc0 (sizeof *context);
- _bson_context_init (context, flags);
-
- return context;
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * bson_context_destroy --
- *
- * Cleans up a bson_context_t and releases any associated resources.
- * This should be called when you are done using @context.
- *
- * Returns:
- * None.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-void
-bson_context_destroy (bson_context_t *context) /* IN */
-{
- bson_free (context);
-}
-
-
-static BSON_ONCE_FUN (_bson_context_init_default)
-{
- _bson_context_init (
- &gContextDefault,
- (BSON_CONTEXT_THREAD_SAFE | BSON_CONTEXT_DISABLE_PID_CACHE));
- BSON_ONCE_RETURN;
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * bson_context_get_default --
- *
- * Fetches the default, thread-safe implementation of #bson_context_t.
- * If you need faster generation, it is recommended you create your
- * own #bson_context_t with bson_context_new().
- *
- * Returns:
- * A shared instance to the default #bson_context_t. This should not
- * be modified or freed.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-bson_context_t *
-bson_context_get_default (void)
-{
- static bson_once_t once = BSON_ONCE_INIT;
-
- bson_once (&once, _bson_context_init_default);
-
- return &gContextDefault;
-}
diff --git a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-context.h b/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-context.h
deleted file mode 100644
index 56e817f8..00000000
--- a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-context.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright 2013 MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "bson-prelude.h"
-
-
-#ifndef BSON_CONTEXT_H
-#define BSON_CONTEXT_H
-
-
-#include "bson-macros.h"
-#include "bson-types.h"
-
-
-BSON_BEGIN_DECLS
-
-
-BSON_EXPORT (bson_context_t *)
-bson_context_new (bson_context_flags_t flags);
-BSON_EXPORT (void)
-bson_context_destroy (bson_context_t *context);
-BSON_EXPORT (bson_context_t *)
-bson_context_get_default (void);
-
-
-BSON_END_DECLS
-
-
-#endif /* BSON_CONTEXT_H */
diff --git a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-endian.h b/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-endian.h
deleted file mode 100644
index b597f573..00000000
--- a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-endian.h
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
- * Copyright 2013 MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "bson-prelude.h"
-
-
-#ifndef BSON_ENDIAN_H
-#define BSON_ENDIAN_H
-
-
-#if defined(__sun)
-#include <sys/byteorder.h>
-#endif
-
-#include "bson-config.h"
-#include "bson-macros.h"
-#include "bson-compat.h"
-
-
-BSON_BEGIN_DECLS
-
-
-#define BSON_BIG_ENDIAN 4321
-#define BSON_LITTLE_ENDIAN 1234
-
-
-#if defined(__sun)
-#define BSON_UINT16_SWAP_LE_BE(v) BSWAP_16 ((uint16_t) v)
-#define BSON_UINT32_SWAP_LE_BE(v) BSWAP_32 ((uint32_t) v)
-#define BSON_UINT64_SWAP_LE_BE(v) BSWAP_64 ((uint64_t) v)
-#elif defined(__clang__) && defined(__clang_major__) && \
- defined(__clang_minor__) && (__clang_major__ >= 3) && \
- (__clang_minor__ >= 1)
-#if __has_builtin(__builtin_bswap16)
-#define BSON_UINT16_SWAP_LE_BE(v) __builtin_bswap16 (v)
-#endif
-#if __has_builtin(__builtin_bswap32)
-#define BSON_UINT32_SWAP_LE_BE(v) __builtin_bswap32 (v)
-#endif
-#if __has_builtin(__builtin_bswap64)
-#define BSON_UINT64_SWAP_LE_BE(v) __builtin_bswap64 (v)
-#endif
-#elif defined(__GNUC__) && (__GNUC__ >= 4)
-#if __GNUC__ > 4 || (defined(__GNUC_MINOR__) && __GNUC_MINOR__ >= 3)
-#define BSON_UINT32_SWAP_LE_BE(v) __builtin_bswap32 ((uint32_t) v)
-#define BSON_UINT64_SWAP_LE_BE(v) __builtin_bswap64 ((uint64_t) v)
-#endif
-#if __GNUC__ > 4 || (defined(__GNUC_MINOR__) && __GNUC_MINOR__ >= 8)
-#define BSON_UINT16_SWAP_LE_BE(v) __builtin_bswap16 ((uint32_t) v)
-#endif
-#endif
-
-
-#ifndef BSON_UINT16_SWAP_LE_BE
-#define BSON_UINT16_SWAP_LE_BE(v) __bson_uint16_swap_slow ((uint16_t) v)
-#endif
-
-
-#ifndef BSON_UINT32_SWAP_LE_BE
-#define BSON_UINT32_SWAP_LE_BE(v) __bson_uint32_swap_slow ((uint32_t) v)
-#endif
-
-
-#ifndef BSON_UINT64_SWAP_LE_BE
-#define BSON_UINT64_SWAP_LE_BE(v) __bson_uint64_swap_slow ((uint64_t) v)
-#endif
-
-
-#if BSON_BYTE_ORDER == BSON_LITTLE_ENDIAN
-#define BSON_UINT16_FROM_LE(v) ((uint16_t) v)
-#define BSON_UINT16_TO_LE(v) ((uint16_t) v)
-#define BSON_UINT16_FROM_BE(v) BSON_UINT16_SWAP_LE_BE (v)
-#define BSON_UINT16_TO_BE(v) BSON_UINT16_SWAP_LE_BE (v)
-#define BSON_UINT32_FROM_LE(v) ((uint32_t) v)
-#define BSON_UINT32_TO_LE(v) ((uint32_t) v)
-#define BSON_UINT32_FROM_BE(v) BSON_UINT32_SWAP_LE_BE (v)
-#define BSON_UINT32_TO_BE(v) BSON_UINT32_SWAP_LE_BE (v)
-#define BSON_UINT64_FROM_LE(v) ((uint64_t) v)
-#define BSON_UINT64_TO_LE(v) ((uint64_t) v)
-#define BSON_UINT64_FROM_BE(v) BSON_UINT64_SWAP_LE_BE (v)
-#define BSON_UINT64_TO_BE(v) BSON_UINT64_SWAP_LE_BE (v)
-#define BSON_DOUBLE_FROM_LE(v) ((double) v)
-#define BSON_DOUBLE_TO_LE(v) ((double) v)
-#elif BSON_BYTE_ORDER == BSON_BIG_ENDIAN
-#define BSON_UINT16_FROM_LE(v) BSON_UINT16_SWAP_LE_BE (v)
-#define BSON_UINT16_TO_LE(v) BSON_UINT16_SWAP_LE_BE (v)
-#define BSON_UINT16_FROM_BE(v) ((uint16_t) v)
-#define BSON_UINT16_TO_BE(v) ((uint16_t) v)
-#define BSON_UINT32_FROM_LE(v) BSON_UINT32_SWAP_LE_BE (v)
-#define BSON_UINT32_TO_LE(v) BSON_UINT32_SWAP_LE_BE (v)
-#define BSON_UINT32_FROM_BE(v) ((uint32_t) v)
-#define BSON_UINT32_TO_BE(v) ((uint32_t) v)
-#define BSON_UINT64_FROM_LE(v) BSON_UINT64_SWAP_LE_BE (v)
-#define BSON_UINT64_TO_LE(v) BSON_UINT64_SWAP_LE_BE (v)
-#define BSON_UINT64_FROM_BE(v) ((uint64_t) v)
-#define BSON_UINT64_TO_BE(v) ((uint64_t) v)
-#define BSON_DOUBLE_FROM_LE(v) (__bson_double_swap_slow (v))
-#define BSON_DOUBLE_TO_LE(v) (__bson_double_swap_slow (v))
-#else
-#error "The endianness of target architecture is unknown."
-#endif
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * __bson_uint16_swap_slow --
- *
- * Fallback endianness conversion for 16-bit integers.
- *
- * Returns:
- * The endian swapped version.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-static BSON_INLINE uint16_t
-__bson_uint16_swap_slow (uint16_t v) /* IN */
-{
- return ((v & 0x00FF) << 8) | ((v & 0xFF00) >> 8);
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * __bson_uint32_swap_slow --
- *
- * Fallback endianness conversion for 32-bit integers.
- *
- * Returns:
- * The endian swapped version.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-static BSON_INLINE uint32_t
-__bson_uint32_swap_slow (uint32_t v) /* IN */
-{
- return ((v & 0x000000FFU) << 24) | ((v & 0x0000FF00U) << 8) |
- ((v & 0x00FF0000U) >> 8) | ((v & 0xFF000000U) >> 24);
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * __bson_uint64_swap_slow --
- *
- * Fallback endianness conversion for 64-bit integers.
- *
- * Returns:
- * The endian swapped version.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-static BSON_INLINE uint64_t
-__bson_uint64_swap_slow (uint64_t v) /* IN */
-{
- return ((v & 0x00000000000000FFULL) << 56) |
- ((v & 0x000000000000FF00ULL) << 40) |
- ((v & 0x0000000000FF0000ULL) << 24) |
- ((v & 0x00000000FF000000ULL) << 8) |
- ((v & 0x000000FF00000000ULL) >> 8) |
- ((v & 0x0000FF0000000000ULL) >> 24) |
- ((v & 0x00FF000000000000ULL) >> 40) |
- ((v & 0xFF00000000000000ULL) >> 56);
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * __bson_double_swap_slow --
- *
- * Fallback endianness conversion for double floating point.
- *
- * Returns:
- * The endian swapped version.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-BSON_STATIC_ASSERT2 (sizeof_uint64_t, sizeof (double) == sizeof (uint64_t));
-
-static BSON_INLINE double
-__bson_double_swap_slow (double v) /* IN */
-{
- uint64_t uv;
-
- memcpy (&uv, &v, sizeof (v));
- uv = BSON_UINT64_SWAP_LE_BE (uv);
- memcpy (&v, &uv, sizeof (v));
-
- return v;
-}
-
-BSON_END_DECLS
-
-
-#endif /* BSON_ENDIAN_H */
diff --git a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-oid.c b/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-oid.c
deleted file mode 100644
index 29b19c30..00000000
--- a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-oid.c
+++ /dev/null
@@ -1,295 +0,0 @@
-/*
- * Copyright 2013 MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "bson-compat.h"
-
-#include <limits.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "bson-context-private.h"
-#include "bson-oid.h"
-#include "bson-string.h"
-
-
-/*
- * This table contains an array of two character pairs for every possible
- * uint8_t. It is used as a lookup table when encoding a bson_oid_t
- * to hex formatted ASCII. Performing two characters at a time roughly
- * reduces the number of operations by one-half.
- */
-static const uint16_t gHexCharPairs[] = {
-#if BSON_BYTE_ORDER == BSON_BIG_ENDIAN
- 12336, 12337, 12338, 12339, 12340, 12341, 12342, 12343, 12344, 12345, 12385,
- 12386, 12387, 12388, 12389, 12390, 12592, 12593, 12594, 12595, 12596, 12597,
- 12598, 12599, 12600, 12601, 12641, 12642, 12643, 12644, 12645, 12646, 12848,
- 12849, 12850, 12851, 12852, 12853, 12854, 12855, 12856, 12857, 12897, 12898,
- 12899, 12900, 12901, 12902, 13104, 13105, 13106, 13107, 13108, 13109, 13110,
- 13111, 13112, 13113, 13153, 13154, 13155, 13156, 13157, 13158, 13360, 13361,
- 13362, 13363, 13364, 13365, 13366, 13367, 13368, 13369, 13409, 13410, 13411,
- 13412, 13413, 13414, 13616, 13617, 13618, 13619, 13620, 13621, 13622, 13623,
- 13624, 13625, 13665, 13666, 13667, 13668, 13669, 13670, 13872, 13873, 13874,
- 13875, 13876, 13877, 13878, 13879, 13880, 13881, 13921, 13922, 13923, 13924,
- 13925, 13926, 14128, 14129, 14130, 14131, 14132, 14133, 14134, 14135, 14136,
- 14137, 14177, 14178, 14179, 14180, 14181, 14182, 14384, 14385, 14386, 14387,
- 14388, 14389, 14390, 14391, 14392, 14393, 14433, 14434, 14435, 14436, 14437,
- 14438, 14640, 14641, 14642, 14643, 14644, 14645, 14646, 14647, 14648, 14649,
- 14689, 14690, 14691, 14692, 14693, 14694, 24880, 24881, 24882, 24883, 24884,
- 24885, 24886, 24887, 24888, 24889, 24929, 24930, 24931, 24932, 24933, 24934,
- 25136, 25137, 25138, 25139, 25140, 25141, 25142, 25143, 25144, 25145, 25185,
- 25186, 25187, 25188, 25189, 25190, 25392, 25393, 25394, 25395, 25396, 25397,
- 25398, 25399, 25400, 25401, 25441, 25442, 25443, 25444, 25445, 25446, 25648,
- 25649, 25650, 25651, 25652, 25653, 25654, 25655, 25656, 25657, 25697, 25698,
- 25699, 25700, 25701, 25702, 25904, 25905, 25906, 25907, 25908, 25909, 25910,
- 25911, 25912, 25913, 25953, 25954, 25955, 25956, 25957, 25958, 26160, 26161,
- 26162, 26163, 26164, 26165, 26166, 26167, 26168, 26169, 26209, 26210, 26211,
- 26212, 26213, 26214
-#else
- 12336, 12592, 12848, 13104, 13360, 13616, 13872, 14128, 14384, 14640, 24880,
- 25136, 25392, 25648, 25904, 26160, 12337, 12593, 12849, 13105, 13361, 13617,
- 13873, 14129, 14385, 14641, 24881, 25137, 25393, 25649, 25905, 26161, 12338,
- 12594, 12850, 13106, 13362, 13618, 13874, 14130, 14386, 14642, 24882, 25138,
- 25394, 25650, 25906, 26162, 12339, 12595, 12851, 13107, 13363, 13619, 13875,
- 14131, 14387, 14643, 24883, 25139, 25395, 25651, 25907, 26163, 12340, 12596,
- 12852, 13108, 13364, 13620, 13876, 14132, 14388, 14644, 24884, 25140, 25396,
- 25652, 25908, 26164, 12341, 12597, 12853, 13109, 13365, 13621, 13877, 14133,
- 14389, 14645, 24885, 25141, 25397, 25653, 25909, 26165, 12342, 12598, 12854,
- 13110, 13366, 13622, 13878, 14134, 14390, 14646, 24886, 25142, 25398, 25654,
- 25910, 26166, 12343, 12599, 12855, 13111, 13367, 13623, 13879, 14135, 14391,
- 14647, 24887, 25143, 25399, 25655, 25911, 26167, 12344, 12600, 12856, 13112,
- 13368, 13624, 13880, 14136, 14392, 14648, 24888, 25144, 25400, 25656, 25912,
- 26168, 12345, 12601, 12857, 13113, 13369, 13625, 13881, 14137, 14393, 14649,
- 24889, 25145, 25401, 25657, 25913, 26169, 12385, 12641, 12897, 13153, 13409,
- 13665, 13921, 14177, 14433, 14689, 24929, 25185, 25441, 25697, 25953, 26209,
- 12386, 12642, 12898, 13154, 13410, 13666, 13922, 14178, 14434, 14690, 24930,
- 25186, 25442, 25698, 25954, 26210, 12387, 12643, 12899, 13155, 13411, 13667,
- 13923, 14179, 14435, 14691, 24931, 25187, 25443, 25699, 25955, 26211, 12388,
- 12644, 12900, 13156, 13412, 13668, 13924, 14180, 14436, 14692, 24932, 25188,
- 25444, 25700, 25956, 26212, 12389, 12645, 12901, 13157, 13413, 13669, 13925,
- 14181, 14437, 14693, 24933, 25189, 25445, 25701, 25957, 26213, 12390, 12646,
- 12902, 13158, 13414, 13670, 13926, 14182, 14438, 14694, 24934, 25190, 25446,
- 25702, 25958, 26214
-#endif
-};
-
-
-void
-bson_oid_init_sequence (bson_oid_t *oid, /* OUT */
- bson_context_t *context) /* IN */
-{
- uint32_t now = (uint32_t) (time (NULL));
-
- if (!context) {
- context = bson_context_get_default ();
- }
-
- now = BSON_UINT32_TO_BE (now);
-
- memcpy (&oid->bytes[0], &now, sizeof (now));
- context->oid_set_seq64 (context, oid);
-}
-
-
-void
-bson_oid_init (bson_oid_t *oid, /* OUT */
- bson_context_t *context) /* IN */
-{
- uint32_t now = (uint32_t) (time (NULL));
-
- BSON_ASSERT (oid);
-
- if (!context) {
- context = bson_context_get_default ();
- }
-
- now = BSON_UINT32_TO_BE (now);
- memcpy (&oid->bytes[0], &now, sizeof (now));
-
- _bson_context_set_oid_rand (context, oid);
- context->oid_set_seq32 (context, oid);
-}
-
-
-void
-bson_oid_init_from_data (bson_oid_t *oid, /* OUT */
- const uint8_t *data) /* IN */
-{
- BSON_ASSERT (oid);
- BSON_ASSERT (data);
-
- memcpy (oid, data, 12);
-}
-
-
-void
-bson_oid_init_from_string (bson_oid_t *oid, /* OUT */
- const char *str) /* IN */
-{
- BSON_ASSERT (oid);
- BSON_ASSERT (str);
-
- bson_oid_init_from_string_unsafe (oid, str);
-}
-
-
-time_t
-bson_oid_get_time_t (const bson_oid_t *oid) /* IN */
-{
- BSON_ASSERT (oid);
-
- return bson_oid_get_time_t_unsafe (oid);
-}
-
-
-void
-bson_oid_to_string (const bson_oid_t *oid, /* IN */
- char str[BSON_ENSURE_ARRAY_PARAM_SIZE (25)]) /* OUT */
-{
-#if !defined(__i386__) && !defined(__x86_64__) && !defined(_M_IX86) && \
- !defined(_M_X64)
- BSON_ASSERT (oid);
- BSON_ASSERT (str);
-
- bson_snprintf (str,
- 25,
- "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
- oid->bytes[0],
- oid->bytes[1],
- oid->bytes[2],
- oid->bytes[3],
- oid->bytes[4],
- oid->bytes[5],
- oid->bytes[6],
- oid->bytes[7],
- oid->bytes[8],
- oid->bytes[9],
- oid->bytes[10],
- oid->bytes[11]);
-#else
- uint16_t *dst;
- uint8_t *id = (uint8_t *) oid;
-
- BSON_ASSERT (oid);
- BSON_ASSERT (str);
-
- dst = (uint16_t *) (void *) str;
- dst[0] = gHexCharPairs[id[0]];
- dst[1] = gHexCharPairs[id[1]];
- dst[2] = gHexCharPairs[id[2]];
- dst[3] = gHexCharPairs[id[3]];
- dst[4] = gHexCharPairs[id[4]];
- dst[5] = gHexCharPairs[id[5]];
- dst[6] = gHexCharPairs[id[6]];
- dst[7] = gHexCharPairs[id[7]];
- dst[8] = gHexCharPairs[id[8]];
- dst[9] = gHexCharPairs[id[9]];
- dst[10] = gHexCharPairs[id[10]];
- dst[11] = gHexCharPairs[id[11]];
- str[24] = '\0';
-#endif
-}
-
-
-uint32_t
-bson_oid_hash (const bson_oid_t *oid) /* IN */
-{
- BSON_ASSERT (oid);
-
- return bson_oid_hash_unsafe (oid);
-}
-
-
-int
-bson_oid_compare (const bson_oid_t *oid1, /* IN */
- const bson_oid_t *oid2) /* IN */
-{
- BSON_ASSERT (oid1);
- BSON_ASSERT (oid2);
-
- return bson_oid_compare_unsafe (oid1, oid2);
-}
-
-
-bool
-bson_oid_equal (const bson_oid_t *oid1, /* IN */
- const bson_oid_t *oid2) /* IN */
-{
- BSON_ASSERT (oid1);
- BSON_ASSERT (oid2);
-
- return bson_oid_equal_unsafe (oid1, oid2);
-}
-
-
-void
-bson_oid_copy (const bson_oid_t *src, /* IN */
- bson_oid_t *dst) /* OUT */
-{
- BSON_ASSERT (src);
- BSON_ASSERT (dst);
-
- bson_oid_copy_unsafe (src, dst);
-}
-
-
-bool
-bson_oid_is_valid (const char *str, /* IN */
- size_t length) /* IN */
-{
- size_t i;
-
- BSON_ASSERT (str);
-
- if ((length == 25) && (str[24] == '\0')) {
- length = 24;
- }
-
- if (length == 24) {
- for (i = 0; i < length; i++) {
- switch (str[i]) {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- break;
- default:
- return false;
- }
- }
- return true;
- }
-
- return false;
-}
diff --git a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-oid.h b/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-oid.h
deleted file mode 100644
index 25f4bd66..00000000
--- a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-oid.h
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- * Copyright 2013 MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "bson-prelude.h"
-
-
-#ifndef BSON_OID_H
-#define BSON_OID_H
-
-
-#include <time.h>
-
-#include "bson-context.h"
-#include "bson-macros.h"
-#include "bson-types.h"
-#include "bson-endian.h"
-
-
-BSON_BEGIN_DECLS
-
-
-BSON_EXPORT (int)
-bson_oid_compare (const bson_oid_t *oid1, const bson_oid_t *oid2);
-BSON_EXPORT (void)
-bson_oid_copy (const bson_oid_t *src, bson_oid_t *dst);
-BSON_EXPORT (bool)
-bson_oid_equal (const bson_oid_t *oid1, const bson_oid_t *oid2);
-BSON_EXPORT (bool)
-bson_oid_is_valid (const char *str, size_t length);
-BSON_EXPORT (time_t)
-bson_oid_get_time_t (const bson_oid_t *oid);
-BSON_EXPORT (uint32_t)
-bson_oid_hash (const bson_oid_t *oid);
-BSON_EXPORT (void)
-bson_oid_init (bson_oid_t *oid, bson_context_t *context);
-BSON_EXPORT (void)
-bson_oid_init_from_data (bson_oid_t *oid, const uint8_t *data);
-BSON_EXPORT (void)
-bson_oid_init_from_string (bson_oid_t *oid, const char *str);
-BSON_EXPORT (void)
-bson_oid_init_sequence (bson_oid_t *oid,
- bson_context_t *context) BSON_GNUC_DEPRECATED;
-BSON_EXPORT (void)
-bson_oid_to_string (const bson_oid_t *oid, char str[25]);
-
-
-/**
- * bson_oid_compare_unsafe:
- * @oid1: A bson_oid_t.
- * @oid2: A bson_oid_t.
- *
- * Performs a qsort() style comparison between @oid1 and @oid2.
- *
- * This function is meant to be as fast as possible and therefore performs
- * no argument validation. That is the callers responsibility.
- *
- * Returns: An integer < 0 if @oid1 is less than @oid2. Zero if they are equal.
- * An integer > 0 if @oid1 is greater than @oid2.
- */
-static BSON_INLINE int
-bson_oid_compare_unsafe (const bson_oid_t *oid1, const bson_oid_t *oid2)
-{
- return memcmp (oid1, oid2, sizeof *oid1);
-}
-
-
-/**
- * bson_oid_equal_unsafe:
- * @oid1: A bson_oid_t.
- * @oid2: A bson_oid_t.
- *
- * Checks the equality of @oid1 and @oid2.
- *
- * This function is meant to be as fast as possible and therefore performs
- * no checks for argument validity. That is the callers responsibility.
- *
- * Returns: true if @oid1 and @oid2 are equal; otherwise false.
- */
-static BSON_INLINE bool
-bson_oid_equal_unsafe (const bson_oid_t *oid1, const bson_oid_t *oid2)
-{
- return !memcmp (oid1, oid2, sizeof *oid1);
-}
-
-/**
- * bson_oid_hash_unsafe:
- * @oid: A bson_oid_t.
- *
- * This function performs a DJB style hash upon the bytes contained in @oid.
- * The result is a hash key suitable for use in a hashtable.
- *
- * This function is meant to be as fast as possible and therefore performs no
- * validation of arguments. The caller is responsible to ensure they are
- * passing valid arguments.
- *
- * Returns: A uint32_t containing a hash code.
- */
-static BSON_INLINE uint32_t
-bson_oid_hash_unsafe (const bson_oid_t *oid)
-{
- uint32_t hash = 5381;
- uint32_t i;
-
- for (i = 0; i < sizeof oid->bytes; i++) {
- hash = ((hash << 5) + hash) + oid->bytes[i];
- }
-
- return hash;
-}
-
-
-/**
- * bson_oid_copy_unsafe:
- * @src: A bson_oid_t to copy from.
- * @dst: A bson_oid_t to copy into.
- *
- * Copies the contents of @src into @dst. This function is meant to be as
- * fast as possible and therefore performs no argument checking. It is the
- * callers responsibility to ensure they are passing valid data into the
- * function.
- */
-static BSON_INLINE void
-bson_oid_copy_unsafe (const bson_oid_t *src, bson_oid_t *dst)
-{
- memcpy (dst, src, sizeof *src);
-}
-
-
-/**
- * bson_oid_parse_hex_char:
- * @hex: A character to parse to its integer value.
- *
- * This function contains a jump table to return the integer value for a
- * character containing a hexadecimal value (0-9, a-f, A-F). If the character
- * is not a hexadecimal character then zero is returned.
- *
- * Returns: An integer between 0 and 15.
- */
-static BSON_INLINE uint8_t
-bson_oid_parse_hex_char (char hex)
-{
- switch (hex) {
- case '0':
- return 0;
- case '1':
- return 1;
- case '2':
- return 2;
- case '3':
- return 3;
- case '4':
- return 4;
- case '5':
- return 5;
- case '6':
- return 6;
- case '7':
- return 7;
- case '8':
- return 8;
- case '9':
- return 9;
- case 'a':
- case 'A':
- return 0xa;
- case 'b':
- case 'B':
- return 0xb;
- case 'c':
- case 'C':
- return 0xc;
- case 'd':
- case 'D':
- return 0xd;
- case 'e':
- case 'E':
- return 0xe;
- case 'f':
- case 'F':
- return 0xf;
- default:
- return 0;
- }
-}
-
-
-/**
- * bson_oid_init_from_string_unsafe:
- * @oid: A bson_oid_t to store the result.
- * @str: A 24-character hexadecimal encoded string.
- *
- * Parses a string containing 24 hexadecimal encoded bytes into a bson_oid_t.
- * This function is meant to be as fast as possible and inlined into your
- * code. For that purpose, the function does not perform any sort of bounds
- * checking and it is the callers responsibility to ensure they are passing
- * valid input to the function.
- */
-static BSON_INLINE void
-bson_oid_init_from_string_unsafe (bson_oid_t *oid, const char *str)
-{
- int i;
-
- for (i = 0; i < 12; i++) {
- oid->bytes[i] = ((bson_oid_parse_hex_char (str[2 * i]) << 4) |
- (bson_oid_parse_hex_char (str[2 * i + 1])));
- }
-}
-
-
-/**
- * bson_oid_get_time_t_unsafe:
- * @oid: A bson_oid_t.
- *
- * Fetches the time @oid was generated.
- *
- * Returns: A time_t containing the UNIX timestamp of generation.
- */
-static BSON_INLINE time_t
-bson_oid_get_time_t_unsafe (const bson_oid_t *oid)
-{
- uint32_t t;
-
- memcpy (&t, oid, sizeof (t));
- return BSON_UINT32_FROM_BE (t);
-}
-
-
-BSON_END_DECLS
-
-
-#endif /* BSON_OID_H */
diff --git a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-types.h b/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-types.h
deleted file mode 100644
index 6a8b1e73..00000000
--- a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-types.h
+++ /dev/null
@@ -1,571 +0,0 @@
-/*
- * Copyright 2013 MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "bson-prelude.h"
-
-
-#ifndef BSON_TYPES_H
-#define BSON_TYPES_H
-
-
-#include <stdlib.h>
-#include <sys/types.h>
-
-#include "bson-macros.h"
-#include "bson-config.h"
-#include "bson-compat.h"
-#include "bson-endian.h"
-
-BSON_BEGIN_DECLS
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * bson_unichar_t --
- *
- * bson_unichar_t provides an unsigned 32-bit type for containing
- * unicode characters. When iterating UTF-8 sequences, this should
- * be used to avoid losing the high-bits of non-ascii characters.
- *
- * See also:
- * bson_string_append_unichar()
- *
- *--------------------------------------------------------------------------
- */
-
-typedef uint32_t bson_unichar_t;
-
-
-/**
- * bson_context_flags_t:
- *
- * This enumeration is used to configure a bson_context_t.
- *
- * %BSON_CONTEXT_NONE: Use default options.
- * %BSON_CONTEXT_THREAD_SAFE: Context will be called from multiple threads.
- * %BSON_CONTEXT_DISABLE_HOST_CACHE: Does nothing, is ignored.
- * %BSON_CONTEXT_DISABLE_PID_CACHE: Call getpid() instead of caching the
- * result of getpid() when initializing the context.
- */
-typedef enum {
- BSON_CONTEXT_NONE = 0,
- BSON_CONTEXT_THREAD_SAFE = (1 << 0),
- BSON_CONTEXT_DISABLE_HOST_CACHE = (1 << 1),
- BSON_CONTEXT_DISABLE_PID_CACHE = (1 << 2),
-#ifdef BSON_HAVE_SYSCALL_TID
- BSON_CONTEXT_USE_TASK_ID = (1 << 3),
-#endif
-} bson_context_flags_t;
-
-
-/**
- * bson_context_t:
- *
- * This structure manages context for the bson library. It handles
- * configuration for thread-safety and other performance related requirements.
- * Consumers will create a context and may use multiple under a variety of
- * situations.
- *
- * If your program calls fork(), you should initialize a new bson_context_t
- * using bson_context_init().
- *
- * If you are using threading, it is suggested that you use a bson_context_t
- * per thread for best performance. Alternatively, you can initialize the
- * bson_context_t with BSON_CONTEXT_THREAD_SAFE, although a performance penalty
- * will be incurred.
- *
- * Many functions will require that you provide a bson_context_t such as OID
- * generation.
- *
- * This structure is opaque in that you cannot see the contents of the
- * structure. However, it is stack allocatable in that enough padding is
- * provided in _bson_context_t to hold the structure.
- */
-typedef struct _bson_context_t bson_context_t;
-
-/**
- * bson_json_opts_t:
- *
- * This structure is used to pass options for serializing BSON into extended
- * JSON to the respective serialization methods.
- *
- * max_len can be either a non-negative integer, or BSON_MAX_LEN_UNLIMITED to
- * set no limit for serialization length.
- */
-typedef struct _bson_json_opts_t bson_json_opts_t;
-
-
-/**
- * bson_t:
- *
- * This structure manages a buffer whose contents are a properly formatted
- * BSON document. You may perform various transforms on the BSON documents.
- * Additionally, it can be iterated over using bson_iter_t.
- *
- * See bson_iter_init() for iterating the contents of a bson_t.
- *
- * When building a bson_t structure using the various append functions,
- * memory allocations may occur. That is performed using power of two
- * allocations and realloc().
- *
- * See http://bsonspec.org for the BSON document spec.
- *
- * This structure is meant to fit in two sequential 64-byte cachelines.
- */
-#ifdef BSON_MEMCHECK
-BSON_ALIGNED_BEGIN (128)
-typedef struct _bson_t {
- uint32_t flags; /* Internal flags for the bson_t. */
- uint32_t len; /* Length of BSON data. */
- char *canary; /* For valgrind check */
- uint8_t padding[120 - sizeof (char *)];
-} bson_t BSON_ALIGNED_END (128);
-#else
-BSON_ALIGNED_BEGIN (128)
-typedef struct _bson_t {
- uint32_t flags; /* Internal flags for the bson_t. */
- uint32_t len; /* Length of BSON data. */
- uint8_t padding[120]; /* Padding for stack allocation. */
-} bson_t BSON_ALIGNED_END (128);
-#endif
-
-/**
- * BSON_INITIALIZER:
- *
- * This macro can be used to initialize a #bson_t structure on the stack
- * without calling bson_init().
- *
- * |[
- * bson_t b = BSON_INITIALIZER;
- * ]|
- */
-#ifdef BSON_MEMCHECK
-#define BSON_INITIALIZER \
- { \
- 3, 5, bson_malloc (1), {5}, \
- }
-#else
-#define BSON_INITIALIZER \
- { \
- 3, 5, \
- { \
- 5 \
- } \
- }
-#endif
-
-
-BSON_STATIC_ASSERT2 (bson_t, sizeof (bson_t) == 128);
-
-
-/**
- * bson_oid_t:
- *
- * This structure contains the binary form of a BSON Object Id as specified
- * on http://bsonspec.org. If you would like the bson_oid_t in string form
- * see bson_oid_to_string() or bson_oid_to_string_r().
- */
-typedef struct {
- uint8_t bytes[12];
-} bson_oid_t;
-
-BSON_STATIC_ASSERT2 (oid_t, sizeof (bson_oid_t) == 12);
-
-/**
- * bson_decimal128_t:
- *
- * @high The high-order bytes of the decimal128. This field contains sign,
- * combination bits, exponent, and part of the coefficient continuation.
- * @low The low-order bytes of the decimal128. This field contains the second
- * part of the coefficient continuation.
- *
- * This structure is a boxed type containing the value for the BSON decimal128
- * type. The structure stores the 128 bits such that they correspond to the
- * native format for the IEEE decimal128 type, if it is implemented.
- **/
-typedef struct {
-#if BSON_BYTE_ORDER == BSON_LITTLE_ENDIAN
- uint64_t low;
- uint64_t high;
-#elif BSON_BYTE_ORDER == BSON_BIG_ENDIAN
- uint64_t high;
- uint64_t low;
-#endif
-} bson_decimal128_t;
-
-
-/**
- * bson_validate_flags_t:
- *
- * This enumeration is used for validation of BSON documents. It allows
- * selective control on what you wish to validate.
- *
- * %BSON_VALIDATE_NONE: No additional validation occurs.
- * %BSON_VALIDATE_UTF8: Check that strings are valid UTF-8.
- * %BSON_VALIDATE_DOLLAR_KEYS: Check that keys do not start with $.
- * %BSON_VALIDATE_DOT_KEYS: Check that keys do not contain a period.
- * %BSON_VALIDATE_UTF8_ALLOW_NULL: Allow NUL bytes in UTF-8 text.
- * %BSON_VALIDATE_EMPTY_KEYS: Prohibit zero-length field names
- */
-typedef enum {
- BSON_VALIDATE_NONE = 0,
- BSON_VALIDATE_UTF8 = (1 << 0),
- BSON_VALIDATE_DOLLAR_KEYS = (1 << 1),
- BSON_VALIDATE_DOT_KEYS = (1 << 2),
- BSON_VALIDATE_UTF8_ALLOW_NULL = (1 << 3),
- BSON_VALIDATE_EMPTY_KEYS = (1 << 4),
-} bson_validate_flags_t;
-
-
-/**
- * bson_type_t:
- *
- * This enumeration contains all of the possible types within a BSON document.
- * Use bson_iter_type() to fetch the type of a field while iterating over it.
- */
-typedef enum {
- BSON_TYPE_EOD = 0x00,
- BSON_TYPE_DOUBLE = 0x01,
- BSON_TYPE_UTF8 = 0x02,
- BSON_TYPE_DOCUMENT = 0x03,
- BSON_TYPE_ARRAY = 0x04,
- BSON_TYPE_BINARY = 0x05,
- BSON_TYPE_UNDEFINED = 0x06,
- BSON_TYPE_OID = 0x07,
- BSON_TYPE_BOOL = 0x08,
- BSON_TYPE_DATE_TIME = 0x09,
- BSON_TYPE_NULL = 0x0A,
- BSON_TYPE_REGEX = 0x0B,
- BSON_TYPE_DBPOINTER = 0x0C,
- BSON_TYPE_CODE = 0x0D,
- BSON_TYPE_SYMBOL = 0x0E,
- BSON_TYPE_CODEWSCOPE = 0x0F,
- BSON_TYPE_INT32 = 0x10,
- BSON_TYPE_TIMESTAMP = 0x11,
- BSON_TYPE_INT64 = 0x12,
- BSON_TYPE_DECIMAL128 = 0x13,
- BSON_TYPE_MAXKEY = 0x7F,
- BSON_TYPE_MINKEY = 0xFF,
-} bson_type_t;
-
-
-/**
- * bson_subtype_t:
- *
- * This enumeration contains the various subtypes that may be used in a binary
- * field. See http://bsonspec.org for more information.
- */
-typedef enum {
- BSON_SUBTYPE_BINARY = 0x00,
- BSON_SUBTYPE_FUNCTION = 0x01,
- BSON_SUBTYPE_BINARY_DEPRECATED = 0x02,
- BSON_SUBTYPE_UUID_DEPRECATED = 0x03,
- BSON_SUBTYPE_UUID = 0x04,
- BSON_SUBTYPE_MD5 = 0x05,
- BSON_SUBTYPE_ENCRYPTED = 0x06,
- BSON_SUBTYPE_COLUMN = 0x07,
- BSON_SUBTYPE_USER = 0x80,
-} bson_subtype_t;
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * bson_value_t --
- *
- * A boxed type to contain various bson_type_t types.
- *
- * See also:
- * bson_value_copy()
- * bson_value_destroy()
- *
- *--------------------------------------------------------------------------
- */
-
-BSON_ALIGNED_BEGIN (8)
-typedef struct _bson_value_t {
- bson_type_t value_type;
- int32_t padding;
- union {
- bson_oid_t v_oid;
- int64_t v_int64;
- int32_t v_int32;
- int8_t v_int8;
- double v_double;
- bool v_bool;
- int64_t v_datetime;
- struct {
- uint32_t timestamp;
- uint32_t increment;
- } v_timestamp;
- struct {
- char *str;
- uint32_t len;
- } v_utf8;
- struct {
- uint8_t *data;
- uint32_t data_len;
- } v_doc;
- struct {
- uint8_t *data;
- uint32_t data_len;
- bson_subtype_t subtype;
- } v_binary;
- struct {
- char *regex;
- char *options;
- } v_regex;
- struct {
- char *collection;
- uint32_t collection_len;
- bson_oid_t oid;
- } v_dbpointer;
- struct {
- char *code;
- uint32_t code_len;
- } v_code;
- struct {
- char *code;
- uint8_t *scope_data;
- uint32_t code_len;
- uint32_t scope_len;
- } v_codewscope;
- struct {
- char *symbol;
- uint32_t len;
- } v_symbol;
- bson_decimal128_t v_decimal128;
- } value;
-} bson_value_t BSON_ALIGNED_END (8);
-
-
-/**
- * bson_iter_t:
- *
- * This structure manages iteration over a bson_t structure. It keeps track
- * of the location of the current key and value within the buffer. Using the
- * various functions to get the value of the iter will read from these
- * locations.
- *
- * This structure is safe to discard on the stack. No cleanup is necessary
- * after using it.
- */
-BSON_ALIGNED_BEGIN (128)
-typedef struct {
- const uint8_t *raw; /* The raw buffer being iterated. */
- uint32_t len; /* The length of raw. */
- uint32_t off; /* The offset within the buffer. */
- uint32_t type; /* The offset of the type byte. */
- uint32_t key; /* The offset of the key byte. */
- uint32_t d1; /* The offset of the first data byte. */
- uint32_t d2; /* The offset of the second data byte. */
- uint32_t d3; /* The offset of the third data byte. */
- uint32_t d4; /* The offset of the fourth data byte. */
- uint32_t next_off; /* The offset of the next field. */
- uint32_t err_off; /* The offset of the error. */
- bson_value_t value; /* Internal value for various state. */
-} bson_iter_t BSON_ALIGNED_END (128);
-
-
-/**
- * bson_reader_t:
- *
- * This structure is used to iterate over a sequence of BSON documents. It
- * allows for them to be iterated with the possibility of no additional
- * memory allocations under certain circumstances such as reading from an
- * incoming mongo packet.
- */
-
-BSON_ALIGNED_BEGIN (BSON_ALIGN_OF_PTR)
-typedef struct {
- uint32_t type;
- /*< private >*/
-} bson_reader_t BSON_ALIGNED_END (BSON_ALIGN_OF_PTR);
-
-
-/**
- * bson_visitor_t:
- *
- * This structure contains a series of pointers that can be executed for
- * each field of a BSON document based on the field type.
- *
- * For example, if an int32 field is found, visit_int32 will be called.
- *
- * When visiting each field using bson_iter_visit_all(), you may provide a
- * data pointer that will be provided with each callback. This might be useful
- * if you are marshaling to another language.
- *
- * You may pre-maturely stop the visitation of fields by returning true in your
- * visitor. Returning false will continue visitation to further fields.
- */
-BSON_ALIGNED_BEGIN (8)
-typedef struct {
- /* run before / after descending into a document */
- bool (*visit_before) (const bson_iter_t *iter, const char *key, void *data);
- bool (*visit_after) (const bson_iter_t *iter, const char *key, void *data);
- /* corrupt BSON, or unsupported type and visit_unsupported_type not set */
- void (*visit_corrupt) (const bson_iter_t *iter, void *data);
- /* normal bson field callbacks */
- bool (*visit_double) (const bson_iter_t *iter,
- const char *key,
- double v_double,
- void *data);
- bool (*visit_utf8) (const bson_iter_t *iter,
- const char *key,
- size_t v_utf8_len,
- const char *v_utf8,
- void *data);
- bool (*visit_document) (const bson_iter_t *iter,
- const char *key,
- const bson_t *v_document,
- void *data);
- bool (*visit_array) (const bson_iter_t *iter,
- const char *key,
- const bson_t *v_array,
- void *data);
- bool (*visit_binary) (const bson_iter_t *iter,
- const char *key,
- bson_subtype_t v_subtype,
- size_t v_binary_len,
- const uint8_t *v_binary,
- void *data);
- /* normal field with deprecated "Undefined" BSON type */
- bool (*visit_undefined) (const bson_iter_t *iter,
- const char *key,
- void *data);
- bool (*visit_oid) (const bson_iter_t *iter,
- const char *key,
- const bson_oid_t *v_oid,
- void *data);
- bool (*visit_bool) (const bson_iter_t *iter,
- const char *key,
- bool v_bool,
- void *data);
- bool (*visit_date_time) (const bson_iter_t *iter,
- const char *key,
- int64_t msec_since_epoch,
- void *data);
- bool (*visit_null) (const bson_iter_t *iter, const char *key, void *data);
- bool (*visit_regex) (const bson_iter_t *iter,
- const char *key,
- const char *v_regex,
- const char *v_options,
- void *data);
- bool (*visit_dbpointer) (const bson_iter_t *iter,
- const char *key,
- size_t v_collection_len,
- const char *v_collection,
- const bson_oid_t *v_oid,
- void *data);
- bool (*visit_code) (const bson_iter_t *iter,
- const char *key,
- size_t v_code_len,
- const char *v_code,
- void *data);
- bool (*visit_symbol) (const bson_iter_t *iter,
- const char *key,
- size_t v_symbol_len,
- const char *v_symbol,
- void *data);
- bool (*visit_codewscope) (const bson_iter_t *iter,
- const char *key,
- size_t v_code_len,
- const char *v_code,
- const bson_t *v_scope,
- void *data);
- bool (*visit_int32) (const bson_iter_t *iter,
- const char *key,
- int32_t v_int32,
- void *data);
- bool (*visit_timestamp) (const bson_iter_t *iter,
- const char *key,
- uint32_t v_timestamp,
- uint32_t v_increment,
- void *data);
- bool (*visit_int64) (const bson_iter_t *iter,
- const char *key,
- int64_t v_int64,
- void *data);
- bool (*visit_maxkey) (const bson_iter_t *iter, const char *key, void *data);
- bool (*visit_minkey) (const bson_iter_t *iter, const char *key, void *data);
- /* if set, called instead of visit_corrupt when an apparently valid BSON
- * includes an unrecognized field type (reading future version of BSON) */
- void (*visit_unsupported_type) (const bson_iter_t *iter,
- const char *key,
- uint32_t type_code,
- void *data);
- bool (*visit_decimal128) (const bson_iter_t *iter,
- const char *key,
- const bson_decimal128_t *v_decimal128,
- void *data);
-
- void *padding[7];
-} bson_visitor_t BSON_ALIGNED_END (8);
-
-#define BSON_ERROR_BUFFER_SIZE 504
-
-BSON_ALIGNED_BEGIN (8)
-typedef struct _bson_error_t {
- uint32_t domain;
- uint32_t code;
- char message[BSON_ERROR_BUFFER_SIZE];
-} bson_error_t BSON_ALIGNED_END (8);
-
-
-BSON_STATIC_ASSERT2 (error_t, sizeof (bson_error_t) == 512);
-
-
-/**
- * bson_next_power_of_two:
- * @v: A 32-bit unsigned integer of required bytes.
- *
- * Determines the next larger power of two for the value of @v
- * in a constant number of operations.
- *
- * It is up to the caller to guarantee this will not overflow.
- *
- * Returns: The next power of 2 from @v.
- */
-static BSON_INLINE size_t
-bson_next_power_of_two (size_t v)
-{
- v--;
- v |= v >> 1;
- v |= v >> 2;
- v |= v >> 4;
- v |= v >> 8;
- v |= v >> 16;
-#if BSON_WORD_SIZE == 64
- v |= v >> 32;
-#endif
- v++;
-
- return v;
-}
-
-
-static BSON_INLINE bool
-bson_is_power_of_two (uint32_t v)
-{
- return ((v != 0) && ((v & (v - 1)) == 0));
-}
-
-
-BSON_END_DECLS
-
-
-#endif /* BSON_TYPES_H */
diff --git a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-version.h b/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-version.h
deleted file mode 100644
index 74ff9cec..00000000
--- a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-version.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright 2013 MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-#if !defined (BSON_INSIDE) && !defined (BSON_COMPILATION)
-#error "Only <bson/bson.h> can be included directly."
-#endif
-
-
-#ifndef BSON_VERSION_H
-#define BSON_VERSION_H
-
-
-/**
- * BSON_MAJOR_VERSION:
- *
- * BSON major version component (e.g. 1 if %BSON_VERSION is 1.2.3)
- */
-#define BSON_MAJOR_VERSION (1)
-
-
-/**
- * BSON_MINOR_VERSION:
- *
- * BSON minor version component (e.g. 2 if %BSON_VERSION is 1.2.3)
- */
-#define BSON_MINOR_VERSION (20)
-
-
-/**
- * BSON_MICRO_VERSION:
- *
- * BSON micro version component (e.g. 3 if %BSON_VERSION is 1.2.3)
- */
-#define BSON_MICRO_VERSION (0)
-
-
-/**
- * BSON_PRERELEASE_VERSION:
- *
- * BSON prerelease version component (e.g. pre if %BSON_VERSION is 1.2.3-pre)
- */
-#define BSON_PRERELEASE_VERSION ()
-
-/**
- * BSON_VERSION:
- *
- * BSON version.
- */
-#define BSON_VERSION (1.20.0)
-
-
-/**
- * BSON_VERSION_S:
- *
- * BSON version, encoded as a string, useful for printing and
- * concatenation.
- */
-#define BSON_VERSION_S "1.20.0"
-
-
-/**
- * BSON_VERSION_HEX:
- *
- * BSON version, encoded as an hexadecimal number, useful for
- * integer comparisons.
- */
-#define BSON_VERSION_HEX (BSON_MAJOR_VERSION << 24 | \
- BSON_MINOR_VERSION << 16 | \
- BSON_MICRO_VERSION << 8)
-
-
-/**
- * BSON_CHECK_VERSION:
- * @major: required major version
- * @minor: required minor version
- * @micro: required micro version
- *
- * Compile-time version checking. Evaluates to %TRUE if the version
- * of BSON is greater than the required one.
- */
-#define BSON_CHECK_VERSION(major,minor,micro) \
- (BSON_MAJOR_VERSION > (major) || \
- (BSON_MAJOR_VERSION == (major) && BSON_MINOR_VERSION > (minor)) || \
- (BSON_MAJOR_VERSION == (major) && BSON_MINOR_VERSION == (minor) && \
- BSON_MICRO_VERSION >= (micro)))
-
-#endif /* BSON_VERSION_H */
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-aggregate.c b/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-aggregate.c
deleted file mode 100644
index 9b078179..00000000
--- a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-aggregate.c
+++ /dev/null
@@ -1,319 +0,0 @@
-/*
- * Copyright 2019 MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-#include "mongoc-aggregate-private.h"
-#include "mongoc-client-private.h"
-#include "mongoc-cursor-private.h"
-#include "mongoc-read-prefs-private.h"
-#include "mongoc-server-stream-private.h"
-#include "mongoc-trace-private.h"
-#include "mongoc-util-private.h"
-
-
-/*--------------------------------------------------------------------------
- *
- * _has_write_key --
- *
- * Returns true if the aggregation pipeline's last stage is "$out"
- * or "$merge"; otherwise returns false.
- *
- * Side effects:
- * Advances @iter to the last element.
- *
- *--------------------------------------------------------------------------
- */
-
-bool
-_has_write_key (bson_iter_t *iter)
-{
- bson_iter_t stage;
- bson_iter_t next;
-
- memcpy (&next, iter, sizeof (bson_iter_t));
- if (!bson_iter_next (&next)) {
- /* default to false when iter is emtpy */
- return false;
- }
-
- while (bson_iter_next (iter)) {
- if (!bson_iter_next (&next) && BSON_ITER_HOLDS_DOCUMENT (iter)) {
- bson_iter_recurse (iter, &stage);
- if (bson_iter_find (&stage, "$out")) {
- return true;
- }
-
- bson_iter_recurse (iter, &stage);
- if (bson_iter_find (&stage, "$merge")) {
- return true;
- }
- }
- }
-
- return false;
-}
-
-
-/*--------------------------------------------------------------------------
- *
- * _make_agg_cmd --
- *
- * Constructs an aggregate command. If @ns does not include a collection
- * name, 1 will be used in its place for the value of "aggregate" in the
- * command document.
- *
- * Returns:
- * true if successful; otherwise false and @error is set.
- *
- * Side effects:
- * @command is always initialized.
- * @error is set if there is a failure.
- *
- *--------------------------------------------------------------------------
- */
-
-static bool
-_make_agg_cmd (const char *ns,
- const bson_t *pipeline,
- mongoc_aggregate_opts_t *opts,
- bson_t *command,
- bson_error_t *err)
-{
- const char *dot;
- bson_iter_t iter;
- bson_t child;
- bool has_write_key;
- bson_iter_t has_write_key_iter;
-
- bson_init (command);
-
- dot = strstr (ns, ".");
-
- if (dot) {
- /* Note: we're not validating that the collection name's length is one or
- * more characters, as functions such as mongoc_client_get_collection also
- * do not validate. */
- BSON_APPEND_UTF8 (command, "aggregate", dot + 1);
- } else {
- BSON_APPEND_INT32 (command, "aggregate", 1);
- }
-
- /*
- * The following will allow @pipeline to be either an array of
- * items for the pipeline, or {"pipeline": [...]}.
- */
- if (bson_iter_init_find (&iter, pipeline, "pipeline") &&
- BSON_ITER_HOLDS_ARRAY (&iter)) {
- bson_iter_recurse (&iter, &has_write_key_iter);
- if (!bson_append_iter (command, "pipeline", 8, &iter)) {
- bson_set_error (err,
- MONGOC_ERROR_COMMAND,
- MONGOC_ERROR_COMMAND_INVALID_ARG,
- "Failed to append \"pipeline\" to create command.");
- return false;
- }
- } else {
- BSON_APPEND_ARRAY (command, "pipeline", pipeline);
- bson_iter_init (&has_write_key_iter, pipeline);
- }
-
- has_write_key = _has_write_key (&has_write_key_iter);
- bson_append_document_begin (command, "cursor", 6, &child);
- /* Ignore batchSize=0 for aggregates with $out or $merge */
- if (opts->batchSize_is_set && !(has_write_key && opts->batchSize == 0)) {
- BSON_APPEND_INT32 (&child, "batchSize", opts->batchSize);
- }
-
- bson_append_document_end (command, &child);
- return true;
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_aggregate --
- *
- * Constructs a mongoc_cursor_t for an "aggregate" command.
- *
- * This function will always return a new mongoc_cursor_t that should
- * be freed with mongoc_cursor_destroy().
- *
- * The cursor may fail once iterated upon, so check
- * mongoc_cursor_error() if mongoc_cursor_next() returns false.
- *
- * See http://docs.mongodb.org/manual/aggregation/ for more
- * information on how to build aggregation pipelines.
- *
- * Parameters:
- * @ns: Namespace (or database name for database-level aggregation).
- * @flags: Bitwise or of mongoc_query_flags_t or 0.
- * @pipeline: A bson_t containing the pipeline request. @pipeline
- * will be sent as an array type in the request.
- * @opts: A bson_t containing aggregation options, such as
- * bypassDocumentValidation (used with $out and $merge), maxTimeMS
- * (declaring maximum server execution time) and explain (return
- * information on the processing of the pipeline).
- * @user_rp: Optional read preferences for the command.
- * @default_rp: Default read preferences from the collection or database.
- * @default_rc: Default read concern from the collection or database.
- * @default_wc: Default write concern from the collection or database.
- *
- * Returns:
- * A newly allocated mongoc_cursor_t that should be freed with
- * mongoc_cursor_destroy().
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-mongoc_cursor_t *
-_mongoc_aggregate (mongoc_client_t *client,
- const char *ns,
- mongoc_query_flags_t flags,
- const bson_t *pipeline,
- const bson_t *opts,
- const mongoc_read_prefs_t *user_rp,
- const mongoc_read_prefs_t *default_rp,
- const mongoc_read_concern_t *default_rc,
- const mongoc_write_concern_t *default_wc)
-
-{
- mongoc_server_stream_t *server_stream = NULL;
- bool has_write_key;
- bson_iter_t ar;
- mongoc_cursor_t *cursor;
- bson_iter_t iter;
- bson_t command;
- bson_t cursor_opts;
- bool created_command;
- bson_error_t create_cmd_err = {0};
- mongoc_aggregate_opts_t aggregate_opts;
- bson_error_t opts_err = {0};
- bool parsed_opts;
-
- ENTRY;
-
- BSON_ASSERT (client);
- BSON_ASSERT (ns);
- BSON_ASSERT (pipeline);
-
- bson_init (&cursor_opts);
- _mongoc_cursor_flags_to_opts (flags, &cursor_opts, NULL);
- if (opts) {
- bson_concat (&cursor_opts /* destination */, opts /* source */);
- }
-
- parsed_opts =
- _mongoc_aggregate_opts_parse (client, opts, &aggregate_opts, &opts_err);
-
- if (parsed_opts) {
- created_command = _make_agg_cmd (
- ns, pipeline, &aggregate_opts, &command, &create_cmd_err);
- } else {
- created_command = false;
- }
-
- cursor = _mongoc_cursor_cmd_new (client,
- ns,
- created_command ? &command : NULL,
- &cursor_opts,
- user_rp,
- default_rp,
- default_rc);
-
- if (created_command) {
- bson_destroy (&command);
- }
- bson_destroy (&cursor_opts);
-
- if (!parsed_opts) {
- memcpy (&cursor->error, &opts_err, sizeof (bson_error_t));
- GOTO (done);
- }
-
- if (!created_command) {
- /* copy error back to cursor. */
- memcpy (&cursor->error, &create_cmd_err, sizeof (bson_error_t));
- GOTO (done);
- }
-
- if (mongoc_cursor_error (cursor, NULL)) {
- GOTO (done);
- }
-
- if (!_mongoc_read_prefs_validate (cursor->read_prefs, &cursor->error)) {
- GOTO (done);
- }
-
- /* pipeline could be like {pipeline: [{$out: 'test'}]} or [{$out: 'test'}] */
- if (bson_iter_init_find (&iter, pipeline, "pipeline") &&
- BSON_ITER_HOLDS_ARRAY (&iter) && bson_iter_recurse (&iter, &ar)) {
- has_write_key = _has_write_key (&ar);
- } else {
- if (!bson_iter_init (&iter, pipeline)) {
- bson_set_error (&cursor->error,
- MONGOC_ERROR_BSON,
- MONGOC_ERROR_BSON_INVALID,
- "Pipeline is invalid BSON");
- GOTO (done);
- }
- has_write_key = _has_write_key (&iter);
- }
-
- if (has_write_key && cursor->read_prefs->mode != MONGOC_READ_PRIMARY) {
- mongoc_read_prefs_destroy (cursor->read_prefs);
- cursor->read_prefs = mongoc_read_prefs_new (MONGOC_READ_PRIMARY);
- MONGOC_WARNING ("$out or $merge stage specified. Overriding read "
- "preference to primary.");
- }
-
- /* server id isn't enough. ensure we're connected & know wire version */
- server_stream = _mongoc_cursor_fetch_stream (cursor);
- if (!server_stream) {
- GOTO (done);
- }
-
- if (aggregate_opts.write_concern_owned && has_write_key &&
- server_stream->sd->max_wire_version < WIRE_VERSION_CMD_WRITE_CONCERN) {
- bson_set_error (
- &cursor->error,
- MONGOC_ERROR_COMMAND,
- MONGOC_ERROR_PROTOCOL_BAD_WIRE_VERSION,
- "\"aggregate\" with \"$out\" or \"$merge\" does not support "
- "writeConcern with wire version %d, wire version %d is "
- "required",
- server_stream->sd->max_wire_version,
- WIRE_VERSION_CMD_WRITE_CONCERN);
- GOTO (done);
- }
-
- /* Only inherit WriteConcern when aggregate has $out or $merge */
- if (!aggregate_opts.write_concern_owned && has_write_key) {
- mongoc_write_concern_destroy (cursor->write_concern);
- cursor->write_concern = mongoc_write_concern_copy (default_wc);
- }
-
-done:
- _mongoc_aggregate_opts_cleanup (&aggregate_opts);
- mongoc_server_stream_cleanup (server_stream); /* null ok */
-
- /* we always return the cursor, even if it fails; users can detect the
- * failure on performing a cursor operation. see CDRIVER-880. */
- RETURN (cursor);
-}
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-change-stream.c b/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-change-stream.c
deleted file mode 100644
index 533496cf..00000000
--- a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-change-stream.c
+++ /dev/null
@@ -1,664 +0,0 @@
-/*
- * Copyright 2017-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <bson/bson.h>
-#include "mongoc-cluster-private.h"
-#include "mongoc-change-stream-private.h"
-#include "mongoc-collection-private.h"
-#include "mongoc-client-private.h"
-#include "mongoc-client-session-private.h"
-#include "mongoc-cursor-private.h"
-#include "mongoc-database-private.h"
-#include "mongoc-error.h"
-#include "mongoc-error-private.h"
-
-#define CHANGE_STREAM_ERR(_str) \
- bson_set_error (&stream->err, \
- MONGOC_ERROR_CURSOR, \
- MONGOC_ERROR_BSON, \
- "Could not set " _str);
-
-/* the caller knows either a client or server error has occurred.
- * `reply` contains the server reply or an empty document. */
-static bool
-_is_resumable_error (mongoc_change_stream_t *stream, const bson_t *reply)
-{
- bson_error_t error = {0};
-
- /* Change Streams Spec resumable criteria: "any error encountered which is
- * not a server error (e.g. a timeout error or network error)" */
- if (bson_empty (reply)) {
- return true;
- }
-
- if (_mongoc_cmd_check_ok (reply, MONGOC_ERROR_API_VERSION_2, &error)) {
- return true;
- }
-
- if (error.code == MONGOC_SERVER_ERR_CURSOR_NOT_FOUND) {
- return true;
- }
-
- if (stream->max_wire_version >= WIRE_VERSION_4_4) {
- return mongoc_error_has_label (reply, "ResumableChangeStreamError");
- }
-
- switch (error.code) {
- case MONGOC_SERVER_ERR_HOSTUNREACHABLE:
- case MONGOC_SERVER_ERR_HOSTNOTFOUND:
- case MONGOC_SERVER_ERR_NETWORKTIMEOUT:
- case MONGOC_SERVER_ERR_SHUTDOWNINPROGRESS:
- case MONGOC_SERVER_ERR_PRIMARYSTEPPEDDOWN:
- case MONGOC_SERVER_ERR_EXCEEDEDTIMELIMIT:
- case MONGOC_SERVER_ERR_SOCKETEXCEPTION:
- case MONGOC_SERVER_ERR_NOTPRIMARY:
- case MONGOC_SERVER_ERR_INTERRUPTEDATSHUTDOWN:
- case MONGOC_SERVER_ERR_INTERRUPTEDDUETOREPLSTATECHANGE:
- case MONGOC_SERVER_ERR_NOTPRIMARYNOSECONDARYOK:
- case MONGOC_SERVER_ERR_NOTPRIMARYORSECONDARY:
- case MONGOC_SERVER_ERR_STALESHARDVERSION:
- case MONGOC_SERVER_ERR_STALEEPOCH:
- case MONGOC_SERVER_ERR_STALECONFIG:
- case MONGOC_SERVER_ERR_RETRYCHANGESTREAM:
- case MONGOC_SERVER_ERR_FAILEDTOSATISFYREADPREFERENCE:
- return true;
- default:
- return false;
- }
-}
-
-
-static void
-_set_resume_token (mongoc_change_stream_t *stream, const bson_t *resume_token)
-{
- BSON_ASSERT (stream);
- BSON_ASSERT (resume_token);
-
- bson_destroy (&stream->resume_token);
- bson_copy_to (resume_token, &stream->resume_token);
-}
-
-
-/* construct the aggregate command in cmd. looks like one of the following:
- * for a collection change stream:
- * { aggregate: collname, pipeline: [], cursor: { batchSize: x } }
- * for a database change stream:
- * { aggregate: 1, pipeline: [], cursor: { batchSize: x } }
- * for a client change stream:
- * { aggregate: 1, pipeline: [{$changeStream: {allChangesForCluster: true}}],
- * cursor: { batchSize: x } }
- */
-static void
-_make_command (mongoc_change_stream_t *stream, bson_t *command)
-{
- bson_iter_t iter;
- bson_t change_stream_stage; /* { $changeStream: <change_stream_doc> } */
- bson_t change_stream_doc;
- bson_t pipeline;
- bson_t cursor_doc;
-
- if (stream->change_stream_type == MONGOC_CHANGE_STREAM_COLLECTION) {
- bson_append_utf8 (
- command, "aggregate", 9, stream->coll, (int) strlen (stream->coll));
- } else {
- bson_append_int32 (command, "aggregate", 9, 1);
- }
-
- bson_append_array_begin (command, "pipeline", 8, &pipeline);
-
- /* append the $changeStream stage. */
- bson_append_document_begin (&pipeline, "0", 1, &change_stream_stage);
- bson_append_document_begin (
- &change_stream_stage, "$changeStream", 13, &change_stream_doc);
- bson_concat (&change_stream_doc, stream->full_document);
-
- if (stream->resumed) {
- /* Change stream spec: Resume Process */
- /* If there is a cached resumeToken: */
- if (!bson_empty (&stream->resume_token)) {
- /* If the ChangeStream was started with startAfter
- and has yet to return a result document: */
- if (!bson_empty (&stream->opts.startAfter) &&
- !stream->has_returned_results) {
- /* The driver MUST set startAfter to the cached resumeToken */
- BSON_APPEND_DOCUMENT (
- &change_stream_doc, "startAfter", &stream->resume_token);
- } else {
- /* The driver MUST set resumeAfter to the cached resumeToken */
- BSON_APPEND_DOCUMENT (
- &change_stream_doc, "resumeAfter", &stream->resume_token);
- }
- } else if (!_mongoc_timestamp_empty (&stream->operation_time) &&
- stream->max_wire_version >= WIRE_VERSION_4_0) {
- /* Else if there is no cached resumeToken and the ChangeStream
- has a saved operation time and the max wire version is >= 7,
- the driver MUST set startAtOperationTime */
- _mongoc_timestamp_append (&stream->operation_time,
- &change_stream_doc,
- "startAtOperationTime");
- }
- } else {
- /* Change streams spec: "startAtOperationTime, resumeAfter, and startAfter
- * are all mutually exclusive; if any two are set, the server will return
- * an error. Drivers MUST NOT throw a custom error, and MUST defer to the
- * server error." */
- if (!bson_empty (&stream->opts.resumeAfter)) {
- BSON_APPEND_DOCUMENT (
- &change_stream_doc, "resumeAfter", &stream->opts.resumeAfter);
-
- /* Update the cached resume token */
- _set_resume_token (stream, &stream->opts.resumeAfter);
- }
-
- if (!bson_empty (&stream->opts.startAfter)) {
- BSON_APPEND_DOCUMENT (
- &change_stream_doc, "startAfter", &stream->opts.startAfter);
-
- /* Update the cached resume token (take precedence over resumeAfter) */
- _set_resume_token (stream, &stream->opts.startAfter);
- }
-
- if (!_mongoc_timestamp_empty (&stream->operation_time)) {
- _mongoc_timestamp_append (&stream->operation_time,
- &change_stream_doc,
- "startAtOperationTime");
- }
- }
-
- if (stream->change_stream_type == MONGOC_CHANGE_STREAM_CLIENT) {
- bson_append_bool (&change_stream_doc, "allChangesForCluster", 20, true);
- }
- bson_append_document_end (&change_stream_stage, &change_stream_doc);
- bson_append_document_end (&pipeline, &change_stream_stage);
-
- /* Append user pipeline if it exists */
- if (bson_iter_init_find (&iter, &stream->pipeline_to_append, "pipeline") &&
- BSON_ITER_HOLDS_ARRAY (&iter)) {
- bson_iter_t child_iter;
- uint32_t key_int = 1;
- char buf[16];
- const char *key_str;
-
- BSON_ASSERT (bson_iter_recurse (&iter, &child_iter));
- while (bson_iter_next (&child_iter)) {
- /* the user pipeline may consist of invalid stages or non-documents.
- * append anyway, and rely on the server error. */
- size_t keyLen =
- bson_uint32_to_string (key_int, &key_str, buf, sizeof (buf));
- bson_append_value (
- &pipeline, key_str, (int) keyLen, bson_iter_value (&child_iter));
- ++key_int;
- }
- }
-
- bson_append_array_end (command, &pipeline);
-
- /* Add batch size if needed */
- bson_append_document_begin (command, "cursor", 6, &cursor_doc);
- if (stream->batch_size > 0) {
- bson_append_int32 (&cursor_doc, "batchSize", 9, stream->batch_size);
- }
- bson_append_document_end (command, &cursor_doc);
-}
-
-/*---------------------------------------------------------------------------
- *
- * _make_cursor --
- *
- * Construct and send the aggregate command and create the resulting
- * cursor. On error, stream->cursor remains NULL, otherwise it is
- * created and must be destroyed.
- *
- * Return:
- * False on error and sets stream->err.
- *
- *--------------------------------------------------------------------------
- */
-static bool
-_make_cursor (mongoc_change_stream_t *stream)
-{
- mongoc_client_session_t *cs = NULL;
- bson_t command_opts;
- bson_t command; /* { aggregate: "coll", pipeline: [], ... } */
- bson_t reply;
- bson_t getmore_opts = BSON_INITIALIZER;
- bson_iter_t iter;
- mongoc_server_stream_t *server_stream;
-
- BSON_ASSERT (stream);
- BSON_ASSERT (!stream->cursor);
- bson_init (&command);
- bson_copy_to (&(stream->opts.extra), &command_opts);
-
- if (bson_iter_init_find (&iter, &command_opts, "sessionId")) {
- if (!_mongoc_client_session_from_iter (
- stream->client, &iter, &cs, &stream->err)) {
- goto cleanup;
- }
- } else if (stream->implicit_session) {
- /* If an implicit session was created before, and this cursor is now
- * being recreated after resuming, then use the same session as before. */
- cs = stream->implicit_session;
- if (!mongoc_client_session_append (cs, &command_opts, &stream->err)) {
- goto cleanup;
- }
- } else {
- /* Create an implicit session. This session lsid must be the same for the
- * agg command and the subsequent getMores. Thus, this implicit session is
- * passed as if it were an explicit session to
- * mongoc_client_read_command_with_opts and
- * _mongoc_cursor_change_stream_new, but it is still implicit and its
- * lifetime is owned by this change_stream_t. */
- mongoc_session_opt_t *session_opts;
- session_opts = mongoc_session_opts_new ();
- mongoc_session_opts_set_causal_consistency (session_opts, false);
- /* returns NULL if sessions aren't supported. ignore errors. */
- cs = mongoc_client_start_session (stream->client, session_opts, NULL);
- stream->implicit_session = cs;
- mongoc_session_opts_destroy (session_opts);
- if (cs &&
- !mongoc_client_session_append (cs, &command_opts, &stream->err)) {
- goto cleanup;
- }
- }
-
- if (cs && !mongoc_client_session_append (cs, &getmore_opts, &stream->err)) {
- goto cleanup;
- }
-
- server_stream = mongoc_cluster_stream_for_reads (
- &stream->client->cluster, stream->read_prefs, cs, &reply, &stream->err);
- if (!server_stream) {
- bson_destroy (&stream->err_doc);
- bson_copy_to (&reply, &stream->err_doc);
- bson_destroy (&reply);
- goto cleanup;
- }
- bson_append_int32 (&command_opts, "serverId", 8, server_stream->sd->id);
- bson_append_int32 (&getmore_opts, "serverId", 8, server_stream->sd->id);
- stream->max_wire_version = server_stream->sd->max_wire_version;
- mongoc_server_stream_cleanup (server_stream);
-
- if (stream->read_concern && !bson_has_field (&command_opts, "readConcern")) {
- mongoc_read_concern_append (stream->read_concern, &command_opts);
- }
-
- _make_command (stream, &command);
-
- /* even though serverId has already been set, still pass the read prefs.
- * they are necessary for OP_MSG if sending to a secondary. */
- if (!mongoc_client_read_command_with_opts (stream->client,
- stream->db,
- &command,
- stream->read_prefs,
- &command_opts,
- &reply,
- &stream->err)) {
- bson_destroy (&stream->err_doc);
- bson_copy_to (&reply, &stream->err_doc);
- bson_destroy (&reply);
- goto cleanup;
- }
-
- bson_append_bool (
- &getmore_opts, MONGOC_CURSOR_TAILABLE, MONGOC_CURSOR_TAILABLE_LEN, true);
- bson_append_bool (&getmore_opts,
- MONGOC_CURSOR_AWAIT_DATA,
- MONGOC_CURSOR_AWAIT_DATA_LEN,
- true);
-
- /* maxTimeMS is only appended to getMores if these are set in cursor opts. */
- if (stream->max_await_time_ms > 0) {
- bson_append_int64 (&getmore_opts,
- MONGOC_CURSOR_MAX_AWAIT_TIME_MS,
- MONGOC_CURSOR_MAX_AWAIT_TIME_MS_LEN,
- stream->max_await_time_ms);
- }
-
- if (stream->batch_size > 0) {
- bson_append_int32 (&getmore_opts,
- MONGOC_CURSOR_BATCH_SIZE,
- MONGOC_CURSOR_BATCH_SIZE_LEN,
- stream->batch_size);
- }
-
- /* steals reply. */
- stream->cursor =
- _mongoc_cursor_change_stream_new (stream->client, &reply, &getmore_opts);
-
- if (mongoc_cursor_error (stream->cursor, NULL)) {
- goto cleanup;
- }
-
- /* Change stream spec: "When aggregate or getMore returns: If an empty batch
- * was returned and a postBatchResumeToken was included, cache it." */
- if (_mongoc_cursor_change_stream_end_of_batch (stream->cursor) &&
- _mongoc_cursor_change_stream_has_post_batch_resume_token (
- stream->cursor)) {
- _set_resume_token (
- stream,
- _mongoc_cursor_change_stream_get_post_batch_resume_token (
- stream->cursor));
- }
-
- /* Change stream spec: startAtOperationTime */
- if (bson_empty (&stream->opts.resumeAfter) &&
- bson_empty (&stream->opts.startAfter) &&
- _mongoc_timestamp_empty (&stream->operation_time) &&
- stream->max_wire_version >= WIRE_VERSION_4_0 &&
- bson_empty (&stream->resume_token) &&
- bson_iter_init_find (
- &iter,
- _mongoc_cursor_change_stream_get_reply (stream->cursor),
- "operationTime") &&
- BSON_ITER_HOLDS_TIMESTAMP (&iter)) {
- _mongoc_timestamp_set_from_bson (&stream->operation_time, &iter);
- }
-
-cleanup:
- bson_destroy (&command);
- bson_destroy (&command_opts);
- bson_destroy (&getmore_opts);
- return stream->err.code == 0;
-}
-
-/*---------------------------------------------------------------------------
- *
- * _change_stream_init --
- *
- * Called after @stream has the collection name, database name, read
- * preferences, and read concern set. Creates the change streams
- * cursor.
- *
- *--------------------------------------------------------------------------
- */
-void
-_change_stream_init (mongoc_change_stream_t *stream,
- const bson_t *pipeline,
- const bson_t *opts)
-{
- BSON_ASSERT (pipeline);
-
- stream->max_await_time_ms = -1;
- stream->batch_size = -1;
- bson_init (&stream->pipeline_to_append);
- bson_init (&stream->resume_token);
- bson_init (&stream->err_doc);
-
- if (!_mongoc_change_stream_opts_parse (
- stream->client, opts, &stream->opts, &stream->err)) {
- return;
- }
-
- stream->full_document = BCON_NEW ("fullDocument", stream->opts.fullDocument);
-
- _mongoc_timestamp_set (&stream->operation_time,
- &stream->opts.startAtOperationTime);
-
- stream->batch_size = stream->opts.batchSize;
- stream->max_await_time_ms = stream->opts.maxAwaitTimeMS;
-
- /* Accept two forms of user pipeline:
- * 1. A document like: { "pipeline": [...] }
- * 2. An array-like document: { "0": {}, "1": {}, ... }
- * If the passed pipeline is invalid, we pass it along and let the server
- * error instead.
- */
- if (!bson_empty (pipeline)) {
- bson_iter_t iter;
- if (bson_iter_init_find (&iter, pipeline, "pipeline") &&
- BSON_ITER_HOLDS_ARRAY (&iter)) {
- if (!BSON_APPEND_VALUE (&stream->pipeline_to_append,
- "pipeline",
- bson_iter_value (&iter))) {
- CHANGE_STREAM_ERR ("pipeline");
- }
- } else {
- if (!BSON_APPEND_ARRAY (
- &stream->pipeline_to_append, "pipeline", pipeline)) {
- CHANGE_STREAM_ERR ("pipeline");
- }
- }
- }
-
- if (stream->err.code == 0) {
- (void) _make_cursor (stream);
- }
-}
-
-mongoc_change_stream_t *
-_mongoc_change_stream_new_from_collection (const mongoc_collection_t *coll,
- const bson_t *pipeline,
- const bson_t *opts)
-{
- mongoc_change_stream_t *stream;
- BSON_ASSERT (coll);
-
- stream =
- (mongoc_change_stream_t *) bson_malloc0 (sizeof (mongoc_change_stream_t));
- stream->db = bson_strdup (coll->db);
- stream->coll = bson_strdup (coll->collection);
- stream->read_prefs = mongoc_read_prefs_copy (coll->read_prefs);
- stream->read_concern = mongoc_read_concern_copy (coll->read_concern);
- stream->client = coll->client;
- stream->change_stream_type = MONGOC_CHANGE_STREAM_COLLECTION;
- _change_stream_init (stream, pipeline, opts);
- return stream;
-}
-
-mongoc_change_stream_t *
-_mongoc_change_stream_new_from_database (const mongoc_database_t *db,
- const bson_t *pipeline,
- const bson_t *opts)
-{
- mongoc_change_stream_t *stream;
- BSON_ASSERT (db);
-
- stream =
- (mongoc_change_stream_t *) bson_malloc0 (sizeof (mongoc_change_stream_t));
- stream->db = bson_strdup (db->name);
- stream->coll = NULL;
- stream->read_prefs = mongoc_read_prefs_copy (db->read_prefs);
- stream->read_concern = mongoc_read_concern_copy (db->read_concern);
- stream->client = db->client;
- stream->change_stream_type = MONGOC_CHANGE_STREAM_DATABASE;
- _change_stream_init (stream, pipeline, opts);
- return stream;
-}
-
-mongoc_change_stream_t *
-_mongoc_change_stream_new_from_client (mongoc_client_t *client,
- const bson_t *pipeline,
- const bson_t *opts)
-{
- mongoc_change_stream_t *stream;
- BSON_ASSERT (client);
-
- stream =
- (mongoc_change_stream_t *) bson_malloc0 (sizeof (mongoc_change_stream_t));
- stream->db = bson_strdup ("admin");
- stream->coll = NULL;
- stream->read_prefs = mongoc_read_prefs_copy (client->read_prefs);
- stream->read_concern = mongoc_read_concern_copy (client->read_concern);
- stream->client = client;
- stream->change_stream_type = MONGOC_CHANGE_STREAM_CLIENT;
- _change_stream_init (stream, pipeline, opts);
- return stream;
-}
-
-
-const bson_t *
-mongoc_change_stream_get_resume_token (mongoc_change_stream_t *stream)
-{
- if (!bson_empty (&stream->resume_token)) {
- return &stream->resume_token;
- }
-
- return NULL;
-}
-
-
-bool
-mongoc_change_stream_next (mongoc_change_stream_t *stream, const bson_t **bson)
-{
- bson_iter_t iter;
- bson_t doc_resume_token;
- uint32_t len;
- const uint8_t *data;
- bool ret = false;
-
- BSON_ASSERT (stream);
- BSON_ASSERT (bson);
-
- if (stream->err.code != 0) {
- goto end;
- }
-
- BSON_ASSERT (stream->cursor);
- if (!mongoc_cursor_next (stream->cursor, bson)) {
- const bson_t *err_doc;
- bson_error_t err;
- bool resumable = false;
-
- if (!mongoc_cursor_error_document (stream->cursor, &err, &err_doc)) {
- /* no error occurred, just no documents left. */
- goto end;
- }
-
- resumable = _is_resumable_error (stream, err_doc);
- while (resumable) {
- /* recreate the cursor. */
- mongoc_cursor_destroy (stream->cursor);
- stream->cursor = NULL;
- stream->resumed = true;
- if (!_make_cursor (stream)) {
- goto end;
- }
- if (mongoc_cursor_next (stream->cursor, bson)) {
- break;
- }
- if (!mongoc_cursor_error_document (stream->cursor, &err, &err_doc)) {
- goto end;
- }
- if (err_doc) {
- resumable = _is_resumable_error (stream, err_doc);
- } else {
- resumable = false;
- }
- }
-
- if (!resumable) {
- stream->err = err;
- bson_destroy (&stream->err_doc);
- bson_copy_to (err_doc, &stream->err_doc);
- goto end;
- }
- }
-
- /* we have received documents, either from the first call to next or after a
- * resume. */
- stream->has_returned_results = true;
-
- if (!bson_iter_init_find (&iter, *bson, "_id") ||
- !BSON_ITER_HOLDS_DOCUMENT (&iter)) {
- bson_set_error (&stream->err,
- MONGOC_ERROR_CURSOR,
- MONGOC_ERROR_CHANGE_STREAM_NO_RESUME_TOKEN,
- "Cannot provide resume functionality when the resume "
- "token is missing");
- goto end;
- }
-
- /* copy the resume token. */
- bson_iter_document (&iter, &len, &data);
- BSON_ASSERT (bson_init_static (&doc_resume_token, data, len));
- _set_resume_token (stream, &doc_resume_token);
-
- /* clear out the operation time, since we no longer need it to resume. */
- _mongoc_timestamp_clear (&stream->operation_time);
- ret = true;
-
-end:
- /* Change stream spec: Updating the Cached Resume Token */
- if (stream->cursor && !mongoc_cursor_error (stream->cursor, NULL) &&
- _mongoc_cursor_change_stream_end_of_batch (stream->cursor) &&
- _mongoc_cursor_change_stream_has_post_batch_resume_token (
- stream->cursor)) {
- _set_resume_token (
- stream,
- _mongoc_cursor_change_stream_get_post_batch_resume_token (
- stream->cursor));
- }
-
-
- /* Driver Sessions Spec: "When an implicit session is associated with a
- * cursor for use with getMore operations, the session MUST be returned to
- * the pool immediately following a getMore operation that indicates that the
- * cursor has been exhausted." */
- if (stream->implicit_session) {
- /* if creating the change stream cursor errored, it may be null. */
- if (!stream->cursor || stream->cursor->cursor_id == 0) {
- mongoc_client_session_destroy (stream->implicit_session);
- stream->implicit_session = NULL;
- }
- }
- return ret;
-}
-
-bool
-mongoc_change_stream_error_document (const mongoc_change_stream_t *stream,
- bson_error_t *err,
- const bson_t **bson)
-{
- BSON_ASSERT (stream);
-
- if (stream->err.code != 0) {
- if (err) {
- *err = stream->err;
- }
- if (bson) {
- *bson = &stream->err_doc;
- }
- return true;
- }
-
- if (bson) {
- *bson = NULL;
- }
- return false;
-}
-
-void
-mongoc_change_stream_destroy (mongoc_change_stream_t *stream)
-{
- if (!stream) {
- return;
- }
-
- bson_destroy (&stream->pipeline_to_append);
- bson_destroy (&stream->resume_token);
- bson_destroy (stream->full_document);
- bson_destroy (&stream->err_doc);
- _mongoc_change_stream_opts_cleanup (&stream->opts);
- mongoc_cursor_destroy (stream->cursor);
- mongoc_client_session_destroy (stream->implicit_session);
- mongoc_read_prefs_destroy (stream->read_prefs);
- mongoc_read_concern_destroy (stream->read_concern);
-
- bson_free (stream->db);
- bson_free (stream->coll);
- bson_free (stream);
-}
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-pool.c b/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-pool.c
deleted file mode 100644
index 73fe761f..00000000
--- a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-pool.c
+++ /dev/null
@@ -1,545 +0,0 @@
-/*
- * Copyright 2013 MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-#include "mongoc.h"
-#include "mongoc-apm-private.h"
-#include "mongoc-counters-private.h"
-#include "mongoc-client-pool-private.h"
-#include "mongoc-client-pool.h"
-#include "mongoc-client-private.h"
-#include "mongoc-client-side-encryption-private.h"
-#include "mongoc-queue-private.h"
-#include "mongoc-thread-private.h"
-#include "mongoc-topology-private.h"
-#include "mongoc-topology-background-monitoring-private.h"
-#include "mongoc-trace-private.h"
-
-#ifdef MONGOC_ENABLE_SSL
-#include "mongoc-ssl-private.h"
-#endif
-
-struct _mongoc_client_pool_t {
- bson_mutex_t mutex;
- mongoc_cond_t cond;
- mongoc_queue_t queue;
- mongoc_topology_t *topology;
- mongoc_uri_t *uri;
- uint32_t min_pool_size;
- uint32_t max_pool_size;
- uint32_t size;
-#ifdef MONGOC_ENABLE_SSL
- bool ssl_opts_set;
- mongoc_ssl_opt_t ssl_opts;
-#endif
- bool apm_callbacks_set;
- mongoc_apm_callbacks_t apm_callbacks;
- void *apm_context;
- int32_t error_api_version;
- bool error_api_set;
- mongoc_server_api_t *api;
- bool client_initialized;
-};
-
-
-#ifdef MONGOC_ENABLE_SSL
-void
-mongoc_client_pool_set_ssl_opts (mongoc_client_pool_t *pool,
- const mongoc_ssl_opt_t *opts)
-{
- bson_mutex_lock (&pool->mutex);
-
- _mongoc_ssl_opts_cleanup (&pool->ssl_opts,
- false /* don't free internal opts. */);
-
- pool->ssl_opts_set = false;
-
- if (opts) {
- _mongoc_ssl_opts_copy_to (
- opts, &pool->ssl_opts, false /* don't overwrite internal opts. */);
- pool->ssl_opts_set = true;
- }
-
- mongoc_topology_scanner_set_ssl_opts (pool->topology->scanner,
- &pool->ssl_opts);
-
- bson_mutex_unlock (&pool->mutex);
-}
-
-void
-_mongoc_client_pool_set_internal_tls_opts (
- mongoc_client_pool_t *pool, _mongoc_internal_tls_opts_t *internal)
-{
- bson_mutex_lock (&pool->mutex);
- if (!pool->ssl_opts_set) {
- bson_mutex_unlock (&pool->mutex);
- return;
- }
- pool->ssl_opts.internal = bson_malloc (sizeof (_mongoc_internal_tls_opts_t));
- memcpy (
- pool->ssl_opts.internal, internal, sizeof (_mongoc_internal_tls_opts_t));
- bson_mutex_unlock (&pool->mutex);
-}
-#endif
-
-
-mongoc_client_pool_t *
-mongoc_client_pool_new (const mongoc_uri_t *uri)
-{
- mongoc_topology_t *topology;
- mongoc_client_pool_t *pool;
- const bson_t *b;
- bson_iter_t iter;
- const char *appname;
-
-
- ENTRY;
-
- BSON_ASSERT (uri);
-
-#ifndef MONGOC_ENABLE_SSL
- if (mongoc_uri_get_tls (uri)) {
- MONGOC_ERROR ("Can't create SSL client pool,"
- " SSL not enabled in this build.");
- return NULL;
- }
-#endif
-
- pool = (mongoc_client_pool_t *) bson_malloc0 (sizeof *pool);
- bson_mutex_init (&pool->mutex);
- mongoc_cond_init (&pool->cond);
- _mongoc_queue_init (&pool->queue);
- pool->uri = mongoc_uri_copy (uri);
- pool->min_pool_size = 0;
- pool->max_pool_size = 100;
- pool->size = 0;
-
- topology = mongoc_topology_new (uri, false);
- pool->topology = topology;
- pool->error_api_version = MONGOC_ERROR_API_VERSION_LEGACY;
-
- b = mongoc_uri_get_options (pool->uri);
-
- if (bson_iter_init_find_case (&iter, b, MONGOC_URI_MINPOOLSIZE)) {
- MONGOC_WARNING (
- MONGOC_URI_MINPOOLSIZE
- " is deprecated; its behavior does not match its name, and its actual"
- " behavior will likely hurt performance.");
-
- if (BSON_ITER_HOLDS_INT32 (&iter)) {
- pool->min_pool_size = BSON_MAX (0, bson_iter_int32 (&iter));
- }
- }
-
- if (bson_iter_init_find_case (&iter, b, MONGOC_URI_MAXPOOLSIZE)) {
- if (BSON_ITER_HOLDS_INT32 (&iter)) {
- pool->max_pool_size = BSON_MAX (1, bson_iter_int32 (&iter));
- }
- }
-
- appname =
- mongoc_uri_get_option_as_utf8 (pool->uri, MONGOC_URI_APPNAME, NULL);
- if (appname) {
- /* the appname should have already been validated */
- BSON_ASSERT (mongoc_client_pool_set_appname (pool, appname));
- }
-
-#ifdef MONGOC_ENABLE_SSL
- if (mongoc_uri_get_tls (pool->uri)) {
- mongoc_ssl_opt_t ssl_opt = {0};
- _mongoc_internal_tls_opts_t internal_tls_opts = {0};
-
- _mongoc_ssl_opts_from_uri (&ssl_opt, &internal_tls_opts, pool->uri);
- /* sets use_ssl = true */
- mongoc_client_pool_set_ssl_opts (pool, &ssl_opt);
- _mongoc_client_pool_set_internal_tls_opts (pool, &internal_tls_opts);
- }
-#endif
- mongoc_counter_client_pools_active_inc ();
-
- RETURN (pool);
-}
-
-
-void
-mongoc_client_pool_destroy (mongoc_client_pool_t *pool)
-{
- mongoc_client_t *client;
-
- ENTRY;
-
- if (!pool) {
- EXIT;
- }
-
- if (!mongoc_server_session_pool_is_empty (pool->topology->session_pool)) {
- client = mongoc_client_pool_pop (pool);
- _mongoc_client_end_sessions (client);
- mongoc_client_pool_push (pool, client);
- }
-
- while (
- (client = (mongoc_client_t *) _mongoc_queue_pop_head (&pool->queue))) {
- mongoc_client_destroy (client);
- }
-
- mongoc_topology_destroy (pool->topology);
-
- mongoc_uri_destroy (pool->uri);
- bson_mutex_destroy (&pool->mutex);
- mongoc_cond_destroy (&pool->cond);
-
- mongoc_server_api_destroy (pool->api);
-
-#ifdef MONGOC_ENABLE_SSL
- _mongoc_ssl_opts_cleanup (&pool->ssl_opts, true);
-#endif
-
- bson_free (pool);
-
- mongoc_counter_client_pools_active_dec ();
- mongoc_counter_client_pools_disposed_inc ();
-
- EXIT;
-}
-
-
-/*
- * Start the background topology scanner.
- *
- * This function assumes the pool's mutex is locked
- */
-static void
-_start_scanner_if_needed (mongoc_client_pool_t *pool)
-{
- if (!pool->topology->single_threaded) {
- _mongoc_topology_background_monitoring_start (pool->topology);
- }
-}
-
-static void
-_initialize_new_client (mongoc_client_pool_t *pool, mongoc_client_t *client)
-{
- /* for tests */
- mongoc_client_set_stream_initiator (
- client,
- pool->topology->scanner->initiator,
- pool->topology->scanner->initiator_context);
-
- pool->client_initialized = true;
- client->is_pooled = true;
- client->error_api_version = pool->error_api_version;
- _mongoc_client_set_apm_callbacks_private (
- client, &pool->apm_callbacks, pool->apm_context);
-
- client->api = mongoc_server_api_copy (pool->api);
-
-#ifdef MONGOC_ENABLE_SSL
- if (pool->ssl_opts_set) {
- mongoc_client_set_ssl_opts (client, &pool->ssl_opts);
- }
-#endif
-}
-
-mongoc_client_t *
-mongoc_client_pool_pop (mongoc_client_pool_t *pool)
-{
- mongoc_client_t *client;
- int32_t wait_queue_timeout_ms;
- int64_t expire_at_ms = -1;
- int64_t now_ms;
- int r;
-
- ENTRY;
-
- BSON_ASSERT (pool);
-
- wait_queue_timeout_ms = mongoc_uri_get_option_as_int32 (
- pool->uri, MONGOC_URI_WAITQUEUETIMEOUTMS, -1);
- if (wait_queue_timeout_ms > 0) {
- expire_at_ms =
- (bson_get_monotonic_time () / 1000) + wait_queue_timeout_ms;
- }
- bson_mutex_lock (&pool->mutex);
-
-again:
- if (!(client = (mongoc_client_t *) _mongoc_queue_pop_head (&pool->queue))) {
- if (pool->size < pool->max_pool_size) {
- client = _mongoc_client_new_from_uri (pool->topology);
- _initialize_new_client (pool, client);
- pool->size++;
- } else {
- if (wait_queue_timeout_ms > 0) {
- now_ms = bson_get_monotonic_time () / 1000;
- if (now_ms < expire_at_ms) {
- r = mongoc_cond_timedwait (
- &pool->cond, &pool->mutex, expire_at_ms - now_ms);
- if (mongo_cond_ret_is_timedout (r)) {
- GOTO (done);
- }
- } else {
- GOTO (done);
- }
- } else {
- mongoc_cond_wait (&pool->cond, &pool->mutex);
- }
- GOTO (again);
- }
- }
-
- _start_scanner_if_needed (pool);
-done:
- bson_mutex_unlock (&pool->mutex);
-
- RETURN (client);
-}
-
-
-mongoc_client_t *
-mongoc_client_pool_try_pop (mongoc_client_pool_t *pool)
-{
- mongoc_client_t *client;
-
- ENTRY;
-
- BSON_ASSERT (pool);
-
- bson_mutex_lock (&pool->mutex);
-
- if (!(client = (mongoc_client_t *) _mongoc_queue_pop_head (&pool->queue))) {
- if (pool->size < pool->max_pool_size) {
- client = _mongoc_client_new_from_uri (pool->topology);
- _initialize_new_client (pool, client);
- pool->size++;
- }
- }
-
- if (client) {
- _start_scanner_if_needed (pool);
- }
- bson_mutex_unlock (&pool->mutex);
-
- RETURN (client);
-}
-
-
-void
-mongoc_client_pool_push (mongoc_client_pool_t *pool, mongoc_client_t *client)
-{
- ENTRY;
-
- BSON_ASSERT (pool);
- BSON_ASSERT (client);
-
- bson_mutex_lock (&pool->mutex);
- _mongoc_queue_push_head (&pool->queue, client);
-
- if (pool->min_pool_size &&
- _mongoc_queue_get_length (&pool->queue) > pool->min_pool_size) {
- mongoc_client_t *old_client;
- old_client = (mongoc_client_t *) _mongoc_queue_pop_tail (&pool->queue);
- if (old_client) {
- mongoc_client_destroy (old_client);
- pool->size--;
- }
- }
-
- mongoc_cond_signal (&pool->cond);
- bson_mutex_unlock (&pool->mutex);
-
- EXIT;
-}
-
-/* for tests */
-void
-_mongoc_client_pool_set_stream_initiator (mongoc_client_pool_t *pool,
- mongoc_stream_initiator_t si,
- void *context)
-{
- mongoc_topology_scanner_set_stream_initiator (
- pool->topology->scanner, si, context);
-}
-
-/* for tests */
-size_t
-mongoc_client_pool_get_size (mongoc_client_pool_t *pool)
-{
- size_t size = 0;
-
- ENTRY;
-
- bson_mutex_lock (&pool->mutex);
- size = pool->size;
- bson_mutex_unlock (&pool->mutex);
-
- RETURN (size);
-}
-
-
-size_t
-mongoc_client_pool_num_pushed (mongoc_client_pool_t *pool)
-{
- size_t num_pushed = 0;
-
- ENTRY;
-
- bson_mutex_lock (&pool->mutex);
- num_pushed = pool->queue.length;
- bson_mutex_unlock (&pool->mutex);
-
- RETURN (num_pushed);
-}
-
-
-mongoc_topology_t *
-_mongoc_client_pool_get_topology (mongoc_client_pool_t *pool)
-{
- return pool->topology;
-}
-
-
-void
-mongoc_client_pool_max_size (mongoc_client_pool_t *pool, uint32_t max_pool_size)
-{
- ENTRY;
-
- bson_mutex_lock (&pool->mutex);
- pool->max_pool_size = max_pool_size;
- bson_mutex_unlock (&pool->mutex);
-
- EXIT;
-}
-
-void
-mongoc_client_pool_min_size (mongoc_client_pool_t *pool, uint32_t min_pool_size)
-{
- ENTRY;
-
- MONGOC_WARNING (
- "mongoc_client_pool_min_size is deprecated; its behavior does not match"
- " its name, and its actual behavior will likely hurt performance.");
-
- bson_mutex_lock (&pool->mutex);
- pool->min_pool_size = min_pool_size;
- bson_mutex_unlock (&pool->mutex);
-
- EXIT;
-}
-
-bool
-mongoc_client_pool_set_apm_callbacks (mongoc_client_pool_t *pool,
- mongoc_apm_callbacks_t *callbacks,
- void *context)
-{
- mongoc_topology_t *const topology = BSON_ASSERT_PTR_INLINE (pool)->topology;
- mc_tpld_modification tdmod;
-
- if (pool->apm_callbacks_set) {
- MONGOC_ERROR ("Can only set callbacks once");
- return false;
- }
-
- tdmod = mc_tpld_modify_begin (topology);
-
- if (callbacks) {
- memcpy (&tdmod.new_td->apm_callbacks,
- callbacks,
- sizeof (mongoc_apm_callbacks_t));
- memcpy (&pool->apm_callbacks, callbacks, sizeof (mongoc_apm_callbacks_t));
- }
-
- mongoc_topology_set_apm_callbacks (
- topology, tdmod.new_td, callbacks, context);
- tdmod.new_td->apm_context = context;
- pool->apm_context = context;
- pool->apm_callbacks_set = true;
-
- mc_tpld_modify_commit (tdmod);
-
- return true;
-}
-
-bool
-mongoc_client_pool_set_error_api (mongoc_client_pool_t *pool, int32_t version)
-{
- if (version != MONGOC_ERROR_API_VERSION_LEGACY &&
- version != MONGOC_ERROR_API_VERSION_2) {
- MONGOC_ERROR ("Unsupported Error API Version: %" PRId32, version);
- return false;
- }
-
- if (pool->error_api_set) {
- MONGOC_ERROR ("Can only set Error API Version once");
- return false;
- }
-
- pool->error_api_version = version;
- pool->error_api_set = true;
-
- return true;
-}
-
-bool
-mongoc_client_pool_set_appname (mongoc_client_pool_t *pool, const char *appname)
-{
- bool ret;
-
- bson_mutex_lock (&pool->mutex);
- ret = _mongoc_topology_set_appname (pool->topology, appname);
- bson_mutex_unlock (&pool->mutex);
-
- return ret;
-}
-
-bool
-mongoc_client_pool_enable_auto_encryption (mongoc_client_pool_t *pool,
- mongoc_auto_encryption_opts_t *opts,
- bson_error_t *error)
-{
- return _mongoc_cse_client_pool_enable_auto_encryption (
- pool->topology, opts, error);
-}
-
-bool
-mongoc_client_pool_set_server_api (mongoc_client_pool_t *pool,
- const mongoc_server_api_t *api,
- bson_error_t *error)
-{
- BSON_ASSERT_PARAM (pool);
- BSON_ASSERT_PARAM (api);
-
- if (pool->api) {
- bson_set_error (error,
- MONGOC_ERROR_POOL,
- MONGOC_ERROR_POOL_API_ALREADY_SET,
- "Cannot set server api more than once per pool");
- return false;
- }
-
- if (pool->client_initialized) {
- bson_set_error (error,
- MONGOC_ERROR_POOL,
- MONGOC_ERROR_POOL_API_TOO_LATE,
- "Cannot set server api after a client has been created");
- return false;
- }
-
- pool->api = mongoc_server_api_copy (api);
-
- _mongoc_topology_scanner_set_server_api (pool->topology->scanner, api);
-
- return true;
-}
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-pool.h b/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-pool.h
deleted file mode 100644
index d524ca1b..00000000
--- a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-pool.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright 2013 MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "mongoc-prelude.h"
-
-#ifndef MONGOC_CLIENT_POOL_H
-#define MONGOC_CLIENT_POOL_H
-
-#include <bson/bson.h>
-
-#include "mongoc-macros.h"
-#include "mongoc-apm.h"
-#include "mongoc-client.h"
-#include "mongoc-config.h"
-#ifdef MONGOC_ENABLE_SSL
-#include "mongoc-ssl.h"
-#endif
-#include "mongoc-uri.h"
-
-
-BSON_BEGIN_DECLS
-
-
-typedef struct _mongoc_client_pool_t mongoc_client_pool_t;
-
-
-MONGOC_EXPORT (mongoc_client_pool_t *)
-mongoc_client_pool_new (const mongoc_uri_t *uri) BSON_GNUC_WARN_UNUSED_RESULT;
-MONGOC_EXPORT (void)
-mongoc_client_pool_destroy (mongoc_client_pool_t *pool);
-MONGOC_EXPORT (mongoc_client_t *)
-mongoc_client_pool_pop (mongoc_client_pool_t *pool)
- BSON_GNUC_WARN_UNUSED_RESULT;
-MONGOC_EXPORT (void)
-mongoc_client_pool_push (mongoc_client_pool_t *pool, mongoc_client_t *client);
-MONGOC_EXPORT (mongoc_client_t *)
-mongoc_client_pool_try_pop (mongoc_client_pool_t *pool)
- BSON_GNUC_WARN_UNUSED_RESULT;
-MONGOC_EXPORT (void)
-mongoc_client_pool_max_size (mongoc_client_pool_t *pool,
- uint32_t max_pool_size);
-MONGOC_EXPORT (void)
-mongoc_client_pool_min_size (mongoc_client_pool_t *pool,
- uint32_t min_pool_size) BSON_GNUC_DEPRECATED;
-#ifdef MONGOC_ENABLE_SSL
-MONGOC_EXPORT (void)
-mongoc_client_pool_set_ssl_opts (mongoc_client_pool_t *pool,
- const mongoc_ssl_opt_t *opts);
-#endif
-MONGOC_EXPORT (bool)
-mongoc_client_pool_set_apm_callbacks (mongoc_client_pool_t *pool,
- mongoc_apm_callbacks_t *callbacks,
- void *context);
-MONGOC_EXPORT (bool)
-mongoc_client_pool_set_error_api (mongoc_client_pool_t *pool, int32_t version);
-MONGOC_EXPORT (bool)
-mongoc_client_pool_set_appname (mongoc_client_pool_t *pool,
- const char *appname);
-MONGOC_EXPORT (bool)
-mongoc_client_pool_enable_auto_encryption (mongoc_client_pool_t *pool,
- mongoc_auto_encryption_opts_t *opts,
- bson_error_t *error);
-MONGOC_EXPORT (bool)
-mongoc_client_pool_set_server_api (mongoc_client_pool_t *pool,
- const mongoc_server_api_t *api,
- bson_error_t *error);
-
-BSON_END_DECLS
-
-
-#endif /* MONGOC_CLIENT_POOL_H */
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-private.h b/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-private.h
deleted file mode 100644
index db5e6cc2..00000000
--- a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-private.h
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * Copyright 2013 MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "mongoc-prelude.h"
-
-#ifndef MONGOC_CLIENT_PRIVATE_H
-#define MONGOC_CLIENT_PRIVATE_H
-
-#include <bson/bson.h>
-
-#include "mongoc-apm-private.h"
-#include "mongoc-buffer-private.h"
-#include "mongoc-client.h"
-#include "mongoc-cluster-private.h"
-#include "mongoc-config.h"
-#include "mongoc-host-list.h"
-#include "mongoc-read-prefs.h"
-#include "mongoc-rpc-private.h"
-#include "mongoc-opcode.h"
-#ifdef MONGOC_ENABLE_SSL
-#include "mongoc-ssl.h"
-#endif
-
-#include "mongoc-stream.h"
-#include "mongoc-topology-private.h"
-#include "mongoc-write-concern.h"
-#include "mongoc-crypt-private.h"
-
-BSON_BEGIN_DECLS
-
-/* protocol versions this driver can speak */
-#define WIRE_VERSION_MIN 3 /* a.k.a. minWireVersion */
-#define WIRE_VERSION_MAX 14 /* a.k.a. maxWireVersion */
-
-/* first version that supported "find" and "getMore" commands */
-#define WIRE_VERSION_FIND_CMD 4
-/* first version with "killCursors" command */
-#define WIRE_VERSION_KILLCURSORS_CMD 4
-/* first version when findAndModify accepts writeConcern */
-#define WIRE_VERSION_FAM_WRITE_CONCERN 4
-/* first version to support readConcern */
-#define WIRE_VERSION_READ_CONCERN 4
-/* first version to support maxStalenessSeconds */
-#define WIRE_VERSION_MAX_STALENESS 5
-/* first version to support writeConcern */
-#define WIRE_VERSION_CMD_WRITE_CONCERN 5
-/* first version to support collation */
-#define WIRE_VERSION_COLLATION 5
-/* first version to support server-side errors for unsupported hint options */
-#define WIRE_VERSION_HINT_SERVER_SIDE_ERROR 5
-/* first version to support OP_MSG */
-#define WIRE_VERSION_OP_MSG 6
-/* first version to support array filters for "update" command */
-#define WIRE_VERSION_ARRAY_FILTERS 6
-/* first version to support retryable reads */
-#define WIRE_VERSION_RETRY_READS 6
-/* first version to support retryable writes */
-#define WIRE_VERSION_RETRY_WRITES 6
-/* version corresponding to server 4.0 release */
-#define WIRE_VERSION_4_0 7
-/* first version to support hint for "update" command */
-#define WIRE_VERSION_UPDATE_HINT 8
-/* version corresponding to server 4.2 release */
-#define WIRE_VERSION_4_2 8
-/* version corresponding to client side field level encryption support. */
-#define WIRE_VERSION_CSE 8
-/* first version to throw server-side errors for unsupported hint in
- * "findAndModify" command */
-#define WIRE_VERSION_FIND_AND_MODIFY_HINT_SERVER_SIDE_ERROR 8
-/* first version to support hint for "delete" command */
-#define WIRE_VERSION_DELETE_HINT 9
-/* first version to support hint for "findAndModify" command */
-#define WIRE_VERSION_FIND_AND_MODIFY_HINT 9
-/* version corresponding to server 4.4 release */
-#define WIRE_VERSION_4_4 9
-/* version corresponding to retryable writes error label */
-#define WIRE_VERSION_RETRYABLE_WRITE_ERROR_LABEL 9
-/* first version to support server hedged reads */
-#define WIRE_VERSION_HEDGED_READS 9
-/* first version to support estimatedDocumentCount with collStats */
-#define WIRE_VERSION_4_9 12
-/* version corresponding to server 5.0 release */
-#define WIRE_VERSION_5_0 13
-/* first version to support snapshot reads */
-#define WIRE_VERSION_SNAPSHOT_READS 13
-
-struct _mongoc_collection_t;
-
-struct _mongoc_client_t {
- mongoc_uri_t *uri;
- mongoc_cluster_t cluster;
- bool in_exhaust;
- bool is_pooled;
-
- mongoc_stream_initiator_t initiator;
- void *initiator_data;
-
-#ifdef MONGOC_ENABLE_SSL
- bool use_ssl;
- mongoc_ssl_opt_t ssl_opts;
-#endif
-
- mongoc_topology_t *topology;
-
- mongoc_read_prefs_t *read_prefs;
- mongoc_read_concern_t *read_concern;
- mongoc_write_concern_t *write_concern;
-
- mongoc_apm_callbacks_t apm_callbacks;
- void *apm_context;
-
- int32_t error_api_version;
- bool error_api_set;
-
- mongoc_server_api_t *api;
-
- /* mongoc_client_session_t's in use, to look up lsids and clusterTimes */
- mongoc_set_t *client_sessions;
- unsigned int csid_rand_seed;
-
- uint32_t generation;
-};
-
-/* Defines whether _mongoc_client_command_with_opts() is acting as a read
- * command helper for a command like "distinct", or a write command helper for
- * a command like "createRole", or both, like "aggregate" with "$out".
- */
-typedef enum {
- MONGOC_CMD_RAW = 0,
- MONGOC_CMD_READ = 1,
- MONGOC_CMD_WRITE = 2,
- MONGOC_CMD_RW = 3,
-} mongoc_command_mode_t;
-
-BSON_STATIC_ASSERT2 (mongoc_cmd_rw,
- MONGOC_CMD_RW == (MONGOC_CMD_READ | MONGOC_CMD_WRITE));
-
-
-/* TODO (CDRIVER-4052): Move MONGOC_RR_DEFAULT_BUFFER_SIZE and
- * _mongoc_client_get_rr to mongoc-topology-private.h or in a separate file.
- * There is no reason these should be in mongoc-client. */
-#define MONGOC_RR_DEFAULT_BUFFER_SIZE 1024
-bool
-_mongoc_client_get_rr (const char *service,
- mongoc_rr_type_t rr_type,
- mongoc_rr_data_t *rr_data,
- size_t initial_buffer_size,
- bson_error_t *error);
-
-mongoc_client_t *
-_mongoc_client_new_from_uri (mongoc_topology_t *topology);
-
-bool
-_mongoc_client_set_apm_callbacks_private (mongoc_client_t *client,
- mongoc_apm_callbacks_t *callbacks,
- void *context);
-
-mongoc_stream_t *
-mongoc_client_default_stream_initiator (const mongoc_uri_t *uri,
- const mongoc_host_list_t *host,
- void *user_data,
- bson_error_t *error);
-
-mongoc_stream_t *
-_mongoc_client_create_stream (mongoc_client_t *client,
- const mongoc_host_list_t *host,
- bson_error_t *error);
-
-bool
-_mongoc_client_recv (mongoc_client_t *client,
- mongoc_rpc_t *rpc,
- mongoc_buffer_t *buffer,
- mongoc_server_stream_t *server_stream,
- bson_error_t *error);
-
-void
-_mongoc_client_kill_cursor (mongoc_client_t *client,
- uint32_t server_id,
- int64_t cursor_id,
- int64_t operation_id,
- const char *db,
- const char *collection,
- mongoc_client_session_t *cs);
-bool
-_mongoc_client_command_with_opts (mongoc_client_t *client,
- const char *db_name,
- const bson_t *command,
- mongoc_command_mode_t mode,
- const bson_t *opts,
- mongoc_query_flags_t flags,
- const mongoc_read_prefs_t *user_prefs,
- const mongoc_read_prefs_t *default_prefs,
- mongoc_read_concern_t *default_rc,
- mongoc_write_concern_t *default_wc,
- bson_t *reply,
- bson_error_t *error);
-
-mongoc_server_session_t *
-_mongoc_client_pop_server_session (mongoc_client_t *client,
- bson_error_t *error);
-
-bool
-_mongoc_client_lookup_session (const mongoc_client_t *client,
- uint32_t client_session_id,
- mongoc_client_session_t **cs,
- bson_error_t *error);
-
-void
-_mongoc_client_unregister_session (mongoc_client_t *client,
- mongoc_client_session_t *session);
-
-void
-_mongoc_client_push_server_session (mongoc_client_t *client,
- mongoc_server_session_t *server_session);
-void
-_mongoc_client_end_sessions (mongoc_client_t *client);
-
-mongoc_stream_t *
-mongoc_client_connect_tcp (int32_t connecttimeoutms,
- const mongoc_host_list_t *host,
- bson_error_t *error);
-
-mongoc_stream_t *
-mongoc_client_connect (bool buffered,
- bool use_ssl,
- void *ssl_opts_void,
- const mongoc_uri_t *uri,
- const mongoc_host_list_t *host,
- bson_error_t *error);
-BSON_END_DECLS
-
-#endif /* MONGOC_CLIENT_PRIVATE_H */
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client.c b/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client.c
deleted file mode 100644
index 00e889c4..00000000
--- a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client.c
+++ /dev/null
@@ -1,3167 +0,0 @@
-/*
- * Copyright 2013 MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-#include <bson/bson.h>
-#include "mongoc-config.h"
-#ifdef MONGOC_HAVE_DNSAPI
-/* for DnsQuery_UTF8 */
-#include <Windows.h>
-#include <WinDNS.h>
-#include <ws2tcpip.h>
-#else
-#if defined(MONGOC_HAVE_RES_NSEARCH) || defined(MONGOC_HAVE_RES_SEARCH)
-#include <netdb.h>
-#include <netinet/tcp.h>
-#include <arpa/nameser.h>
-#include <resolv.h>
-#define BSON_INSIDE
-#include <bson/bson-string.h>
-#undef BSON_INSIDE
-
-#endif
-#endif
-
-#include "mongoc-client-private.h"
-#include "mongoc-client-side-encryption-private.h"
-#include "mongoc-collection-private.h"
-#include "mongoc-counters-private.h"
-#include "mongoc-database-private.h"
-#include "mongoc-gridfs-private.h"
-#include "mongoc-error.h"
-#include "mongoc-error-private.h"
-#include "mongoc-log.h"
-#include "mongoc-queue-private.h"
-#include "mongoc-socket.h"
-#include "mongoc-stream-buffered.h"
-#include "mongoc-stream-socket.h"
-#include "mongoc-thread-private.h"
-#include "mongoc-trace-private.h"
-#include "mongoc-uri-private.h"
-#include "mongoc-util-private.h"
-#include "mongoc-set-private.h"
-#include "mongoc-log.h"
-#include "mongoc-write-concern-private.h"
-#include "mongoc-read-concern-private.h"
-#include "mongoc-host-list-private.h"
-#include "mongoc-read-prefs-private.h"
-#include "mongoc-change-stream-private.h"
-#include "mongoc-client-session-private.h"
-#include "mongoc-cursor-private.h"
-
-#ifdef MONGOC_ENABLE_SSL
-#include "mongoc-stream-tls.h"
-#include "mongoc-ssl-private.h"
-#include "mongoc-cmd-private.h"
-#include "mongoc-opts-private.h"
-#endif
-
-
-#undef MONGOC_LOG_DOMAIN
-#define MONGOC_LOG_DOMAIN "client"
-
-
-static void
-_mongoc_client_op_killcursors (mongoc_cluster_t *cluster,
- mongoc_server_stream_t *server_stream,
- int64_t cursor_id,
- int64_t operation_id,
- const char *db,
- const char *collection);
-
-static void
-_mongoc_client_killcursors_command (mongoc_cluster_t *cluster,
- mongoc_server_stream_t *server_stream,
- int64_t cursor_id,
- const char *db,
- const char *collection,
- mongoc_client_session_t *cs);
-
-#define DNS_ERROR(_msg, ...) \
- do { \
- bson_set_error (error, \
- MONGOC_ERROR_STREAM, \
- MONGOC_ERROR_STREAM_NAME_RESOLUTION, \
- _msg, \
- __VA_ARGS__); \
- GOTO (done); \
- } while (0)
-
-
-#ifdef MONGOC_HAVE_DNSAPI
-
-typedef bool (*mongoc_rr_callback_t) (const char *service,
- PDNS_RECORD pdns,
- mongoc_rr_data_t *rr_data,
- bson_error_t *error);
-
-static bool
-srv_callback (const char *service,
- PDNS_RECORD pdns,
- mongoc_rr_data_t *rr_data,
- bson_error_t *error)
-{
- mongoc_host_list_t new_host;
-
- if (rr_data && rr_data->hosts) {
- _mongoc_host_list_remove_host (
- &(rr_data->hosts), pdns->Data.SRV.pNameTarget, pdns->Data.SRV.wPort);
- }
-
- if (!_mongoc_host_list_from_hostport_with_err (
- &new_host, pdns->Data.SRV.pNameTarget, pdns->Data.SRV.wPort, error)) {
- return false;
- }
- _mongoc_host_list_upsert (&rr_data->hosts, &new_host);
-
- return true;
-}
-
-/* rr_data is unused, but here to match srv_callback signature */
-static bool
-txt_callback (const char *service,
- PDNS_RECORD pdns,
- mongoc_rr_data_t *rr_data,
- bson_error_t *error)
-{
- DWORD i;
- bson_string_t *txt;
-
- txt = bson_string_new (NULL);
-
- for (i = 0; i < pdns->Data.TXT.dwStringCount; i++) {
- bson_string_append (txt, pdns->Data.TXT.pStringArray[i]);
- }
-
- rr_data->txt_record_opts = bson_strdup (txt->str);
- bson_string_free (txt, true);
-
- return true;
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_get_rr_dnsapi --
- *
- * Fetch SRV or TXT resource records using the Windows DNS API and
- * put results in @rr_data.
- *
- * Returns:
- * Success or failure.
- *
- * For an SRV lookup, returns false if there is any error.
- *
- * For TXT lookup, ignores any error fetching the resource record and
- * always returns true.
- *
- * Side effects:
- * @error is set if there is a failure.
- * @rr_data->hosts may be set if querying SRV. Caller must destroy.
- * @rr_data->txt_record_opts may be set if querying TXT. Caller must
- * free.
- *
- *--------------------------------------------------------------------------
- */
-
-static bool
-_mongoc_get_rr_dnsapi (const char *service,
- mongoc_rr_type_t rr_type,
- mongoc_rr_data_t *rr_data,
- bson_error_t *error)
-{
- const char *rr_type_name;
- WORD nst;
- mongoc_rr_callback_t callback;
- PDNS_RECORD pdns = NULL;
- DNS_STATUS res;
- LPVOID lpMsgBuf = NULL;
- bool dns_success;
- bool callback_success = true;
- int i;
-
- ENTRY;
-
- if (rr_type == MONGOC_RR_SRV) {
- /* return true only if DNS succeeds */
- dns_success = false;
- rr_type_name = "SRV";
- nst = DNS_TYPE_SRV;
- callback = srv_callback;
- } else {
- /* return true whether or not DNS succeeds */
- dns_success = true;
- rr_type_name = "TXT";
- nst = DNS_TYPE_TEXT;
- callback = txt_callback;
- }
-
- res = DnsQuery_UTF8 (service,
- nst,
- DNS_QUERY_BYPASS_CACHE,
- NULL /* IP Address */,
- &pdns,
- 0 /* reserved */);
-
- if (res) {
- DWORD flags = FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS;
-
- if (FormatMessage (flags,
- 0,
- res,
- MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPTSTR) &lpMsgBuf,
- 0,
- 0)) {
- DNS_ERROR ("Failed to look up %s record \"%s\": %s",
- rr_type_name,
- service,
- (char *) lpMsgBuf);
- }
-
- DNS_ERROR ("Failed to look up %s record \"%s\": Unknown error",
- rr_type_name,
- service);
- }
-
- if (!pdns) {
- DNS_ERROR ("No %s records for \"%s\"", rr_type_name, service);
- }
-
- i = 0;
-
- do {
- /* DnsQuery can return additional records not of the requested type */
- if ((rr_type == MONGOC_RR_TXT && pdns->wType == DNS_TYPE_TEXT) ||
- (rr_type == MONGOC_RR_SRV && pdns->wType == DNS_TYPE_SRV)) {
- if (i > 0 && rr_type == MONGOC_RR_TXT) {
- /* Initial DNS Seedlist Discovery Spec: a client "MUST raise an
- error when multiple TXT records are encountered". */
- callback_success = false;
- DNS_ERROR ("Multiple TXT records for \"%s\"", service);
- }
-
- if (rr_data) {
- if ((i == 0) || (pdns->dwTtl < rr_data->min_ttl)) {
- rr_data->min_ttl = pdns->dwTtl;
- }
- }
-
- if (!callback (service, pdns, rr_data, error)) {
- callback_success = false;
- GOTO (done);
- }
-
- i++;
- }
-
- pdns = pdns->pNext;
- } while (pdns);
-
-
- rr_data->count = i;
- if (i == 0) {
- DNS_ERROR ("No matching %s records for \"%s\"", rr_type_name, service);
- }
- dns_success = true;
-
-done:
- if (pdns) {
- DnsRecordListFree (pdns, DnsFreeRecordList);
- }
-
- if (lpMsgBuf) {
- LocalFree (lpMsgBuf);
- }
-
- RETURN (dns_success && callback_success);
-}
-
-#elif (defined(MONGOC_HAVE_RES_NSEARCH) || defined(MONGOC_HAVE_RES_SEARCH))
-
-typedef bool (*mongoc_rr_callback_t) (const char *service,
- ns_msg *ns_answer,
- ns_rr *rr,
- mongoc_rr_data_t *rr_data,
- bson_error_t *error);
-
-static const char *
-_mongoc_hstrerror (int code)
-{
- switch (code) {
- case HOST_NOT_FOUND:
- return "The specified host is unknown.";
- case NO_ADDRESS:
- return "The requested name is valid but does not have an IP address.";
- case NO_RECOVERY:
- return "A nonrecoverable name server error occurred.";
- case TRY_AGAIN:
- return "A temporary error occurred on an authoritative name server. Try "
- "again later.";
- default:
- return "An unknown error occurred.";
- }
-}
-
-static bool
-srv_callback (const char *service,
- ns_msg *ns_answer,
- ns_rr *rr,
- mongoc_rr_data_t *rr_data,
- bson_error_t *error)
-{
- const uint8_t *data;
- char name[1024];
- uint16_t port;
- int size;
- bool ret = false;
- mongoc_host_list_t new_host;
-
- data = ns_rr_rdata (*rr);
- /* memcpy the network endian port before converting to host endian. we cannot
- * cast (data + 4) directly as a uint16_t*, because it may not align on an
- * 2-byte boundary. */
- memcpy (&port, data + 4, sizeof (port));
- port = ntohs (port);
- size = dn_expand (ns_msg_base (*ns_answer),
- ns_msg_end (*ns_answer),
- data + 6,
- name,
- sizeof (name));
-
- if (size < 1) {
- DNS_ERROR ("Invalid record in SRV answer for \"%s\": \"%s\"",
- service,
- _mongoc_hstrerror (h_errno));
- }
-
- if (!_mongoc_host_list_from_hostport_with_err (
- &new_host, name, port, error)) {
- GOTO (done);
- }
- _mongoc_host_list_upsert (&rr_data->hosts, &new_host);
- ret = true;
-done:
- return ret;
-}
-
-static bool
-txt_callback (const char *service,
- ns_msg *ns_answer,
- ns_rr *rr,
- mongoc_rr_data_t *rr_data,
- bson_error_t *error)
-{
- char s[256];
- const uint8_t *data;
- bson_string_t *txt;
- uint16_t pos, total;
- uint8_t len;
- bool ret = false;
-
- total = (uint16_t) ns_rr_rdlen (*rr);
- if (total < 1 || total > 255) {
- DNS_ERROR ("Invalid TXT record size %hu for \"%s\"", total, service);
- }
-
- /* a TXT record has one or more strings, each up to 255 chars, each is
- * prefixed by its length as 1 byte. thus endianness doesn't matter. */
- txt = bson_string_new (NULL);
- pos = 0;
- data = ns_rr_rdata (*rr);
-
- while (pos < total) {
- memcpy (&len, data + pos, sizeof (uint8_t));
- pos++;
- bson_strncpy (s, (const char *) (data + pos), (size_t) len + 1);
- bson_string_append (txt, s);
- pos += len;
- }
-
- rr_data->txt_record_opts = bson_strdup (txt->str);
- bson_string_free (txt, true);
- ret = true;
-
-done:
- return ret;
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_get_rr_search --
- *
- * Fetch SRV or TXT resource records using libresolv and put results in
- * @rr_data.
- *
- * Returns:
- * Success or failure.
- *
- * For an SRV lookup, returns false if there is any error.
- *
- * For TXT lookup, ignores any error fetching the resource record and
- * always returns true.
- *
- * Side effects:
- * @error is set if there is a failure.
- * @rr_data->hosts may be set if querying SRV. Caller must destroy.
- * @rr_data->txt_record_opts may be set if querying TXT. Caller must
- * free.
- *
- *--------------------------------------------------------------------------
- */
-
-static bool
-_mongoc_get_rr_search (const char *service,
- mongoc_rr_type_t rr_type,
- mongoc_rr_data_t *rr_data,
- size_t initial_buffer_size,
- bson_error_t *error)
-{
-#ifdef MONGOC_HAVE_RES_NSEARCH
- struct __res_state state = {0};
-#endif
- int size = 0;
- unsigned char *search_buf = NULL;
- size_t buffer_size = initial_buffer_size;
- ns_msg ns_answer;
- int n;
- int i;
- const char *rr_type_name;
- ns_type nst;
- mongoc_rr_callback_t callback;
- ns_rr resource_record;
- bool dns_success;
- bool callback_success = true;
- int num_matching_records;
- uint32_t ttl;
-
- ENTRY;
-
- if (rr_type == MONGOC_RR_SRV) {
- /* return true only if DNS succeeds */
- dns_success = false;
- rr_type_name = "SRV";
- nst = ns_t_srv;
- callback = srv_callback;
- } else {
- /* return true whether or not DNS succeeds */
- dns_success = true;
- rr_type_name = "TXT";
- nst = ns_t_txt;
- callback = txt_callback;
- }
-
- do {
- if (search_buf) {
- bson_free (search_buf);
-
- /* increase buffer size by the previous response size. This ensures
- * that even if a subsequent response is larger, we'll still be able
- * to fit it in the response buffer */
- buffer_size = buffer_size + size;
- }
-
- search_buf = (unsigned char *) bson_malloc (buffer_size);
- BSON_ASSERT (search_buf);
-
-#ifdef MONGOC_HAVE_RES_NSEARCH
- /* thread-safe */
- res_ninit (&state);
- size =
- res_nsearch (&state, service, ns_c_in, nst, search_buf, buffer_size);
-#elif defined(MONGOC_HAVE_RES_SEARCH)
- size = res_search (service, ns_c_in, nst, search_buf, buffer_size);
-#endif
-
- if (size < 0) {
- DNS_ERROR ("Failed to look up %s record \"%s\": %s",
- rr_type_name,
- service,
- _mongoc_hstrerror (h_errno));
- }
- } while (size >= buffer_size);
-
- if (ns_initparse (search_buf, size, &ns_answer)) {
- DNS_ERROR ("Invalid %s answer for \"%s\"", rr_type_name, service);
- }
-
- n = ns_msg_count (ns_answer, ns_s_an);
- if (!n) {
- DNS_ERROR ("No %s records for \"%s\"", rr_type_name, service);
- }
-
- rr_data->count = n;
- num_matching_records = 0;
- for (i = 0; i < n; i++) {
- if (ns_parserr (&ns_answer, ns_s_an, i, &resource_record)) {
- DNS_ERROR ("Invalid record %d of %s answer for \"%s\": \"%s\"",
- i,
- rr_type_name,
- service,
- _mongoc_hstrerror (h_errno));
- }
-
- /* Skip records that don't match the ones we requested. CDRIVER-3628 shows
- * that we can receive records that were not requested. */
- if (rr_type == MONGOC_RR_TXT) {
- if (ns_rr_type (resource_record) != ns_t_txt) {
- continue;
- }
- } else if (rr_type == MONGOC_RR_SRV) {
- if (ns_rr_type (resource_record) != ns_t_srv) {
- continue;
- }
- }
-
- if (num_matching_records > 0 && rr_type == MONGOC_RR_TXT) {
- /* Initial DNS Seedlist Discovery Spec: a client "MUST raise an error
- * when multiple TXT records are encountered". */
- callback_success = false;
- DNS_ERROR ("Multiple TXT records for \"%s\"", service);
- }
-
- num_matching_records++;
-
- ttl = ns_rr_ttl (resource_record);
- if ((i == 0) || (ttl < rr_data->min_ttl)) {
- rr_data->min_ttl = ttl;
- }
-
- if (!callback (service, &ns_answer, &resource_record, rr_data, error)) {
- callback_success = false;
- GOTO (done);
- }
- }
-
- if (num_matching_records == 0) {
- DNS_ERROR ("No matching %s records for \"%s\"", rr_type_name, service);
- }
-
- dns_success = true;
-
-done:
-
- bson_free (search_buf);
-
-#ifdef MONGOC_HAVE_RES_NDESTROY
- /* defined on BSD/Darwin, and only if MONGOC_HAVE_RES_NSEARCH is defined */
- res_ndestroy (&state);
-#elif defined(MONGOC_HAVE_RES_NCLOSE)
- /* defined on Linux, and only if MONGOC_HAVE_RES_NSEARCH is defined */
- res_nclose (&state);
-#endif
- RETURN (dns_success && callback_success);
-}
-#endif
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_client_get_rr --
- *
- * Fetch an SRV or TXT resource record and update put results in
- * @rr_data.
- *
- * See RFCs 1464 and 2782, MongoDB's "Initial DNS Seedlist Discovery"
- * spec, and MongoDB's "Polling SRV Records for Mongos Discovery"
- * spec.
- *
- * Returns:
- * Success or failure.
- *
- * Side effects:
- * @error is set if there is a failure. Errors fetching TXT are
- * ignored.
- * @rr_data->hosts may be set if querying SRV. Caller must destroy.
- * @rr_data->txt_record_opts may be set if querying TXT. Caller must
- * free.
- *
- *--------------------------------------------------------------------------
- */
-
-bool
-_mongoc_client_get_rr (const char *service,
- mongoc_rr_type_t rr_type,
- mongoc_rr_data_t *rr_data,
- size_t initial_buffer_size,
- bson_error_t *error)
-{
- BSON_ASSERT (rr_data);
-
-#ifdef MONGOC_HAVE_DNSAPI
- return _mongoc_get_rr_dnsapi (service, rr_type, rr_data, error);
-#elif (defined(MONGOC_HAVE_RES_NSEARCH) || defined(MONGOC_HAVE_RES_SEARCH))
- return _mongoc_get_rr_search (
- service, rr_type, rr_data, initial_buffer_size, error);
-#else
- bson_set_error (error,
- MONGOC_ERROR_STREAM,
- MONGOC_ERROR_STREAM_NAME_RESOLUTION,
- "libresolv unavailable, cannot use mongodb+srv URI");
- return false;
-#endif
-}
-
-#undef DNS_ERROR
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_client_connect_tcp --
- *
- * Connect to a host using a TCP socket.
- *
- * This will be performed synchronously and return a mongoc_stream_t
- * that can be used to connect with the remote host.
- *
- * Returns:
- * A newly allocated mongoc_stream_t if successful; otherwise
- * NULL and @error is set.
- *
- * Side effects:
- * @error is set if return value is NULL.
- *
- *--------------------------------------------------------------------------
- */
-
-mongoc_stream_t *
-mongoc_client_connect_tcp (int32_t connecttimeoutms,
- const mongoc_host_list_t *host,
- bson_error_t *error)
-{
- mongoc_socket_t *sock = NULL;
- struct addrinfo hints;
- struct addrinfo *result, *rp;
- int64_t expire_at;
- char portstr[8];
- int s;
-
- ENTRY;
-
- BSON_ASSERT (connecttimeoutms);
- BSON_ASSERT (host);
-
- bson_snprintf (portstr, sizeof portstr, "%hu", host->port);
-
- memset (&hints, 0, sizeof hints);
- hints.ai_family = host->family;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_flags = 0;
- hints.ai_protocol = 0;
-
- TRACE ("DNS lookup for %s", host->host);
- s = getaddrinfo (host->host, portstr, &hints, &result);
-
- if (s != 0) {
- mongoc_counter_dns_failure_inc ();
- TRACE ("Failed to resolve %s", host->host);
- bson_set_error (error,
- MONGOC_ERROR_STREAM,
- MONGOC_ERROR_STREAM_NAME_RESOLUTION,
- "Failed to resolve %s",
- host->host);
- RETURN (NULL);
- }
-
- mongoc_counter_dns_success_inc ();
-
- for (rp = result; rp; rp = rp->ai_next) {
- /*
- * Create a new non-blocking socket.
- */
- if (!(sock = mongoc_socket_new (
- rp->ai_family, rp->ai_socktype, rp->ai_protocol))) {
- continue;
- }
-
- /*
- * Try to connect to the peer.
- */
- expire_at = bson_get_monotonic_time () + (connecttimeoutms * 1000L);
- if (0 !=
- mongoc_socket_connect (
- sock, rp->ai_addr, (mongoc_socklen_t) rp->ai_addrlen, expire_at)) {
- mongoc_socket_destroy (sock);
- sock = NULL;
- continue;
- }
-
- break;
- }
-
- if (!sock) {
- bson_set_error (error,
- MONGOC_ERROR_STREAM,
- MONGOC_ERROR_STREAM_CONNECT,
- "Failed to connect to target host: %s",
- host->host_and_port);
- freeaddrinfo (result);
- RETURN (NULL);
- }
-
- freeaddrinfo (result);
-
- return mongoc_stream_socket_new (sock);
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_client_connect_unix --
- *
- * Connect to a MongoDB server using a UNIX domain socket.
- *
- * Returns:
- * A newly allocated mongoc_stream_t if successful; otherwise
- * NULL and @error is set.
- *
- * Side effects:
- * @error is set if return value is NULL.
- *
- *--------------------------------------------------------------------------
- */
-
-static mongoc_stream_t *
-mongoc_client_connect_unix (const mongoc_host_list_t *host, bson_error_t *error)
-{
-#ifdef _WIN32
- ENTRY;
- bson_set_error (error,
- MONGOC_ERROR_STREAM,
- MONGOC_ERROR_STREAM_CONNECT,
- "UNIX domain sockets not supported on win32.");
- RETURN (NULL);
-#else
- struct sockaddr_un saddr;
- mongoc_socket_t *sock;
- mongoc_stream_t *ret = NULL;
-
- ENTRY;
-
- BSON_ASSERT (host);
-
- memset (&saddr, 0, sizeof saddr);
- saddr.sun_family = AF_UNIX;
- bson_snprintf (saddr.sun_path, sizeof saddr.sun_path - 1, "%s", host->host);
-
- sock = mongoc_socket_new (AF_UNIX, SOCK_STREAM, 0);
-
- if (sock == NULL) {
- bson_set_error (error,
- MONGOC_ERROR_STREAM,
- MONGOC_ERROR_STREAM_SOCKET,
- "Failed to create socket.");
- RETURN (NULL);
- }
-
- if (-1 == mongoc_socket_connect (
- sock, (struct sockaddr *) &saddr, sizeof saddr, -1)) {
- mongoc_socket_destroy (sock);
- bson_set_error (error,
- MONGOC_ERROR_STREAM,
- MONGOC_ERROR_STREAM_CONNECT,
- "Failed to connect to UNIX domain socket.");
- RETURN (NULL);
- }
-
- ret = mongoc_stream_socket_new (sock);
-
- RETURN (ret);
-#endif
-}
-
-mongoc_stream_t *
-mongoc_client_connect (bool buffered,
- bool use_ssl,
- void *ssl_opts_void,
- const mongoc_uri_t *uri,
- const mongoc_host_list_t *host,
- bson_error_t *error)
-{
- mongoc_stream_t *base_stream = NULL;
- int32_t connecttimeoutms;
-
- BSON_ASSERT (uri);
- BSON_ASSERT (host);
-
-#ifndef MONGOC_ENABLE_SSL
- if (ssl_opts_void || mongoc_uri_get_tls (uri)) {
- bson_set_error (error,
- MONGOC_ERROR_CLIENT,
- MONGOC_ERROR_CLIENT_NO_ACCEPTABLE_PEER,
- "TLS is not enabled in this build of mongo-c-driver.");
- return NULL;
- }
-#endif
-
- connecttimeoutms = mongoc_uri_get_option_as_int32 (
- uri, MONGOC_URI_CONNECTTIMEOUTMS, MONGOC_DEFAULT_CONNECTTIMEOUTMS);
-
- switch (host->family) {
- case AF_UNSPEC:
-#if defined(AF_INET6)
- case AF_INET6:
-#endif
- case AF_INET:
- base_stream = mongoc_client_connect_tcp (connecttimeoutms, host, error);
- break;
- case AF_UNIX:
- base_stream = mongoc_client_connect_unix (host, error);
- break;
- default:
- bson_set_error (error,
- MONGOC_ERROR_STREAM,
- MONGOC_ERROR_STREAM_INVALID_TYPE,
- "Invalid address family: 0x%02x",
- host->family);
- break;
- }
-
-#ifdef MONGOC_ENABLE_SSL
- if (base_stream) {
- mongoc_ssl_opt_t *ssl_opts;
- const char *mechanism;
-
- ssl_opts = (mongoc_ssl_opt_t *) ssl_opts_void;
- mechanism = mongoc_uri_get_auth_mechanism (uri);
-
- if (use_ssl || (mechanism && (0 == strcmp (mechanism, "MONGODB-X509")))) {
- mongoc_stream_t *original = base_stream;
-
- base_stream = mongoc_stream_tls_new_with_hostname (
- base_stream, host->host, ssl_opts, true);
-
- if (!base_stream) {
- mongoc_stream_destroy (original);
- bson_set_error (error,
- MONGOC_ERROR_STREAM,
- MONGOC_ERROR_STREAM_SOCKET,
- "Failed initialize TLS state.");
- return NULL;
- }
-
- if (!mongoc_stream_tls_handshake_block (
- base_stream, host->host, connecttimeoutms, error)) {
- mongoc_stream_destroy (base_stream);
- return NULL;
- }
- }
- }
-#endif
-
- if (!base_stream) {
- return NULL;
- }
- if (buffered) {
- return mongoc_stream_buffered_new (base_stream, 1024);
- }
- return base_stream;
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_client_default_stream_initiator --
- *
- * A mongoc_stream_initiator_t that will handle the various type
- * of supported sockets by MongoDB including TCP and UNIX.
- *
- * Language binding authors may want to implement an alternate
- * version of this method to use their native stream format.
- *
- * Returns:
- * A mongoc_stream_t if successful; otherwise NULL and @error is set.
- *
- * Side effects:
- * @error is set if return value is NULL.
- *
- *--------------------------------------------------------------------------
- */
-
-mongoc_stream_t *
-mongoc_client_default_stream_initiator (const mongoc_uri_t *uri,
- const mongoc_host_list_t *host,
- void *user_data,
- bson_error_t *error)
-{
- void *ssl_opts_void = NULL;
- bool use_ssl = false;
-#ifdef MONGOC_ENABLE_SSL
- mongoc_client_t *client = (mongoc_client_t *) user_data;
-
- use_ssl = client->use_ssl;
- ssl_opts_void = (void *) &client->ssl_opts;
-
-#endif
-
- return mongoc_client_connect (
- true, use_ssl, ssl_opts_void, uri, host, error);
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_client_create_stream --
- *
- * INTERNAL API
- *
- * This function is used by the mongoc_cluster_t to initiate a
- * new stream. This is done because cluster is private API and
- * those using mongoc_client_t may need to override this process.
- *
- * This function calls the default initiator for new streams.
- *
- * Returns:
- * A newly allocated mongoc_stream_t if successful; otherwise
- * NULL and @error is set.
- *
- * Side effects:
- * @error is set if return value is NULL.
- *
- *--------------------------------------------------------------------------
- */
-
-mongoc_stream_t *
-_mongoc_client_create_stream (mongoc_client_t *client,
- const mongoc_host_list_t *host,
- bson_error_t *error)
-{
- BSON_ASSERT (client);
- BSON_ASSERT (host);
-
- return client->initiator (client->uri, host, client->initiator_data, error);
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_client_recv --
- *
- * Receives a RPC from a remote MongoDB cluster node.
- *
- * Returns:
- * true if successful; otherwise false and @error is set.
- *
- * Side effects:
- * @error is set if return value is false.
- *
- *--------------------------------------------------------------------------
- */
-
-bool
-_mongoc_client_recv (mongoc_client_t *client,
- mongoc_rpc_t *rpc,
- mongoc_buffer_t *buffer,
- mongoc_server_stream_t *server_stream,
- bson_error_t *error)
-{
- BSON_ASSERT (client);
- BSON_ASSERT (rpc);
- BSON_ASSERT (buffer);
- BSON_ASSERT (server_stream);
-
- return mongoc_cluster_try_recv (
- &client->cluster, rpc, buffer, server_stream, error);
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_client_new --
- *
- * Create a new mongoc_client_t using the URI provided.
- *
- * @uri should be a MongoDB URI string such as "mongodb://localhost/"
- * More information on the format can be found at
- * http://docs.mongodb.org/manual/reference/connection-string/
- *
- * Returns:
- * A newly allocated mongoc_client_t or NULL if @uri_string is
- * invalid.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-mongoc_client_t *
-mongoc_client_new (const char *uri_string)
-{
- mongoc_topology_t *topology;
- mongoc_client_t *client;
- mongoc_uri_t *uri;
-
-
- if (!uri_string) {
- uri_string = "mongodb://127.0.0.1/";
- }
-
- if (!(uri = mongoc_uri_new (uri_string))) {
- return NULL;
- }
-
- topology = mongoc_topology_new (uri, true);
-
- client = _mongoc_client_new_from_uri (topology);
- if (!client) {
- mongoc_topology_destroy (topology);
- }
- mongoc_uri_destroy (uri);
-
- return client;
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_client_set_ssl_opts
- *
- * set ssl opts for a client
- *
- * Returns:
- * Nothing
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-#ifdef MONGOC_ENABLE_SSL
-/* Only called internally. Caller must ensure opts->internal is valid. */
-void
-_mongoc_client_set_internal_tls_opts (mongoc_client_t *client,
- _mongoc_internal_tls_opts_t *internal)
-{
- if (!client->use_ssl) {
- return;
- }
- client->ssl_opts.internal =
- bson_malloc (sizeof (_mongoc_internal_tls_opts_t));
- memcpy (client->ssl_opts.internal,
- internal,
- sizeof (_mongoc_internal_tls_opts_t));
-}
-
-void
-mongoc_client_set_ssl_opts (mongoc_client_t *client,
- const mongoc_ssl_opt_t *opts)
-{
- BSON_ASSERT (client);
- BSON_ASSERT (opts);
-
- _mongoc_ssl_opts_cleanup (&client->ssl_opts,
- false /* don't free internal opts */);
-
- client->use_ssl = true;
- _mongoc_ssl_opts_copy_to (
- opts, &client->ssl_opts, false /* don't overwrite internal opts */);
-
- if (client->topology->single_threaded) {
- mongoc_topology_scanner_set_ssl_opts (client->topology->scanner,
- &client->ssl_opts);
- }
-}
-#endif
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_client_new_from_uri --
- *
- * Create a new mongoc_client_t for a mongoc_uri_t.
- *
- * Returns:
- * A newly allocated mongoc_client_t.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-mongoc_client_t *
-mongoc_client_new_from_uri (const mongoc_uri_t *uri)
-{
- mongoc_topology_t *topology;
-
- topology = mongoc_topology_new (uri, true);
-
- /* topology->uri may be different from uri: if this is a mongodb+srv:// URI
- * then mongoc_topology_new has fetched SRV and TXT records and updated its
- * uri from them.
- */
- return _mongoc_client_new_from_uri (topology);
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_client_new_from_uri --
- *
- * Create a new mongoc_client_t for a given topology object.
- *
- * Returns:
- * A newly allocated mongoc_client_t.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-mongoc_client_t *
-_mongoc_client_new_from_uri (mongoc_topology_t *topology)
-{
- mongoc_client_t *client;
- const mongoc_read_prefs_t *read_prefs;
- const mongoc_read_concern_t *read_concern;
- const mongoc_write_concern_t *write_concern;
- const char *appname;
-
- BSON_ASSERT (topology);
-
-#ifndef MONGOC_ENABLE_SSL
- if (mongoc_uri_get_tls (topology->uri)) {
- MONGOC_ERROR ("Can't create SSL client, SSL not enabled in this build.");
- return NULL;
- }
-#endif
-
- client = (mongoc_client_t *) bson_malloc0 (sizeof *client);
- client->uri = mongoc_uri_copy (topology->uri);
- client->initiator = mongoc_client_default_stream_initiator;
- client->initiator_data = client;
- client->topology = topology;
- client->error_api_version = MONGOC_ERROR_API_VERSION_LEGACY;
- client->error_api_set = false;
- client->client_sessions = mongoc_set_new (8, NULL, NULL);
- client->csid_rand_seed = (unsigned int) bson_get_monotonic_time ();
-
- write_concern = mongoc_uri_get_write_concern (client->uri);
- client->write_concern = mongoc_write_concern_copy (write_concern);
-
- read_concern = mongoc_uri_get_read_concern (client->uri);
- client->read_concern = mongoc_read_concern_copy (read_concern);
-
- read_prefs = mongoc_uri_get_read_prefs_t (client->uri);
- client->read_prefs = mongoc_read_prefs_copy (read_prefs);
-
- appname =
- mongoc_uri_get_option_as_utf8 (client->uri, MONGOC_URI_APPNAME, NULL);
- if (appname && client->topology->single_threaded) {
- /* the appname should have already been validated */
- BSON_ASSERT (mongoc_client_set_appname (client, appname));
- }
-
- mongoc_cluster_init (&client->cluster, client->uri, client);
-
-#ifdef MONGOC_ENABLE_SSL
- client->use_ssl = false;
- if (mongoc_uri_get_tls (client->uri)) {
- mongoc_ssl_opt_t ssl_opt = {0};
- _mongoc_internal_tls_opts_t internal_tls_opts = {0};
-
- _mongoc_ssl_opts_from_uri (&ssl_opt, &internal_tls_opts, client->uri);
- /* sets use_ssl = true */
- mongoc_client_set_ssl_opts (client, &ssl_opt);
- _mongoc_client_set_internal_tls_opts (client, &internal_tls_opts);
- }
-#endif
-
- mongoc_counter_clients_active_inc ();
-
- return client;
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_client_destroy --
- *
- * Destroys a mongoc_client_t and cleans up all resources associated
- * with the client instance.
- *
- * Returns:
- * None.
- *
- * Side effects:
- * @client is destroyed.
- *
- *--------------------------------------------------------------------------
- */
-
-void
-mongoc_client_destroy (mongoc_client_t *client)
-{
- if (client) {
- if (client->topology->single_threaded) {
- _mongoc_client_end_sessions (client);
- mongoc_topology_destroy (client->topology);
- }
-
- mongoc_write_concern_destroy (client->write_concern);
- mongoc_read_concern_destroy (client->read_concern);
- mongoc_read_prefs_destroy (client->read_prefs);
- mongoc_cluster_destroy (&client->cluster);
- mongoc_uri_destroy (client->uri);
- mongoc_set_destroy (client->client_sessions);
- mongoc_server_api_destroy (client->api);
-
-#ifdef MONGOC_ENABLE_SSL
- _mongoc_ssl_opts_cleanup (&client->ssl_opts, true);
-#endif
-
- bson_free (client);
-
- mongoc_counter_clients_active_dec ();
- mongoc_counter_clients_disposed_inc ();
- }
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_client_get_uri --
- *
- * Fetch the URI used for @client.
- *
- * Returns:
- * A mongoc_uri_t that should not be modified or freed.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-const mongoc_uri_t *
-mongoc_client_get_uri (const mongoc_client_t *client)
-{
- BSON_ASSERT (client);
-
- return client->uri;
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_client_start_session --
- *
- * Creates a structure to communicate in a session over @client.
- *
- * This structure should be freed when the caller is done with it
- * using mongoc_client_session_destroy().
- *
- * Returns:
- * A newly allocated mongoc_client_session_t.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-mongoc_client_session_t *
-mongoc_client_start_session (mongoc_client_t *client,
- const mongoc_session_opt_t *opts,
- bson_error_t *error)
-{
- mongoc_server_session_t *ss;
- mongoc_client_session_t *cs;
- uint32_t csid;
-
- ENTRY;
-
- ss = _mongoc_client_pop_server_session (client, error);
- if (!ss) {
- RETURN (NULL);
- }
-
- /* get a random internal id for the session, retrying on collision */
- do {
- csid = (uint32_t) _mongoc_rand_simple (&client->csid_rand_seed);
- } while (mongoc_set_get (client->client_sessions, csid));
-
- /* causal consistency and snapshot cannot both be set. */
- if (opts && mongoc_session_opts_get_causal_consistency (opts) &&
- mongoc_session_opts_get_snapshot (opts)) {
- bson_set_error (
- error,
- MONGOC_ERROR_CLIENT,
- MONGOC_ERROR_CLIENT_SESSION_FAILURE,
- "Only one of causal consistency and snapshot can be enabled.");
- _mongoc_client_push_server_session (client, ss);
- RETURN (NULL);
- }
- cs = _mongoc_client_session_new (client, ss, opts, csid);
-
- /* remember session so if we see its client_session_id in a command, we can
- * find its lsid and clusterTime */
- mongoc_set_add (client->client_sessions, csid, cs);
-
- RETURN (cs);
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_client_get_database --
- *
- * Fetches a newly allocated database structure to communicate with
- * a database over @client.
- *
- * @database should be a db name such as "test".
- *
- * This structure should be freed when the caller is done with it
- * using mongoc_database_destroy().
- *
- * Returns:
- * A newly allocated mongoc_database_t.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-mongoc_database_t *
-mongoc_client_get_database (mongoc_client_t *client, const char *name)
-{
- BSON_ASSERT (client);
- BSON_ASSERT (name);
-
- return _mongoc_database_new (client,
- name,
- client->read_prefs,
- client->read_concern,
- client->write_concern);
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_client_get_default_database --
- *
- * Get the database named in the MongoDB connection URI, or NULL
- * if none was specified in the URI.
- *
- * This structure should be freed when the caller is done with it
- * using mongoc_database_destroy().
- *
- * Returns:
- * A newly allocated mongoc_database_t or NULL.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-mongoc_database_t *
-mongoc_client_get_default_database (mongoc_client_t *client)
-{
- const char *db;
-
- BSON_ASSERT (client);
- db = mongoc_uri_get_database (client->uri);
-
- if (db) {
- return mongoc_client_get_database (client, db);
- }
-
- return NULL;
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_client_get_collection --
- *
- * This function returns a newly allocated collection structure.
- *
- * @db should be the name of the database, such as "test".
- * @collection should be the name of the collection such as "test".
- *
- * The above would result in the namespace "test.test".
- *
- * You should free this structure when you are done with it using
- * mongoc_collection_destroy().
- *
- * Returns:
- * A newly allocated mongoc_collection_t that should be freed with
- * mongoc_collection_destroy().
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-mongoc_collection_t *
-mongoc_client_get_collection (mongoc_client_t *client,
- const char *db,
- const char *collection)
-{
- BSON_ASSERT (client);
- BSON_ASSERT (db);
- BSON_ASSERT (collection);
-
- return _mongoc_collection_new (client,
- db,
- collection,
- client->read_prefs,
- client->read_concern,
- client->write_concern);
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_client_get_gridfs --
- *
- * This function returns a newly allocated collection structure.
- *
- * @db should be the name of the database, such as "test".
- *
- * @prefix optional prefix for GridFS collection names, or NULL. Default
- * is "fs", thus the default collection names for GridFS are "fs.files"
- * and "fs.chunks".
- *
- * Returns:
- * A newly allocated mongoc_gridfs_t that should be freed with
- * mongoc_gridfs_destroy().
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-mongoc_gridfs_t *
-mongoc_client_get_gridfs (mongoc_client_t *client,
- const char *db,
- const char *prefix,
- bson_error_t *error)
-{
- BSON_ASSERT (client);
- BSON_ASSERT (db);
-
- if (!prefix) {
- prefix = "fs";
- }
-
- return _mongoc_gridfs_new (client, db, prefix, error);
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_client_get_write_concern --
- *
- * Fetches the default write concern for @client.
- *
- * Returns:
- * A mongoc_write_concern_t that should not be modified or freed.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-const mongoc_write_concern_t *
-mongoc_client_get_write_concern (const mongoc_client_t *client)
-{
- BSON_ASSERT (client);
-
- return client->write_concern;
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_client_set_write_concern --
- *
- * Sets the default write concern for @client.
- *
- * Returns:
- * None.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-void
-mongoc_client_set_write_concern (mongoc_client_t *client,
- const mongoc_write_concern_t *write_concern)
-{
- BSON_ASSERT (client);
-
- if (write_concern != client->write_concern) {
- if (client->write_concern) {
- mongoc_write_concern_destroy (client->write_concern);
- }
- client->write_concern = write_concern
- ? mongoc_write_concern_copy (write_concern)
- : mongoc_write_concern_new ();
- }
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_client_get_read_concern --
- *
- * Fetches the default read concern for @client.
- *
- * Returns:
- * A mongoc_read_concern_t that should not be modified or freed.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-const mongoc_read_concern_t *
-mongoc_client_get_read_concern (const mongoc_client_t *client)
-{
- BSON_ASSERT (client);
-
- return client->read_concern;
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_client_set_read_concern --
- *
- * Sets the default read concern for @client.
- *
- * Returns:
- * None.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-void
-mongoc_client_set_read_concern (mongoc_client_t *client,
- const mongoc_read_concern_t *read_concern)
-{
- BSON_ASSERT (client);
-
- if (read_concern != client->read_concern) {
- if (client->read_concern) {
- mongoc_read_concern_destroy (client->read_concern);
- }
- client->read_concern = read_concern
- ? mongoc_read_concern_copy (read_concern)
- : mongoc_read_concern_new ();
- }
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_client_get_read_prefs --
- *
- * Fetch the default read preferences for @client.
- *
- * Returns:
- * None.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-const mongoc_read_prefs_t *
-mongoc_client_get_read_prefs (const mongoc_client_t *client)
-{
- BSON_ASSERT (client);
-
- return client->read_prefs;
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_client_set_read_prefs --
- *
- * Set the default read preferences for @client.
- *
- * Returns:
- * None.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-void
-mongoc_client_set_read_prefs (mongoc_client_t *client,
- const mongoc_read_prefs_t *read_prefs)
-{
- BSON_ASSERT (client);
-
- if (read_prefs != client->read_prefs) {
- if (client->read_prefs) {
- mongoc_read_prefs_destroy (client->read_prefs);
- }
- client->read_prefs = read_prefs
- ? mongoc_read_prefs_copy (read_prefs)
- : mongoc_read_prefs_new (MONGOC_READ_PRIMARY);
- }
-}
-
-mongoc_cursor_t *
-mongoc_client_command (mongoc_client_t *client,
- const char *db_name,
- mongoc_query_flags_t flags,
- uint32_t skip,
- uint32_t limit,
- uint32_t batch_size,
- const bson_t *query,
- const bson_t *fields,
- const mongoc_read_prefs_t *read_prefs)
-{
- char *ns = NULL;
- mongoc_cursor_t *cursor;
-
- BSON_ASSERT (client);
- BSON_ASSERT (db_name);
- BSON_ASSERT (query);
-
- /*
- * Allow a caller to provide a fully qualified namespace
- */
- if (NULL == strstr (db_name, "$cmd")) {
- ns = bson_strdup_printf ("%s.$cmd", db_name);
- db_name = ns;
- }
-
- cursor =
- _mongoc_cursor_cmd_deprecated_new (client, db_name, query, read_prefs);
-
- bson_free (ns);
- return cursor;
-}
-
-
-static bool
-_mongoc_client_retryable_write_command_with_stream (
- mongoc_client_t *client,
- mongoc_cmd_parts_t *parts,
- mongoc_server_stream_t *server_stream,
- bson_t *reply,
- bson_error_t *error)
-{
- mongoc_server_stream_t *retry_server_stream = NULL;
- bson_iter_t txn_number_iter;
- bool is_retryable = true;
- bool ret;
-
- ENTRY;
-
- BSON_ASSERT (parts->is_retryable_write);
-
- /* increment the transaction number for the first attempt of each retryable
- * write command */
- BSON_ASSERT (bson_iter_init_find (
- &txn_number_iter, parts->assembled.command, "txnNumber"));
- bson_iter_overwrite_int64 (
- &txn_number_iter, ++parts->assembled.session->server_session->txn_number);
-
-retry:
- ret = mongoc_cluster_run_command_monitored (
- &client->cluster, &parts->assembled, reply, error);
-
- _mongoc_write_error_handle_labels (
- ret, error, reply, server_stream->sd->max_wire_version);
-
- if (is_retryable) {
- _mongoc_write_error_update_if_unsupported_storage_engine (
- ret, error, reply);
- }
-
- /* If a retryable error is encountered and the write is retryable, select
- * a new writable stream and retry. If server selection fails or the selected
- * server does not support retryable writes, fall through and allow the
- * original error to be reported. */
- if (is_retryable &&
- _mongoc_write_error_get_type (reply) == MONGOC_WRITE_ERR_RETRY) {
- bson_error_t ignored_error;
-
- /* each write command may be retried at most once */
- is_retryable = false;
-
- if (retry_server_stream) {
- mongoc_server_stream_cleanup (retry_server_stream);
- }
-
- retry_server_stream = mongoc_cluster_stream_for_writes (
- &client->cluster, parts->assembled.session, NULL, &ignored_error);
-
- if (retry_server_stream && retry_server_stream->sd->max_wire_version >=
- WIRE_VERSION_RETRY_WRITES) {
- parts->assembled.server_stream = retry_server_stream;
- bson_destroy (reply);
- GOTO (retry);
- }
- }
-
- if (retry_server_stream) {
- mongoc_server_stream_cleanup (retry_server_stream);
- }
-
- if (ret && error) {
- /* if a retry succeeded, clear the initial error */
- memset (error, 0, sizeof (bson_error_t));
- }
-
- RETURN (ret);
-}
-
-
-static bool
-_mongoc_client_retryable_read_command_with_stream (
- mongoc_client_t *client,
- mongoc_cmd_parts_t *parts,
- mongoc_server_stream_t *server_stream,
- bson_t *reply,
- bson_error_t *error)
-{
- mongoc_server_stream_t *retry_server_stream = NULL;
- bool is_retryable = true;
- bool ret;
- bson_t reply_local;
-
- if (reply == NULL) {
- reply = &reply_local;
- }
-
- ENTRY;
-
- BSON_ASSERT (parts->is_retryable_read);
-
-retry:
- ret = mongoc_cluster_run_command_monitored (
- &client->cluster, &parts->assembled, reply, error);
-
- /* If a retryable error is encountered and the read is retryable, select
- * a new readable stream and retry. If server selection fails or the selected
- * server does not support retryable reads, fall through and allow the
- * original error to be reported. */
- if (is_retryable && _mongoc_read_error_get_type (ret, error, reply) ==
- MONGOC_READ_ERR_RETRY) {
- bson_error_t ignored_error;
-
- /* each read command may be retried at most once */
- is_retryable = false;
-
- if (retry_server_stream) {
- mongoc_server_stream_cleanup (retry_server_stream);
- }
-
- retry_server_stream =
- mongoc_cluster_stream_for_reads (&client->cluster,
- parts->read_prefs,
- parts->assembled.session,
- NULL,
- &ignored_error);
-
- if (retry_server_stream && retry_server_stream->sd->max_wire_version >=
- WIRE_VERSION_RETRY_READS) {
- parts->assembled.server_stream = retry_server_stream;
- bson_destroy (reply);
- GOTO (retry);
- }
- }
-
- if (retry_server_stream) {
- mongoc_server_stream_cleanup (retry_server_stream);
- }
-
- if (ret && error) {
- /* if a retry succeeded, clear the initial error */
- memset (error, 0, sizeof (bson_error_t));
- }
-
- RETURN (ret);
-}
-
-
-static bool
-_mongoc_client_command_with_stream (mongoc_client_t *client,
- mongoc_cmd_parts_t *parts,
- const mongoc_read_prefs_t *read_prefs,
- mongoc_server_stream_t *server_stream,
- bson_t *reply,
- bson_error_t *error)
-{
- ENTRY;
-
- parts->assembled.operation_id = ++client->cluster.operation_id;
- if (!mongoc_cmd_parts_assemble (parts, server_stream, error)) {
- _mongoc_bson_init_if_set (reply);
- return false;
- };
-
- if (parts->is_retryable_write) {
- RETURN (_mongoc_client_retryable_write_command_with_stream (
- client, parts, server_stream, reply, error));
- }
-
- if (parts->is_retryable_read) {
- RETURN (_mongoc_client_retryable_read_command_with_stream (
- client, parts, server_stream, reply, error));
- }
-
- RETURN (mongoc_cluster_run_command_monitored (
- &client->cluster, &parts->assembled, reply, error));
-}
-
-
-bool
-mongoc_client_command_simple (mongoc_client_t *client,
- const char *db_name,
- const bson_t *command,
- const mongoc_read_prefs_t *read_prefs,
- bson_t *reply,
- bson_error_t *error)
-{
- mongoc_cluster_t *cluster;
- mongoc_server_stream_t *server_stream = NULL;
- mongoc_cmd_parts_t parts;
- bool ret;
-
- ENTRY;
-
- BSON_ASSERT (client);
- BSON_ASSERT (db_name);
- BSON_ASSERT (command);
-
- if (!_mongoc_read_prefs_validate (read_prefs, error)) {
- RETURN (false);
- }
-
- cluster = &client->cluster;
- mongoc_cmd_parts_init (&parts, client, db_name, MONGOC_QUERY_NONE, command);
- parts.read_prefs = read_prefs;
-
- /* Server Selection Spec: "The generic command method has a default read
- * preference of mode 'primary'. The generic command method MUST ignore any
- * default read preference from client, database or collection
- * configuration. The generic command method SHOULD allow an optional read
- * preference argument."
- */
- server_stream =
- mongoc_cluster_stream_for_reads (cluster, read_prefs, NULL, reply, error);
-
- if (server_stream) {
- ret = _mongoc_client_command_with_stream (
- client, &parts, read_prefs, server_stream, reply, error);
- } else {
- /* reply initialized by mongoc_cluster_stream_for_reads */
- ret = false;
- }
-
- mongoc_cmd_parts_cleanup (&parts);
- mongoc_server_stream_cleanup (server_stream);
-
- RETURN (ret);
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_client_command_with_opts --
- *
- * Execute a command on the server. If mode is MONGOC_CMD_READ or
- * MONGOC_CMD_RW, then read concern is applied from @opts, or else from
- * @default_rc, and read preferences are applied from @user_prefs, or else
- * from @default_prefs. If mode is MONGOC_CMD_WRITE or MONGOC_CMD_RW, then
- * write concern is applied from @opts if present, or else @default_wc.
- *
- * If mode is MONGOC_CMD_RAW, then read concern and write concern are
- * applied from @opts only. Read preferences are applied from
- * @user_prefs.
- *
- * The mongoc_client_t's read preference, read concern, and write concern
- * are *NOT* applied.
- *
- * Returns:
- * Success or failure.
- * A write concern timeout or write concern error is considered a failure.
- *
- * Side effects:
- * @reply is always initialized.
- * @error is filled out if the command fails.
- *
- *--------------------------------------------------------------------------
- */
-bool
-_mongoc_client_command_with_opts (mongoc_client_t *client,
- const char *db_name,
- const bson_t *command,
- mongoc_command_mode_t mode,
- const bson_t *opts,
- mongoc_query_flags_t flags,
- const mongoc_read_prefs_t *user_prefs,
- const mongoc_read_prefs_t *default_prefs,
- mongoc_read_concern_t *default_rc,
- mongoc_write_concern_t *default_wc,
- bson_t *reply,
- bson_error_t *error)
-{
- mongoc_read_write_opts_t read_write_opts;
- mongoc_cmd_parts_t parts;
- const char *command_name;
- const mongoc_read_prefs_t *prefs = COALESCE (user_prefs, default_prefs);
- mongoc_server_stream_t *server_stream = NULL;
- mongoc_cluster_t *cluster;
- mongoc_client_session_t *cs;
- bson_t reply_local;
- bson_t *reply_ptr;
- int32_t wire_version;
- int32_t wc_wire_version;
- bool reply_initialized = false;
- bool ret = false;
-
- ENTRY;
-
- BSON_ASSERT (client);
- BSON_ASSERT (db_name);
- BSON_ASSERT (command);
-
- command_name = _mongoc_get_command_name (command);
- cluster = &client->cluster;
- reply_ptr = reply ? reply : &reply_local;
-
- mongoc_cmd_parts_init (&parts, client, db_name, flags, command);
- parts.is_read_command = (mode & MONGOC_CMD_READ);
- parts.is_write_command = (mode & MONGOC_CMD_WRITE);
-
- if (!_mongoc_read_write_opts_parse (client, opts, &read_write_opts, error)) {
- GOTO (done);
- }
-
- cs = read_write_opts.client_session;
-
- if (!command_name) {
- bson_set_error (error,
- MONGOC_ERROR_COMMAND,
- MONGOC_ERROR_COMMAND_INVALID_ARG,
- "Empty command document");
- GOTO (done);
- }
-
- if (_mongoc_client_session_in_txn (read_write_opts.client_session)) {
- if ((mode == MONGOC_CMD_READ || mode == MONGOC_CMD_RAW) &&
- !IS_PREF_PRIMARY (user_prefs)) {
- bson_set_error (error,
- MONGOC_ERROR_COMMAND,
- MONGOC_ERROR_COMMAND_INVALID_ARG,
- "Read preference in a transaction must be primary");
- GOTO (done);
- }
-
- if (!bson_empty (&read_write_opts.readConcern)) {
- bson_set_error (error,
- MONGOC_ERROR_COMMAND,
- MONGOC_ERROR_COMMAND_INVALID_ARG,
- "Cannot set read concern after starting transaction");
- GOTO (done);
- }
-
- if (read_write_opts.writeConcern &&
- strcmp (command_name, "commitTransaction") != 0 &&
- strcmp (command_name, "abortTransaction") != 0) {
- bson_set_error (error,
- MONGOC_ERROR_COMMAND,
- MONGOC_ERROR_COMMAND_INVALID_ARG,
- "Cannot set write concern after starting transaction");
- GOTO (done);
- }
- }
-
- if (mode == MONGOC_CMD_READ || mode == MONGOC_CMD_RAW) {
- /* NULL read pref is ok */
- if (!_mongoc_read_prefs_validate (prefs, error)) {
- GOTO (done);
- }
-
- parts.read_prefs = prefs;
- } else {
- /* this is a command that writes */
- prefs = NULL;
- }
-
- if (read_write_opts.serverId) {
- /* "serverId" passed in opts */
- server_stream =
- mongoc_cluster_stream_for_server (cluster,
- read_write_opts.serverId,
- true /* reconnect ok */,
- cs,
- reply_ptr,
- error);
-
- if (server_stream && server_stream->sd->type != MONGOC_SERVER_MONGOS) {
- parts.user_query_flags |= MONGOC_QUERY_SECONDARY_OK;
- }
- } else if (parts.is_write_command) {
- server_stream =
- mongoc_cluster_stream_for_writes (cluster, cs, reply_ptr, error);
- } else {
- server_stream =
- mongoc_cluster_stream_for_reads (cluster, prefs, cs, reply_ptr, error);
- }
-
- if (!server_stream) {
- /* stream_for_reads/writes/server has initialized reply */
- reply_initialized = true;
- GOTO (done);
- }
-
- wire_version = server_stream->sd->max_wire_version;
- if (!mongoc_cmd_parts_append_read_write (
- &parts, &read_write_opts, wire_version, error)) {
- GOTO (done);
- }
-
- if (mode & MONGOC_CMD_WRITE) {
- wc_wire_version = !strcasecmp (command_name, "findandmodify")
- ? WIRE_VERSION_FAM_WRITE_CONCERN
- : WIRE_VERSION_CMD_WRITE_CONCERN;
-
- if (read_write_opts.write_concern_owned &&
- wire_version < wc_wire_version) {
- bson_set_error (error,
- MONGOC_ERROR_COMMAND,
- MONGOC_ERROR_PROTOCOL_BAD_WIRE_VERSION,
- "\"%s\" command does not support writeConcern with "
- "wire version %d, wire version %d is required",
- command_name,
- wire_version,
- wc_wire_version);
- GOTO (done);
- }
-
- /* use default write concern unless it's in opts */
- if (!mongoc_write_concern_is_default (default_wc) &&
- !read_write_opts.write_concern_owned &&
- wire_version >= wc_wire_version) {
- if (!mongoc_cmd_parts_set_write_concern (
- &parts, default_wc, wire_version, error)) {
- GOTO (done);
- }
- }
- }
-
- /* use default read concern for read command, unless it's in opts */
- if ((mode & MONGOC_CMD_READ) && bson_empty (&read_write_opts.readConcern)) {
- if (!mongoc_cmd_parts_set_read_concern (
- &parts, default_rc, wire_version, error)) {
- GOTO (done);
- }
- }
-
- ret = _mongoc_client_command_with_stream (
- client, &parts, user_prefs, server_stream, reply_ptr, error);
-
- reply_initialized = true;
-
- if (ret && (mode & MONGOC_CMD_WRITE)) {
- ret = !_mongoc_parse_wc_err (reply_ptr, error);
- }
-
-done:
- if (reply_ptr == &reply_local) {
- if (reply_initialized) {
- bson_destroy (reply_ptr);
- }
- } else if (!reply_initialized) {
- _mongoc_bson_init_if_set (reply);
- }
-
- if (server_stream) {
- mongoc_server_stream_cleanup (server_stream);
- }
-
- mongoc_cmd_parts_cleanup (&parts);
- _mongoc_read_write_opts_cleanup (&read_write_opts);
-
- RETURN (ret);
-}
-
-
-bool
-mongoc_client_read_command_with_opts (mongoc_client_t *client,
- const char *db_name,
- const bson_t *command,
- const mongoc_read_prefs_t *read_prefs,
- const bson_t *opts,
- bson_t *reply,
- bson_error_t *error)
-{
- return _mongoc_client_command_with_opts (client,
- db_name,
- command,
- MONGOC_CMD_READ,
- opts,
- MONGOC_QUERY_NONE,
- read_prefs,
- client->read_prefs,
- client->read_concern,
- client->write_concern,
- reply,
- error);
-}
-
-
-bool
-mongoc_client_write_command_with_opts (mongoc_client_t *client,
- const char *db_name,
- const bson_t *command,
- const bson_t *opts,
- bson_t *reply,
- bson_error_t *error)
-{
- return _mongoc_client_command_with_opts (client,
- db_name,
- command,
- MONGOC_CMD_WRITE,
- opts,
- MONGOC_QUERY_NONE,
- NULL,
- client->read_prefs,
- client->read_concern,
- client->write_concern,
- reply,
- error);
-}
-
-
-bool
-mongoc_client_read_write_command_with_opts (
- mongoc_client_t *client,
- const char *db_name,
- const bson_t *command,
- const mongoc_read_prefs_t *read_prefs /* IGNORED */,
- const bson_t *opts,
- bson_t *reply,
- bson_error_t *error)
-{
- return _mongoc_client_command_with_opts (client,
- db_name,
- command,
- MONGOC_CMD_RW,
- opts,
- MONGOC_QUERY_NONE,
- read_prefs,
- client->read_prefs,
- client->read_concern,
- client->write_concern,
- reply,
- error);
-}
-
-
-bool
-mongoc_client_command_with_opts (mongoc_client_t *client,
- const char *db_name,
- const bson_t *command,
- const mongoc_read_prefs_t *read_prefs,
- const bson_t *opts,
- bson_t *reply,
- bson_error_t *error)
-{
- return _mongoc_client_command_with_opts (client,
- db_name,
- command,
- MONGOC_CMD_RAW,
- opts,
- MONGOC_QUERY_NONE,
- read_prefs,
- NULL,
- client->read_concern,
- client->write_concern,
- reply,
- error);
-}
-
-
-bool
-mongoc_client_command_simple_with_server_id (
- mongoc_client_t *client,
- const char *db_name,
- const bson_t *command,
- const mongoc_read_prefs_t *read_prefs,
- uint32_t server_id,
- bson_t *reply,
- bson_error_t *error)
-{
- mongoc_server_stream_t *server_stream;
- mongoc_cmd_parts_t parts;
- bool ret;
-
- ENTRY;
-
- BSON_ASSERT (client);
- BSON_ASSERT (db_name);
- BSON_ASSERT (command);
-
- if (!_mongoc_read_prefs_validate (read_prefs, error)) {
- RETURN (false);
- }
-
- server_stream = mongoc_cluster_stream_for_server (
- &client->cluster, server_id, true /* reconnect ok */, NULL, reply, error);
-
- if (server_stream) {
- mongoc_cmd_parts_init (
- &parts, client, db_name, MONGOC_QUERY_NONE, command);
- parts.read_prefs = read_prefs;
-
- ret = _mongoc_client_command_with_stream (
- client, &parts, read_prefs, server_stream, reply, error);
-
- mongoc_cmd_parts_cleanup (&parts);
- mongoc_server_stream_cleanup (server_stream);
- RETURN (ret);
- } else {
- /* stream_for_server initialized reply */
- RETURN (false);
- }
-}
-
-
-static void
-_mongoc_client_prepare_killcursors_command (int64_t cursor_id,
- const char *collection,
- bson_t *command)
-{
- bson_t child;
-
- bson_append_utf8 (command, "killCursors", 11, collection, -1);
- bson_append_array_begin (command, "cursors", 7, &child);
- bson_append_int64 (&child, "0", 1, cursor_id);
- bson_append_array_end (command, &child);
-}
-
-
-void
-_mongoc_client_kill_cursor (mongoc_client_t *client,
- uint32_t server_id,
- int64_t cursor_id,
- int64_t operation_id,
- const char *db,
- const char *collection,
- mongoc_client_session_t *cs)
-{
- mongoc_server_stream_t *server_stream;
-
- ENTRY;
-
- BSON_ASSERT (client);
- BSON_ASSERT (cursor_id);
-
- /* don't attempt reconnect if server unavailable, and ignore errors */
- server_stream = mongoc_cluster_stream_for_server (
- &client->cluster, server_id, false /* reconnect_ok */, NULL, NULL, NULL);
-
- if (!server_stream) {
- return;
- }
-
- if (db && collection &&
- server_stream->sd->max_wire_version >= WIRE_VERSION_KILLCURSORS_CMD) {
- _mongoc_client_killcursors_command (
- &client->cluster, server_stream, cursor_id, db, collection, cs);
- } else {
- _mongoc_client_op_killcursors (&client->cluster,
- server_stream,
- cursor_id,
- operation_id,
- db,
- collection);
- }
-
- mongoc_server_stream_cleanup (server_stream);
-
- EXIT;
-}
-
-
-static void
-_mongoc_client_monitor_op_killcursors (mongoc_cluster_t *cluster,
- mongoc_server_stream_t *server_stream,
- int64_t cursor_id,
- int64_t operation_id,
- const char *db,
- const char *collection)
-{
- bson_t doc;
- mongoc_client_t *client;
- mongoc_apm_command_started_t event;
-
- ENTRY;
-
- client = cluster->client;
-
- if (!client->apm_callbacks.started) {
- return;
- }
-
- bson_init (&doc);
- _mongoc_client_prepare_killcursors_command (cursor_id, collection, &doc);
- mongoc_apm_command_started_init (&event,
- &doc,
- db,
- "killCursors",
- cluster->request_id,
- operation_id,
- &server_stream->sd->host,
- server_stream->sd->id,
- &server_stream->sd->service_id,
- NULL,
- client->apm_context);
-
- client->apm_callbacks.started (&event);
- mongoc_apm_command_started_cleanup (&event);
- bson_destroy (&doc);
-
- EXIT;
-}
-
-
-static void
-_mongoc_client_monitor_op_killcursors_succeeded (
- mongoc_cluster_t *cluster,
- int64_t duration,
- mongoc_server_stream_t *server_stream,
- int64_t cursor_id,
- int64_t operation_id)
-{
- mongoc_client_t *client;
- bson_t doc;
- bson_t cursors_unknown;
- mongoc_apm_command_succeeded_t event;
-
- ENTRY;
-
- client = cluster->client;
-
- if (!client->apm_callbacks.succeeded) {
- EXIT;
- }
-
- /* fake server reply to killCursors command: {ok: 1, cursorsUnknown: [42]} */
- bson_init (&doc);
- bson_append_int32 (&doc, "ok", 2, 1);
- bson_append_array_begin (&doc, "cursorsUnknown", 14, &cursors_unknown);
- bson_append_int64 (&cursors_unknown, "0", 1, cursor_id);
- bson_append_array_end (&doc, &cursors_unknown);
-
- mongoc_apm_command_succeeded_init (&event,
- duration,
- &doc,
- "killCursors",
- cluster->request_id,
- operation_id,
- &server_stream->sd->host,
- server_stream->sd->id,
- &server_stream->sd->service_id,
- false,
- client->apm_context);
-
- client->apm_callbacks.succeeded (&event);
-
- mongoc_apm_command_succeeded_cleanup (&event);
- bson_destroy (&doc);
-}
-
-
-static void
-_mongoc_client_monitor_op_killcursors_failed (
- mongoc_cluster_t *cluster,
- int64_t duration,
- mongoc_server_stream_t *server_stream,
- const bson_error_t *error,
- int64_t operation_id)
-{
- mongoc_client_t *client;
- bson_t doc;
- mongoc_apm_command_failed_t event;
-
- ENTRY;
-
- client = cluster->client;
-
- if (!client->apm_callbacks.failed) {
- EXIT;
- }
-
- /* fake server reply to killCursors command: {ok: 0} */
- bson_init (&doc);
- bson_append_int32 (&doc, "ok", 2, 0);
-
- mongoc_apm_command_failed_init (&event,
- duration,
- "killCursors",
- error,
- &doc,
- cluster->request_id,
- operation_id,
- &server_stream->sd->host,
- server_stream->sd->id,
- &server_stream->sd->service_id,
- false,
- client->apm_context);
-
- client->apm_callbacks.failed (&event);
-
- mongoc_apm_command_failed_cleanup (&event);
- bson_destroy (&doc);
-}
-
-
-static void
-_mongoc_client_op_killcursors (mongoc_cluster_t *cluster,
- mongoc_server_stream_t *server_stream,
- int64_t cursor_id,
- int64_t operation_id,
- const char *db,
- const char *collection)
-{
- int64_t started;
- mongoc_rpc_t rpc = {{0}};
- bson_error_t error;
- bool has_ns;
- bool r;
-
- /* called by old mongoc_client_kill_cursor without db/collection? */
- has_ns = (db && collection);
- started = bson_get_monotonic_time ();
-
- ++cluster->request_id;
-
- rpc.header.msg_len = 0;
- rpc.header.request_id = cluster->request_id;
- rpc.header.response_to = 0;
- rpc.header.opcode = MONGOC_OPCODE_KILL_CURSORS;
- rpc.kill_cursors.zero = 0;
- rpc.kill_cursors.cursors = &cursor_id;
- rpc.kill_cursors.n_cursors = 1;
-
- if (has_ns) {
- _mongoc_client_monitor_op_killcursors (
- cluster, server_stream, cursor_id, operation_id, db, collection);
- }
-
- r = mongoc_cluster_legacy_rpc_sendv_to_server (
- cluster, &rpc, server_stream, &error);
-
- if (has_ns) {
- if (r) {
- _mongoc_client_monitor_op_killcursors_succeeded (
- cluster,
- bson_get_monotonic_time () - started,
- server_stream,
- cursor_id,
- operation_id);
- } else {
- _mongoc_client_monitor_op_killcursors_failed (
- cluster,
- bson_get_monotonic_time () - started,
- server_stream,
- &error,
- operation_id);
- }
- }
-}
-
-
-static void
-_mongoc_client_killcursors_command (mongoc_cluster_t *cluster,
- mongoc_server_stream_t *server_stream,
- int64_t cursor_id,
- const char *db,
- const char *collection,
- mongoc_client_session_t *cs)
-{
- bson_t command = BSON_INITIALIZER;
- mongoc_cmd_parts_t parts;
-
- ENTRY;
-
- _mongoc_client_prepare_killcursors_command (cursor_id, collection, &command);
- mongoc_cmd_parts_init (
- &parts, cluster->client, db, MONGOC_QUERY_SECONDARY_OK, &command);
- parts.assembled.operation_id = ++cluster->operation_id;
- mongoc_cmd_parts_set_session (&parts, cs);
-
- if (mongoc_cmd_parts_assemble (&parts, server_stream, NULL)) {
- /* Find, getMore And killCursors Commands Spec: "The result from the
- * killCursors command MAY be safely ignored."
- */
- (void) mongoc_cluster_run_command_monitored (
- cluster, &parts.assembled, NULL, NULL);
- }
-
- mongoc_cmd_parts_cleanup (&parts);
- bson_destroy (&command);
-
- EXIT;
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_client_kill_cursor --
- *
- * Destroy a cursor on the server.
- *
- * NOTE: this is only reliable when connected to a single mongod or
- * mongos. If connected to a replica set, the driver attempts to
- * kill the cursor on the primary. If connected to multiple mongoses
- * the kill-cursors message is sent to a *random* mongos.
- *
- * If no primary, mongos, or standalone server is known, return
- * without attempting to reconnect.
- *
- * Returns:
- * None.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-void
-mongoc_client_kill_cursor (mongoc_client_t *client, int64_t cursor_id)
-{
- mongoc_topology_t *const topology =
- BSON_ASSERT_PTR_INLINE (client)->topology;
- mongoc_server_description_t const *selected_server;
- mongoc_read_prefs_t *read_prefs;
- bson_error_t error;
- uint32_t server_id = 0;
- mc_shared_tpld td = mc_tpld_take_ref (topology);
-
- read_prefs = mongoc_read_prefs_new (MONGOC_READ_PRIMARY);
-
- if (!mongoc_topology_compatible (td.ptr, NULL, &error)) {
- MONGOC_ERROR ("Could not kill cursor: %s", error.message);
- mc_tpld_drop_ref (&td);
- mongoc_read_prefs_destroy (read_prefs);
- return;
- }
-
- /* see if there's a known writable server - do no I/O or retries */
- selected_server = mongoc_topology_description_select (
- td.ptr, MONGOC_SS_WRITE, read_prefs, topology->local_threshold_msec);
-
- if (selected_server) {
- server_id = selected_server->id;
- }
-
- if (server_id) {
- _mongoc_client_kill_cursor (client,
- server_id,
- cursor_id,
- 0 /* operation_id */,
- NULL /* db */,
- NULL /* collection */,
- NULL /* session */);
- } else {
- MONGOC_INFO ("No server available for mongoc_client_kill_cursor");
- }
-
- mongoc_read_prefs_destroy (read_prefs);
- mc_tpld_drop_ref (&td);
-}
-
-
-char **
-mongoc_client_get_database_names (mongoc_client_t *client, bson_error_t *error)
-{
- return mongoc_client_get_database_names_with_opts (client, NULL, error);
-}
-
-
-char **
-mongoc_client_get_database_names_with_opts (mongoc_client_t *client,
- const bson_t *opts,
- bson_error_t *error)
-{
- bson_iter_t iter;
- const char *name;
- char **ret = NULL;
- int i = 0;
- mongoc_cursor_t *cursor;
- const bson_t *doc;
- bson_t cmd = BSON_INITIALIZER;
-
- BSON_ASSERT (client);
- BSON_APPEND_INT32 (&cmd, "listDatabases", 1);
- BSON_APPEND_BOOL (&cmd, "nameOnly", true);
-
- /* ignore client read prefs */
- cursor = _mongoc_cursor_array_new (client, "admin", &cmd, opts, "databases");
- bson_destroy (&cmd);
-
- while (mongoc_cursor_next (cursor, &doc)) {
- if (bson_iter_init (&iter, doc) && bson_iter_find (&iter, "name") &&
- BSON_ITER_HOLDS_UTF8 (&iter) &&
- (name = bson_iter_utf8 (&iter, NULL))) {
- ret = (char **) bson_realloc (ret, sizeof (char *) * (i + 2));
- ret[i] = bson_strdup (name);
- ret[++i] = NULL;
- }
- }
-
- if (!ret && !mongoc_cursor_error (cursor, error)) {
- ret = (char **) bson_malloc0 (sizeof (void *));
- }
-
- mongoc_cursor_destroy (cursor);
-
- return ret;
-}
-
-
-mongoc_cursor_t *
-mongoc_client_find_databases (mongoc_client_t *client, bson_error_t *error)
-{
- /* existing bug in this deprecated API: error pointer is unused */
- return mongoc_client_find_databases_with_opts (client, NULL);
-}
-
-
-mongoc_cursor_t *
-mongoc_client_find_databases_with_opts (mongoc_client_t *client,
- const bson_t *opts)
-{
- bson_t cmd = BSON_INITIALIZER;
- mongoc_cursor_t *cursor;
-
- BSON_ASSERT (client);
- BSON_APPEND_INT32 (&cmd, "listDatabases", 1);
- cursor = _mongoc_cursor_array_new (client, "admin", &cmd, opts, "databases");
- bson_destroy (&cmd);
- return cursor;
-}
-
-
-int32_t
-mongoc_client_get_max_message_size (mongoc_client_t *client) /* IN */
-{
- BSON_ASSERT (client);
-
- return mongoc_cluster_get_max_msg_size (&client->cluster);
-}
-
-
-int32_t
-mongoc_client_get_max_bson_size (mongoc_client_t *client) /* IN */
-{
- BSON_ASSERT (client);
-
- return mongoc_cluster_get_max_bson_obj_size (&client->cluster);
-}
-
-
-bool
-mongoc_client_get_server_status (mongoc_client_t *client, /* IN */
- mongoc_read_prefs_t *read_prefs, /* IN */
- bson_t *reply, /* OUT */
- bson_error_t *error) /* OUT */
-{
- bson_t cmd = BSON_INITIALIZER;
- bool ret = false;
-
- BSON_ASSERT (client);
-
- BSON_APPEND_INT32 (&cmd, "serverStatus", 1);
- ret = mongoc_client_command_simple (
- client, "admin", &cmd, read_prefs, reply, error);
- bson_destroy (&cmd);
-
- return ret;
-}
-
-
-void
-mongoc_client_set_stream_initiator (mongoc_client_t *client,
- mongoc_stream_initiator_t initiator,
- void *user_data)
-{
- BSON_ASSERT (client);
-
- if (!initiator) {
- initiator = mongoc_client_default_stream_initiator;
- user_data = client;
- } else {
- MONGOC_DEBUG ("Using custom stream initiator.");
- }
-
- client->initiator = initiator;
- client->initiator_data = user_data;
-
- if (client->topology->single_threaded) {
- mongoc_topology_scanner_set_stream_initiator (
- client->topology->scanner, initiator, user_data);
- }
-}
-
-
-bool
-_mongoc_client_set_apm_callbacks_private (mongoc_client_t *client,
- mongoc_apm_callbacks_t *callbacks,
- void *context)
-{
- if (callbacks) {
- memcpy (
- &client->apm_callbacks, callbacks, sizeof (mongoc_apm_callbacks_t));
- } else {
- memset (&client->apm_callbacks, 0, sizeof (mongoc_apm_callbacks_t));
- }
-
- client->apm_context = context;
-
- /* A client pool sets APM callbacks for the entire pool. */
- if (client->topology->single_threaded) {
- mongoc_topology_set_apm_callbacks (
- client->topology,
- /* We are safe to modify the shared_descr directly, since we are
- * single-threaded */
- mc_tpld_unsafe_get_mutable (client->topology),
- callbacks,
- context);
- }
-
- return true;
-}
-
-
-bool
-mongoc_client_set_apm_callbacks (mongoc_client_t *client,
- mongoc_apm_callbacks_t *callbacks,
- void *context)
-{
- if (!client->topology->single_threaded) {
- MONGOC_ERROR ("Cannot set callbacks on a pooled client, use "
- "mongoc_client_pool_set_apm_callbacks");
- return false;
- }
-
- return _mongoc_client_set_apm_callbacks_private (client, callbacks, context);
-}
-
-mongoc_server_description_t *
-mongoc_client_get_server_description (mongoc_client_t *client,
- uint32_t server_id)
-{
- mongoc_server_description_t *ret;
- mc_shared_tpld td = mc_tpld_take_ref (client->topology);
- mongoc_server_description_t const *sd =
- mongoc_topology_description_server_by_id_const (
- td.ptr, server_id, NULL /* <- the error info isn't useful */);
- ret = mongoc_server_description_new_copy (sd);
- mc_tpld_drop_ref (&td);
- return ret;
-}
-
-
-mongoc_server_description_t **
-mongoc_client_get_server_descriptions (const mongoc_client_t *client,
- size_t *n /* OUT */)
-{
- mc_shared_tpld td =
- mc_tpld_take_ref (BSON_ASSERT_PTR_INLINE (client)->topology);
- mongoc_server_description_t **const sds =
- mongoc_topology_description_get_servers (td.ptr,
- BSON_ASSERT_PTR_INLINE (n));
- mc_tpld_drop_ref (&td);
- return sds;
-}
-
-
-void
-mongoc_server_descriptions_destroy_all (mongoc_server_description_t **sds,
- size_t n)
-{
- size_t i;
-
- for (i = 0; i < n; ++i) {
- mongoc_server_description_destroy (sds[i]);
- }
-
- bson_free (sds);
-}
-
-
-mongoc_server_description_t *
-mongoc_client_select_server (mongoc_client_t *client,
- bool for_writes,
- const mongoc_read_prefs_t *prefs,
- bson_error_t *error)
-{
- mongoc_ss_optype_t optype = for_writes ? MONGOC_SS_WRITE : MONGOC_SS_READ;
- mongoc_server_description_t *sd;
-
- if (for_writes && prefs) {
- bson_set_error (error,
- MONGOC_ERROR_SERVER_SELECTION,
- MONGOC_ERROR_SERVER_SELECTION_FAILURE,
- "Cannot use read preferences with for_writes = true");
- return NULL;
- }
-
- if (!_mongoc_read_prefs_validate (prefs, error)) {
- return NULL;
- }
-
- sd = mongoc_topology_select (client->topology, optype, prefs, error);
- if (!sd) {
- return NULL;
- }
-
- if (mongoc_cluster_check_interval (&client->cluster, sd->id)) {
- /* check not required, or it succeeded */
- return sd;
- }
-
- /* check failed, retry once */
- mongoc_server_description_destroy (sd);
- sd = mongoc_topology_select (client->topology, optype, prefs, error);
- if (sd) {
- return sd;
- }
-
- return NULL;
-}
-
-bool
-mongoc_client_set_error_api (mongoc_client_t *client, int32_t version)
-{
- if (!client->topology->single_threaded) {
- MONGOC_ERROR ("Cannot set Error API Version on a pooled client, use "
- "mongoc_client_pool_set_error_api");
- return false;
- }
-
- if (version != MONGOC_ERROR_API_VERSION_LEGACY &&
- version != MONGOC_ERROR_API_VERSION_2) {
- MONGOC_ERROR ("Unsupported Error API Version: %" PRId32, version);
- return false;
- }
-
- if (client->error_api_set) {
- MONGOC_ERROR ("Can only set Error API Version once");
- return false;
- }
-
- client->error_api_version = version;
- client->error_api_set = true;
-
- return true;
-}
-
-bool
-mongoc_client_set_appname (mongoc_client_t *client, const char *appname)
-{
- if (!client->topology->single_threaded) {
- MONGOC_ERROR ("Cannot call set_appname on a client from a pool");
- return false;
- }
-
- return _mongoc_topology_set_appname (client->topology, appname);
-}
-
-mongoc_server_session_t *
-_mongoc_client_pop_server_session (mongoc_client_t *client, bson_error_t *error)
-{
- return _mongoc_topology_pop_server_session (client->topology, error);
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_client_lookup_session --
- *
- * Retrieve a mongoc_client_session_t associated with @client_session_id.
- * Use this to find the "lsid" and "$clusterTime" to send in the server
- * command.
- *
- * Returns:
- * True on success, false on error and @error is set. Will return false
- * if the session is from an outdated client generation, a holdover
- * from before a call to mongoc_client_reset.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-bool
-_mongoc_client_lookup_session (const mongoc_client_t *client,
- uint32_t client_session_id,
- mongoc_client_session_t **cs /* OUT */,
- bson_error_t *error /* OUT */)
-{
- ENTRY;
-
- *cs = mongoc_set_get (client->client_sessions, client_session_id);
-
- if (*cs) {
- RETURN (true);
- }
-
- bson_set_error (error,
- MONGOC_ERROR_COMMAND,
- MONGOC_ERROR_COMMAND_INVALID_ARG,
- "Invalid sessionId");
-
- RETURN (false);
-}
-
-void
-_mongoc_client_unregister_session (mongoc_client_t *client,
- mongoc_client_session_t *session)
-{
- mongoc_set_rm (client->client_sessions, session->client_session_id);
-}
-
-void
-_mongoc_client_push_server_session (mongoc_client_t *client,
- mongoc_server_session_t *server_session)
-{
- _mongoc_topology_push_server_session (client->topology, server_session);
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_client_end_sessions --
- *
- * End all server sessions in the topology's server session pool.
- * Don't block long: if server selection or connecting fails, quit.
- *
- * The server session pool becomes invalid, but may not be empty.
- * Destroy the topology after this without using any sessions.
- *
- *--------------------------------------------------------------------------
- */
-
-void
-_mongoc_client_end_sessions (mongoc_client_t *client)
-{
- mongoc_topology_t *t = client->topology;
- mongoc_read_prefs_t *prefs;
- bson_error_t error;
- uint32_t server_id;
- bson_t cmd;
- mongoc_server_stream_t *stream;
- mongoc_cmd_parts_t parts;
- mongoc_cluster_t *cluster = &client->cluster;
- bool r;
-
- while (!mongoc_server_session_pool_is_empty (t->session_pool)) {
- prefs = mongoc_read_prefs_new (MONGOC_READ_PRIMARY_PREFERRED);
- server_id =
- mongoc_topology_select_server_id (t, MONGOC_SS_READ, prefs, &error);
-
- mongoc_read_prefs_destroy (prefs);
- if (!server_id) {
- MONGOC_WARNING ("Couldn't send \"endSessions\": %s", error.message);
- return;
- }
-
- stream = mongoc_cluster_stream_for_server (
- cluster, server_id, false /* reconnect_ok */, NULL, NULL, &error);
-
- if (!stream) {
- MONGOC_WARNING ("Couldn't send \"endSessions\": %s", error.message);
- return;
- }
-
- /* end sessions in chunks */
- while (_mongoc_topology_end_sessions_cmd (t, &cmd)) {
- mongoc_cmd_parts_init (
- &parts, client, "admin", MONGOC_QUERY_SECONDARY_OK, &cmd);
- parts.assembled.operation_id = ++cluster->operation_id;
- parts.prohibit_lsid = true;
-
- r = mongoc_cmd_parts_assemble (&parts, stream, &error);
- if (!r) {
- MONGOC_WARNING ("Couldn't construct \"endSessions\" command: %s",
- error.message);
- } else {
- r = mongoc_cluster_run_command_monitored (
- cluster, &parts.assembled, NULL, &error);
-
- if (!r) {
- MONGOC_WARNING ("Couldn't send \"endSessions\": %s",
- error.message);
- }
- }
-
- mongoc_cmd_parts_cleanup (&parts);
-
- if (!mongoc_cluster_stream_valid (cluster, stream)) {
- /* The stream was invalidated as a result of a network error, so we
- * stop sending commands. */
- break;
- }
-
- bson_destroy (&cmd);
- }
-
- bson_destroy (&cmd);
- mongoc_server_stream_cleanup (stream);
- }
-}
-
-void
-mongoc_client_reset (mongoc_client_t *client)
-{
- BSON_ASSERT (client);
-
- client->generation++;
-
- /* Client sessions are owned and destroyed by the user, but we keep
- local pointers to them for reference. On reset, clear our local
- set without destroying the sessions or calling endSessions.
- client_sessions has no dtor, so it won't destroy its items.
-
- Destroying the local cache of client sessions here ensures they
- cannot be used by future operations--lookup for them will fail. */
- mongoc_set_destroy (client->client_sessions);
- client->client_sessions = mongoc_set_new (8, NULL, NULL);
-
- /* Server sessions are owned by us, so we clear the pool on reset. */
- mongoc_server_session_pool_clear (client->topology->session_pool);
-}
-
-mongoc_change_stream_t *
-mongoc_client_watch (mongoc_client_t *client,
- const bson_t *pipeline,
- const bson_t *opts)
-{
- return _mongoc_change_stream_new_from_client (client, pipeline, opts);
-}
-
-bool
-mongoc_client_enable_auto_encryption (mongoc_client_t *client,
- mongoc_auto_encryption_opts_t *opts,
- bson_error_t *error)
-{
- if (!client->topology->single_threaded) {
- bson_set_error (error,
- MONGOC_ERROR_CLIENT,
- MONGOC_ERROR_CLIENT_INVALID_ENCRYPTION_ARG,
- "Cannot enable auto encryption on a pooled client, use "
- "mongoc_client_pool_enable_auto_encryption");
- return false;
- }
- return _mongoc_cse_client_enable_auto_encryption (client, opts, error);
-}
-
-bool
-mongoc_client_set_server_api (mongoc_client_t *client,
- const mongoc_server_api_t *api,
- bson_error_t *error)
-{
- BSON_ASSERT_PARAM (client);
- BSON_ASSERT_PARAM (api);
-
- if (client->is_pooled) {
- bson_set_error (
- error,
- MONGOC_ERROR_CLIENT,
- MONGOC_ERROR_CLIENT_API_FROM_POOL,
- "Cannot set server api on a client checked out from a pool");
- return false;
- }
-
- if (client->api) {
- bson_set_error (error,
- MONGOC_ERROR_CLIENT,
- MONGOC_ERROR_CLIENT_API_ALREADY_SET,
- "Cannot set server api more than once per client");
- return false;
- }
-
- client->api = mongoc_server_api_copy (api);
- _mongoc_topology_scanner_set_server_api (client->topology->scanner, api);
- return true;
-}
-
-mongoc_server_description_t *
-mongoc_client_get_handshake_description (mongoc_client_t *client,
- uint32_t server_id,
- bson_t *opts,
- bson_error_t *error)
-{
- mongoc_server_stream_t *server_stream;
- mongoc_server_description_t *sd;
-
- server_stream = mongoc_cluster_stream_for_server (&client->cluster,
- server_id,
- true /* reconnect */,
- NULL /* client session */,
- NULL /* reply */,
- error);
- if (!server_stream) {
- return NULL;
- }
-
- sd = mongoc_server_description_new_copy (server_stream->sd);
- mongoc_server_stream_cleanup (server_stream);
- return sd;
-}
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client.h b/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client.h
deleted file mode 100644
index ed87d0f3..00000000
--- a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client.h
+++ /dev/null
@@ -1,295 +0,0 @@
-/*
- * Copyright 2013 MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "mongoc-prelude.h"
-
-#ifndef MONGOC_CLIENT_H
-#define MONGOC_CLIENT_H
-
-#include <bson/bson.h>
-
-#include "mongoc-apm.h"
-#include "mongoc-client-side-encryption.h"
-#include "mongoc-collection.h"
-#include "mongoc-config.h"
-#include "mongoc-cursor.h"
-#include "mongoc-database.h"
-#include "mongoc-gridfs.h"
-#include "mongoc-index.h"
-#include "mongoc-macros.h"
-#include "mongoc-read-prefs.h"
-#include "mongoc-server-api.h"
-#ifdef MONGOC_ENABLE_SSL
-#include "mongoc-ssl.h"
-#endif
-#include "mongoc-stream.h"
-#include "mongoc-uri.h"
-#include "mongoc-write-concern.h"
-#include "mongoc-read-concern.h"
-#include "mongoc-server-description.h"
-
-BSON_BEGIN_DECLS
-
-/* This define is part of our public API. But per MongoDB 4.4, there is no
- * longer a size limit on collection names. */
-#define MONGOC_NAMESPACE_MAX 128
-
-
-#ifndef MONGOC_DEFAULT_CONNECTTIMEOUTMS
-#define MONGOC_DEFAULT_CONNECTTIMEOUTMS (10 * 1000L)
-#endif
-
-
-#ifndef MONGOC_DEFAULT_SOCKETTIMEOUTMS
-/*
- * NOTE: The default socket timeout for connections is 5 minutes. This
- * means that if your MongoDB server dies or becomes unavailable
- * it will take 5 minutes to detect this.
- *
- * You can change this by providing sockettimeoutms= in your
- * connection URI.
- */
-#define MONGOC_DEFAULT_SOCKETTIMEOUTMS (1000L * 60L * 5L)
-#endif
-
-
-/**
- * mongoc_client_t:
- *
- * The mongoc_client_t structure maintains information about a connection to
- * a MongoDB server.
- */
-typedef struct _mongoc_client_t mongoc_client_t;
-
-
-typedef struct _mongoc_client_session_t mongoc_client_session_t;
-typedef struct _mongoc_session_opt_t mongoc_session_opt_t;
-typedef struct _mongoc_transaction_opt_t mongoc_transaction_opt_t;
-
-/**
- * mongoc_stream_initiator_t:
- * @uri: The uri and options for the stream.
- * @host: The host and port (or UNIX domain socket path) to connect to.
- * @user_data: The pointer passed to mongoc_client_set_stream_initiator.
- * @error: A location for an error.
- *
- * Creates a new mongoc_stream_t for the host and port. Begin a
- * non-blocking connect and return immediately.
- *
- * This can be used by language bindings to create network transports other
- * than those built into libmongoc. An example of such would be the streams
- * API provided by PHP.
- *
- * Returns: A newly allocated mongoc_stream_t or NULL on failure.
- */
-typedef mongoc_stream_t *(*mongoc_stream_initiator_t) (
- const mongoc_uri_t *uri,
- const mongoc_host_list_t *host,
- void *user_data,
- bson_error_t *error);
-
-
-MONGOC_EXPORT (mongoc_client_t *)
-mongoc_client_new (const char *uri_string) BSON_GNUC_WARN_UNUSED_RESULT;
-MONGOC_EXPORT (mongoc_client_t *)
-mongoc_client_new_from_uri (const mongoc_uri_t *uri)
- BSON_GNUC_WARN_UNUSED_RESULT;
-MONGOC_EXPORT (const mongoc_uri_t *)
-mongoc_client_get_uri (const mongoc_client_t *client);
-MONGOC_EXPORT (void)
-mongoc_client_set_stream_initiator (mongoc_client_t *client,
- mongoc_stream_initiator_t initiator,
- void *user_data);
-MONGOC_EXPORT (mongoc_cursor_t *)
-mongoc_client_command (mongoc_client_t *client,
- const char *db_name,
- mongoc_query_flags_t flags,
- uint32_t skip,
- uint32_t limit,
- uint32_t batch_size,
- const bson_t *query,
- const bson_t *fields,
- const mongoc_read_prefs_t *read_prefs)
- BSON_GNUC_WARN_UNUSED_RESULT;
-MONGOC_EXPORT (void)
-mongoc_client_kill_cursor (mongoc_client_t *client,
- int64_t cursor_id) BSON_GNUC_DEPRECATED;
-MONGOC_EXPORT (bool)
-mongoc_client_command_simple (mongoc_client_t *client,
- const char *db_name,
- const bson_t *command,
- const mongoc_read_prefs_t *read_prefs,
- bson_t *reply,
- bson_error_t *error);
-MONGOC_EXPORT (bool)
-mongoc_client_read_command_with_opts (mongoc_client_t *client,
- const char *db_name,
- const bson_t *command,
- const mongoc_read_prefs_t *read_prefs,
- const bson_t *opts,
- bson_t *reply,
- bson_error_t *error);
-MONGOC_EXPORT (bool)
-mongoc_client_write_command_with_opts (mongoc_client_t *client,
- const char *db_name,
- const bson_t *command,
- const bson_t *opts,
- bson_t *reply,
- bson_error_t *error);
-MONGOC_EXPORT (bool)
-mongoc_client_read_write_command_with_opts (
- mongoc_client_t *client,
- const char *db_name,
- const bson_t *command,
- const mongoc_read_prefs_t *read_prefs /* IGNORED */,
- const bson_t *opts,
- bson_t *reply,
- bson_error_t *error);
-MONGOC_EXPORT (bool)
-mongoc_client_command_with_opts (mongoc_client_t *client,
- const char *db_name,
- const bson_t *command,
- const mongoc_read_prefs_t *read_prefs,
- const bson_t *opts,
- bson_t *reply,
- bson_error_t *error);
-MONGOC_EXPORT (bool)
-mongoc_client_command_simple_with_server_id (
- mongoc_client_t *client,
- const char *db_name,
- const bson_t *command,
- const mongoc_read_prefs_t *read_prefs,
- uint32_t server_id,
- bson_t *reply,
- bson_error_t *error);
-MONGOC_EXPORT (void)
-mongoc_client_destroy (mongoc_client_t *client);
-MONGOC_EXPORT (mongoc_client_session_t *)
-mongoc_client_start_session (mongoc_client_t *client,
- const mongoc_session_opt_t *opts,
- bson_error_t *error) BSON_GNUC_WARN_UNUSED_RESULT;
-MONGOC_EXPORT (mongoc_database_t *)
-mongoc_client_get_database (mongoc_client_t *client,
- const char *name) BSON_GNUC_WARN_UNUSED_RESULT;
-MONGOC_EXPORT (mongoc_database_t *)
-mongoc_client_get_default_database (mongoc_client_t *client)
- BSON_GNUC_WARN_UNUSED_RESULT;
-MONGOC_EXPORT (mongoc_gridfs_t *)
-mongoc_client_get_gridfs (mongoc_client_t *client,
- const char *db,
- const char *prefix,
- bson_error_t *error) BSON_GNUC_WARN_UNUSED_RESULT;
-MONGOC_EXPORT (mongoc_collection_t *)
-mongoc_client_get_collection (mongoc_client_t *client,
- const char *db,
- const char *collection)
- BSON_GNUC_WARN_UNUSED_RESULT;
-MONGOC_EXPORT (char **)
-mongoc_client_get_database_names (mongoc_client_t *client, bson_error_t *error)
- BSON_GNUC_WARN_UNUSED_RESULT
- BSON_GNUC_DEPRECATED_FOR (mongoc_client_get_database_names_with_opts);
-MONGOC_EXPORT (char **)
-mongoc_client_get_database_names_with_opts (mongoc_client_t *client,
- const bson_t *opts,
- bson_error_t *error)
- BSON_GNUC_WARN_UNUSED_RESULT;
-MONGOC_EXPORT (mongoc_cursor_t *)
-mongoc_client_find_databases (mongoc_client_t *client,
- bson_error_t *error) BSON_GNUC_WARN_UNUSED_RESULT
- BSON_GNUC_DEPRECATED_FOR (mongoc_client_find_databases_with_opts);
-MONGOC_EXPORT (mongoc_cursor_t *)
-mongoc_client_find_databases_with_opts (
- mongoc_client_t *client, const bson_t *opts) BSON_GNUC_WARN_UNUSED_RESULT;
-MONGOC_EXPORT (bool)
-mongoc_client_get_server_status (mongoc_client_t *client,
- mongoc_read_prefs_t *read_prefs,
- bson_t *reply,
- bson_error_t *error) BSON_GNUC_DEPRECATED;
-MONGOC_EXPORT (int32_t)
-mongoc_client_get_max_message_size (mongoc_client_t *client)
- BSON_GNUC_DEPRECATED;
-MONGOC_EXPORT (int32_t)
-mongoc_client_get_max_bson_size (mongoc_client_t *client) BSON_GNUC_DEPRECATED;
-MONGOC_EXPORT (const mongoc_write_concern_t *)
-mongoc_client_get_write_concern (const mongoc_client_t *client);
-MONGOC_EXPORT (void)
-mongoc_client_set_write_concern (mongoc_client_t *client,
- const mongoc_write_concern_t *write_concern);
-MONGOC_EXPORT (const mongoc_read_concern_t *)
-mongoc_client_get_read_concern (const mongoc_client_t *client);
-MONGOC_EXPORT (void)
-mongoc_client_set_read_concern (mongoc_client_t *client,
- const mongoc_read_concern_t *read_concern);
-MONGOC_EXPORT (const mongoc_read_prefs_t *)
-mongoc_client_get_read_prefs (const mongoc_client_t *client);
-MONGOC_EXPORT (void)
-mongoc_client_set_read_prefs (mongoc_client_t *client,
- const mongoc_read_prefs_t *read_prefs);
-#ifdef MONGOC_ENABLE_SSL
-MONGOC_EXPORT (void)
-mongoc_client_set_ssl_opts (mongoc_client_t *client,
- const mongoc_ssl_opt_t *opts);
-#endif
-MONGOC_EXPORT (bool)
-mongoc_client_set_apm_callbacks (mongoc_client_t *client,
- mongoc_apm_callbacks_t *callbacks,
- void *context);
-MONGOC_EXPORT (mongoc_server_description_t *)
-mongoc_client_get_server_description (
- mongoc_client_t *client, uint32_t server_id) BSON_GNUC_WARN_UNUSED_RESULT;
-MONGOC_EXPORT (mongoc_server_description_t **)
-mongoc_client_get_server_descriptions (const mongoc_client_t *client,
- size_t *n) BSON_GNUC_WARN_UNUSED_RESULT;
-MONGOC_EXPORT (void)
-mongoc_server_descriptions_destroy_all (mongoc_server_description_t **sds,
- size_t n);
-MONGOC_EXPORT (mongoc_server_description_t *)
-mongoc_client_select_server (mongoc_client_t *client,
- bool for_writes,
- const mongoc_read_prefs_t *prefs,
- bson_error_t *error) BSON_GNUC_WARN_UNUSED_RESULT;
-MONGOC_EXPORT (bool)
-mongoc_client_set_error_api (mongoc_client_t *client, int32_t version);
-MONGOC_EXPORT (bool)
-mongoc_client_set_appname (mongoc_client_t *client, const char *appname);
-MONGOC_EXPORT (mongoc_change_stream_t *)
-mongoc_client_watch (mongoc_client_t *client,
- const bson_t *pipeline,
- const bson_t *opts) BSON_GNUC_WARN_UNUSED_RESULT;
-MONGOC_EXPORT (void)
-mongoc_client_reset (mongoc_client_t *client);
-
-MONGOC_EXPORT (bool)
-mongoc_client_enable_auto_encryption (mongoc_client_t *client,
- mongoc_auto_encryption_opts_t *opts,
- bson_error_t *error);
-
-MONGOC_EXPORT (bool)
-mongoc_client_set_server_api (mongoc_client_t *client,
- const mongoc_server_api_t *api,
- bson_error_t *error);
-
-MONGOC_EXPORT (mongoc_server_description_t *)
-mongoc_client_get_handshake_description (mongoc_client_t *client,
- uint32_t server_id,
- bson_t *opts,
- bson_error_t *error)
- BSON_GNUC_WARN_UNUSED_RESULT;
-
-BSON_END_DECLS
-
-
-#endif /* MONGOC_CLIENT_H */
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cluster-private.h b/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cluster-private.h
deleted file mode 100644
index 8cfde440..00000000
--- a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cluster-private.h
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- * Copyright 2013 MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "mongoc-prelude.h"
-
-#ifndef MONGOC_CLUSTER_PRIVATE_H
-#define MONGOC_CLUSTER_PRIVATE_H
-
-#include <bson/bson.h>
-
-#include "mongoc-array-private.h"
-#include "mongoc-buffer-private.h"
-#include "mongoc-config.h"
-#include "mongoc-client.h"
-#include "mongoc-list-private.h"
-#include "mongoc-opcode.h"
-#include "mongoc-rpc-private.h"
-#include "mongoc-server-stream-private.h"
-#include "mongoc-set-private.h"
-#include "mongoc-stream.h"
-#include "mongoc-topology-private.h"
-#include "mongoc-topology-description-private.h"
-#include "mongoc-write-concern.h"
-#include "mongoc-scram-private.h"
-#include "mongoc-cmd-private.h"
-#include "mongoc-crypto-private.h"
-
-BSON_BEGIN_DECLS
-
-
-typedef struct _mongoc_cluster_node_t {
- mongoc_stream_t *stream;
- char *connection_address;
- /* handshake_sd is a server description created from the handshake on the stream. */
- mongoc_server_description_t *handshake_sd;
-} mongoc_cluster_node_t;
-
-typedef struct _mongoc_cluster_t {
- int64_t operation_id;
- uint32_t request_id;
- uint32_t sockettimeoutms;
- uint32_t socketcheckintervalms;
- mongoc_uri_t *uri;
- unsigned requires_auth : 1;
-
- mongoc_client_t *client;
-
- mongoc_set_t *nodes;
- mongoc_array_t iov;
-
- mongoc_scram_cache_t *scram_cache;
-} mongoc_cluster_t;
-
-
-void
-mongoc_cluster_init (mongoc_cluster_t *cluster,
- const mongoc_uri_t *uri,
- void *client);
-
-void
-mongoc_cluster_destroy (mongoc_cluster_t *cluster);
-
-void
-mongoc_cluster_disconnect_node (mongoc_cluster_t *cluster, uint32_t id);
-
-int32_t
-mongoc_cluster_get_max_bson_obj_size (mongoc_cluster_t *cluster);
-
-int32_t
-mongoc_cluster_get_max_msg_size (mongoc_cluster_t *cluster);
-
-size_t
-_mongoc_cluster_buffer_iovec (mongoc_iovec_t *iov,
- size_t iovcnt,
- int skip,
- char *buffer);
-
-bool
-mongoc_cluster_check_interval (mongoc_cluster_t *cluster, uint32_t server_id);
-
-bool
-mongoc_cluster_legacy_rpc_sendv_to_server (
- mongoc_cluster_t *cluster,
- mongoc_rpc_t *rpcs,
- mongoc_server_stream_t *server_stream,
- bson_error_t *error);
-
-bool
-mongoc_cluster_try_recv (mongoc_cluster_t *cluster,
- mongoc_rpc_t *rpc,
- mongoc_buffer_t *buffer,
- mongoc_server_stream_t *server_stream,
- bson_error_t *error);
-
-/**
- * @brief Obtain a server stream appropriate for read operations on the
- * cluster.
- *
- * Returns a new stream (that must be freed) or NULL and sets an error via
- * `error`.
- *
- * @note The returned stream must be released via
- * `mongoc_server_stream_cleanup`.
- *
- * @note May add nodes and/or update the cluster's topology.
- */
-mongoc_server_stream_t *
-mongoc_cluster_stream_for_reads (mongoc_cluster_t *cluster,
- const mongoc_read_prefs_t *read_prefs,
- mongoc_client_session_t *cs,
- bson_t *reply,
- bson_error_t *error);
-
-/**
- * @brief Obtain a server stream appropriate for write operations on the
- * cluster.
- *
- * Returns a new stream (that must be freed) or NULL and sets an error via
- * `error`.
- *
- * @note The returned stream must be released via `mongoc_server_stream_cleanup`
- *
- * @note May add nodes and/or update the cluster's topology.
- */
-mongoc_server_stream_t *
-mongoc_cluster_stream_for_writes (mongoc_cluster_t *cluster,
- mongoc_client_session_t *cs,
- bson_t *reply,
- bson_error_t *error);
-
-/**
- * @brief Obtain a server stream associated with the cluster node associated
- * with the given server ID.
- *
- * Returns a new server stream (that must be freed) or NULL and sets `error`.
- *
- * @param server_id The ID of a server in the cluster topology.
- * @param reconnect_ok If `true`, the server exists in the topology but is not
- * connected, then attempt to reconnect with the server. If `false`, then only
- * create a stream if the server is connected and ready.
- *
- * @note The returned stream must be released via `mongoc_server_stream_cleanup`
- *
- * @note May update the cluster's topology.
- */
-mongoc_server_stream_t *
-mongoc_cluster_stream_for_server (mongoc_cluster_t *cluster,
- uint32_t server_id,
- bool reconnect_ok,
- mongoc_client_session_t *cs,
- bson_t *reply,
- bson_error_t *error);
-
-bool
-mongoc_cluster_stream_valid (mongoc_cluster_t *cluster,
- mongoc_server_stream_t *server_stream);
-
-bool
-mongoc_cluster_run_command_monitored (mongoc_cluster_t *cluster,
- mongoc_cmd_t *cmd,
- bson_t *reply,
- bson_error_t *error);
-
-bool
-mongoc_cluster_run_command_parts (mongoc_cluster_t *cluster,
- mongoc_server_stream_t *server_stream,
- mongoc_cmd_parts_t *parts,
- bson_t *reply,
- bson_error_t *error);
-
-bool
-mongoc_cluster_run_command_private (mongoc_cluster_t *cluster,
- mongoc_cmd_t *cmd,
- bson_t *reply,
- bson_error_t *error);
-
-void
-_mongoc_cluster_build_sasl_start (bson_t *cmd,
- const char *mechanism,
- const char *buf,
- uint32_t buflen);
-
-void
-_mongoc_cluster_build_sasl_continue (bson_t *cmd,
- int conv_id,
- const char *buf,
- uint32_t buflen);
-
-int
-_mongoc_cluster_get_conversation_id (const bson_t *reply);
-
-mongoc_server_stream_t *
-_mongoc_cluster_create_server_stream (const mongoc_topology_description_t *td,
- const mongoc_server_description_t *sd,
- mongoc_stream_t *stream);
-
-bool
-_mongoc_cluster_get_auth_cmd_x509 (const mongoc_uri_t *uri,
- const mongoc_ssl_opt_t *ssl_opts,
- bson_t *cmd /* OUT */,
- bson_error_t *error /* OUT */);
-
-#ifdef MONGOC_ENABLE_CRYPTO
-void
-_mongoc_cluster_init_scram (const mongoc_cluster_t *cluster,
- mongoc_scram_t *scram,
- mongoc_crypto_hash_algorithm_t algo);
-
-bool
-_mongoc_cluster_get_auth_cmd_scram (mongoc_crypto_hash_algorithm_t algo,
- mongoc_scram_t *scram,
- bson_t *cmd /* OUT */,
- bson_error_t *error /* OUT */);
-#endif /* MONGOC_ENABLE_CRYPTO */
-
-BSON_END_DECLS
-
-
-#endif /* MONGOC_CLUSTER_PRIVATE_H */
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cluster.c b/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cluster.c
deleted file mode 100644
index 5b1993f9..00000000
--- a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cluster.c
+++ /dev/null
@@ -1,3548 +0,0 @@
-/*
- * Copyright 2013 MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-#include "mongoc-config.h"
-
-#include <string.h>
-
-#include "mongoc-cluster-private.h"
-#include "mongoc-client-private.h"
-#include "mongoc-client-side-encryption-private.h"
-#include "mongoc-counters-private.h"
-#include "mongoc-config.h"
-#include "mongoc-error.h"
-#include "mongoc-flags-private.h"
-#include "mongoc-host-list-private.h"
-#include "mongoc-log.h"
-#include "mongoc-cluster-sasl-private.h"
-#ifdef MONGOC_ENABLE_SSL
-#include "mongoc-ssl.h"
-#include "mongoc-ssl-private.h"
-#include "mongoc-stream-tls.h"
-#endif
-#include "common-b64-private.h"
-#include "mongoc-scram-private.h"
-#include "mongoc-set-private.h"
-#include "mongoc-socket.h"
-#include "mongoc-stream-private.h"
-#include "mongoc-stream-socket.h"
-#include "mongoc-stream-tls.h"
-#include "mongoc-thread-private.h"
-#include "mongoc-topology-private.h"
-#include "mongoc-topology-background-monitoring-private.h"
-#include "mongoc-trace-private.h"
-#include "mongoc-util-private.h"
-#include "mongoc-write-concern-private.h"
-#include "mongoc-uri-private.h"
-#include "mongoc-rpc-private.h"
-#include "mongoc-compression-private.h"
-#include "mongoc-cmd-private.h"
-#include "utlist.h"
-#include "mongoc-handshake-private.h"
-#include "mongoc-cluster-aws-private.h"
-#include "mongoc-error-private.h"
-
-#undef MONGOC_LOG_DOMAIN
-#define MONGOC_LOG_DOMAIN "cluster"
-
-
-#define CHECK_CLOSED_DURATION_MSEC 1000
-
-#define IS_NOT_COMMAND(_name) (!!strcasecmp (cmd->command_name, _name))
-
-static mongoc_server_stream_t *
-_cluster_fetch_stream_single (mongoc_cluster_t *cluster,
- const mongoc_topology_description_t *td,
- uint32_t server_id,
- bool reconnect_ok,
- bson_error_t *error);
-
-static mongoc_server_stream_t *
-_cluster_fetch_stream_pooled (mongoc_cluster_t *cluster,
- const mongoc_topology_description_t *td,
- uint32_t server_id,
- bool reconnect_ok,
- bson_error_t *error);
-
-static bool
-mongoc_cluster_run_opmsg (mongoc_cluster_t *cluster,
- mongoc_cmd_t *cmd,
- bson_t *reply,
- bson_error_t *error);
-
-static void
-_bson_error_message_printf (bson_error_t *error, const char *format, ...)
- BSON_GNUC_PRINTF (2, 3);
-
-static void
-_handle_not_primary_error (mongoc_cluster_t *cluster,
- const mongoc_server_stream_t *server_stream,
- const bson_t *reply)
-{
- uint32_t server_id;
-
- server_id = server_stream->sd->id;
- if (_mongoc_topology_handle_app_error (cluster->client->topology,
- server_id,
- true /* handshake complete */,
- MONGOC_SDAM_APP_ERROR_COMMAND,
- reply,
- NULL,
- server_stream->sd->max_wire_version,
- server_stream->sd->generation,
- &server_stream->sd->service_id)) {
- mongoc_cluster_disconnect_node (cluster, server_id);
- }
-}
-
-/* Called when a network error occurs on an application socket.
- */
-static void
-_handle_network_error (mongoc_cluster_t *cluster,
- mongoc_server_stream_t *server_stream,
- bool handshake_complete,
- const bson_error_t *why)
-{
- mongoc_topology_t *topology;
- uint32_t server_id;
- _mongoc_sdam_app_error_type_t type;
-
- BSON_ASSERT (server_stream);
-
- ENTRY;
- topology = cluster->client->topology;
- server_id = server_stream->sd->id;
- type = MONGOC_SDAM_APP_ERROR_NETWORK;
- if (mongoc_stream_timed_out (server_stream->stream)) {
- type = MONGOC_SDAM_APP_ERROR_TIMEOUT;
- }
-
- _mongoc_topology_handle_app_error (topology,
- server_id,
- handshake_complete,
- type,
- NULL,
- why,
- server_stream->sd->max_wire_version,
- server_stream->sd->generation,
- &server_stream->sd->service_id);
- /* Always disconnect the current connection on network error. */
- mongoc_cluster_disconnect_node (cluster, server_id);
-
- EXIT;
-}
-
-
-size_t
-_mongoc_cluster_buffer_iovec (mongoc_iovec_t *iov,
- size_t iovcnt,
- int skip,
- char *buffer)
-{
- int n;
- size_t buffer_offset = 0;
- int total_iov_len = 0;
- int difference = 0;
-
- for (n = 0; n < iovcnt; n++) {
- total_iov_len += iov[n].iov_len;
-
- if (total_iov_len <= skip) {
- continue;
- }
-
- /* If this iovec starts before the skip, and takes the total count
- * beyond the skip, we need to figure out the portion of the iovec
- * we should skip passed */
- if (total_iov_len - iov[n].iov_len < skip) {
- difference = skip - (total_iov_len - iov[n].iov_len);
- } else {
- difference = 0;
- }
-
- memcpy (buffer + buffer_offset,
- ((char *) iov[n].iov_base) + difference,
- iov[n].iov_len - difference);
- buffer_offset += iov[n].iov_len - difference;
- }
-
- return buffer_offset;
-}
-
-/* Allows caller to safely overwrite error->message with a formatted string,
- * even if the formatted string includes original error->message. */
-static void
-_bson_error_message_printf (bson_error_t *error, const char *format, ...)
-{
- va_list args;
- char error_message[sizeof error->message];
-
- if (error) {
- va_start (args, format);
- bson_vsnprintf (error_message, sizeof error->message, format, args);
- va_end (args);
-
- bson_strncpy (error->message, error_message, sizeof error->message);
- }
-}
-
-#define RUN_CMD_ERR_DECORATE \
- do { \
- _bson_error_message_printf ( \
- error, \
- "Failed to send \"%s\" command with database \"%s\": %s", \
- cmd->command_name, \
- cmd->db_name, \
- error->message); \
- } while (0)
-
-#define RUN_CMD_ERR(_domain, _code, ...) \
- do { \
- bson_set_error (error, _domain, _code, __VA_ARGS__); \
- RUN_CMD_ERR_DECORATE; \
- } while (0)
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_cluster_run_command_opquery --
- *
- * Internal function to run a command on a given stream. @error and
- * @reply are optional out-pointers.
- *
- * Returns:
- * true if successful; otherwise false and @error is set.
- *
- * Side effects:
- * @reply is set and should ALWAYS be released with bson_destroy().
- * On failure, @error is filled out. If this was a network error
- * and server_id is nonzero, the cluster disconnects from the server.
- *
- *--------------------------------------------------------------------------
- */
-
-static bool
-mongoc_cluster_run_command_opquery (mongoc_cluster_t *cluster,
- mongoc_cmd_t *cmd,
- int32_t compressor_id,
- bson_t *reply,
- bson_error_t *error)
-{
- const size_t reply_header_size = sizeof (mongoc_rpc_reply_header_t);
- uint8_t reply_header_buf[sizeof (mongoc_rpc_reply_header_t)];
- uint8_t *reply_buf; /* reply body */
- mongoc_rpc_t rpc; /* sent to server */
- bson_t reply_local;
- bson_t *reply_ptr;
- char *cmd_ns;
- uint32_t request_id;
- int32_t msg_len;
- size_t doc_len;
- bool ret = false;
- char *output = NULL;
- mongoc_stream_t *stream;
-
- ENTRY;
-
- BSON_ASSERT (cluster);
- BSON_ASSERT (cmd);
- BSON_ASSERT (cmd->server_stream);
-
- stream = cmd->server_stream->stream;
- /*
- * setup
- */
- reply_ptr = reply ? reply : &reply_local;
- bson_init (reply_ptr);
-
- error->code = 0;
-
- /*
- * prepare the request
- */
-
- _mongoc_array_clear (&cluster->iov);
-
- cmd_ns = bson_strdup_printf ("%s.$cmd", cmd->db_name);
- request_id = ++cluster->request_id;
- _mongoc_rpc_prep_command (&rpc, cmd_ns, cmd);
- rpc.header.request_id = request_id;
-
- _mongoc_rpc_gather (&rpc, &cluster->iov);
- _mongoc_rpc_swab_to_le (&rpc);
-
- if (compressor_id != -1 && IS_NOT_COMMAND (HANDSHAKE_CMD_LEGACY_HELLO) &&
- IS_NOT_COMMAND ("hello") && IS_NOT_COMMAND ("saslstart") &&
- IS_NOT_COMMAND ("saslcontinue") && IS_NOT_COMMAND ("getnonce") &&
- IS_NOT_COMMAND ("authenticate") && IS_NOT_COMMAND ("createuser") &&
- IS_NOT_COMMAND ("updateuser")) {
- output = _mongoc_rpc_compress (cluster, compressor_id, &rpc, error);
- if (output == NULL) {
- GOTO (done);
- }
- }
-
- if (cluster->client->in_exhaust) {
- bson_set_error (error,
- MONGOC_ERROR_CLIENT,
- MONGOC_ERROR_CLIENT_IN_EXHAUST,
- "A cursor derived from this client is in exhaust.");
- GOTO (done);
- }
-
- /*
- * send and receive
- */
- if (!_mongoc_stream_writev_full (stream,
- cluster->iov.data,
- cluster->iov.len,
- cluster->sockettimeoutms,
- error)) {
- _handle_network_error (
- cluster, cmd->server_stream, true /* handshake complete */, error);
-
- /* add info about the command to writev_full's error message */
- RUN_CMD_ERR_DECORATE;
- GOTO (done);
- }
-
- if (reply_header_size != mongoc_stream_read (stream,
- &reply_header_buf,
- reply_header_size,
- reply_header_size,
- cluster->sockettimeoutms)) {
- RUN_CMD_ERR (MONGOC_ERROR_STREAM,
- MONGOC_ERROR_STREAM_SOCKET,
- "socket error or timeout");
-
- _handle_network_error (
- cluster, cmd->server_stream, true /* handshake complete */, error);
- GOTO (done);
- }
-
- memcpy (&msg_len, reply_header_buf, 4);
- msg_len = BSON_UINT32_FROM_LE (msg_len);
- if ((msg_len < reply_header_size) ||
- (msg_len > MONGOC_DEFAULT_MAX_MSG_SIZE)) {
- _handle_network_error (
- cluster, cmd->server_stream, true /* handshake complete */, error);
- GOTO (done);
- }
-
- if (!_mongoc_rpc_scatter_reply_header_only (
- &rpc, reply_header_buf, reply_header_size)) {
- _handle_network_error (
- cluster, cmd->server_stream, true /* handshake complete */, error);
- GOTO (done);
- }
- doc_len = (size_t) msg_len - reply_header_size;
-
- if (BSON_UINT32_FROM_LE (rpc.header.opcode) == MONGOC_OPCODE_COMPRESSED) {
- bson_t tmp = BSON_INITIALIZER;
- uint8_t *buf = NULL;
- size_t len = BSON_UINT32_FROM_LE (rpc.compressed.uncompressed_size) +
- sizeof (mongoc_rpc_header_t);
-
- reply_buf = bson_malloc0 (msg_len);
- memcpy (reply_buf, reply_header_buf, reply_header_size);
-
- if (doc_len != mongoc_stream_read (stream,
- reply_buf + reply_header_size,
- doc_len,
- doc_len,
- cluster->sockettimeoutms)) {
- RUN_CMD_ERR (MONGOC_ERROR_STREAM,
- MONGOC_ERROR_STREAM_SOCKET,
- "socket error or timeout");
- _handle_network_error (
- cluster, cmd->server_stream, true /* handshake complete */, error);
- GOTO (done);
- }
- if (!_mongoc_rpc_scatter (&rpc, reply_buf, msg_len)) {
- GOTO (done);
- }
-
- buf = bson_malloc0 (len);
- if (!_mongoc_rpc_decompress (&rpc, buf, len)) {
- RUN_CMD_ERR (MONGOC_ERROR_PROTOCOL,
- MONGOC_ERROR_PROTOCOL_INVALID_REPLY,
- "Could not decompress server reply");
- bson_free (reply_buf);
- bson_free (buf);
- GOTO (done);
- }
-
- _mongoc_rpc_swab_from_le (&rpc);
-
- if (!_mongoc_rpc_get_first_document (&rpc, &tmp)) {
- RUN_CMD_ERR (MONGOC_ERROR_PROTOCOL,
- MONGOC_ERROR_PROTOCOL_INVALID_REPLY,
- "Corrupt compressed OP_QUERY reply from server");
- bson_free (reply_buf);
- bson_free (buf);
- GOTO (done);
- }
- bson_copy_to (&tmp, reply_ptr);
- bson_free (reply_buf);
- bson_free (buf);
- } else if (BSON_UINT32_FROM_LE (rpc.header.opcode) == MONGOC_OPCODE_REPLY &&
- BSON_UINT32_FROM_LE (rpc.reply_header.n_returned) == 1) {
- reply_buf = bson_reserve_buffer (reply_ptr, (uint32_t) doc_len);
- BSON_ASSERT (reply_buf);
-
- if (doc_len != mongoc_stream_read (stream,
- (void *) reply_buf,
- doc_len,
- doc_len,
- cluster->sockettimeoutms)) {
- RUN_CMD_ERR (MONGOC_ERROR_STREAM,
- MONGOC_ERROR_STREAM_SOCKET,
- "socket error or timeout");
- _handle_network_error (
- cluster, cmd->server_stream, true /* handshake complete */, error);
- GOTO (done);
- }
- _mongoc_rpc_swab_from_le (&rpc);
- } else {
- GOTO (done);
- }
-
- if (!_mongoc_cmd_check_ok (
- reply_ptr, cluster->client->error_api_version, error)) {
- GOTO (done);
- }
-
- ret = true;
-
-done:
-
- if (!ret && error->code == 0) {
- /* generic error */
- RUN_CMD_ERR (MONGOC_ERROR_PROTOCOL,
- MONGOC_ERROR_PROTOCOL_INVALID_REPLY,
- "Invalid reply from server.");
- }
-
- if (reply_ptr == &reply_local) {
- bson_destroy (reply_ptr);
- }
- bson_free (output);
- bson_free (cmd_ns);
-
- RETURN (ret);
-}
-
-bool
-_in_sharded_txn (const mongoc_client_session_t *session)
-{
- return session && _mongoc_client_session_in_txn_or_ending (session) &&
- _mongoc_topology_get_type (session->client->topology) ==
- MONGOC_TOPOLOGY_SHARDED;
-}
-
-static void
-_handle_txn_error_labels (bool cmd_ret,
- const bson_error_t *cmd_err,
- const mongoc_cmd_t *cmd,
- bson_t *reply)
-{
- if (!cmd->is_txn_finish) {
- return;
- }
-
- _mongoc_write_error_handle_labels (
- cmd_ret, cmd_err, reply, cmd->server_stream->sd->max_wire_version);
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_cluster_run_command_monitored --
- *
- * Internal function to run a command on a given stream.
- * @error and @reply are optional out-pointers.
- *
- * Returns:
- * true if successful; otherwise false and @error is set.
- *
- * Side effects:
- * If the client's APM callbacks are set, they are executed.
- * @reply is set and should ALWAYS be released with bson_destroy().
- *
- *--------------------------------------------------------------------------
- */
-
-bool
-mongoc_cluster_run_command_monitored (mongoc_cluster_t *cluster,
- mongoc_cmd_t *cmd,
- bson_t *reply,
- bson_error_t *error)
-{
- bool retval;
- uint32_t request_id = ++cluster->request_id;
- uint32_t server_id;
- mongoc_apm_callbacks_t *callbacks;
- mongoc_apm_command_started_t started_event;
- mongoc_apm_command_succeeded_t succeeded_event;
- mongoc_apm_command_failed_t failed_event;
- int64_t started = bson_get_monotonic_time ();
- const mongoc_server_stream_t *server_stream;
- bson_t reply_local;
- bson_error_t error_local;
- int32_t compressor_id;
- bson_iter_t iter;
- bson_t encrypted = BSON_INITIALIZER;
- bson_t decrypted = BSON_INITIALIZER;
- mongoc_cmd_t encrypted_cmd;
- bool is_redacted = false;
-
- server_stream = cmd->server_stream;
- server_id = server_stream->sd->id;
- compressor_id = mongoc_server_description_compressor_id (server_stream->sd);
-
- callbacks = &cluster->client->apm_callbacks;
- if (!reply) {
- reply = &reply_local;
- }
- if (!error) {
- error = &error_local;
- }
-
- if (_mongoc_cse_is_enabled (cluster->client)) {
- bson_destroy (&encrypted);
-
- retval = _mongoc_cse_auto_encrypt (
- cluster->client, cmd, &encrypted_cmd, &encrypted, error);
- cmd = &encrypted_cmd;
- if (!retval) {
- bson_init (reply);
- goto fail_no_events;
- }
- }
-
- if (callbacks->started) {
- mongoc_apm_command_started_init_with_cmd (&started_event,
- cmd,
- request_id,
- &is_redacted,
- cluster->client->apm_context);
-
- callbacks->started (&started_event);
- mongoc_apm_command_started_cleanup (&started_event);
- }
-
- if (server_stream->sd->max_wire_version >= WIRE_VERSION_OP_MSG) {
- retval = mongoc_cluster_run_opmsg (cluster, cmd, reply, error);
- } else {
- retval = mongoc_cluster_run_command_opquery (
- cluster, cmd, compressor_id, reply, error);
- }
-
- if (_mongoc_cse_is_enabled (cluster->client)) {
- bson_destroy (&decrypted);
- retval = _mongoc_cse_auto_decrypt (
- cluster->client, cmd->db_name, reply, &decrypted, error);
- bson_destroy (reply);
- bson_steal (reply, &decrypted);
- bson_init (&decrypted);
- if (!retval) {
- goto fail_no_events;
- }
- }
-
- if (retval && callbacks->succeeded) {
- bson_t fake_reply = BSON_INITIALIZER;
- /*
- * Unacknowledged writes must provide a CommandSucceededEvent with an
- * {ok: 1} reply.
- * https://github.com/mongodb/specifications/blob/master/source/command-monitoring/command-monitoring.rst#unacknowledged-acknowledged-writes
- */
- if (!cmd->is_acknowledged) {
- bson_append_int32 (&fake_reply, "ok", 2, 1);
- }
- mongoc_apm_command_succeeded_init (&succeeded_event,
- bson_get_monotonic_time () - started,
- cmd->is_acknowledged ? reply
- : &fake_reply,
- cmd->command_name,
- request_id,
- cmd->operation_id,
- &server_stream->sd->host,
- server_id,
- &server_stream->sd->service_id,
- is_redacted,
- cluster->client->apm_context);
-
- callbacks->succeeded (&succeeded_event);
- mongoc_apm_command_succeeded_cleanup (&succeeded_event);
- bson_destroy (&fake_reply);
- }
- if (!retval && callbacks->failed) {
- mongoc_apm_command_failed_init (&failed_event,
- bson_get_monotonic_time () - started,
- cmd->command_name,
- error,
- reply,
- request_id,
- cmd->operation_id,
- &server_stream->sd->host,
- server_id,
- &server_stream->sd->service_id,
- is_redacted,
- cluster->client->apm_context);
-
- callbacks->failed (&failed_event);
- mongoc_apm_command_failed_cleanup (&failed_event);
- }
-
- _handle_not_primary_error (cluster, server_stream, reply);
-
- _handle_txn_error_labels (retval, error, cmd, reply);
-
- if (retval && _in_sharded_txn (cmd->session) &&
- bson_iter_init_find (&iter, reply, "recoveryToken")) {
- bson_destroy (cmd->session->recovery_token);
- if (BSON_ITER_HOLDS_DOCUMENT (&iter)) {
- cmd->session->recovery_token =
- bson_new_from_data (bson_iter_value (&iter)->value.v_doc.data,
- bson_iter_value (&iter)->value.v_doc.data_len);
- } else {
- MONGOC_ERROR ("Malformed recovery token from server");
- cmd->session->recovery_token = NULL;
- }
- }
-
-fail_no_events:
- if (reply == &reply_local) {
- bson_destroy (&reply_local);
- }
-
- bson_destroy (&encrypted);
- bson_destroy (&decrypted);
-
- _mongoc_topology_update_last_used (cluster->client->topology, server_id);
-
- return retval;
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_cluster_run_command_private --
- *
- * Internal function to run a command on a given stream.
- * @error and @reply are optional out-pointers.
- * The client's APM callbacks are not executed.
- * Automatic encryption/decryption is not performed.
- *
- * Returns:
- * true if successful; otherwise false and @error is set.
- *
- * Side effects:
- * @reply is set and should ALWAYS be released with bson_destroy().
- *
- *--------------------------------------------------------------------------
- */
-
-bool
-mongoc_cluster_run_command_private (mongoc_cluster_t *cluster,
- mongoc_cmd_t *cmd,
- bson_t *reply,
- bson_error_t *error)
-{
- bool retval;
- const mongoc_server_stream_t *server_stream;
- bson_t reply_local;
- bson_error_t error_local;
-
- if (!error) {
- error = &error_local;
- }
-
- if (!reply) {
- reply = &reply_local;
- }
- server_stream = cmd->server_stream;
- if (server_stream->sd->max_wire_version >= WIRE_VERSION_OP_MSG) {
- retval = mongoc_cluster_run_opmsg (cluster, cmd, reply, error);
- } else {
- retval =
- mongoc_cluster_run_command_opquery (cluster, cmd, -1, reply, error);
- }
- _handle_not_primary_error (cluster, server_stream, reply);
- if (reply == &reply_local) {
- bson_destroy (&reply_local);
- }
-
- _mongoc_topology_update_last_used (cluster->client->topology,
- server_stream->sd->id);
-
- return retval;
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_cluster_run_command_parts --
- *
- * Internal function to assemble command parts and run a command
- * on a given stream. @error and @reply are optional out-pointers.
- * The client's APM callbacks are not executed.
- *
- * Returns:
- * true if successful; otherwise false and @error is set.
- *
- * Side effects:
- * @reply is set and should ALWAYS be released with bson_destroy().
- * mongoc_cmd_parts_cleanup will be always be called on parts. The
- * caller should *not* call cleanup on the parts.
- *
- *--------------------------------------------------------------------------
- */
-
-bool
-mongoc_cluster_run_command_parts (mongoc_cluster_t *cluster,
- mongoc_server_stream_t *server_stream,
- mongoc_cmd_parts_t *parts,
- bson_t *reply,
- bson_error_t *error)
-{
- bool ret;
-
- if (!mongoc_cmd_parts_assemble (parts, server_stream, error)) {
- _mongoc_bson_init_if_set (reply);
- mongoc_cmd_parts_cleanup (parts);
- return false;
- }
-
- ret = mongoc_cluster_run_command_private (
- cluster, &parts->assembled, reply, error);
- mongoc_cmd_parts_cleanup (parts);
- return ret;
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * _stream_run_hello --
- *
- * Run a hello command on the given stream. If
- * @negotiate_sasl_supported_mechs is true, then saslSupportedMechs is
- * added to the hello command.
- *
- * Returns:
- * A mongoc_server_description_t you must destroy or NULL. If the call
- * failed its error is set and its type is MONGOC_SERVER_UNKNOWN.
- *
- *--------------------------------------------------------------------------
- */
-static mongoc_server_description_t *
-_stream_run_hello (mongoc_cluster_t *cluster,
- mongoc_stream_t *stream,
- const char *address,
- uint32_t server_id,
- bool negotiate_sasl_supported_mechs,
- mongoc_scram_cache_t *scram_cache,
- mongoc_scram_t *scram,
- bson_t *speculative_auth_response /* OUT */,
- bson_error_t *error)
-{
- bson_t command; /* Initialized by dup_handshake below */
- mongoc_cmd_t hello_cmd;
- bson_t reply;
- int64_t start;
- int64_t rtt_msec;
- mongoc_server_description_t empty_sd;
- mongoc_server_description_t *ret_handshake_sd;
- mongoc_server_stream_t *server_stream;
- bool r;
- bson_iter_t iter;
- mongoc_ssl_opt_t *ssl_opts = NULL;
- mc_shared_tpld td =
- mc_tpld_take_ref (BSON_ASSERT_PTR_INLINE (cluster)->client->topology);
-
- ENTRY;
-
- BSON_ASSERT (stream);
-
- _mongoc_topology_dup_handshake_cmd (cluster->client->topology, &command);
-
- if (cluster->requires_auth && speculative_auth_response) {
-#ifdef MONGOC_ENABLE_SSL
- ssl_opts = &cluster->client->ssl_opts;
-#endif
-
- _mongoc_topology_scanner_add_speculative_authentication (
- &command, cluster->uri, ssl_opts, scram_cache, scram);
- }
-
- if (negotiate_sasl_supported_mechs) {
- _mongoc_handshake_append_sasl_supported_mechs (cluster->uri, &command);
- }
-
- start = bson_get_monotonic_time ();
- /* TODO CDRIVER-3654: do not use a mongoc_server_stream here.
- * Instead, use a plain stream. If a network error occurs, check the cluster
- * node's generation (which is the generation of the created connection) to
- * determine if the error should be handled.
- * The current behavior may double invalidate.
- * If a network error occurs in mongoc_cluster_run_command_private below,
- * that invalidates (thinking the error is a post-handshake network error).
- * Then _mongoc_cluster_stream_for_server also handles the error, and
- * invalidates again.
- */
- mongoc_server_description_init (&empty_sd, address, server_id);
- server_stream =
- _mongoc_cluster_create_server_stream (td.ptr, &empty_sd, stream);
- mongoc_server_description_cleanup (&empty_sd);
-
- /* Always use OP_QUERY for the handshake, regardless of whether the last
- * known hello indicates the server supports a newer wire protocol.
- */
- memset (&hello_cmd, 0, sizeof (hello_cmd));
- hello_cmd.db_name = "admin";
- hello_cmd.command = &command;
- hello_cmd.command_name = _mongoc_get_command_name (&command);
- hello_cmd.query_flags = MONGOC_QUERY_SECONDARY_OK;
- hello_cmd.server_stream = server_stream;
-
- if (!mongoc_cluster_run_command_private (
- cluster, &hello_cmd, &reply, error)) {
- if (negotiate_sasl_supported_mechs) {
- if (bson_iter_init_find (&iter, &reply, "ok") &&
- !bson_iter_as_bool (&iter)) {
- /* hello response returned ok: 0. According to auth spec: "If the
- * hello of the MongoDB Handshake fails with an error, drivers
- * MUST treat this an authentication error." */
- error->domain = MONGOC_ERROR_CLIENT;
- error->code = MONGOC_ERROR_CLIENT_AUTHENTICATE;
- }
- }
-
- mongoc_server_stream_cleanup (server_stream);
- ret_handshake_sd = NULL;
- goto done;
- }
-
- rtt_msec = (bson_get_monotonic_time () - start) / 1000;
-
- ret_handshake_sd = (mongoc_server_description_t *) bson_malloc0 (
- sizeof (mongoc_server_description_t));
-
- mongoc_server_description_init (ret_handshake_sd, address, server_id);
- /* send the error from run_command IN to handle_hello */
- mongoc_server_description_handle_hello (
- ret_handshake_sd, &reply, rtt_msec, error);
-
- if (cluster->requires_auth && speculative_auth_response) {
- _mongoc_topology_scanner_parse_speculative_authentication (
- &reply, speculative_auth_response);
- }
-
- /* Note: This call will render our copy of the topology description to be
- * stale */
- r = _mongoc_topology_update_from_handshake (cluster->client->topology,
- ret_handshake_sd);
- if (!r) {
- mongoc_server_description_reset (ret_handshake_sd);
- bson_set_error (&ret_handshake_sd->error,
- MONGOC_ERROR_STREAM,
- MONGOC_ERROR_STREAM_NOT_ESTABLISHED,
- "\"%s\" removed from topology",
- address);
- }
-
- mongoc_server_stream_cleanup (server_stream);
-
-done:
- bson_destroy (&command);
- bson_destroy (&reply);
- mc_tpld_drop_ref (&td);
-
- RETURN (ret_handshake_sd);
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_cluster_run_hello --
- *
- * Run an initial hello command for the given node and handle result.
- *
- * Returns:
- * mongoc_server_description_t on success, NULL otherwise.
- * the mongoc_server_description_t MUST BE DESTROYED BY THE CALLER.
- *
- * Side effects:
- * Makes a blocking I/O call, updates cluster->topology->description
- * with hello result.
- *
- *--------------------------------------------------------------------------
- */
-static mongoc_server_description_t *
-_cluster_run_hello (mongoc_cluster_t *cluster,
- mongoc_cluster_node_t *node,
- uint32_t server_id,
- mongoc_scram_cache_t *scram_cache,
- mongoc_scram_t *scram /* OUT */,
- bson_t *speculative_auth_response /* OUT */,
- bson_error_t *error /* OUT */)
-{
- mongoc_server_description_t *sd;
-
- ENTRY;
-
- BSON_ASSERT (cluster);
- BSON_ASSERT (node);
- BSON_ASSERT (node->stream);
-
- sd = _stream_run_hello (cluster,
- node->stream,
- node->connection_address,
- server_id,
- _mongoc_uri_requires_auth_negotiation (cluster->uri),
- scram_cache,
- scram,
- speculative_auth_response,
- error);
-
- if (!sd) {
- return NULL;
- }
-
- if (sd->type == MONGOC_SERVER_UNKNOWN) {
- memcpy (error, &sd->error, sizeof (bson_error_t));
- mongoc_server_description_destroy (sd);
- return NULL;
- }
-
- return sd;
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_cluster_build_basic_auth_digest --
- *
- * Computes the Basic Authentication digest using the credentials
- * configured for @cluster and the @nonce provided.
- *
- * The result should be freed by the caller using bson_free() when
- * they are finished with it.
- *
- * Returns:
- * A newly allocated string containing the digest.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-static char *
-_mongoc_cluster_build_basic_auth_digest (mongoc_cluster_t *cluster,
- const char *nonce)
-{
- const char *username;
- const char *password;
- char *password_digest;
- char *password_md5;
- char *digest_in;
- char *ret;
-
- ENTRY;
-
- /*
- * The following generates the digest to be used for basic authentication
- * with a MongoDB server. More information on the format can be found
- * at the following location:
- *
- * http://docs.mongodb.org/meta-driver/latest/legacy/
- * implement-authentication-in-driver/
- */
-
- BSON_ASSERT (cluster);
- BSON_ASSERT (cluster->uri);
-
- username = mongoc_uri_get_username (cluster->uri);
- password = mongoc_uri_get_password (cluster->uri);
- password_digest = bson_strdup_printf ("%s:mongo:%s", username, password);
- password_md5 = _mongoc_hex_md5 (password_digest);
- digest_in = bson_strdup_printf ("%s%s%s", nonce, username, password_md5);
- ret = _mongoc_hex_md5 (digest_in);
- bson_free (digest_in);
- bson_free (password_md5);
- bson_free (password_digest);
-
- RETURN (ret);
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_cluster_auth_node_cr --
- *
- * Performs authentication of @node using the credentials provided
- * when configuring the @cluster instance.
- *
- * This is the Challenge-Response mode of authentication.
- *
- * Returns:
- * true if authentication was successful; otherwise false and
- * @error is set.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-static bool
-_mongoc_cluster_auth_node_cr (mongoc_cluster_t *cluster,
- mongoc_stream_t *stream,
- mongoc_server_description_t *sd,
- bson_error_t *error)
-{
- mongoc_cmd_parts_t parts;
- bson_iter_t iter;
- const char *auth_source;
- bson_t command;
- bson_t reply;
- char *digest;
- char *nonce;
- bool ret;
- mongoc_server_stream_t *server_stream;
- mc_shared_tpld td;
-
- ENTRY;
-
- BSON_ASSERT (cluster);
- BSON_ASSERT (stream);
-
- if (!(auth_source = mongoc_uri_get_auth_source (cluster->uri)) ||
- (*auth_source == '\0')) {
- auth_source = "admin";
- }
-
- /*
- * To authenticate a node using basic authentication, we need to first
- * get the nonce from the server. We use that to hash our password which
- * is sent as a reply to the server. If everything went good we get a
- * success notification back from the server.
- */
-
- /*
- * Execute the getnonce command to fetch the nonce used for generating
- * md5 digest of our password information.
- */
- bson_init (&command);
- bson_append_int32 (&command, "getnonce", 8, 1);
- mongoc_cmd_parts_init (&parts,
- cluster->client,
- auth_source,
- MONGOC_QUERY_SECONDARY_OK,
- &command);
- parts.prohibit_lsid = true;
-
- td = mc_tpld_take_ref (cluster->client->topology);
- server_stream = _mongoc_cluster_create_server_stream (td.ptr, sd, stream);
- mc_tpld_drop_ref (&td);
-
- if (!mongoc_cluster_run_command_parts (
- cluster, server_stream, &parts, &reply, error)) {
- mongoc_server_stream_cleanup (server_stream);
- bson_destroy (&command);
- bson_destroy (&reply);
- RETURN (false);
- }
- bson_destroy (&command);
- if (!bson_iter_init_find_case (&iter, &reply, "nonce")) {
- bson_set_error (error,
- MONGOC_ERROR_CLIENT,
- MONGOC_ERROR_CLIENT_GETNONCE,
- "Invalid reply from getnonce");
- bson_destroy (&reply);
- RETURN (false);
- }
-
- /*
- * Build our command to perform the authentication.
- */
- nonce = bson_iter_dup_utf8 (&iter, NULL);
- digest = _mongoc_cluster_build_basic_auth_digest (cluster, nonce);
- bson_init (&command);
- bson_append_int32 (&command, "authenticate", 12, 1);
- bson_append_utf8 (
- &command, "user", 4, mongoc_uri_get_username (cluster->uri), -1);
- bson_append_utf8 (&command, "nonce", 5, nonce, -1);
- bson_append_utf8 (&command, "key", 3, digest, -1);
- bson_destroy (&reply);
- bson_free (nonce);
- bson_free (digest);
-
- /*
- * Execute the authenticate command. mongoc_cluster_run_command_private
- * checks for {ok: 1} in the response.
- */
- mongoc_cmd_parts_init (&parts,
- cluster->client,
- auth_source,
- MONGOC_QUERY_SECONDARY_OK,
- &command);
- parts.prohibit_lsid = true;
- ret = mongoc_cluster_run_command_parts (
- cluster, server_stream, &parts, &reply, error);
-
- if (!ret) {
- /* error->message is already set */
- error->domain = MONGOC_ERROR_CLIENT;
- error->code = MONGOC_ERROR_CLIENT_AUTHENTICATE;
- }
-
- mongoc_server_stream_cleanup (server_stream);
- bson_destroy (&command);
- bson_destroy (&reply);
-
- RETURN (ret);
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_cluster_auth_node_plain --
- *
- * Perform SASL PLAIN authentication for @node. We do this manually
- * instead of using the SASL module because it is rather simplistic.
- *
- * Returns:
- * true if successful; otherwise false and error is set.
- *
- * Side effects:
- * error may be set.
- *
- *--------------------------------------------------------------------------
- */
-
-static bool
-_mongoc_cluster_auth_node_plain (mongoc_cluster_t *cluster,
- mongoc_stream_t *stream,
- mongoc_server_description_t *sd,
- bson_error_t *error)
-{
- mongoc_cmd_parts_t parts;
- char buf[4096];
- int buflen = 0;
- const char *username;
- const char *password;
- bson_t b = BSON_INITIALIZER;
- bson_t reply;
- size_t len;
- char *str;
- bool ret;
- mongoc_server_stream_t *server_stream;
- mc_shared_tpld td;
-
- BSON_ASSERT (cluster);
- BSON_ASSERT (stream);
-
- username = mongoc_uri_get_username (cluster->uri);
- if (!username) {
- username = "";
- }
-
- password = mongoc_uri_get_password (cluster->uri);
- if (!password) {
- password = "";
- }
-
- str = bson_strdup_printf ("%c%s%c%s", '\0', username, '\0', password);
- len = strlen (username) + strlen (password) + 2;
- buflen = COMMON_PREFIX (
- bson_b64_ntop ((const uint8_t *) str, len, buf, sizeof buf));
- bson_free (str);
-
- if (buflen == -1) {
- bson_set_error (error,
- MONGOC_ERROR_CLIENT,
- MONGOC_ERROR_CLIENT_AUTHENTICATE,
- "failed base64 encoding message");
- return false;
- }
-
- BSON_APPEND_INT32 (&b, "saslStart", 1);
- BSON_APPEND_UTF8 (&b, "mechanism", "PLAIN");
- bson_append_utf8 (&b, "payload", 7, (const char *) buf, buflen);
- BSON_APPEND_INT32 (&b, "autoAuthorize", 1);
-
- mongoc_cmd_parts_init (
- &parts, cluster->client, "$external", MONGOC_QUERY_SECONDARY_OK, &b);
- parts.prohibit_lsid = true;
-
- td = mc_tpld_take_ref (cluster->client->topology);
- server_stream = _mongoc_cluster_create_server_stream (td.ptr, sd, stream);
- mc_tpld_drop_ref (&td);
-
- ret = mongoc_cluster_run_command_parts (
- cluster, server_stream, &parts, &reply, error);
- mongoc_server_stream_cleanup (server_stream);
- if (!ret) {
- /* error->message is already set */
- error->domain = MONGOC_ERROR_CLIENT;
- error->code = MONGOC_ERROR_CLIENT_AUTHENTICATE;
- }
-
- bson_destroy (&b);
- bson_destroy (&reply);
-
- return ret;
-}
-
-bool
-_mongoc_cluster_get_auth_cmd_x509 (const mongoc_uri_t *uri,
- const mongoc_ssl_opt_t *ssl_opts,
- bson_t *cmd /* OUT */,
- bson_error_t *error /* OUT */)
-{
-#ifndef MONGOC_ENABLE_SSL
- bson_set_error (error,
- MONGOC_ERROR_CLIENT,
- MONGOC_ERROR_CLIENT_AUTHENTICATE,
- "The MONGODB-X509 authentication mechanism requires "
- "libmongoc built with ENABLE_SSL");
- return false;
-#else
- const char *username_from_uri = NULL;
- char *username_from_subject = NULL;
-
- BSON_ASSERT (uri);
-
- username_from_uri = mongoc_uri_get_username (uri);
- if (username_from_uri) {
- TRACE ("%s", "X509: got username from URI");
- } else {
- if (!ssl_opts || !ssl_opts->pem_file) {
- bson_set_error (error,
- MONGOC_ERROR_CLIENT,
- MONGOC_ERROR_CLIENT_AUTHENTICATE,
- "cannot determine username for "
- "X-509 authentication.");
- return false;
- }
-
- username_from_subject =
- mongoc_ssl_extract_subject (ssl_opts->pem_file, ssl_opts->pem_pwd);
- if (!username_from_subject) {
- bson_set_error (error,
- MONGOC_ERROR_CLIENT,
- MONGOC_ERROR_CLIENT_AUTHENTICATE,
- "No username provided for X509 authentication.");
- return false;
- }
-
- TRACE ("%s", "X509: got username from certificate");
- }
-
- bson_init (cmd);
- BSON_APPEND_INT32 (cmd, "authenticate", 1);
- BSON_APPEND_UTF8 (cmd, "mechanism", "MONGODB-X509");
- BSON_APPEND_UTF8 (cmd,
- "user",
- username_from_uri ? username_from_uri
- : username_from_subject);
-
- bson_free (username_from_subject);
-
- return true;
-#endif
-}
-
-
-static bool
-_mongoc_cluster_auth_node_x509 (mongoc_cluster_t *cluster,
- mongoc_stream_t *stream,
- mongoc_server_description_t *sd,
- bson_error_t *error)
-{
-#ifndef MONGOC_ENABLE_SSL
- bson_set_error (error,
- MONGOC_ERROR_CLIENT,
- MONGOC_ERROR_CLIENT_AUTHENTICATE,
- "The MONGODB-X509 authentication mechanism requires "
- "libmongoc built with ENABLE_SSL");
- return false;
-#else
- mongoc_cmd_parts_t parts;
- bson_t cmd;
- bson_t reply;
- bool ret;
- mongoc_server_stream_t *server_stream;
- mc_shared_tpld td;
-
- BSON_ASSERT (cluster);
- BSON_ASSERT (stream);
-
- if (!_mongoc_cluster_get_auth_cmd_x509 (
- cluster->uri, &cluster->client->ssl_opts, &cmd, error)) {
- return false;
- }
-
- mongoc_cmd_parts_init (
- &parts, cluster->client, "$external", MONGOC_QUERY_SECONDARY_OK, &cmd);
- parts.prohibit_lsid = true;
- td = mc_tpld_take_ref (cluster->client->topology);
- server_stream = _mongoc_cluster_create_server_stream (td.ptr, sd, stream);
- mc_tpld_drop_ref (&td);
-
- ret = mongoc_cluster_run_command_parts (
- cluster, server_stream, &parts, &reply, error);
- mongoc_server_stream_cleanup (server_stream);
- if (!ret) {
- /* error->message is already set */
- error->domain = MONGOC_ERROR_CLIENT;
- error->code = MONGOC_ERROR_CLIENT_AUTHENTICATE;
- }
-
- bson_destroy (&cmd);
- bson_destroy (&reply);
-
- return ret;
-#endif
-}
-
-#ifdef MONGOC_ENABLE_CRYPTO
-void
-_mongoc_cluster_init_scram (const mongoc_cluster_t *cluster,
- mongoc_scram_t *scram,
- mongoc_crypto_hash_algorithm_t algo)
-{
- _mongoc_uri_init_scram (cluster->uri, scram, algo);
-
- /* Apply previously cached SCRAM secrets if available */
- if (cluster->scram_cache) {
- _mongoc_scram_set_cache (scram, cluster->scram_cache);
- }
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_cluster_get_auth_cmd_scram --
- *
- * Generates the saslStart command for scram authentication. Used
- * during explicit authentication as well as speculative
- * authentication during hello.
- *
- *
- * Returns:
- * true if the command could be generated, false otherwise
- *
- * Side effects:
- * @error is set on failure.
- *
- *--------------------------------------------------------------------------
- */
-
-bool
-_mongoc_cluster_get_auth_cmd_scram (mongoc_crypto_hash_algorithm_t algo,
- mongoc_scram_t *scram,
- bson_t *cmd /* OUT */,
- bson_error_t *error /* OUT */)
-{
- uint8_t buf[4096] = {0};
- uint32_t buflen = 0;
- bson_t options;
-
- if (!_mongoc_scram_step (
- scram, buf, buflen, buf, sizeof buf, &buflen, error)) {
- return false;
- }
-
- BSON_ASSERT (scram->step == 1);
-
- bson_init (cmd);
-
- BSON_APPEND_INT32 (cmd, "saslStart", 1);
- if (algo == MONGOC_CRYPTO_ALGORITHM_SHA_1) {
- BSON_APPEND_UTF8 (cmd, "mechanism", "SCRAM-SHA-1");
- } else if (algo == MONGOC_CRYPTO_ALGORITHM_SHA_256) {
- BSON_APPEND_UTF8 (cmd, "mechanism", "SCRAM-SHA-256");
- } else {
- BSON_ASSERT (false);
- }
- bson_append_binary (cmd, "payload", 7, BSON_SUBTYPE_BINARY, buf, buflen);
- BSON_APPEND_INT32 (cmd, "autoAuthorize", 1);
-
- BSON_APPEND_DOCUMENT_BEGIN (cmd, "options", &options);
- BSON_APPEND_BOOL (&options, "skipEmptyExchange", true);
- bson_append_document_end (cmd, &options);
-
- bson_destroy (&options);
-
- return true;
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_cluster_run_scram_command --
- *
- * Runs a scram authentication command, handling auth_source and
- * errors during the command.
- *
- *
- * Returns:
- * true if the command was successful, false otherwise
- *
- * Side effects:
- * @error is set on failure.
- *
- *--------------------------------------------------------------------------
- */
-
-static bool
-_mongoc_cluster_run_scram_command (
- mongoc_cluster_t *cluster,
- mongoc_stream_t *stream,
- const mongoc_server_description_t *handshake_sd,
- const bson_t *cmd,
- bson_t *reply,
- bson_error_t *error)
-{
- mongoc_cmd_parts_t parts;
- mongoc_server_stream_t *server_stream;
- const char *auth_source;
- mc_shared_tpld td =
- mc_tpld_take_ref (BSON_ASSERT_PTR_INLINE (cluster)->client->topology);
-
- if (!(auth_source = mongoc_uri_get_auth_source (cluster->uri)) ||
- (*auth_source == '\0')) {
- auth_source = "admin";
- }
-
- mongoc_cmd_parts_init (
- &parts, cluster->client, auth_source, MONGOC_QUERY_SECONDARY_OK, cmd);
- parts.prohibit_lsid = true;
- server_stream =
- _mongoc_cluster_create_server_stream (td.ptr, handshake_sd, stream);
- mc_tpld_drop_ref (&td);
-
- if (!mongoc_cluster_run_command_parts (
- cluster, server_stream, &parts, reply, error)) {
- mongoc_server_stream_cleanup (server_stream);
- bson_destroy (reply);
-
- /* error->message is already set */
- error->domain = MONGOC_ERROR_CLIENT;
- error->code = MONGOC_ERROR_CLIENT_AUTHENTICATE;
-
- return false;
- }
-
- mongoc_server_stream_cleanup (server_stream);
-
- return true;
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_cluster_auth_scram_start --
- *
- * Starts scram authentication by generating and sending the saslStart
- * command. The conversation can then be resumed using
- * _mongoc_cluster_auth_scram_continue.
- *
- *
- * Returns:
- * true if the saslStart command was successful, false otherwise
- *
- * Side effects:
- * @error is set on failure.
- *
- *--------------------------------------------------------------------------
- */
-
-static bool
-_mongoc_cluster_auth_scram_start (
- mongoc_cluster_t *cluster,
- mongoc_stream_t *stream,
- const mongoc_server_description_t *handshake_sd,
- mongoc_crypto_hash_algorithm_t algo,
- mongoc_scram_t *scram,
- bson_t *reply,
- bson_error_t *error)
-{
- bson_t cmd;
-
- BSON_ASSERT (scram->step == 0);
-
- if (!_mongoc_cluster_get_auth_cmd_scram (algo, scram, &cmd, error)) {
- /* error->message is already set */
- error->domain = MONGOC_ERROR_CLIENT;
- error->code = MONGOC_ERROR_CLIENT_AUTHENTICATE;
-
- return false;
- }
-
- if (!_mongoc_cluster_run_scram_command (
- cluster, stream, handshake_sd, &cmd, reply, error)) {
- bson_destroy (&cmd);
-
- return false;
- }
-
- bson_destroy (&cmd);
-
- return true;
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_cluster_scram_handle_reply --
- *
- * Handles replies from _mongoc_cluster_run_scram_command. The @done
- * argument will be set to true if the scram conversation was
- * completed successfully.
- *
- *
- * Returns:
- * true if the reply was handled successfully, false if there was an
- * error. Note that the return value itself does not indicate whether
- * authentication was completed successfully.
- *
- * Side effects:
- * @error is set on failure. @done, @conv_id, @buf, and @buflen are
- * set for use in the next scram step.
- *
- *--------------------------------------------------------------------------
- */
-
-static bool
-_mongoc_cluster_scram_handle_reply (mongoc_scram_t *scram,
- const bson_t *reply,
- bool *done /* OUT */,
- int *conv_id /* OUT */,
- uint8_t *buf /* OUT */,
- uint32_t bufmax,
- uint32_t *buflen /* OUT */,
- bson_error_t *error)
-{
- bson_iter_t iter;
- bson_subtype_t btype;
- const char *tmpstr;
-
- BSON_ASSERT (scram);
-
- if (bson_iter_init_find (&iter, reply, "done") &&
- bson_iter_as_bool (&iter)) {
- if (scram->step < 2) {
- /* Prior to step 2, we haven't even received server proof. */
- bson_set_error (error,
- MONGOC_ERROR_CLIENT,
- MONGOC_ERROR_CLIENT_AUTHENTICATE,
- "Incorrect step for 'done'");
- return false;
- }
- *done = true;
- if (scram->step >= 3) {
- return true;
- }
- }
-
- if (!bson_iter_init_find (&iter, reply, "conversationId") ||
- !BSON_ITER_HOLDS_INT32 (&iter) ||
- !(*conv_id = bson_iter_int32 (&iter)) ||
- !bson_iter_init_find (&iter, reply, "payload") ||
- !BSON_ITER_HOLDS_BINARY (&iter)) {
- const char *errmsg = "Received invalid SCRAM reply from MongoDB server.";
-
- MONGOC_DEBUG ("SCRAM: authentication failed");
-
- if (bson_iter_init_find (&iter, reply, "errmsg") &&
- BSON_ITER_HOLDS_UTF8 (&iter)) {
- errmsg = bson_iter_utf8 (&iter, NULL);
- }
-
- bson_set_error (error,
- MONGOC_ERROR_CLIENT,
- MONGOC_ERROR_CLIENT_AUTHENTICATE,
- "%s",
- errmsg);
- return false;
- }
-
- bson_iter_binary (&iter, &btype, buflen, (const uint8_t **) &tmpstr);
-
- if (*buflen > bufmax) {
- bson_set_error (error,
- MONGOC_ERROR_CLIENT,
- MONGOC_ERROR_CLIENT_AUTHENTICATE,
- "SCRAM reply from MongoDB is too large.");
- return false;
- }
-
- memcpy (buf, tmpstr, *buflen);
-
- return true;
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_cluster_auth_scram_continue --
- *
- * Continues the scram conversation from the reply to a saslStart
- * command, either sent explicitly or received through speculative
- * authentication during hello.
- *
- *
- * Returns:
- * true if authenticated. false on failure and @error is set.
- *
- * Side effects:
- * @error is set on failure.
- *
- *--------------------------------------------------------------------------
- */
-
-static bool
-_mongoc_cluster_auth_scram_continue (
- mongoc_cluster_t *cluster,
- mongoc_stream_t *stream,
- const mongoc_server_description_t *handshake_sd,
- mongoc_scram_t *scram,
- const bson_t *sasl_start_reply,
- bson_error_t *error)
-{
- bson_t cmd;
- uint8_t buf[4096] = {0};
- uint32_t buflen = 0;
- int conv_id = 0;
- bool done = false;
- bson_t reply_local;
-
- if (!_mongoc_cluster_scram_handle_reply (scram,
- sasl_start_reply,
- &done,
- &conv_id,
- buf,
- sizeof buf,
- &buflen,
- error)) {
- return false;
- }
-
- for (;;) {
- if (!_mongoc_scram_step (
- scram, buf, buflen, buf, sizeof buf, &buflen, error)) {
- return false;
- }
-
- if (done && (scram->step >= 3)) {
- break;
- }
-
- bson_init (&cmd);
-
- BSON_APPEND_INT32 (&cmd, "saslContinue", 1);
- BSON_APPEND_INT32 (&cmd, "conversationId", conv_id);
- bson_append_binary (&cmd, "payload", 7, BSON_SUBTYPE_BINARY, buf, buflen);
-
- TRACE ("SCRAM: authenticating (step %d)", scram->step);
-
- if (!_mongoc_cluster_run_scram_command (
- cluster, stream, handshake_sd, &cmd, &reply_local, error)) {
- bson_destroy (&cmd);
- return false;
- }
-
- bson_destroy (&cmd);
-
- if (!_mongoc_cluster_scram_handle_reply (scram,
- &reply_local,
- &done,
- &conv_id,
- buf,
- sizeof buf,
- &buflen,
- error)) {
- bson_destroy (&reply_local);
- return false;
- }
-
- bson_destroy (&reply_local);
-
- if (done && (scram->step >= 3)) {
- break;
- }
- }
-
- TRACE ("%s", "SCRAM: authenticated");
-
- /* Save cached SCRAM secrets for future use */
- if (cluster->scram_cache) {
- _mongoc_scram_cache_destroy (cluster->scram_cache);
- }
-
- cluster->scram_cache = _mongoc_scram_get_cache (scram);
-
- return true;
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_cluster_auth_node_scram --
- *
- * Invokes scram authentication by sending a saslStart command and
- * handling all replies.
- *
- *
- * Returns:
- * true if authenticated. false on failure and @error is set.
- *
- * Side effects:
- * @error is set on failure.
- *
- *--------------------------------------------------------------------------
- */
-
-static bool
-_mongoc_cluster_auth_node_scram (mongoc_cluster_t *cluster,
- mongoc_stream_t *stream,
- mongoc_server_description_t *handshake_sd,
- mongoc_crypto_hash_algorithm_t algo,
- bson_error_t *error)
-{
- mongoc_scram_t scram;
- bool ret = false;
- bson_t reply;
-
- BSON_ASSERT (cluster);
-
- _mongoc_cluster_init_scram (cluster, &scram, algo);
-
- if (!_mongoc_cluster_auth_scram_start (
- cluster, stream, handshake_sd, algo, &scram, &reply, error)) {
- goto failure;
- }
-
- if (!_mongoc_cluster_auth_scram_continue (
- cluster, stream, handshake_sd, &scram, &reply, error)) {
- bson_destroy (&reply);
-
- goto failure;
- }
-
- TRACE ("%s", "SCRAM: authenticated");
-
- ret = true;
-
- bson_destroy (&reply);
-
-failure:
- _mongoc_scram_destroy (&scram);
-
- return ret;
-}
-#endif
-
-static bool
-_mongoc_cluster_auth_node_scram_sha_1 (mongoc_cluster_t *cluster,
- mongoc_stream_t *stream,
- mongoc_server_description_t *sd,
- bson_error_t *error)
-{
-#ifndef MONGOC_ENABLE_CRYPTO
- bson_set_error (error,
- MONGOC_ERROR_CLIENT,
- MONGOC_ERROR_CLIENT_AUTHENTICATE,
- "The SCRAM_SHA_1 authentication mechanism requires "
- "libmongoc built with ENABLE_SSL");
- return false;
-#else
- return _mongoc_cluster_auth_node_scram (
- cluster, stream, sd, MONGOC_CRYPTO_ALGORITHM_SHA_1, error);
-#endif
-}
-
-static bool
-_mongoc_cluster_auth_node_scram_sha_256 (mongoc_cluster_t *cluster,
- mongoc_stream_t *stream,
- mongoc_server_description_t *sd,
- bson_error_t *error)
-{
-#ifndef MONGOC_ENABLE_CRYPTO
- bson_set_error (error,
- MONGOC_ERROR_CLIENT,
- MONGOC_ERROR_CLIENT_AUTHENTICATE,
- "The SCRAM_SHA_256 authentication mechanism requires "
- "libmongoc built with ENABLE_SSL");
- return false;
-#else
- return _mongoc_cluster_auth_node_scram (
- cluster, stream, sd, MONGOC_CRYPTO_ALGORITHM_SHA_256, error);
-#endif
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_cluster_auth_node --
- *
- * Authenticate a cluster node depending on the required mechanism.
- *
- * Returns:
- * true if authenticated. false on failure and @error is set.
- *
- * Side effects:
- * @error is set on failure.
- *
- *--------------------------------------------------------------------------
- */
-
-static bool
-_mongoc_cluster_auth_node (
- mongoc_cluster_t *cluster,
- mongoc_stream_t *stream,
- mongoc_server_description_t *sd,
- const mongoc_handshake_sasl_supported_mechs_t *sasl_supported_mechs,
- bson_error_t *error)
-{
- bool ret = false;
- const char *mechanism;
- ENTRY;
-
- BSON_ASSERT (cluster);
- BSON_ASSERT (stream);
-
- mechanism = mongoc_uri_get_auth_mechanism (cluster->uri);
-
- if (!mechanism) {
- if (sasl_supported_mechs->scram_sha_256) {
- /* Auth spec: "If SCRAM-SHA-256 is present in the list of mechanisms,
- * then it MUST be used as the default; otherwise, SCRAM-SHA-1 MUST be
- * used as the default, regardless of whether SCRAM-SHA-1 is in the
- * list. Drivers MUST NOT attempt to use any other mechanism (e.g.
- * PLAIN) as the default." [...] "If saslSupportedMechs is not present
- * in the hello results for mechanism negotiation, then SCRAM-SHA-1
- * MUST be used when talking to servers >= 3.0." */
- mechanism = "SCRAM-SHA-256";
- } else {
- mechanism = "SCRAM-SHA-1";
- }
- }
-
- if (0 == strcasecmp (mechanism, "MONGODB-CR")) {
- ret = _mongoc_cluster_auth_node_cr (cluster, stream, sd, error);
- } else if (0 == strcasecmp (mechanism, "MONGODB-X509")) {
- ret = _mongoc_cluster_auth_node_x509 (cluster, stream, sd, error);
- } else if (0 == strcasecmp (mechanism, "SCRAM-SHA-1")) {
- ret = _mongoc_cluster_auth_node_scram_sha_1 (cluster, stream, sd, error);
- } else if (0 == strcasecmp (mechanism, "SCRAM-SHA-256")) {
- ret =
- _mongoc_cluster_auth_node_scram_sha_256 (cluster, stream, sd, error);
- } else if (0 == strcasecmp (mechanism, "GSSAPI")) {
- ret = _mongoc_cluster_auth_node_sasl (cluster, stream, sd, error);
- } else if (0 == strcasecmp (mechanism, "PLAIN")) {
- ret = _mongoc_cluster_auth_node_plain (cluster, stream, sd, error);
- } else if (0 == strcasecmp (mechanism, "MONGODB-AWS")) {
- ret = _mongoc_cluster_auth_node_aws (cluster, stream, sd, error);
- } else {
- bson_set_error (error,
- MONGOC_ERROR_CLIENT,
- MONGOC_ERROR_CLIENT_AUTHENTICATE,
- "Unknown authentication mechanism \"%s\".",
- mechanism);
- }
-
- if (!ret) {
- mongoc_counter_auth_failure_inc ();
- MONGOC_DEBUG ("Authentication failed: %s", error->message);
- } else {
- mongoc_counter_auth_success_inc ();
- TRACE ("%s", "Authentication succeeded");
- }
-
- RETURN (ret);
-}
-
-
-/*
- * Close the connection associated with this server.
- *
- * Called when a network error occurs, or to close connection tied to an exhaust
- * cursor.
- * If the cluster is pooled, removes the node from cluster's set of nodes.
- * WARNING: pointers to a disconnected mongoc_cluster_node_t or its stream are
- * now invalid, be careful of dangling pointers.
- */
-
-void
-mongoc_cluster_disconnect_node (mongoc_cluster_t *cluster, uint32_t server_id)
-{
- mongoc_topology_t *topology = cluster->client->topology;
-
- ENTRY;
-
- if (topology->single_threaded) {
- mongoc_topology_scanner_node_t *scanner_node;
-
- scanner_node =
- mongoc_topology_scanner_get_node (topology->scanner, server_id);
-
- /* might never actually have connected */
- if (scanner_node && scanner_node->stream) {
- mongoc_topology_scanner_node_disconnect (scanner_node, true);
- }
- } else {
- mongoc_set_rm (cluster->nodes, server_id);
- }
-
- EXIT;
-}
-
-static void
-_mongoc_cluster_node_destroy (mongoc_cluster_node_t *node)
-{
- /* Failure, or Replica Set reconfigure without this node */
- mongoc_stream_failed (node->stream);
- bson_free (node->connection_address);
- mongoc_server_description_destroy (node->handshake_sd);
-
- bson_free (node);
-}
-
-static void
-_mongoc_cluster_node_dtor (void *data_, void *ctx_)
-{
- mongoc_cluster_node_t *node = (mongoc_cluster_node_t *) data_;
-
- _mongoc_cluster_node_destroy (node);
-}
-
-static mongoc_cluster_node_t *
-_mongoc_cluster_node_new (mongoc_stream_t *stream,
- const char *connection_address)
-{
- mongoc_cluster_node_t *node;
-
- if (!stream) {
- return NULL;
- }
-
- node = (mongoc_cluster_node_t *) bson_malloc0 (sizeof *node);
-
- node->stream = stream;
- node->connection_address = bson_strdup (connection_address);
-
- return node;
-}
-
-static bool
-_mongoc_cluster_finish_speculative_auth (
- mongoc_cluster_t *cluster,
- mongoc_stream_t *stream,
- mongoc_server_description_t *handshake_sd,
- bson_t *speculative_auth_response,
- mongoc_scram_t *scram,
- bson_error_t *error)
-{
- const char *mechanism =
- _mongoc_topology_scanner_get_speculative_auth_mechanism (cluster->uri);
- bool ret = false;
- bool auth_handled = false;
-
- BSON_ASSERT (handshake_sd);
- BSON_ASSERT (speculative_auth_response);
-
- if (!mechanism) {
- return false;
- }
-
- if (bson_empty (speculative_auth_response)) {
- return false;
- }
-
-#ifdef MONGOC_ENABLE_SSL
- if (strcasecmp (mechanism, "MONGODB-X509") == 0) {
- /* For X509, a successful hello with speculativeAuthenticate field
- * indicates successful auth */
- ret = true;
- auth_handled = true;
- }
-#endif
-
-#ifdef MONGOC_ENABLE_CRYPTO
- if (strcasecmp (mechanism, "SCRAM-SHA-1") == 0 ||
- strcasecmp (mechanism, "SCRAM-SHA-256") == 0) {
- /* Don't attempt authentication if scram objects have advanced past
- * saslStart */
- if (scram->step != 1) {
- return false;
- }
-
- auth_handled = true;
-
- ret = _mongoc_cluster_auth_scram_continue (cluster,
- stream,
- handshake_sd,
- scram,
- speculative_auth_response,
- error);
- }
-#endif
-
- if (auth_handled) {
- if (!ret) {
- mongoc_counter_auth_failure_inc ();
- MONGOC_DEBUG ("Speculative authentication failed: %s", error->message);
- } else {
- mongoc_counter_auth_success_inc ();
- TRACE ("%s", "Speculative authentication succeeded");
- }
- }
-
- bson_reinit (speculative_auth_response);
-
- return ret;
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_cluster_add_node --
- *
- * Add a new node to this cluster for the given server description.
- *
- * NOTE: does NOT check if this server is already in the cluster.
- *
- * Returns:
- * A stream connected to the server, or NULL on failure.
- *
- * Side effects:
- * Adds a cluster node, or sets error on failure.
- *
- *--------------------------------------------------------------------------
- */
-static mongoc_cluster_node_t *
-_cluster_add_node (mongoc_cluster_t *cluster,
- const mongoc_topology_description_t *td,
- uint32_t server_id,
- bson_error_t *error /* OUT */)
-{
- mongoc_host_list_t *host = NULL;
- mongoc_cluster_node_t *cluster_node = NULL;
- mongoc_stream_t *stream;
- mongoc_server_description_t *handshake_sd;
- mongoc_handshake_sasl_supported_mechs_t sasl_supported_mechs;
- mongoc_scram_t scram = {0};
- bson_t speculative_auth_response = BSON_INITIALIZER;
-
- ENTRY;
-
- BSON_ASSERT (!cluster->client->topology->single_threaded);
-
- host = _mongoc_topology_host_by_id (td, server_id, error);
-
- if (!host) {
- GOTO (error);
- }
-
- TRACE ("Adding new server to cluster: %s", host->host_and_port);
-
- stream = _mongoc_client_create_stream (cluster->client, host, error);
-
- if (!stream) {
- MONGOC_WARNING (
- "Failed connection to %s (%s)", host->host_and_port, error->message);
- GOTO (error);
- /* TODO CDRIVER-3654: if this is a non-timeout network error and the
- * generation is not stale, mark the server unknown and increment the
- * generation. */
- }
-
- /* take critical fields from a fresh hello */
- cluster_node = _mongoc_cluster_node_new (stream, host->host_and_port);
-
- handshake_sd = _cluster_run_hello (cluster,
- cluster_node,
- server_id,
- cluster->scram_cache,
- &scram,
- &speculative_auth_response,
- error);
- if (!handshake_sd) {
- GOTO (error);
- }
-
- _mongoc_handshake_parse_sasl_supported_mechs (
- &handshake_sd->last_hello_response, &sasl_supported_mechs);
-
- if (cluster->requires_auth) {
- /* Complete speculative authentication */
- bool is_auth =
- _mongoc_cluster_finish_speculative_auth (cluster,
- stream,
- handshake_sd,
- &speculative_auth_response,
- &scram,
- error);
-
- if (!is_auth && !_mongoc_cluster_auth_node (cluster,
- cluster_node->stream,
- handshake_sd,
- &sasl_supported_mechs,
- error)) {
- MONGOC_WARNING ("Failed authentication to %s (%s)",
- host->host_and_port,
- error->message);
- mongoc_server_description_destroy (handshake_sd);
- GOTO (error);
- }
- }
-
- /* Transfer ownership of the server description into the cluster node. */
- cluster_node->handshake_sd = handshake_sd;
- /* Copy the latest connection pool generation.
- * TODO (CDRIVER-4078) do not store the generation counter on the server
- * description */
- handshake_sd->generation = _mongoc_topology_get_connection_pool_generation (
- td, server_id, &handshake_sd->service_id);
-
- bson_destroy (&speculative_auth_response);
- mongoc_set_add (cluster->nodes, server_id, cluster_node);
- _mongoc_host_list_destroy_all (host);
-
-#ifdef MONGOC_ENABLE_CRYPTO
- _mongoc_scram_destroy (&scram);
-#endif
-
- RETURN (cluster_node);
-
-error:
- bson_destroy (&speculative_auth_response);
- _mongoc_host_list_destroy_all (host); /* null ok */
-
-#ifdef MONGOC_ENABLE_CRYPTO
- _mongoc_scram_destroy (&scram);
-#endif
-
- if (cluster_node) {
- _mongoc_cluster_node_destroy (cluster_node); /* also destroys stream */
- }
-
- RETURN (NULL);
-}
-
-static void
-node_not_found (const mongoc_topology_description_t *td,
- uint32_t server_id,
- bson_error_t *error /* OUT */)
-{
- mongoc_server_description_t const *sd;
-
- if (!error) {
- return;
- }
-
- sd = mongoc_topology_description_server_by_id_const (td, server_id, error);
-
- if (!sd) {
- return;
- }
-
- if (sd->error.code) {
- memcpy (error, &sd->error, sizeof *error);
- } else {
- bson_set_error (error,
- MONGOC_ERROR_STREAM,
- MONGOC_ERROR_STREAM_NOT_ESTABLISHED,
- "Could not find node %s",
- sd->host.host_and_port);
- }
-}
-
-
-static void
-stream_not_found (const mongoc_topology_description_t *td,
- uint32_t server_id,
- const char *connection_address,
- bson_error_t *error /* OUT */)
-{
- mongoc_server_description_t const *sd;
-
- sd = mongoc_topology_description_server_by_id_const (td, server_id, error);
-
- if (error) {
- if (sd && sd->error.code) {
- memcpy (error, &sd->error, sizeof *error);
- } else {
- bson_set_error (error,
- MONGOC_ERROR_STREAM,
- MONGOC_ERROR_STREAM_NOT_ESTABLISHED,
- "Could not find stream for node %s",
- connection_address);
- }
- }
-}
-
-static mongoc_server_stream_t *
-_try_get_server_stream (mongoc_cluster_t *cluster,
- const mongoc_topology_description_t *td,
- uint32_t server_id,
- bool reconnect_ok,
- bson_error_t *error)
-{
- if (cluster->client->topology->single_threaded) {
- /* in the single-threaded use case we share topology's streams */
- return _cluster_fetch_stream_single (
- cluster, td, server_id, reconnect_ok, error);
- } else {
- return _cluster_fetch_stream_pooled (
- cluster, td, server_id, reconnect_ok, error);
- }
-}
-
-mongoc_server_stream_t *
-_mongoc_cluster_stream_for_server (mongoc_cluster_t *cluster,
- uint32_t server_id,
- bool reconnect_ok,
- const mongoc_client_session_t *cs,
- bson_t *reply,
- bson_error_t *error /* OUT */)
-{
- mongoc_topology_t *const topology =
- BSON_ASSERT_PTR_INLINE (cluster)->client->topology;
- mongoc_server_stream_t *ret_server_stream;
- bson_error_t err_local;
- /* if fetch_stream fails we need a place to receive error details and pass
- * them to mongoc_topology_description_invalidate_server. */
- bson_error_t *err_ptr = error ? error : &err_local;
- mc_tpld_modification tdmod;
- mc_shared_tpld td;
-
- ENTRY;
-
- td = mc_tpld_take_ref (topology);
-
- ret_server_stream = _try_get_server_stream (
- cluster, td.ptr, server_id, reconnect_ok, err_ptr);
-
- if (!ret_server_stream) {
- /* TODO CDRIVER-3654. A null server stream could be due to:
- * 1. Network error during handshake.
- * 2. Failure to retrieve server description (if it was removed from
- * topology).
- * 3. Auth error during handshake.
- * Only (1) should mark the server unknown and clear the pool.
- * Network errors should be checked at a lower layer than this, when an
- * operation on a stream fails, and should take the connection generation
- * into account.
- */
-
- /* Update the topology */
- tdmod = mc_tpld_modify_begin (topology);
-
- /* Add a transient transaction label if applicable. */
- _mongoc_bson_init_with_transient_txn_error (cs, reply);
-
- /* When establishing a new connection in load balanced mode, drivers MUST
- * NOT perform SDAM error handling for any errors that occur before the
- * MongoDB Handshake. */
- if (tdmod.new_td->type == MONGOC_TOPOLOGY_LOAD_BALANCED) {
- mc_tpld_modify_drop (tdmod);
- ret_server_stream = NULL;
- goto done;
- }
-
- mongoc_topology_description_invalidate_server (
- tdmod.new_td, server_id, err_ptr);
- mongoc_cluster_disconnect_node (cluster, server_id);
- /* This is not load balanced mode, so there are no service IDs associated
- * with connections. Pass kZeroServiceId to clear the entire connection
- * pool to this server. */
- _mongoc_topology_description_clear_connection_pool (
- tdmod.new_td, server_id, &kZeroServiceId);
-
- if (!topology->single_threaded) {
- _mongoc_topology_background_monitoring_cancel_check (topology,
- server_id);
- }
- mc_tpld_modify_commit (tdmod);
- ret_server_stream = NULL;
- goto done;
- }
-
- /* If this is a load balanced topology and the server stream does not have a
- * service id, disconnect and return an error. */
- if (td.ptr->type == MONGOC_TOPOLOGY_LOAD_BALANCED) {
- if (!mongoc_server_description_has_service_id (ret_server_stream->sd)) {
- bson_set_error (error,
- MONGOC_ERROR_CLIENT,
- MONGOC_ERROR_CLIENT_INVALID_LOAD_BALANCER,
- "Driver attempted to initialize in load balancing "
- "mode, but the server does not support this mode.");
- mongoc_server_stream_cleanup (ret_server_stream);
- mongoc_cluster_disconnect_node (cluster, server_id);
- _mongoc_bson_init_if_set (reply);
- ret_server_stream = NULL;
- goto done;
- }
- }
-
-done:
- mc_tpld_drop_ref (&td);
- RETURN (ret_server_stream);
-}
-
-
-mongoc_server_stream_t *
-mongoc_cluster_stream_for_server (mongoc_cluster_t *cluster,
- uint32_t server_id,
- bool reconnect_ok,
- mongoc_client_session_t *cs,
- bson_t *reply,
- bson_error_t *error)
-{
- mongoc_server_stream_t *server_stream = NULL;
- bson_error_t err_local = {0};
-
- ENTRY;
-
- BSON_ASSERT (cluster);
-
- if (cs && cs->server_id && cs->server_id != server_id) {
- _mongoc_bson_init_if_set (reply);
- bson_set_error (error,
- MONGOC_ERROR_COMMAND,
- MONGOC_ERROR_SERVER_SELECTION_INVALID_ID,
- "Requested server id does not matched pinned server id");
- RETURN (NULL);
- }
-
- if (!error) {
- error = &err_local;
- }
-
- server_stream = _mongoc_cluster_stream_for_server (
- cluster, server_id, reconnect_ok, cs, reply, error);
-
-
- if (_in_sharded_txn (cs)) {
- _mongoc_client_session_pin (cs, server_id);
- } else {
- /* Transactions Spec: Additionally, any non-transaction operation using
- * a pinned ClientSession MUST unpin the session and the operation MUST
- * perform normal server selection. */
- if (cs && !_mongoc_client_session_in_txn_or_ending (cs)) {
- _mongoc_client_session_unpin (cs);
- }
- }
-
- RETURN (server_stream);
-}
-
-
-static mongoc_server_stream_t *
-_cluster_fetch_stream_single (mongoc_cluster_t *cluster,
- const mongoc_topology_description_t *td,
- uint32_t server_id,
- bool reconnect_ok,
- bson_error_t *error /* OUT */)
-{
- mongoc_server_description_t *handshake_sd;
- mongoc_topology_scanner_node_t *scanner_node;
- char *address;
-
- scanner_node = mongoc_topology_scanner_get_node (
- cluster->client->topology->scanner, server_id);
- /* This could happen if a user explicitly passes a bad server id. */
- if (!scanner_node) {
- bson_set_error (error,
- MONGOC_ERROR_COMMAND,
- MONGOC_ERROR_COMMAND_INVALID_ARG,
- "Could not find server with id: %d",
- server_id);
- return NULL;
- }
-
- /* Retired scanner nodes are removed at the end of a scan. If the node was
- * retired, that would indicate a bug. */
- if (scanner_node->retired) {
- bson_set_error (error,
- MONGOC_ERROR_COMMAND,
- MONGOC_ERROR_COMMAND_INVALID_ARG,
- "Unexpected, selecting server marked for removal: %s",
- scanner_node->host.host_and_port);
- return NULL;
- }
-
- if (scanner_node->stream) {
- handshake_sd =
- mongoc_server_description_new_copy (scanner_node->handshake_sd);
- } else {
- if (!reconnect_ok) {
- stream_not_found (
- td, server_id, scanner_node->host.host_and_port, error);
- return NULL;
- }
-
- /* save the scanner node address in case it is removed during the scan. */
- address = bson_strdup (scanner_node->host.host_and_port);
- _mongoc_topology_do_blocking_scan (cluster->client->topology, error);
- if (error->code) {
- bson_free (address);
- return NULL;
- }
-
- scanner_node = mongoc_topology_scanner_get_node (
- cluster->client->topology->scanner, server_id);
-
- if (!scanner_node || !scanner_node->stream) {
- stream_not_found (td, server_id, address, error);
- bson_free (address);
- return NULL;
- }
- bson_free (address);
-
- handshake_sd =
- mongoc_server_description_new_copy (scanner_node->handshake_sd);
- }
-
- if (handshake_sd->type == MONGOC_SERVER_UNKNOWN) {
- *error = handshake_sd->error;
- mongoc_server_description_destroy (handshake_sd);
- return NULL;
- }
-
- /* stream open but not auth'ed: first use since connect or reconnect */
- if (cluster->requires_auth && !scanner_node->has_auth) {
- /* Complete speculative authentication */
- bool has_speculative_auth = _mongoc_cluster_finish_speculative_auth (
- cluster,
- scanner_node->stream,
- handshake_sd,
- &scanner_node->speculative_auth_response,
- &scanner_node->scram,
- &handshake_sd->error);
-
-#ifdef MONGOC_ENABLE_CRYPTO
- _mongoc_scram_destroy (&scanner_node->scram);
-#endif
-
- if (!scanner_node->stream) {
- *error = handshake_sd->error;
- mongoc_server_description_destroy (handshake_sd);
- return NULL;
- }
-
- if (!has_speculative_auth &&
- !_mongoc_cluster_auth_node (cluster,
- scanner_node->stream,
- handshake_sd,
- &scanner_node->sasl_supported_mechs,
- &handshake_sd->error)) {
- *error = handshake_sd->error;
- mongoc_server_description_destroy (handshake_sd);
- return NULL;
- }
-
- scanner_node->has_auth = true;
- }
-
- /* Copy the latest connection pool generation.
- * TODO (CDRIVER-4078) do not store the generation counter on the server
- * description */
- handshake_sd->generation = _mongoc_topology_get_connection_pool_generation (
- td, server_id, &handshake_sd->service_id);
- return mongoc_server_stream_new (td, handshake_sd, scanner_node->stream);
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_cluster_stream_valid --
- *
- * Internal function to determine if @server_stream is valid and
- * associated with the given cluster.
- *
- * Returns:
- * true if @server_stream is not NULL, hasn't been freed or changed;
- * otherwise false.
- *
- *--------------------------------------------------------------------------
- */
-
-bool
-mongoc_cluster_stream_valid (mongoc_cluster_t *cluster,
- mongoc_server_stream_t *server_stream)
-{
- mongoc_server_stream_t *tmp_stream = NULL;
- mongoc_topology_t *topology =
- BSON_ASSERT_PTR_INLINE (cluster)->client->topology;
- const mongoc_server_description_t *sd;
- bool ret = false;
- bson_error_t error;
- mc_shared_tpld td = mc_tpld_take_ref (topology);
-
- if (!server_stream) {
- goto done;
- }
-
- tmp_stream = mongoc_cluster_stream_for_server (
- cluster, server_stream->sd->id, false, NULL, NULL, NULL);
- if (!tmp_stream || tmp_stream->stream != server_stream->stream) {
- /* stream was freed, or has changed. */
- goto done;
- }
-
- /* Check that the server stream is still valid for the given server, and that
- * the server is still registered. */
- sd = mongoc_topology_description_server_by_id_const (
- td.ptr, server_stream->sd->id, &error);
- if (!sd ||
- server_stream->sd->generation <
- _mongoc_topology_get_connection_pool_generation (
- td.ptr, server_stream->sd->id, &server_stream->sd->service_id)) {
- /* No server description, or the pool has been cleared. */
- goto done;
- }
-
- ret = true;
-done:
- mc_tpld_drop_ref (&td);
- mongoc_server_stream_cleanup (tmp_stream);
- return ret;
-}
-
-mongoc_server_stream_t *
-_mongoc_cluster_create_server_stream (
- mongoc_topology_description_t const *td,
- const mongoc_server_description_t *handshake_sd,
- mongoc_stream_t *stream)
-{
- mongoc_server_description_t *const sd =
- mongoc_server_description_new_copy (handshake_sd);
- /* can't just use mongoc_topology_server_by_id(), since we must hold the
- * lock while copying topology->shared_descr.ptr->logical_time below */
- return mongoc_server_stream_new (td, sd, stream);
-}
-
-
-static mongoc_server_stream_t *
-_cluster_fetch_stream_pooled (mongoc_cluster_t *cluster,
- const mongoc_topology_description_t *td,
- uint32_t server_id,
- bool reconnect_ok,
- bson_error_t *error /* OUT */)
-{
- mongoc_cluster_node_t *cluster_node;
- mongoc_server_description_t const *sd;
- bool has_server_description = false;
-
- cluster_node =
- (mongoc_cluster_node_t *) mongoc_set_get (cluster->nodes, server_id);
-
- sd = mongoc_topology_description_server_by_id_const (td, server_id, error);
- if (sd) {
- has_server_description = true;
- }
-
- if (cluster_node) {
- uint32_t connection_pool_generation = 0;
- BSON_ASSERT (cluster_node->stream);
-
- connection_pool_generation =
- _mongoc_topology_get_connection_pool_generation (
- td, server_id, &cluster_node->handshake_sd->service_id);
-
- if (!has_server_description ||
- cluster_node->handshake_sd->generation < connection_pool_generation) {
- /* Since the stream was created, connections to this server were
- * invalidated.
- * This may have happened if:
- * - A background scan removed the server description.
- * - A network error or a "not primary"/"node is recovering" error
- * occurred on an app connection.
- * - A network error occurred on the monitor connection.
- */
- mongoc_cluster_disconnect_node (cluster, server_id);
- } else {
- return _mongoc_cluster_create_server_stream (
- td, cluster_node->handshake_sd, cluster_node->stream);
- }
- }
-
- /* no node, or out of date */
- if (!reconnect_ok) {
- node_not_found (td, server_id, error);
- return NULL;
- }
-
- cluster_node = _cluster_add_node (cluster, td, server_id, error);
- if (cluster_node) {
- return _mongoc_cluster_create_server_stream (
- td, cluster_node->handshake_sd, cluster_node->stream);
- } else {
- return NULL;
- }
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_cluster_init --
- *
- * Initializes @cluster using the @uri and @client provided. The
- * @uri is used to determine the "mode" of the cluster. Based on the
- * uri we can determine if we are connected to a single host, a
- * replicaSet, or a shardedCluster.
- *
- * Returns:
- * None.
- *
- * Side effects:
- * @cluster is initialized.
- *
- *--------------------------------------------------------------------------
- */
-
-void
-mongoc_cluster_init (mongoc_cluster_t *cluster,
- const mongoc_uri_t *uri,
- void *client)
-{
- ENTRY;
-
- BSON_ASSERT (cluster);
- BSON_ASSERT (uri);
-
- memset (cluster, 0, sizeof *cluster);
-
- cluster->uri = mongoc_uri_copy (uri);
- cluster->client = (mongoc_client_t *) client;
- cluster->requires_auth =
- (mongoc_uri_get_username (uri) || mongoc_uri_get_auth_mechanism (uri));
-
- cluster->sockettimeoutms = mongoc_uri_get_option_as_int32 (
- uri, MONGOC_URI_SOCKETTIMEOUTMS, MONGOC_DEFAULT_SOCKETTIMEOUTMS);
-
- cluster->socketcheckintervalms =
- mongoc_uri_get_option_as_int32 (uri,
- MONGOC_URI_SOCKETCHECKINTERVALMS,
- MONGOC_TOPOLOGY_SOCKET_CHECK_INTERVAL_MS);
-
- /* TODO for single-threaded case we don't need this */
- cluster->nodes = mongoc_set_new (8, _mongoc_cluster_node_dtor, NULL);
-
- _mongoc_array_init (&cluster->iov, sizeof (mongoc_iovec_t));
-
- cluster->operation_id = rand ();
-
- EXIT;
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_cluster_destroy --
- *
- * Clean up after @cluster and destroy all active connections.
- * All resources for @cluster are released.
- *
- * Returns:
- * None.
- *
- * Side effects:
- * Everything.
- *
- *--------------------------------------------------------------------------
- */
-
-void
-mongoc_cluster_destroy (mongoc_cluster_t *cluster) /* INOUT */
-{
- ENTRY;
-
- BSON_ASSERT (cluster);
-
- mongoc_uri_destroy (cluster->uri);
-
- mongoc_set_destroy (cluster->nodes);
-
- _mongoc_array_destroy (&cluster->iov);
-
-#ifdef MONGOC_ENABLE_CRYPTO
- if (cluster->scram_cache) {
- _mongoc_scram_cache_destroy (cluster->scram_cache);
- }
-#endif
-
- EXIT;
-}
-
-static uint32_t
-_mongoc_cluster_select_server_id (mongoc_client_session_t *cs,
- mongoc_topology_t *topology,
- mongoc_ss_optype_t optype,
- const mongoc_read_prefs_t *read_prefs,
- bson_error_t *error)
-{
- uint32_t server_id;
-
- if (_in_sharded_txn (cs)) {
- server_id = cs->server_id;
- if (!server_id) {
- server_id = mongoc_topology_select_server_id (
- topology, optype, read_prefs, error);
- if (server_id) {
- _mongoc_client_session_pin (cs, server_id);
- }
- }
- } else {
- server_id =
- mongoc_topology_select_server_id (topology, optype, read_prefs, error);
- /* Transactions Spec: Additionally, any non-transaction operation using a
- * pinned ClientSession MUST unpin the session and the operation MUST
- * perform normal server selection. */
- if (cs && !_mongoc_client_session_in_txn_or_ending (cs)) {
- _mongoc_client_session_unpin (cs);
- }
- }
-
- return server_id;
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_cluster_stream_for_optype --
- *
- * Internal server selection.
- *
- * Returns:
- * A mongoc_server_stream_t on which you must call
- * mongoc_server_stream_cleanup, or NULL on failure (sets @error)
- *
- * Side effects:
- * May add or disconnect nodes in @cluster->nodes.
- * Sets @error and initializes @reply on error.
- *
- *--------------------------------------------------------------------------
- */
-
-static mongoc_server_stream_t *
-_mongoc_cluster_stream_for_optype (mongoc_cluster_t *cluster,
- mongoc_ss_optype_t optype,
- const mongoc_read_prefs_t *read_prefs,
- mongoc_client_session_t *cs,
- bson_t *reply,
- bson_error_t *error)
-{
- mongoc_server_stream_t *server_stream;
- uint32_t server_id;
- mongoc_topology_t *topology = cluster->client->topology;
-
- ENTRY;
-
- BSON_ASSERT (cluster);
-
- server_id = _mongoc_cluster_select_server_id (
- cs, topology, optype, read_prefs, error);
-
- if (!server_id) {
- _mongoc_bson_init_with_transient_txn_error (cs, reply);
- RETURN (NULL);
- }
-
- if (!mongoc_cluster_check_interval (cluster, server_id)) {
- /* Server Selection Spec: try once more */
- server_id = _mongoc_cluster_select_server_id (
- cs, topology, optype, read_prefs, error);
-
- if (!server_id) {
- _mongoc_bson_init_with_transient_txn_error (cs, reply);
- RETURN (NULL);
- }
- }
-
- /* connect or reconnect to server if necessary */
- server_stream = _mongoc_cluster_stream_for_server (
- cluster, server_id, true /* reconnect_ok */, cs, reply, error);
-
- RETURN (server_stream);
-}
-
-mongoc_server_stream_t *
-mongoc_cluster_stream_for_reads (mongoc_cluster_t *cluster,
- const mongoc_read_prefs_t *read_prefs,
- mongoc_client_session_t *cs,
- bson_t *reply,
- bson_error_t *error)
-{
- const mongoc_read_prefs_t *prefs_override = read_prefs;
-
- if (_mongoc_client_session_in_txn (cs)) {
- prefs_override = cs->txn.opts.read_prefs;
- }
-
- return _mongoc_cluster_stream_for_optype (
- cluster, MONGOC_SS_READ, prefs_override, cs, reply, error);
-}
-
-mongoc_server_stream_t *
-mongoc_cluster_stream_for_writes (mongoc_cluster_t *cluster,
- mongoc_client_session_t *cs,
- bson_t *reply,
- bson_error_t *error)
-{
- return _mongoc_cluster_stream_for_optype (
- cluster, MONGOC_SS_WRITE, NULL, cs, reply, error);
-}
-
-static bool
-_mongoc_cluster_min_of_max_obj_size_sds (const void *item, void *ctx)
-{
- const mongoc_server_description_t *sd = item;
- int32_t *current_min = (int32_t *) ctx;
-
- if (sd->max_bson_obj_size < *current_min) {
- *current_min = sd->max_bson_obj_size;
- }
- return true;
-}
-
-static bool
-_mongoc_cluster_min_of_max_obj_size_nodes (void *item, void *ctx)
-{
- mongoc_cluster_node_t *node = (mongoc_cluster_node_t *) item;
- int32_t *current_min = (int32_t *) ctx;
-
- if (node->handshake_sd->max_bson_obj_size < *current_min) {
- *current_min = node->handshake_sd->max_bson_obj_size;
- }
- return true;
-}
-
-static bool
-_mongoc_cluster_min_of_max_msg_size_sds (const void *item, void *ctx)
-{
- const mongoc_server_description_t *sd = item;
- int32_t *current_min = (int32_t *) ctx;
-
- if (sd->max_msg_size < *current_min) {
- *current_min = sd->max_msg_size;
- }
- return true;
-}
-
-static bool
-_mongoc_cluster_min_of_max_msg_size_nodes (void *item, void *ctx)
-{
- mongoc_cluster_node_t *node = (mongoc_cluster_node_t *) item;
- int32_t *current_min = (int32_t *) ctx;
-
- if (node->handshake_sd->max_msg_size < *current_min) {
- *current_min = node->handshake_sd->max_msg_size;
- }
- return true;
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_cluster_get_max_bson_obj_size --
- *
- * Return the minimum max_bson_obj_size across all servers in cluster.
- *
- * Returns:
- * The minimum max_bson_obj_size.
- *
- * Side effects:
- * None
- *
- *--------------------------------------------------------------------------
- */
-int32_t
-mongoc_cluster_get_max_bson_obj_size (mongoc_cluster_t *cluster)
-{
- int32_t max_bson_obj_size = -1;
-
- max_bson_obj_size = MONGOC_DEFAULT_BSON_OBJ_SIZE;
-
- if (!cluster->client->topology->single_threaded) {
- mongoc_set_for_each (cluster->nodes,
- _mongoc_cluster_min_of_max_obj_size_nodes,
- &max_bson_obj_size);
- } else {
- mc_shared_tpld td =
- mc_tpld_take_ref (BSON_ASSERT_PTR_INLINE (cluster)->client->topology);
- mongoc_set_for_each_const (mc_tpld_servers_const (td.ptr),
- _mongoc_cluster_min_of_max_obj_size_sds,
- &max_bson_obj_size);
- mc_tpld_drop_ref (&td);
- }
-
- return max_bson_obj_size;
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_cluster_get_max_msg_size --
- *
- * Return the minimum max msg size across all servers in cluster.
- *
- * Returns:
- * The minimum max_msg_size
- *
- * Side effects:
- * None
- *
- *--------------------------------------------------------------------------
- */
-int32_t
-mongoc_cluster_get_max_msg_size (mongoc_cluster_t *cluster)
-{
- int32_t max_msg_size = MONGOC_DEFAULT_MAX_MSG_SIZE;
-
- if (!cluster->client->topology->single_threaded) {
- mongoc_set_for_each (cluster->nodes,
- _mongoc_cluster_min_of_max_msg_size_nodes,
- &max_msg_size);
- } else {
- mc_shared_tpld td =
- mc_tpld_take_ref (BSON_ASSERT_PTR_INLINE (cluster)->client->topology);
- mongoc_set_for_each_const (mc_tpld_servers_const (td.ptr),
- _mongoc_cluster_min_of_max_msg_size_sds,
- &max_msg_size);
- mc_tpld_drop_ref (&td);
- }
-
- return max_msg_size;
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_cluster_check_interval --
- *
- * Server Selection Spec:
- *
- * Only for single-threaded drivers.
- *
- * If a server is selected that has an existing connection that has been
- * idle for socketCheckIntervalMS, the driver MUST check the connection
- * with the "ping" command. If the ping succeeds, use the selected
- * connection. If not, set the server's type to Unknown and update the
- * Topology Description according to the Server Discovery and Monitoring
- * Spec, and attempt once more to select a server.
- *
- * Returns:
- * True if the check succeeded or no check was required, false if the
- * check failed.
- *
- * Side effects:
- * If a check fails, closes stream and may set server type Unknown.
- *
- *--------------------------------------------------------------------------
- */
-
-bool
-mongoc_cluster_check_interval (mongoc_cluster_t *cluster, uint32_t server_id)
-{
- mongoc_cmd_parts_t parts;
- mongoc_topology_t *topology;
- mongoc_topology_scanner_node_t *scanner_node;
- mongoc_stream_t *stream;
- int64_t now;
- bson_t command;
- bson_error_t error;
- bool r = true;
- mongoc_server_stream_t *server_stream;
- mongoc_server_description_t *handshake_sd;
-
- topology = cluster->client->topology;
-
- if (!topology->single_threaded) {
- return true;
- }
-
- scanner_node =
- mongoc_topology_scanner_get_node (topology->scanner, server_id);
-
- if (!scanner_node) {
- return false;
- }
-
- BSON_ASSERT (!scanner_node->retired);
-
- stream = scanner_node->stream;
-
- if (!stream) {
- return false;
- }
-
- handshake_sd = scanner_node->handshake_sd;
- BSON_ASSERT (handshake_sd);
-
- now = bson_get_monotonic_time ();
-
- if (scanner_node->last_used + (1000 * CHECK_CLOSED_DURATION_MSEC) < now) {
- if (mongoc_stream_check_closed (stream)) {
- mc_tpld_modification tdmod;
- bson_set_error (&error,
- MONGOC_ERROR_STREAM,
- MONGOC_ERROR_STREAM_SOCKET,
- "connection closed");
- mongoc_cluster_disconnect_node (cluster, server_id);
- tdmod = mc_tpld_modify_begin (topology);
- /* invalidate_server() is okay if 'server_id' was already removed. */
- mongoc_topology_description_invalidate_server (
- tdmod.new_td, server_id, &error);
- mc_tpld_modify_commit (tdmod);
- return false;
- }
- }
-
- if (scanner_node->last_used + (1000 * cluster->socketcheckintervalms) <
- now) {
- mc_shared_tpld td;
-
- bson_init (&command);
- BSON_APPEND_INT32 (&command, "ping", 1);
- mongoc_cmd_parts_init (
- &parts, cluster->client, "admin", MONGOC_QUERY_SECONDARY_OK, &command);
- parts.prohibit_lsid = true;
-
- td = mc_tpld_take_ref (cluster->client->topology);
- server_stream =
- _mongoc_cluster_create_server_stream (td.ptr, handshake_sd, stream);
- mc_tpld_drop_ref (&td);
-
- if (!server_stream) {
- bson_destroy (&command);
- return false;
- }
- r = mongoc_cluster_run_command_parts (
- cluster, server_stream, &parts, NULL, &error);
-
- mongoc_server_stream_cleanup (server_stream);
- bson_destroy (&command);
-
- if (!r) {
- mc_tpld_modification tdmod;
- mongoc_cluster_disconnect_node (cluster, server_id);
- tdmod = mc_tpld_modify_begin (cluster->client->topology);
- /* invalidate_server() is okay if 'server_id' was already removed. */
- mongoc_topology_description_invalidate_server (
- tdmod.new_td, server_id, &error);
- mc_tpld_modify_commit (tdmod);
- }
- }
-
- return r;
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_cluster_legacy_rpc_sendv_to_server --
- *
- * Sends the given RPCs to the given server. Used for OP_QUERY cursors,
- * OP_KILLCURSORS, and legacy writes with OP_INSERT, OP_UPDATE, and
- * OP_DELETE. This function is *not* in the OP_QUERY command path.
- *
- * Returns:
- * True if successful.
- *
- * Side effects:
- * @rpc may be mutated and should be considered invalid after calling
- * this method.
- *
- * @error may be set.
- *
- *--------------------------------------------------------------------------
- */
-
-bool
-mongoc_cluster_legacy_rpc_sendv_to_server (
- mongoc_cluster_t *cluster,
- mongoc_rpc_t *rpc,
- mongoc_server_stream_t *server_stream,
- bson_error_t *error)
-{
- uint32_t server_id;
- int32_t max_msg_size;
- bool ret = false;
- int32_t compressor_id = 0;
- char *output = NULL;
-
- ENTRY;
-
- BSON_ASSERT (cluster);
- BSON_ASSERT (rpc);
- BSON_ASSERT (server_stream);
-
- server_id = server_stream->sd->id;
-
- if (cluster->client->in_exhaust) {
- bson_set_error (error,
- MONGOC_ERROR_CLIENT,
- MONGOC_ERROR_CLIENT_IN_EXHAUST,
- "A cursor derived from this client is in exhaust.");
- GOTO (done);
- }
-
- _mongoc_array_clear (&cluster->iov);
- compressor_id = mongoc_server_description_compressor_id (server_stream->sd);
-
- _mongoc_rpc_gather (rpc, &cluster->iov);
- _mongoc_rpc_swab_to_le (rpc);
-
- if (compressor_id != -1) {
- output = _mongoc_rpc_compress (cluster, compressor_id, rpc, error);
- if (output == NULL) {
- GOTO (done);
- }
- }
-
- max_msg_size = mongoc_server_stream_max_msg_size (server_stream);
-
- if (BSON_UINT32_FROM_LE (rpc->header.msg_len) > max_msg_size) {
- bson_set_error (error,
- MONGOC_ERROR_CLIENT,
- MONGOC_ERROR_CLIENT_TOO_BIG,
- "Attempted to send an RPC larger than the "
- "max allowed message size. Was %u, allowed %u.",
- BSON_UINT32_FROM_LE (rpc->header.msg_len),
- max_msg_size);
- GOTO (done);
- }
-
- if (!_mongoc_stream_writev_full (server_stream->stream,
- cluster->iov.data,
- cluster->iov.len,
- cluster->sockettimeoutms,
- error)) {
- GOTO (done);
- }
-
- _mongoc_topology_update_last_used (cluster->client->topology, server_id);
-
- ret = true;
-
-done:
-
- if (compressor_id) {
- bson_free (output);
- }
-
- RETURN (ret);
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_cluster_try_recv --
- *
- * Tries to receive the next event from the MongoDB server.
- * The contents are loaded into @buffer and then
- * scattered into the @rpc structure. @rpc is valid as long as
- * @buffer contains the contents read into it.
- *
- * Callers that can optimize a reuse of @buffer should do so. It
- * can save many memory allocations.
- *
- * Returns:
- * True if successful.
- *
- * Side effects:
- * @rpc is set on success, @error on failure.
- * @buffer will be filled with the input data.
- *
- *--------------------------------------------------------------------------
- */
-
-bool
-mongoc_cluster_try_recv (mongoc_cluster_t *cluster,
- mongoc_rpc_t *rpc,
- mongoc_buffer_t *buffer,
- mongoc_server_stream_t *server_stream,
- bson_error_t *error)
-{
- bson_error_t err_local;
- int32_t msg_len;
- int32_t max_msg_size;
- off_t pos;
-
- ENTRY;
-
- BSON_ASSERT (cluster);
- BSON_ASSERT (rpc);
- BSON_ASSERT (buffer);
- BSON_ASSERT (server_stream);
-
-
- TRACE ("Waiting for reply from server_id \"%u\"", server_stream->sd->id);
-
- if (!error) {
- error = &err_local;
- }
-
- /*
- * Buffer the message length to determine how much more to read.
- */
- pos = buffer->len;
- if (!_mongoc_buffer_append_from_stream (
- buffer, server_stream->stream, 4, cluster->sockettimeoutms, error)) {
- MONGOC_DEBUG (
- "Could not read 4 bytes, stream probably closed or timed out");
- mongoc_counter_protocol_ingress_error_inc ();
- _handle_network_error (
- cluster, server_stream, true /* handshake complete */, error);
- RETURN (false);
- }
-
- /*
- * Read the msg length from the buffer.
- */
- memcpy (&msg_len, &buffer->data[pos], 4);
- msg_len = BSON_UINT32_FROM_LE (msg_len);
- max_msg_size = mongoc_server_stream_max_msg_size (server_stream);
- if ((msg_len < 16) || (msg_len > max_msg_size)) {
- bson_set_error (error,
- MONGOC_ERROR_PROTOCOL,
- MONGOC_ERROR_PROTOCOL_INVALID_REPLY,
- "Corrupt or malicious reply received.");
- _handle_network_error (
- cluster, server_stream, true /* handshake complete */, error);
- mongoc_counter_protocol_ingress_error_inc ();
- RETURN (false);
- }
-
- /*
- * Read the rest of the message from the stream.
- */
- if (!_mongoc_buffer_append_from_stream (buffer,
- server_stream->stream,
- msg_len - 4,
- cluster->sockettimeoutms,
- error)) {
- _handle_network_error (
- cluster, server_stream, true /* handshake complete */, error);
- mongoc_counter_protocol_ingress_error_inc ();
- RETURN (false);
- }
-
- /*
- * Scatter the buffer into the rpc structure.
- */
- if (!_mongoc_rpc_scatter (rpc, &buffer->data[pos], msg_len)) {
- bson_set_error (error,
- MONGOC_ERROR_PROTOCOL,
- MONGOC_ERROR_PROTOCOL_INVALID_REPLY,
- "Failed to decode reply from server.");
- _handle_network_error (
- cluster, server_stream, true /* handshake complete */, error);
- mongoc_counter_protocol_ingress_error_inc ();
- RETURN (false);
- }
-
- if (BSON_UINT32_FROM_LE (rpc->header.opcode) == MONGOC_OPCODE_COMPRESSED) {
- uint8_t *buf = NULL;
- size_t len = BSON_UINT32_FROM_LE (rpc->compressed.uncompressed_size) +
- sizeof (mongoc_rpc_header_t);
-
- buf = bson_malloc0 (len);
- if (!_mongoc_rpc_decompress (rpc, buf, len)) {
- bson_free (buf);
- bson_set_error (error,
- MONGOC_ERROR_PROTOCOL,
- MONGOC_ERROR_PROTOCOL_INVALID_REPLY,
- "Could not decompress server reply");
- RETURN (false);
- }
-
- _mongoc_buffer_destroy (buffer);
- _mongoc_buffer_init (buffer, buf, len, NULL, NULL);
- }
- _mongoc_rpc_swab_from_le (rpc);
-
- RETURN (true);
-}
-
-
-static void
-network_error_reply (bson_t *reply, mongoc_cmd_t *cmd)
-{
- bson_t labels;
-
- if (reply) {
- bson_init (reply);
- }
-
- if (cmd->session) {
- if (cmd->session->server_session) {
- cmd->session->server_session->dirty = true;
- }
- /* Transactions Spec defines TransientTransactionError: "Any
- * network error or server selection error encountered running any
- * command besides commitTransaction in a transaction. In the case
- * of command errors, the server adds the label; in the case of
- * network errors or server selection errors where the client
- * receives no server reply, the client adds the label." */
- if (_mongoc_client_session_in_txn (cmd->session) && !cmd->is_txn_finish) {
- /* Transaction Spec: "Drivers MUST unpin a ClientSession when a command
- * within a transaction, including commitTransaction and
- * abortTransaction,
- * fails with a TransientTransactionError". If we're about to add
- * a TransientTransactionError label due to a client side error then we
- * unpin. If commitTransaction/abortTransation includes a label in the
- * server reply, we unpin in _mongoc_client_session_handle_reply. */
- cmd->session->server_id = 0;
- if (!reply) {
- return;
- }
-
- BSON_APPEND_ARRAY_BEGIN (reply, "errorLabels", &labels);
- BSON_APPEND_UTF8 (&labels, "0", TRANSIENT_TXN_ERR);
- bson_append_array_end (reply, &labels);
- }
- }
-}
-
-
-static bool
-mongoc_cluster_run_opmsg (mongoc_cluster_t *cluster,
- mongoc_cmd_t *cmd,
- bson_t *reply,
- bson_error_t *error)
-{
- mongoc_rpc_section_t section[2];
- mongoc_buffer_t buffer;
- bson_t reply_local; /* only statically initialized */
- char *output = NULL;
- mongoc_rpc_t rpc;
- int32_t msg_len;
- bool ok;
- mongoc_server_stream_t *server_stream;
-
- server_stream = cmd->server_stream;
- if (!cmd->command_name) {
- bson_set_error (error,
- MONGOC_ERROR_COMMAND,
- MONGOC_ERROR_COMMAND_INVALID_ARG,
- "Empty command document");
- _mongoc_bson_init_if_set (reply);
- return false;
- }
- if (cluster->client->in_exhaust) {
- bson_set_error (error,
- MONGOC_ERROR_CLIENT,
- MONGOC_ERROR_CLIENT_IN_EXHAUST,
- "A cursor derived from this client is in exhaust.");
- _mongoc_bson_init_if_set (reply);
- return false;
- }
-
- _mongoc_array_clear (&cluster->iov);
- _mongoc_buffer_init (&buffer, NULL, 0, NULL, NULL);
-
- rpc.header.msg_len = 0;
- rpc.header.request_id = ++cluster->request_id;
- rpc.header.response_to = 0;
- rpc.header.opcode = MONGOC_OPCODE_MSG;
-
- if (cmd->is_acknowledged) {
- rpc.msg.flags = 0;
- } else {
- rpc.msg.flags = MONGOC_MSG_MORE_TO_COME;
- }
-
- rpc.msg.n_sections = 1;
-
- section[0].payload_type = 0;
- section[0].payload.bson_document = bson_get_data (cmd->command);
- rpc.msg.sections[0] = section[0];
-
- if (cmd->payload) {
- section[1].payload_type = 1;
- section[1].payload.sequence.size = cmd->payload_size +
- strlen (cmd->payload_identifier) + 1 +
- sizeof (int32_t);
- section[1].payload.sequence.identifier = cmd->payload_identifier;
- section[1].payload.sequence.bson_documents = cmd->payload;
- rpc.msg.sections[1] = section[1];
- rpc.msg.n_sections++;
- }
-
- _mongoc_rpc_gather (&rpc, &cluster->iov);
- _mongoc_rpc_swab_to_le (&rpc);
-
- if (mongoc_cmd_is_compressible (cmd)) {
- int32_t compressor_id =
- mongoc_server_description_compressor_id (server_stream->sd);
-
- TRACE (
- "Function '%s' is compressible: %d", cmd->command_name, compressor_id);
- if (compressor_id != -1) {
- output = _mongoc_rpc_compress (cluster, compressor_id, &rpc, error);
- if (output == NULL) {
- _mongoc_bson_init_if_set (reply);
- _mongoc_buffer_destroy (&buffer);
- return false;
- }
- }
- }
- ok = _mongoc_stream_writev_full (server_stream->stream,
- (mongoc_iovec_t *) cluster->iov.data,
- cluster->iov.len,
- cluster->sockettimeoutms,
- error);
- if (!ok) {
- /* add info about the command to writev_full's error message */
- RUN_CMD_ERR_DECORATE;
- _handle_network_error (
- cluster, server_stream, true /* handshake complete */, error);
- server_stream->stream = NULL;
- bson_free (output);
- network_error_reply (reply, cmd);
- _mongoc_buffer_destroy (&buffer);
- return false;
- }
-
- /* If acknowledged, wait for a server response. Otherwise, exit early */
- if (cmd->is_acknowledged) {
- ok = _mongoc_buffer_append_from_stream (
- &buffer, server_stream->stream, 4, cluster->sockettimeoutms, error);
- if (!ok) {
- RUN_CMD_ERR_DECORATE;
- _handle_network_error (
- cluster, server_stream, true /* handshake complete */, error);
- server_stream->stream = NULL;
- bson_free (output);
- network_error_reply (reply, cmd);
- _mongoc_buffer_destroy (&buffer);
- return false;
- }
-
- BSON_ASSERT (buffer.len == 4);
- memcpy (&msg_len, buffer.data, 4);
- msg_len = BSON_UINT32_FROM_LE (msg_len);
- if ((msg_len < 16) || (msg_len > server_stream->sd->max_msg_size)) {
- RUN_CMD_ERR (
- MONGOC_ERROR_PROTOCOL,
- MONGOC_ERROR_PROTOCOL_INVALID_REPLY,
- "Message size %d is not within expected range 16-%d bytes",
- msg_len,
- server_stream->sd->max_msg_size);
- _handle_network_error (
- cluster, server_stream, true /* handshake complete */, error);
- server_stream->stream = NULL;
- bson_free (output);
- network_error_reply (reply, cmd);
- _mongoc_buffer_destroy (&buffer);
- return false;
- }
-
- ok = _mongoc_buffer_append_from_stream (&buffer,
- server_stream->stream,
- (size_t) msg_len - 4,
- cluster->sockettimeoutms,
- error);
- if (!ok) {
- RUN_CMD_ERR_DECORATE;
- _handle_network_error (
- cluster, server_stream, true /* handshake complete */, error);
- server_stream->stream = NULL;
- bson_free (output);
- network_error_reply (reply, cmd);
- _mongoc_buffer_destroy (&buffer);
- return false;
- }
-
- ok = _mongoc_rpc_scatter (&rpc, buffer.data, buffer.len);
- if (!ok) {
- RUN_CMD_ERR (MONGOC_ERROR_PROTOCOL,
- MONGOC_ERROR_PROTOCOL_INVALID_REPLY,
- "Malformed message from server");
- bson_free (output);
- network_error_reply (reply, cmd);
- _mongoc_buffer_destroy (&buffer);
- return false;
- }
- if (BSON_UINT32_FROM_LE (rpc.header.opcode) == MONGOC_OPCODE_COMPRESSED) {
- size_t len = BSON_UINT32_FROM_LE (rpc.compressed.uncompressed_size) +
- sizeof (mongoc_rpc_header_t);
-
- output = bson_realloc (output, len);
- if (!_mongoc_rpc_decompress (&rpc, (uint8_t *) output, len)) {
- RUN_CMD_ERR (MONGOC_ERROR_PROTOCOL,
- MONGOC_ERROR_PROTOCOL_INVALID_REPLY,
- "Could not decompress message from server");
- _handle_network_error (
- cluster, server_stream, true /* handshake complete */, error);
- server_stream->stream = NULL;
- bson_free (output);
- network_error_reply (reply, cmd);
- _mongoc_buffer_destroy (&buffer);
- return false;
- }
- }
- _mongoc_rpc_swab_from_le (&rpc);
-
- memcpy (&msg_len, rpc.msg.sections[0].payload.bson_document, 4);
- msg_len = BSON_UINT32_FROM_LE (msg_len);
- bson_init_static (
- &reply_local, rpc.msg.sections[0].payload.bson_document, msg_len);
-
- _mongoc_topology_update_cluster_time (cluster->client->topology,
- &reply_local);
- ok = _mongoc_cmd_check_ok (
- &reply_local, cluster->client->error_api_version, error);
-
- if (cmd->session) {
- _mongoc_client_session_handle_reply (cmd->session,
- cmd->is_acknowledged,
- cmd->command_name,
- &reply_local);
- }
-
- if (reply) {
- bson_copy_to (&reply_local, reply);
- }
- } else {
- _mongoc_bson_init_if_set (reply);
- }
-
- _mongoc_buffer_destroy (&buffer);
- bson_free (output);
-
- return ok;
-}
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cmd.c b/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cmd.c
deleted file mode 100644
index 47813ff9..00000000
--- a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cmd.c
+++ /dev/null
@@ -1,1178 +0,0 @@
-/*
- * Copyright 2017 MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-#include "mongoc-cmd-private.h"
-#include "mongoc-read-prefs-private.h"
-#include "mongoc-trace-private.h"
-#include "mongoc-client-private.h"
-#include "mongoc-read-concern-private.h"
-#include "mongoc-server-api-private.h"
-#include "mongoc-write-concern-private.h"
-/* For strcasecmp on Windows */
-#include "mongoc-util-private.h"
-
-
-void
-mongoc_cmd_parts_init (mongoc_cmd_parts_t *parts,
- mongoc_client_t *client,
- const char *db_name,
- mongoc_query_flags_t user_query_flags,
- const bson_t *command_body)
-{
- parts->body = command_body;
- parts->user_query_flags = user_query_flags;
- parts->read_prefs = NULL;
- parts->is_read_command = false;
- parts->is_write_command = false;
- parts->prohibit_lsid = false;
- parts->allow_txn_number = MONGOC_CMD_PARTS_ALLOW_TXN_NUMBER_UNKNOWN;
- parts->is_retryable_read = false;
- parts->is_retryable_write = false;
- parts->has_temp_session = false;
- parts->client = client;
- bson_init (&parts->read_concern_document);
- bson_init (&parts->write_concern_document);
- bson_init (&parts->extra);
- bson_init (&parts->assembled_body);
-
- parts->assembled.db_name = db_name;
- parts->assembled.command = NULL;
- parts->assembled.query_flags = MONGOC_QUERY_NONE;
- parts->assembled.payload_identifier = NULL;
- parts->assembled.payload = NULL;
- parts->assembled.session = NULL;
- parts->assembled.is_acknowledged = true;
- parts->assembled.is_txn_finish = false;
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_cmd_parts_set_session --
- *
- * Set the client session field.
- *
- * Side effects:
- * Aborts if the command is assembled or if mongoc_cmd_parts_append_opts
- * was called before.
- *
- *--------------------------------------------------------------------------
- */
-
-void
-mongoc_cmd_parts_set_session (mongoc_cmd_parts_t *parts,
- mongoc_client_session_t *cs)
-{
- BSON_ASSERT (parts);
- BSON_ASSERT (!parts->assembled.command);
- BSON_ASSERT (!parts->assembled.session);
-
- parts->assembled.session = cs;
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_cmd_parts_append_opts --
- *
- * Take an iterator over user-supplied options document and append the
- * options to @parts->command_extra, taking the selected server's max
- * wire version into account.
- *
- * Return:
- * True if the options were successfully applied. If any options are
- * invalid, returns false and fills out @error. In that case @parts is
- * invalid and must not be used.
- *
- * Side effects:
- * May partly apply options before returning an error.
- *
- *--------------------------------------------------------------------------
- */
-
-bool
-mongoc_cmd_parts_append_opts (mongoc_cmd_parts_t *parts,
- bson_iter_t *iter,
- int max_wire_version,
- bson_error_t *error)
-{
- mongoc_client_session_t *cs = NULL;
- mongoc_write_concern_t *wc;
- uint32_t len;
- const uint8_t *data;
- bson_t read_concern;
- const char *to_append;
-
- ENTRY;
-
- /* not yet assembled */
- BSON_ASSERT (!parts->assembled.command);
-
- while (bson_iter_next (iter)) {
- if (BSON_ITER_IS_KEY (iter, "collation")) {
- if (max_wire_version < WIRE_VERSION_COLLATION) {
- bson_set_error (error,
- MONGOC_ERROR_COMMAND,
- MONGOC_ERROR_PROTOCOL_BAD_WIRE_VERSION,
- "The selected server does not support collation");
- RETURN (false);
- }
-
- } else if (BSON_ITER_IS_KEY (iter, "writeConcern")) {
- wc = _mongoc_write_concern_new_from_iter (iter, error);
- if (!wc) {
- RETURN (false);
- }
-
- if (!mongoc_cmd_parts_set_write_concern (
- parts, wc, max_wire_version, error)) {
- mongoc_write_concern_destroy (wc);
- RETURN (false);
- }
-
- mongoc_write_concern_destroy (wc);
- continue;
- } else if (BSON_ITER_IS_KEY (iter, "readConcern")) {
- if (max_wire_version < WIRE_VERSION_READ_CONCERN) {
- bson_set_error (error,
- MONGOC_ERROR_COMMAND,
- MONGOC_ERROR_PROTOCOL_BAD_WIRE_VERSION,
- "The selected server does not support readConcern");
- RETURN (false);
- }
-
- if (!BSON_ITER_HOLDS_DOCUMENT (iter)) {
- bson_set_error (error,
- MONGOC_ERROR_COMMAND,
- MONGOC_ERROR_PROTOCOL_BAD_WIRE_VERSION,
- "Invalid readConcern");
- RETURN (false);
- }
-
- /* add readConcern later, once we know about causal consistency */
- bson_iter_document (iter, &len, &data);
- BSON_ASSERT (bson_init_static (&read_concern, data, (size_t) len));
- bson_destroy (&parts->read_concern_document);
- bson_copy_to (&read_concern, &parts->read_concern_document);
- continue;
- } else if (BSON_ITER_IS_KEY (iter, "sessionId")) {
- BSON_ASSERT (!parts->assembled.session);
-
- if (!_mongoc_client_session_from_iter (
- parts->client, iter, &cs, error)) {
- RETURN (false);
- }
-
- parts->assembled.session = cs;
- continue;
- } else if (BSON_ITER_IS_KEY (iter, "serverId") ||
- BSON_ITER_IS_KEY (iter, "maxAwaitTimeMS")) {
- continue;
- }
-
- to_append = bson_iter_key (iter);
- if (!bson_append_iter (&parts->extra, to_append, -1, iter)) {
- bson_set_error (error,
- MONGOC_ERROR_COMMAND,
- MONGOC_ERROR_COMMAND_INVALID_ARG,
- "Failed to append \"%s\" to create command.",
- to_append);
- RETURN (false);
- }
- }
-
- RETURN (true);
-}
-
-
-#define OPTS_ERR(_code, ...) \
- do { \
- bson_set_error ( \
- error, MONGOC_ERROR_COMMAND, MONGOC_ERROR_##_code, __VA_ARGS__); \
- RETURN (false); \
- } while (0)
-
-
-/* set readConcern if allowed, otherwise error */
-bool
-mongoc_cmd_parts_set_read_concern (mongoc_cmd_parts_t *parts,
- const mongoc_read_concern_t *rc,
- int max_wire_version,
- bson_error_t *error)
-{
- const char *command_name;
-
- ENTRY;
-
- /* In a txn, set read concern in mongoc_cmd_parts_assemble, not here. *
- * Transactions Spec: "The readConcern MUST NOT be inherited from the
- * collection, database, or client associated with the driver method that
- * invokes the first command." */
- if (_mongoc_client_session_in_txn (parts->assembled.session)) {
- RETURN (true);
- }
-
- command_name = _mongoc_get_command_name (parts->body);
-
- if (!command_name) {
- OPTS_ERR (COMMAND_INVALID_ARG, "Empty command document");
- }
-
- if (mongoc_read_concern_is_default (rc)) {
- RETURN (true);
- }
-
- if (max_wire_version < WIRE_VERSION_READ_CONCERN) {
- bson_set_error (error,
- MONGOC_ERROR_COMMAND,
- MONGOC_ERROR_PROTOCOL_BAD_WIRE_VERSION,
- "\"%s\" command does not support readConcern with "
- "wire version %d, wire version %d is required",
- command_name,
- max_wire_version,
- WIRE_VERSION_READ_CONCERN);
- RETURN (false);
- }
-
- bson_destroy (&parts->read_concern_document);
- bson_copy_to (_mongoc_read_concern_get_bson ((mongoc_read_concern_t *) rc),
- &parts->read_concern_document);
-
- RETURN (true);
-}
-
-
-/* set writeConcern if allowed, otherwise ignore - unlike set_read_concern, it's
- * the caller's responsibility to check if writeConcern is supported */
-bool
-mongoc_cmd_parts_set_write_concern (mongoc_cmd_parts_t *parts,
- const mongoc_write_concern_t *wc,
- int max_wire_version,
- bson_error_t *error)
-{
- const char *command_name;
- bool is_fam;
- bool wc_allowed;
-
- ENTRY;
-
- if (!wc) {
- RETURN (true);
- }
-
- command_name = _mongoc_get_command_name (parts->body);
-
- if (!command_name) {
- OPTS_ERR (COMMAND_INVALID_ARG, "Empty command document");
- }
-
- is_fam = !strcasecmp (command_name, "findandmodify");
-
- wc_allowed =
- parts->is_write_command ||
- (is_fam && max_wire_version >= WIRE_VERSION_FAM_WRITE_CONCERN) ||
- (!is_fam && max_wire_version >= WIRE_VERSION_CMD_WRITE_CONCERN);
-
- if (wc_allowed) {
- parts->assembled.is_acknowledged =
- mongoc_write_concern_is_acknowledged (wc);
- bson_destroy (&parts->write_concern_document);
- bson_copy_to (
- _mongoc_write_concern_get_bson ((mongoc_write_concern_t *) wc),
- &parts->write_concern_document);
- }
-
- RETURN (true);
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_cmd_parts_append_read_write --
- *
- * Append user-supplied options to @parts->command_extra, taking the
- * selected server's max wire version into account.
- *
- * Return:
- * True if the options were successfully applied. If any options are
- * invalid, returns false and fills out @error. In that case @parts is
- * invalid and must not be used.
- *
- * Side effects:
- * May partly apply options before returning an error.
- *
- *--------------------------------------------------------------------------
- */
-
-bool
-mongoc_cmd_parts_append_read_write (mongoc_cmd_parts_t *parts,
- mongoc_read_write_opts_t *rw_opts,
- int max_wire_version,
- bson_error_t *error)
-{
- ENTRY;
-
- /* not yet assembled */
- BSON_ASSERT (!parts->assembled.command);
-
- if (!bson_empty (&rw_opts->collation)) {
- if (max_wire_version < WIRE_VERSION_COLLATION) {
- OPTS_ERR (PROTOCOL_BAD_WIRE_VERSION,
- "The selected server does not support collation");
- }
-
- if (!bson_append_document (
- &parts->extra, "collation", 9, &rw_opts->collation)) {
- OPTS_ERR (COMMAND_INVALID_ARG, "'opts' with 'collation' is too large");
- }
- }
-
- if (!mongoc_cmd_parts_set_write_concern (
- parts, rw_opts->writeConcern, max_wire_version, error)) {
- RETURN (false);
- }
-
- /* process explicit read concern */
- if (!bson_empty (&rw_opts->readConcern)) {
- if (max_wire_version < WIRE_VERSION_READ_CONCERN) {
- OPTS_ERR (PROTOCOL_BAD_WIRE_VERSION,
- "The selected server does not support readConcern");
- }
-
- /* save readConcern for later, once we know about causal consistency */
- bson_destroy (&parts->read_concern_document);
- bson_copy_to (&rw_opts->readConcern, &parts->read_concern_document);
- }
-
- if (rw_opts->client_session) {
- BSON_ASSERT (!parts->assembled.session);
- parts->assembled.session = rw_opts->client_session;
- }
-
- if (!bson_concat (&parts->extra, &rw_opts->extra)) {
- OPTS_ERR (COMMAND_INVALID_ARG, "'opts' with extra fields is too large");
- }
-
- RETURN (true);
-}
-
-#undef OPTS_ERR
-
-static void
-_mongoc_cmd_parts_ensure_copied (mongoc_cmd_parts_t *parts)
-{
- if (parts->assembled.command == parts->body) {
- bson_concat (&parts->assembled_body, parts->body);
- bson_concat (&parts->assembled_body, &parts->extra);
- parts->assembled.command = &parts->assembled_body;
- }
-}
-
-
-static void
-_mongoc_cmd_parts_add_write_concern (mongoc_cmd_parts_t *parts)
-{
- if (!bson_empty (&parts->write_concern_document)) {
- _mongoc_cmd_parts_ensure_copied (parts);
- bson_append_document (&parts->assembled_body,
- "writeConcern",
- 12,
- &parts->write_concern_document);
- }
-}
-
-
-/* The server type must be mongos, or message must be OP_MSG. */
-static void
-_mongoc_cmd_parts_add_read_prefs (bson_t *query,
- const mongoc_read_prefs_t *prefs)
-{
- bson_t child;
- const char *mode_str;
- const bson_t *tags;
- int64_t stale;
- const bson_t *hedge;
-
- mode_str = _mongoc_read_mode_as_str (mongoc_read_prefs_get_mode (prefs));
- tags = mongoc_read_prefs_get_tags (prefs);
- stale = mongoc_read_prefs_get_max_staleness_seconds (prefs);
- hedge = mongoc_read_prefs_get_hedge (prefs);
-
- bson_append_document_begin (query, "$readPreference", 15, &child);
- bson_append_utf8 (&child, "mode", 4, mode_str, -1);
- if (!bson_empty0 (tags)) {
- bson_append_array (&child, "tags", 4, tags);
- }
-
- if (stale != MONGOC_NO_MAX_STALENESS) {
- bson_append_int64 (&child, "maxStalenessSeconds", 19, stale);
- }
-
- if (!bson_empty0 (hedge)) {
- bson_append_document (&child, "hedge", 5, hedge);
- }
-
- bson_append_document_end (query, &child);
-}
-
-
-static void
-_iter_concat (bson_t *dst, bson_iter_t *iter)
-{
- uint32_t len;
- const uint8_t *data;
- bson_t src;
-
- bson_iter_document (iter, &len, &data);
- BSON_ASSERT (bson_init_static (&src, data, len));
- BSON_ASSERT (bson_concat (dst, &src));
-}
-
-
-/* Update result with the read prefs. Server must be mongos.
- */
-static void
-_mongoc_cmd_parts_assemble_mongos (mongoc_cmd_parts_t *parts,
- const mongoc_server_stream_t *server_stream)
-{
- mongoc_read_mode_t mode;
- const bson_t *tags = NULL;
- int64_t max_staleness_seconds = MONGOC_NO_MAX_STALENESS;
- const bson_t *hedge = NULL;
- bool add_read_prefs = false;
- bson_t query;
- bson_iter_t dollar_query;
- bool has_dollar_query = false;
- bool requires_read_concern;
- bool requires_write_concern;
-
- ENTRY;
-
- mode = mongoc_read_prefs_get_mode (parts->read_prefs);
- if (parts->read_prefs) {
- max_staleness_seconds =
- mongoc_read_prefs_get_max_staleness_seconds (parts->read_prefs);
-
- tags = mongoc_read_prefs_get_tags (parts->read_prefs);
- hedge = mongoc_read_prefs_get_hedge (parts->read_prefs);
- }
-
- /* Server Selection Spec says:
- *
- * For mode 'primary', drivers MUST NOT set the secondaryOk wire protocol
- * flag and MUST NOT use $readPreference
- *
- * For mode 'secondary', drivers MUST set the secondaryOk wire protocol flag
- * and MUST also use $readPreference
- *
- * For mode 'primaryPreferred', drivers MUST set the secondaryOk wire
- * protocol flag and MUST also use $readPreference
- *
- * For mode 'secondaryPreferred', drivers MUST set the secondaryOk wire
- * protocol flag. If the read preference contains a non-empty tag_sets
- * parameter, maxStalenessSeconds is a positive integer, or the hedge
- * parameter is non-empty, drivers MUST use $readPreference; otherwise,
- * drivers MUST NOT use $readPreference
- *
- * For mode 'nearest', drivers MUST set the secondaryOk wire protocol flag
- * and MUST also use $readPreference
- */
- switch (mode) {
- case MONGOC_READ_PRIMARY:
- break;
- case MONGOC_READ_SECONDARY_PREFERRED:
- if (!bson_empty0 (tags) || max_staleness_seconds > 0 ||
- !bson_empty0 (hedge)) {
- add_read_prefs = true;
- }
- parts->assembled.query_flags |= MONGOC_QUERY_SECONDARY_OK;
- break;
- case MONGOC_READ_PRIMARY_PREFERRED:
- case MONGOC_READ_SECONDARY:
- case MONGOC_READ_NEAREST:
- default:
- parts->assembled.query_flags |= MONGOC_QUERY_SECONDARY_OK;
- add_read_prefs = true;
- }
-
- requires_read_concern =
- !bson_empty (&parts->read_concern_document) &&
- strcmp (parts->assembled.command_name, "getMore") != 0;
-
- requires_write_concern = !bson_empty (&parts->write_concern_document);
-
- if (add_read_prefs) {
- /* produce {$query: {user query, readConcern}, $readPreference: ... } */
- bson_append_document_begin (&parts->assembled_body, "$query", 6, &query);
-
- if (bson_iter_init_find (&dollar_query, parts->body, "$query")) {
- /* user provided something like {$query: {key: "x"}} */
- has_dollar_query = true;
- _iter_concat (&query, &dollar_query);
- } else {
- bson_concat (&query, parts->body);
- }
-
- bson_concat (&query, &parts->extra);
- if (requires_read_concern) {
- bson_append_document (
- &query, "readConcern", 11, &parts->read_concern_document);
- }
-
- if (requires_write_concern) {
- bson_append_document (
- &query, "writeConcern", 12, &parts->write_concern_document);
- }
-
- bson_append_document_end (&parts->assembled_body, &query);
- _mongoc_cmd_parts_add_read_prefs (&parts->assembled_body,
- parts->read_prefs);
-
- if (has_dollar_query) {
- /* copy anything that isn't in user's $query */
- bson_copy_to_excluding_noinit (
- parts->body, &parts->assembled_body, "$query", NULL);
- }
-
- parts->assembled.command = &parts->assembled_body;
- } else if (bson_iter_init_find (&dollar_query, parts->body, "$query")) {
- /* user provided $query, we have no read prefs */
- bson_append_document_begin (&parts->assembled_body, "$query", 6, &query);
- _iter_concat (&query, &dollar_query);
- bson_concat (&query, &parts->extra);
- if (requires_read_concern) {
- bson_append_document (
- &query, "readConcern", 11, &parts->read_concern_document);
- }
-
- if (requires_write_concern) {
- bson_append_document (
- &query, "writeConcern", 12, &parts->write_concern_document);
- }
-
- bson_append_document_end (&parts->assembled_body, &query);
- /* copy anything that isn't in user's $query */
- bson_copy_to_excluding_noinit (
- parts->body, &parts->assembled_body, "$query", NULL);
-
- parts->assembled.command = &parts->assembled_body;
- } else {
- if (requires_read_concern) {
- _mongoc_cmd_parts_ensure_copied (parts);
- bson_append_document (&parts->assembled_body,
- "readConcern",
- 11,
- &parts->read_concern_document);
- }
-
- _mongoc_cmd_parts_add_write_concern (parts);
- }
-
- if (!bson_empty (&parts->extra)) {
- /* if none of the above logic has merged "extra", do it now */
- _mongoc_cmd_parts_ensure_copied (parts);
- }
-
- EXIT;
-}
-
-
-static void
-_mongoc_cmd_parts_assemble_mongod (mongoc_cmd_parts_t *parts,
- const mongoc_server_stream_t *server_stream)
-{
- ENTRY;
-
- if (!parts->is_write_command) {
- switch (server_stream->topology_type) {
- case MONGOC_TOPOLOGY_SINGLE:
- /* Server Selection Spec: for topology type single and server types
- * besides mongos, "clients MUST always set the secondaryOk wire
- * protocol flag on reads to ensure that any server type can handle
- * the request."
- */
- parts->assembled.query_flags |= MONGOC_QUERY_SECONDARY_OK;
- break;
-
- case MONGOC_TOPOLOGY_RS_NO_PRIMARY:
- case MONGOC_TOPOLOGY_RS_WITH_PRIMARY:
- /* Server Selection Spec: for RS topology types, "For all read
- * preferences modes except primary, clients MUST set the secondaryOk
- * wire protocol flag to ensure that any suitable server can handle the
- * request. Clients MUST NOT set the secondaryOk wire protocol flag if
- * the read preference mode is primary.
- */
- if (parts->read_prefs &&
- parts->read_prefs->mode != MONGOC_READ_PRIMARY) {
- parts->assembled.query_flags |= MONGOC_QUERY_SECONDARY_OK;
- }
-
- break;
- case MONGOC_TOPOLOGY_SHARDED:
- case MONGOC_TOPOLOGY_UNKNOWN:
- case MONGOC_TOPOLOGY_LOAD_BALANCED:
- case MONGOC_TOPOLOGY_DESCRIPTION_TYPES:
- default:
- /* must not call this function w/ sharded, load balanced, or unknown topology type */
- BSON_ASSERT (false);
- }
- } /* if (!parts->is_write_command) */
-
- if (!bson_empty (&parts->extra)) {
- _mongoc_cmd_parts_ensure_copied (parts);
- }
-
- if (!bson_empty (&parts->read_concern_document) &&
- strcmp (parts->assembled.command_name, "getMore") != 0) {
- _mongoc_cmd_parts_ensure_copied (parts);
- bson_append_document (&parts->assembled_body,
- "readConcern",
- 11,
- &parts->read_concern_document);
- }
-
- _mongoc_cmd_parts_add_write_concern (parts);
-
- EXIT;
-}
-
-
-static const bson_t *
-_largest_cluster_time (const bson_t *a, const bson_t *b)
-{
- if (!a) {
- return b;
- }
-
- if (!b) {
- return a;
- }
-
- if (_mongoc_cluster_time_greater (a, b)) {
- return a;
- }
-
- return b;
-}
-
-
-/* Check if the command should allow a transaction number if that has not
- * already been determined.
- *
- * This should only return true for write commands that are always retryable for
- * the server stream's wire version.
- *
- * The basic write commands (i.e. insert, update, delete) are intentionally
- * excluded here. While insert is always retryable, update and delete are only
- * retryable if they include no multi-document writes. Since it would be costly
- * to inspect the command document here, the bulk operation API explicitly sets
- * allow_txn_number for us. This means that insert, update, and delete are not
- * retryable if executed via mongoc_client_write_command_with_opts(); however,
- * documentation already instructs users not to use that for basic writes.
- */
-static bool
-_allow_txn_number (const mongoc_cmd_parts_t *parts,
- const mongoc_server_stream_t *server_stream)
-{
- /* There is no reason to call this function if allow_txn_number is set */
- BSON_ASSERT (parts->allow_txn_number ==
- MONGOC_CMD_PARTS_ALLOW_TXN_NUMBER_UNKNOWN);
-
- if (!parts->is_write_command) {
- return false;
- }
-
- if (server_stream->sd->max_wire_version < WIRE_VERSION_RETRY_WRITES) {
- return false;
- }
-
- if (!parts->assembled.is_acknowledged) {
- return false;
- }
-
- if (!strcasecmp (parts->assembled.command_name, "findandmodify")) {
- return true;
- }
-
- return false;
-}
-
-
-/* Check if the write command should support retryable behavior. */
-static bool
-_is_retryable_write (const mongoc_cmd_parts_t *parts,
- const mongoc_server_stream_t *server_stream)
-{
- if (!parts->assembled.session) {
- return false;
- }
-
- if (!parts->is_write_command) {
- return false;
- }
-
- if (parts->allow_txn_number != MONGOC_CMD_PARTS_ALLOW_TXN_NUMBER_YES) {
- return false;
- }
-
- if (server_stream->sd->max_wire_version < WIRE_VERSION_RETRY_WRITES) {
- return false;
- }
-
- if (server_stream->sd->type == MONGOC_SERVER_STANDALONE) {
- return false;
- }
-
- if (_mongoc_client_session_in_txn (parts->assembled.session)) {
- return false;
- }
-
- if (!mongoc_uri_get_option_as_bool (parts->client->uri,
- MONGOC_URI_RETRYWRITES,
- MONGOC_DEFAULT_RETRYWRITES)) {
- return false;
- }
-
- return true;
-}
-
-
-/* Check if the read command should support retryable behavior. */
-bool
-_is_retryable_read (const mongoc_cmd_parts_t *parts,
- const mongoc_server_stream_t *server_stream)
-{
- if (!parts->is_read_command) {
- return false;
- }
-
- /* Commands that go through read_write_command helpers are also write
- * commands. Prohibit from read retry. */
- if (parts->is_write_command) {
- return false;
- }
-
- if (server_stream->sd->max_wire_version < WIRE_VERSION_RETRY_READS) {
- return false;
- }
-
- if (_mongoc_client_session_in_txn (parts->assembled.session)) {
- return false;
- }
-
- if (!mongoc_uri_get_option_as_bool (parts->client->uri,
- MONGOC_URI_RETRYREADS,
- MONGOC_DEFAULT_RETRYREADS)) {
- return false;
- }
-
- return true;
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_cmd_parts_assemble --
- *
- * Assemble the command body, options, and read preference into one
- * command.
- *
- * Return:
- * True if the options were successfully applied. If any options are
- * invalid, returns false and fills out @error. In that case @parts is
- * invalid and must not be used.
- *
- * Side effects:
- * May partly assemble before returning an error.
- * mongoc_cmd_parts_cleanup should be called in all cases.
- *
- *--------------------------------------------------------------------------
- */
-
-bool
-mongoc_cmd_parts_assemble (mongoc_cmd_parts_t *parts,
- mongoc_server_stream_t *server_stream,
- bson_error_t *error)
-{
- mongoc_server_description_type_t server_type;
- mongoc_client_session_t *cs;
- const bson_t *cluster_time = NULL;
- mongoc_read_prefs_t *prefs = NULL;
- const char *cmd_name;
- bool is_get_more;
- const mongoc_read_prefs_t *prefs_ptr;
- bool ret = false;
-
- ENTRY;
-
- BSON_ASSERT (parts);
- BSON_ASSERT (server_stream);
-
- server_type = server_stream->sd->type;
- cs = parts->prohibit_lsid ? NULL : parts->assembled.session;
-
- /* Assembling the command depends on the type of server. If the server has
- * been invalidated, error. */
- if (server_type == MONGOC_SERVER_UNKNOWN) {
- if (error) {
- bson_set_error (error,
- MONGOC_ERROR_COMMAND,
- MONGOC_ERROR_COMMAND_INVALID_ARG,
- "Cannot assemble command for invalidated server: %s",
- server_stream->sd->error.message);
- }
- RETURN (false);
- }
-
- /* must not be assembled already */
- BSON_ASSERT (!parts->assembled.command);
- BSON_ASSERT (bson_empty (&parts->assembled_body));
-
- /* begin with raw flags/cmd as assembled flags/cmd, might change below */
- parts->assembled.command = parts->body;
- /* unused in OP_MSG: */
- parts->assembled.query_flags = parts->user_query_flags;
- parts->assembled.server_stream = server_stream;
- cmd_name = parts->assembled.command_name =
- _mongoc_get_command_name (parts->assembled.command);
-
- if (!parts->assembled.command_name) {
- bson_set_error (error,
- MONGOC_ERROR_COMMAND,
- MONGOC_ERROR_COMMAND_INVALID_ARG,
- "Empty command document");
- GOTO (done);
- }
-
- TRACE ("Preparing '%s'", cmd_name);
-
- is_get_more = !strcmp (cmd_name, "getMore");
- parts->assembled.is_txn_finish = !strcmp (cmd_name, "commitTransaction") ||
- !strcmp (cmd_name, "abortTransaction");
-
- if (!parts->is_write_command && IS_PREF_PRIMARY (parts->read_prefs) &&
- server_stream->topology_type == MONGOC_TOPOLOGY_SINGLE &&
- server_type != MONGOC_SERVER_MONGOS) {
- prefs = mongoc_read_prefs_new (MONGOC_READ_PRIMARY_PREFERRED);
- prefs_ptr = prefs;
- } else {
- prefs_ptr = parts->read_prefs;
- }
-
- if (server_stream->sd->max_wire_version >= WIRE_VERSION_OP_MSG) {
- if (!bson_has_field (parts->body, "$db")) {
- BSON_APPEND_UTF8 (&parts->extra, "$db", parts->assembled.db_name);
- }
-
- if (cs && _mongoc_client_session_in_txn (cs)) {
- if (!IS_PREF_PRIMARY (cs->txn.opts.read_prefs) &&
- !parts->is_write_command) {
- bson_set_error (error,
- MONGOC_ERROR_TRANSACTION,
- MONGOC_ERROR_TRANSACTION_INVALID_STATE,
- "Read preference in a transaction must be primary");
- GOTO (done);
- }
- } else if (!IS_PREF_PRIMARY (prefs_ptr) &&
- server_type != MONGOC_SERVER_STANDALONE) {
- /* "Type Standalone: clients MUST NOT send the read preference to the
- * server" */
- _mongoc_cmd_parts_add_read_prefs (&parts->extra, prefs_ptr);
- }
-
- if (!bson_empty (&parts->extra)) {
- _mongoc_cmd_parts_ensure_copied (parts);
- }
-
- /* If an explicit session was not provided and lsid is not prohibited,
- * attempt to create an implicit session (ignoring any errors). */
- if (!cs && !parts->prohibit_lsid && parts->assembled.is_acknowledged) {
- cs = mongoc_client_start_session (parts->client, NULL, NULL);
-
- if (cs) {
- parts->assembled.session = cs;
- parts->has_temp_session = true;
- }
- }
-
- /* Driver Sessions Spec: "For unacknowledged writes with an explicit
- * session, drivers SHOULD raise an error.... Without an explicit
- * session, drivers SHOULD NOT use an implicit session." We intentionally
- * do not restrict this logic to parts->is_write_command, since
- * mongoc_client_command_with_opts() does not identify as a write
- * command but may still include a write concern.
- */
- if (cs) {
- if (!parts->assembled.is_acknowledged) {
- bson_set_error (
- error,
- MONGOC_ERROR_COMMAND,
- MONGOC_ERROR_COMMAND_INVALID_ARG,
- "Cannot use client session with unacknowledged command");
- GOTO (done);
- }
-
- _mongoc_cmd_parts_ensure_copied (parts);
- bson_append_document (&parts->assembled_body,
- "lsid",
- 4,
- mongoc_client_session_get_lsid (cs));
-
- cs->server_session->last_used_usec = bson_get_monotonic_time ();
- cluster_time = mongoc_client_session_get_cluster_time (cs);
- }
-
- /* Ensure we know if the write command allows a transaction number */
- if (!_mongoc_client_session_txn_in_progress (cs) &&
- parts->is_write_command &&
- parts->allow_txn_number ==
- MONGOC_CMD_PARTS_ALLOW_TXN_NUMBER_UNKNOWN) {
- parts->allow_txn_number = _allow_txn_number (parts, server_stream)
- ? MONGOC_CMD_PARTS_ALLOW_TXN_NUMBER_YES
- : MONGOC_CMD_PARTS_ALLOW_TXN_NUMBER_NO;
- }
-
- /* Determine if the command is retryable. If so, append txnNumber now
- * for future use and mark the command as such. */
- if (_is_retryable_write (parts, server_stream)) {
- _mongoc_cmd_parts_ensure_copied (parts);
- bson_append_int64 (&parts->assembled_body, "txnNumber", 9, 0);
- parts->is_retryable_write = true;
- }
-
- /* Conversely, check if the command is retryable if it is a read. */
- if (_is_retryable_read (parts, server_stream) && !is_get_more) {
- parts->is_retryable_read = true;
- }
-
- if (!bson_empty (&server_stream->cluster_time)) {
- cluster_time =
- _largest_cluster_time (&server_stream->cluster_time, cluster_time);
- }
-
- if (cluster_time && server_type != MONGOC_SERVER_STANDALONE) {
- _mongoc_cmd_parts_ensure_copied (parts);
- bson_append_document (
- &parts->assembled_body, "$clusterTime", 12, cluster_time);
- }
-
- /* Add versioned server api, if it is set. */
- if (parts->client->api) {
- _mongoc_cmd_append_server_api (&parts->assembled_body,
- parts->client->api);
- }
-
- if (!is_get_more) {
- if (cs) {
- /* Snapshot Sessions Spec: "Snapshot reads require MongoDB 5.0+."
- * Throw an error if snapshot is enabled and wire version is less
- * than 13 before potentially appending "snapshot" read concern. */
- if (mongoc_session_opts_get_snapshot (&cs->opts) &&
- server_stream->sd->max_wire_version <
- WIRE_VERSION_SNAPSHOT_READS) {
- bson_set_error (error,
- MONGOC_ERROR_CLIENT,
- MONGOC_ERROR_CLIENT_SESSION_FAILURE,
- "Snapshot reads require MongoDB 5.0 or later");
- GOTO (done);
- }
-
- _mongoc_cmd_parts_ensure_copied (parts);
- _mongoc_client_session_append_read_concern (
- cs,
- &parts->read_concern_document,
- parts->is_read_command,
- &parts->assembled_body);
- } else if (!bson_empty (&parts->read_concern_document)) {
- _mongoc_cmd_parts_ensure_copied (parts);
- bson_append_document (&parts->assembled_body,
- "readConcern",
- 11,
- &parts->read_concern_document);
- }
- }
-
- /* if transaction is in progress do not inherit write concern */
- if (parts->assembled.is_txn_finish ||
- !_mongoc_client_session_in_txn (cs)) {
- _mongoc_cmd_parts_add_write_concern (parts);
- }
-
- _mongoc_cmd_parts_ensure_copied (parts);
- if (!_mongoc_client_session_append_txn (
- cs, &parts->assembled_body, error)) {
- GOTO (done);
- }
-
- ret = true;
- } else if (server_type == MONGOC_SERVER_MONGOS ||
- server_stream->topology_type == MONGOC_TOPOLOGY_LOAD_BALANCED) {
- /* TODO (CDRIVER-4117) remove the check of the topology description type. */
- _mongoc_cmd_parts_assemble_mongos (parts, server_stream);
- ret = true;
- } else {
- _mongoc_cmd_parts_assemble_mongod (parts, server_stream);
- ret = true;
- }
-
-done:
- mongoc_read_prefs_destroy (prefs);
- RETURN (ret);
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_cmd_parts_cleanup --
- *
- * Free memory associated with a stack-allocated mongoc_cmd_parts_t.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-void
-mongoc_cmd_parts_cleanup (mongoc_cmd_parts_t *parts)
-{
- bson_destroy (&parts->read_concern_document);
- bson_destroy (&parts->write_concern_document);
- bson_destroy (&parts->extra);
- bson_destroy (&parts->assembled_body);
-
- if (parts->has_temp_session) {
- /* client session returns its server session to server session pool */
- mongoc_client_session_destroy (parts->assembled.session);
- }
-}
-
-bool
-mongoc_cmd_is_compressible (mongoc_cmd_t *cmd)
-{
- BSON_ASSERT (cmd);
- BSON_ASSERT (cmd->command_name);
-
- return !!strcasecmp (cmd->command_name, "hello") &&
- !!strcasecmp (cmd->command_name, HANDSHAKE_CMD_LEGACY_HELLO) &&
- !!strcasecmp (cmd->command_name, "authenticate") &&
- !!strcasecmp (cmd->command_name, "getnonce") &&
- !!strcasecmp (cmd->command_name, "saslstart") &&
- !!strcasecmp (cmd->command_name, "saslcontinue") &&
- !!strcasecmp (cmd->command_name, "createuser") &&
- !!strcasecmp (cmd->command_name, "updateuser");
-}
-
-/*--------------------------------------------------------------------------
- *
- * _mongoc_cmd_append_payload_as_array --
- * Append a write command payload as an array in a BSON document.
- * Used by APM and Client-Side Encryption
- *
- * Arguments:
- * cmd The mongoc_cmd_t, which may contain a payload to be appended.
- * out A bson_t, which will be appended to if @cmd->payload is set.
- *
- * Pre-conditions:
- * - @out is initialized.
- * - cmd has a payload (i.e. is a write command).
- *
- * Post-conditions:
- * - If @cmd->payload is set, then @out is appended to with the payload
- * field's name ("documents" if insert, "updates" if update,
- * "deletes" if delete) an the payload as a BSON array.
- *
- *--------------------------------------------------------------------------
- */
-void
-_mongoc_cmd_append_payload_as_array (const mongoc_cmd_t *cmd, bson_t *out)
-{
- int32_t doc_len;
- bson_t doc;
- const uint8_t *pos;
- const char *field_name;
- bson_t bson;
- char str[16];
- const char *key;
- uint32_t i;
-
- BSON_ASSERT (cmd->payload && cmd->payload_size);
-
- /* make array from outgoing OP_MSG payload type 1 on an "insert",
- * "update", or "delete" command. */
- field_name = _mongoc_get_documents_field_name (cmd->command_name);
- BSON_ASSERT (field_name);
- BSON_ASSERT (BSON_APPEND_ARRAY_BEGIN (out, field_name, &bson));
-
- pos = cmd->payload;
- i = 0;
- while (pos < cmd->payload + cmd->payload_size) {
- memcpy (&doc_len, pos, sizeof (doc_len));
- doc_len = BSON_UINT32_FROM_LE (doc_len);
- BSON_ASSERT (bson_init_static (&doc, pos, (size_t) doc_len));
- bson_uint32_to_string (i, &key, str, sizeof (str));
- BSON_APPEND_DOCUMENT (&bson, key, &doc);
-
- pos += doc_len;
- i++;
- }
-
- bson_append_array_end (out, &bson);
-}
-
-/*--------------------------------------------------------------------------
- *
- * _mongoc_cmd_append_server_api --
- * Append versioned API fields to a mongoc_cmd_t
- *
- * Arguments:
- * cmd The mongoc_cmd_t, which will have versioned API fields added
- * api A mongoc_server_api_t holding server API information
- *
- * Pre-conditions:
- * - @api is initialized.
- * - @command_body is initialised
- *
- *--------------------------------------------------------------------------
- */
-void
-_mongoc_cmd_append_server_api (bson_t *command_body,
- const mongoc_server_api_t *api)
-{
- const char *string_version;
-
- BSON_ASSERT (command_body);
- BSON_ASSERT (api);
-
- string_version = mongoc_server_api_version_to_string (api->version);
-
- bson_append_utf8 (command_body, "apiVersion", -1, string_version, -1);
-
- if (api->strict.is_set) {
- bson_append_bool (command_body, "apiStrict", -1, api->strict.value);
- }
-
- if (api->deprecation_errors.is_set) {
- bson_append_bool (command_body,
- "apiDeprecationErrors",
- -1,
- api->deprecation_errors.value);
- }
-}
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-collection.c b/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-collection.c
deleted file mode 100644
index 0c04a542..00000000
--- a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-collection.c
+++ /dev/null
@@ -1,3587 +0,0 @@
-/*
- * Copyright 2013 MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-#include <stdio.h>
-
-#include "mongoc-aggregate-private.h"
-#include "mongoc-bulk-operation.h"
-#include "mongoc-bulk-operation-private.h"
-#include "mongoc-change-stream-private.h"
-#include "mongoc-client-private.h"
-#include "mongoc-find-and-modify-private.h"
-#include "mongoc-find-and-modify.h"
-#include "mongoc-collection.h"
-#include "mongoc-collection-private.h"
-#include "mongoc-cursor-private.h"
-#include "mongoc-error.h"
-#include "mongoc-index.h"
-#include "mongoc-log.h"
-#include "mongoc-trace-private.h"
-#include "mongoc-read-concern-private.h"
-#include "mongoc-write-concern-private.h"
-#include "mongoc-read-prefs-private.h"
-#include "mongoc-util-private.h"
-#include "mongoc-write-command-private.h"
-#include "mongoc-opts-private.h"
-#include "mongoc-write-command-private.h"
-#include "mongoc-error-private.h"
-
-#undef MONGOC_LOG_DOMAIN
-#define MONGOC_LOG_DOMAIN "collection"
-
-static void
-_mongoc_collection_write_command_execute (
- mongoc_write_command_t *command,
- const mongoc_collection_t *collection,
- const mongoc_write_concern_t *write_concern,
- mongoc_client_session_t *cs,
- mongoc_write_result_t *result)
-{
- mongoc_server_stream_t *server_stream;
-
- ENTRY;
-
- server_stream = mongoc_cluster_stream_for_writes (
- &collection->client->cluster, cs, NULL, &result->error);
-
- if (!server_stream) {
- /* result->error has been filled out */
- EXIT;
- }
-
- _mongoc_write_command_execute (command,
- collection->client,
- server_stream,
- collection->db,
- collection->collection,
- write_concern,
- 0 /* offset */,
- cs,
- result);
-
- mongoc_server_stream_cleanup (server_stream);
-
- EXIT;
-}
-
-
-static void
-_mongoc_collection_write_command_execute_idl (
- mongoc_write_command_t *command,
- const mongoc_collection_t *collection,
- mongoc_crud_opts_t *crud,
- mongoc_write_result_t *result)
-{
- mongoc_server_stream_t *server_stream;
- bson_t reply;
-
- ENTRY;
-
- server_stream =
- mongoc_cluster_stream_for_writes (&collection->client->cluster,
- crud->client_session,
- &reply,
- &result->error);
-
- if (!server_stream) {
- /* result->error and reply have been filled out */
- _mongoc_bson_array_copy_labels_to (&reply, &result->errorLabels);
- bson_destroy (&reply);
- EXIT;
- }
-
- if (_mongoc_client_session_in_txn (crud->client_session) &&
- crud->writeConcern) {
- bson_set_error (&result->error,
- MONGOC_ERROR_COMMAND,
- MONGOC_ERROR_COMMAND_INVALID_ARG,
- "Cannot set write concern after starting transaction");
- mongoc_server_stream_cleanup (server_stream);
- EXIT;
- }
-
- if (!crud->writeConcern &&
- !_mongoc_client_session_in_txn (crud->client_session)) {
- crud->writeConcern = collection->write_concern;
- crud->write_concern_owned = false;
- }
-
- _mongoc_write_command_execute_idl (command,
- collection->client,
- server_stream,
- collection->db,
- collection->collection,
- 0 /* offset */,
- crud,
- result);
-
- mongoc_server_stream_cleanup (server_stream);
-
- EXIT;
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_collection_new --
- *
- * INTERNAL API
- *
- * Create a new mongoc_collection_t structure for the given client.
- *
- * @client must remain valid during the lifetime of this structure.
- * @db is the db name of the collection.
- * @collection is the name of the collection.
- * @read_prefs is the default read preferences to apply or NULL.
- * @read_concern is the default read concern to apply or NULL.
- * @write_concern is the default write concern to apply or NULL.
- *
- * Returns:
- * A newly allocated mongoc_collection_t that should be freed with
- * mongoc_collection_destroy().
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-mongoc_collection_t *
-_mongoc_collection_new (mongoc_client_t *client,
- const char *db,
- const char *collection,
- const mongoc_read_prefs_t *read_prefs,
- const mongoc_read_concern_t *read_concern,
- const mongoc_write_concern_t *write_concern)
-{
- mongoc_collection_t *col;
-
- ENTRY;
-
- BSON_ASSERT_PARAM (client);
- BSON_ASSERT_PARAM (db);
- BSON_ASSERT_PARAM (collection);
-
- col = (mongoc_collection_t *) bson_malloc0 (sizeof *col);
- col->client = client;
- col->write_concern = write_concern
- ? mongoc_write_concern_copy (write_concern)
- : mongoc_write_concern_new ();
- col->read_concern = read_concern ? mongoc_read_concern_copy (read_concern)
- : mongoc_read_concern_new ();
- col->read_prefs = read_prefs ? mongoc_read_prefs_copy (read_prefs)
- : mongoc_read_prefs_new (MONGOC_READ_PRIMARY);
-
- col->ns = bson_strdup_printf ("%s.%s", db, collection);
- col->db = bson_strdup (db);
- col->collection = bson_strdup (collection);
-
- col->collectionlen = (uint32_t) strlen (col->collection);
- col->nslen = (uint32_t) strlen (col->ns);
-
- col->gle = NULL;
-
- RETURN (col);
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_collection_destroy --
- *
- * Release resources associated with @collection and frees the
- * structure.
- *
- * Returns:
- * None.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-void
-mongoc_collection_destroy (mongoc_collection_t *collection) /* IN */
-{
- ENTRY;
-
- if (!collection) {
- EXIT;
- }
-
- bson_clear (&collection->gle);
-
- if (collection->read_prefs) {
- mongoc_read_prefs_destroy (collection->read_prefs);
- collection->read_prefs = NULL;
- }
-
- if (collection->read_concern) {
- mongoc_read_concern_destroy (collection->read_concern);
- collection->read_concern = NULL;
- }
-
- if (collection->write_concern) {
- mongoc_write_concern_destroy (collection->write_concern);
- collection->write_concern = NULL;
- }
-
- bson_free (collection->collection);
- bson_free (collection->db);
- bson_free (collection->ns);
- bson_free (collection);
-
- EXIT;
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_collection_copy --
- *
- * Returns a copy of @collection that needs to be freed by calling
- * mongoc_collection_destroy.
- *
- * Returns:
- * A copy of this collection.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-mongoc_collection_t *
-mongoc_collection_copy (mongoc_collection_t *collection) /* IN */
-{
- ENTRY;
-
- BSON_ASSERT_PARAM (collection);
-
- RETURN (_mongoc_collection_new (collection->client,
- collection->db,
- collection->collection,
- collection->read_prefs,
- collection->read_concern,
- collection->write_concern));
-}
-
-
-mongoc_cursor_t *
-mongoc_collection_aggregate (mongoc_collection_t *collection, /* IN */
- mongoc_query_flags_t flags, /* IN */
- const bson_t *pipeline, /* IN */
- const bson_t *opts, /* IN */
- const mongoc_read_prefs_t *read_prefs) /* IN */
-{
- return _mongoc_aggregate (collection->client,
- collection->ns,
- flags,
- pipeline,
- opts,
- read_prefs,
- collection->read_prefs,
- collection->read_concern,
- collection->write_concern);
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_collection_find --
- *
- * DEPRECATED: use mongoc_collection_find_with_opts.
- *
- * Performs a query against the configured MongoDB server. If @read_prefs
- * is provided, it will be used to locate a MongoDB node in the cluster
- * to deliver the query to.
- *
- * @flags may be bitwise-or'd flags or MONGOC_QUERY_NONE.
- *
- * @skip may contain the number of documents to skip before returning the
- * matching document.
- *
- * @limit may contain the maximum number of documents that may be
- * returned.
- *
- * This function will always return a cursor, with the exception of
- * invalid API use.
- *
- * Parameters:
- * @collection: A mongoc_collection_t.
- * @flags: A bitwise or of mongoc_query_flags_t.
- * @skip: The number of documents to skip.
- * @limit: The maximum number of items.
- * @batch_size: The batch size
- * @query: The query to locate matching documents.
- * @fields: The fields to return, or NULL for all fields.
- * @read_prefs: Read preferences to choose cluster node.
- *
- * Returns:
- * A newly allocated mongoc_cursor_t that should be freed with
- * mongoc_cursor_destroy().
- *
- * The client used by mongoc_collection_t must be valid for the
- * lifetime of the resulting mongoc_cursor_t.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-mongoc_cursor_t *
-mongoc_collection_find (mongoc_collection_t *collection, /* IN */
- mongoc_query_flags_t flags, /* IN */
- uint32_t skip, /* IN */
- uint32_t limit, /* IN */
- uint32_t batch_size, /* IN */
- const bson_t *query, /* IN */
- const bson_t *fields, /* IN */
- const mongoc_read_prefs_t *read_prefs) /* IN */
-{
- bool has_unwrapped;
- bson_t unwrapped;
- bson_error_t error = {0};
- bson_t opts;
- bool secondary_ok;
- mongoc_cursor_t *cursor;
- BSON_ASSERT_PARAM (collection);
- BSON_ASSERT_PARAM (query);
-
- bson_clear (&collection->gle);
-
- bson_init (&opts);
- _mongoc_cursor_flags_to_opts (flags, &opts, &secondary_ok);
- /* check if the query is wrapped in $query */
- has_unwrapped = _mongoc_cursor_translate_dollar_query_opts (
- query, &opts, &unwrapped, &error);
- if (!bson_empty0 (fields)) {
- bson_append_document (
- &opts, MONGOC_CURSOR_PROJECTION, MONGOC_CURSOR_PROJECTION_LEN, fields);
- }
- cursor = _mongoc_cursor_find_new (collection->client,
- collection->ns,
- has_unwrapped ? &unwrapped : query,
- &opts,
- read_prefs,
- collection->read_prefs,
- collection->read_concern);
- if (skip) {
- _mongoc_cursor_set_opt_int64 (cursor, MONGOC_CURSOR_SKIP, skip);
- }
- if (limit) {
- /* limit must be cast to int32_t. Although the argument is a uint32_t,
- * callers can specify a negative limit by casting to a signed int32_t
- * value to uint32_t. E.g. to set a limit of -4, the caller passes
- * UINT32_MAX - 3 */
- (void) mongoc_cursor_set_limit (cursor, (int32_t) limit);
- }
- if (batch_size) {
- mongoc_cursor_set_batch_size (cursor, batch_size);
- }
- bson_destroy (&unwrapped);
- bson_destroy (&opts);
-
- if (error.domain) {
- memcpy (&cursor->error, &error, sizeof (error));
- }
-
- return cursor;
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_collection_find_with_opts --
- *
- * Create a cursor with a query filter. All other options are
- * specified in a free-form BSON document.
- *
- * Parameters:
- * @collection: A mongoc_collection_t.
- * @filter: The query to locate matching documents.
- * @opts: Other options.
- * @read_prefs: Optional read preferences to choose cluster node.
- *
- * Returns:
- * A newly allocated mongoc_cursor_t that should be freed with
- * mongoc_cursor_destroy().
- *
- * The client used by mongoc_collection_t must be valid for the
- * lifetime of the resulting mongoc_cursor_t.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-mongoc_cursor_t *
-mongoc_collection_find_with_opts (mongoc_collection_t *collection,
- const bson_t *filter,
- const bson_t *opts,
- const mongoc_read_prefs_t *read_prefs)
-{
- BSON_ASSERT_PARAM (collection);
- BSON_ASSERT_PARAM (filter);
-
- bson_clear (&collection->gle);
-
- return _mongoc_cursor_find_new (collection->client,
- collection->ns,
- filter,
- opts,
- read_prefs,
- collection->read_prefs,
- collection->read_concern);
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_collection_command --
- *
- * Executes a command on a cluster node matching @read_prefs. If
- * @read_prefs is not provided, it will be run on the primary node.
- *
- * This function will always return a mongoc_cursor_t.
- *
- * Parameters:
- * @collection: A mongoc_collection_t.
- * @flags: Bitwise-or'd flags for command.
- * @skip: Number of documents to skip, typically 0.
- * @limit : Number of documents to return
- * @batch_size : Batch size
- * @query: The command to execute.
- * @fields: The fields to return, or NULL.
- * @read_prefs: Command read preferences or NULL.
- *
- * Returns:
- * None.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-mongoc_cursor_t *
-mongoc_collection_command (mongoc_collection_t *collection,
- mongoc_query_flags_t flags,
- uint32_t skip,
- uint32_t limit,
- uint32_t batch_size,
- const bson_t *query,
- const bson_t *fields,
- const mongoc_read_prefs_t *read_prefs)
-{
- char *ns;
- mongoc_cursor_t *cursor;
-
- BSON_ASSERT_PARAM (collection);
- BSON_ASSERT_PARAM (query);
-
- if (!read_prefs) {
- read_prefs = collection->read_prefs;
- }
-
- bson_clear (&collection->gle);
-
- if (NULL == strstr (collection->collection, "$cmd")) {
- ns = bson_strdup_printf ("%s.$cmd", collection->db);
- } else {
- ns = bson_strdup (collection->db);
- }
-
- /* Server Selection Spec: "The generic command method has a default read
- * preference of mode 'primary'. The generic command method MUST ignore any
- * default read preference from client, database or collection
- * configuration. The generic command method SHOULD allow an optional read
- * preference argument."
- */
-
- /* flags, skip, limit, batch_size, fields are unused */
- cursor = _mongoc_cursor_cmd_deprecated_new (
- collection->client, ns, query, read_prefs);
- bson_free (ns);
- return cursor;
-}
-
-
-bool
-mongoc_collection_read_command_with_opts (mongoc_collection_t *collection,
- const bson_t *command,
- const mongoc_read_prefs_t *read_prefs,
- const bson_t *opts,
- bson_t *reply,
- bson_error_t *error)
-{
- BSON_ASSERT_PARAM (collection);
-
- return _mongoc_client_command_with_opts (collection->client,
- collection->db,
- command,
- MONGOC_CMD_READ,
- opts,
- MONGOC_QUERY_NONE,
- read_prefs,
- collection->read_prefs,
- collection->read_concern,
- collection->write_concern,
- reply,
- error);
-}
-
-
-bool
-mongoc_collection_write_command_with_opts (mongoc_collection_t *collection,
- const bson_t *command,
- const bson_t *opts,
- bson_t *reply,
- bson_error_t *error)
-{
- BSON_ASSERT_PARAM (collection);
-
- return _mongoc_client_command_with_opts (collection->client,
- collection->db,
- command,
- MONGOC_CMD_WRITE,
- opts,
- MONGOC_QUERY_NONE,
- NULL,
- collection->read_prefs,
- collection->read_concern,
- collection->write_concern,
- reply,
- error);
-}
-
-
-bool
-mongoc_collection_read_write_command_with_opts (
- mongoc_collection_t *collection,
- const bson_t *command,
- const mongoc_read_prefs_t *read_prefs /* IGNORED */,
- const bson_t *opts,
- bson_t *reply,
- bson_error_t *error)
-{
- BSON_ASSERT_PARAM (collection);
-
- return _mongoc_client_command_with_opts (collection->client,
- collection->db,
- command,
- MONGOC_CMD_RW,
- opts,
- MONGOC_QUERY_NONE,
- read_prefs,
- collection->read_prefs,
- collection->read_concern,
- collection->write_concern,
- reply,
- error);
-}
-
-
-bool
-mongoc_collection_command_with_opts (mongoc_collection_t *collection,
- const bson_t *command,
- const mongoc_read_prefs_t *read_prefs,
- const bson_t *opts,
- bson_t *reply,
- bson_error_t *error)
-{
- BSON_ASSERT_PARAM (collection);
-
- /* Server Selection Spec: "The generic command method has a default read
- * preference of mode 'primary'. The generic command method MUST ignore any
- * default read preference from client, database or collection
- * configuration. The generic command method SHOULD allow an optional read
- * preference argument." */
-
- return _mongoc_client_command_with_opts (collection->client,
- collection->db,
- command,
- MONGOC_CMD_RAW,
- opts,
- MONGOC_QUERY_NONE,
- read_prefs,
- NULL /* default prefs */,
- collection->read_concern,
- collection->write_concern,
- reply,
- error);
-}
-
-
-bool
-mongoc_collection_command_simple (mongoc_collection_t *collection,
- const bson_t *command,
- const mongoc_read_prefs_t *read_prefs,
- bson_t *reply,
- bson_error_t *error)
-{
- BSON_ASSERT_PARAM (collection);
- BSON_ASSERT_PARAM (command);
-
- bson_clear (&collection->gle);
-
- /* Server Selection Spec: "The generic command method has a default read
- * preference of mode 'primary'. The generic command method MUST ignore any
- * default read preference from client, database or collection
- * configuration. The generic command method SHOULD allow an optional read
- * preference argument."
- */
-
- return _mongoc_client_command_with_opts (collection->client,
- collection->db,
- command,
- MONGOC_CMD_RAW,
- NULL /* opts */,
- MONGOC_QUERY_NONE,
- read_prefs,
- NULL /* default prefs */,
- NULL /* read concern */,
- NULL /* write concern */,
- reply,
- error);
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_collection_count --
- *
- * Count the number of documents matching @query.
- *
- * Parameters:
- * @flags: A mongoc_query_flags_t describing the query flags or 0.
- * @query: The query to perform or NULL for {}.
- * @skip: The $skip to perform within the query or 0.
- * @limit: The $limit to perform within the query or 0.
- * @read_prefs: desired read preferences or NULL.
- * @error: A location for an error or NULL.
- *
- * Returns:
- * -1 on failure; otherwise the number of matching documents.
- *
- * Side effects:
- * @error is set upon failure if non-NULL.
- *
- *--------------------------------------------------------------------------
- */
-
-int64_t
-mongoc_collection_count (mongoc_collection_t *collection, /* IN */
- mongoc_query_flags_t flags, /* IN */
- const bson_t *query, /* IN */
- int64_t skip, /* IN */
- int64_t limit, /* IN */
- const mongoc_read_prefs_t *read_prefs, /* IN */
- bson_error_t *error) /* OUT */
-{
- int64_t ret;
- bson_t opts = BSON_INITIALIZER;
-
- /* Complex types must be parts of `opts`, otherwise we can't
- * follow various specs that require validation etc */
- if (collection->read_concern->level != NULL) {
- const bson_t *read_concern_bson;
-
- read_concern_bson =
- _mongoc_read_concern_get_bson (collection->read_concern);
- BSON_APPEND_DOCUMENT (&opts, "readConcern", read_concern_bson);
- }
-
- /* Server Selection Spec: "may-use-secondary" commands SHOULD take a read
- * preference argument and otherwise MUST use the default read preference
- * from client, database or collection configuration. */
- BEGIN_IGNORE_DEPRECATIONS
- ret = mongoc_collection_count_with_opts (
- collection, flags, query, skip, limit, &opts, read_prefs, error);
- END_IGNORE_DEPRECATIONS
-
- bson_destroy (&opts);
- return ret;
-}
-
-
-int64_t
-mongoc_collection_count_with_opts (
- mongoc_collection_t *collection, /* IN */
- mongoc_query_flags_t flags, /* IN */
- const bson_t *query, /* IN */
- int64_t skip, /* IN */
- int64_t limit, /* IN */
- const bson_t *opts, /* IN */
- const mongoc_read_prefs_t *read_prefs, /* IN */
- bson_error_t *error) /* OUT */
-{
- bson_iter_t iter;
- int64_t ret = -1;
- bool success;
- bson_t reply;
- bson_t cmd = BSON_INITIALIZER;
- bson_t q;
-
- ENTRY;
-
- BSON_ASSERT_PARAM (collection);
-
- bson_append_utf8 (
- &cmd, "count", 5, collection->collection, collection->collectionlen);
- if (query) {
- bson_append_document (&cmd, "query", 5, query);
- } else {
- bson_init (&q);
- bson_append_document (&cmd, "query", 5, &q);
- bson_destroy (&q);
- }
- if (limit) {
- bson_append_int64 (&cmd, "limit", 5, limit);
- }
- if (skip) {
- bson_append_int64 (&cmd, "skip", 4, skip);
- }
-
- success = _mongoc_client_command_with_opts (collection->client,
- collection->db,
- &cmd,
- MONGOC_CMD_READ,
- opts,
- flags,
- read_prefs,
- collection->read_prefs,
- collection->read_concern,
- collection->write_concern,
- &reply,
- error);
-
- if (success) {
- if (bson_iter_init_find (&iter, &reply, "n")) {
- ret = bson_iter_as_int64 (&iter);
- }
- }
-
- bson_destroy (&reply);
- bson_destroy (&cmd);
-
- RETURN (ret);
-}
-
-/* --------------------------------------------------------------------------
- *
- * _make_aggregate_for_edc --
- *
- * Construct an aggregate pipeline with the following form:
- *
- *
- * { pipeline: [
- * { $collStats: { count: {} } },
- * { $group: { _id: 1, n: { $sum: $count } } },
- * ]
- * }
- *
- *--------------------------------------------------------------------------
- */
-static void
-_make_aggregate_for_edc (const mongoc_collection_t *coll, bson_t *out)
-{
- bson_t pipeline;
- bson_t coll_stats_stage;
- bson_t coll_stats_stage_doc;
- bson_t group_stage;
- bson_t group_stage_doc;
- bson_t sum;
- bson_t cursor_empty;
- bson_t empty;
-
- BSON_APPEND_UTF8 (out, "aggregate", coll->collection);
- BSON_APPEND_DOCUMENT_BEGIN (out, "cursor", &cursor_empty);
- bson_append_document_end (out, &cursor_empty);
- BSON_APPEND_ARRAY_BEGIN (out, "pipeline", &pipeline);
-
- BSON_APPEND_DOCUMENT_BEGIN (&pipeline, "0", &coll_stats_stage);
- BSON_APPEND_DOCUMENT_BEGIN (
- &coll_stats_stage, "$collStats", &coll_stats_stage_doc);
- BSON_APPEND_DOCUMENT_BEGIN (&coll_stats_stage_doc, "count", &empty);
- bson_append_document_end (&coll_stats_stage_doc, &empty);
- bson_append_document_end (&coll_stats_stage, &coll_stats_stage_doc);
- bson_append_document_end (&pipeline, &coll_stats_stage);
-
- BSON_APPEND_DOCUMENT_BEGIN (&pipeline, "1", &group_stage);
- BSON_APPEND_DOCUMENT_BEGIN (&group_stage, "$group", &group_stage_doc);
- BSON_APPEND_INT32 (&group_stage_doc, "_id", 1);
- BSON_APPEND_DOCUMENT_BEGIN (&group_stage_doc, "n", &sum);
- BSON_APPEND_UTF8 (&sum, "$sum", "$count");
- bson_append_document_end (&group_stage_doc, &sum);
- bson_append_document_end (&group_stage, &group_stage_doc);
- bson_append_document_end (&pipeline, &group_stage);
- bson_append_array_end (out, &pipeline);
-}
-
-int64_t
-mongoc_collection_estimated_document_count (
- mongoc_collection_t *coll,
- const bson_t *opts,
- const mongoc_read_prefs_t *read_prefs,
- bson_t *reply,
- bson_error_t *error)
-{
- bson_iter_t iter;
- int64_t count = -1;
- bool ret;
- bson_t reply_local;
- bson_t *reply_ptr;
- bson_t cmd = BSON_INITIALIZER;
- mongoc_server_stream_t *server_stream = NULL;
-
- ENTRY;
-
- BSON_ASSERT_PARAM (coll);
-
- server_stream = mongoc_cluster_stream_for_reads (
- &coll->client->cluster, read_prefs, NULL, reply, error);
-
- if (opts && bson_has_field (opts, "sessionId")) {
- bson_set_error (error,
- MONGOC_ERROR_COMMAND,
- MONGOC_ERROR_COMMAND_INVALID_ARG,
- "Collection count must not specify explicit session");
- GOTO (done);
- }
-
- reply_ptr = reply ? reply : &reply_local;
- if (server_stream->sd->max_wire_version < WIRE_VERSION_4_9) {
- /* On < 4.9, use actual count command for estimatedDocumentCount */
- BSON_APPEND_UTF8 (&cmd, "count", coll->collection);
- ret = _mongoc_client_command_with_opts (coll->client,
- coll->db,
- &cmd,
- MONGOC_CMD_READ,
- opts,
- MONGOC_QUERY_NONE,
- read_prefs,
- coll->read_prefs,
- coll->read_concern,
- coll->write_concern,
- reply_ptr,
- error);
- if (ret) {
- if (bson_iter_init_find (&iter, reply_ptr, "n")) {
- count = bson_iter_as_int64 (&iter);
- }
- }
- } else {
- /* On >= 4.9, use aggregate with collStats for estimatedDocumentCount */
- _make_aggregate_for_edc (coll, &cmd);
- ret = mongoc_collection_read_command_with_opts (
- coll, &cmd, read_prefs, opts, reply_ptr, error);
-
- if (!ret && error->code == MONGOC_ERROR_COLLECTION_DOES_NOT_EXIST) {
- /* Collection does not exist. From spec: return 0 but no err:
- * https://github.com/mongodb/specifications/blob/master/source/crud/crud.rst#estimateddocumentcount
- */
- if (reply) {
- bson_reinit (reply);
- }
- memset (error, 0, sizeof *error);
- count = 0;
- GOTO (done);
- }
- if (ret && bson_iter_init (&iter, reply_ptr)) {
- if (bson_iter_find_descendant (
- &iter, "cursor.firstBatch.0.n", &iter)) {
- count = bson_iter_as_int64 (&iter);
- }
- }
- }
-
-done:
- if (!reply) {
- bson_destroy (&reply_local);
- }
- bson_destroy (&cmd);
- mongoc_server_stream_cleanup (server_stream);
-
- RETURN (count);
-}
-
-
-/* --------------------------------------------------------------------------
- *
- * _make_aggregate_for_count --
- *
- * Construct an aggregate pipeline with the following form:
- * { pipeline: [
- * { $match: {...} },
- * { $group: { _id: 1, n: { sum: 1 } } },
- * { $skip: ... },
- * { $limit: ... }
- * ]
- * }
- *
- *--------------------------------------------------------------------------
- */
-static void
-_make_aggregate_for_count (const mongoc_collection_t *coll,
- const bson_t *filter,
- const bson_t *opts,
- bson_t *out)
-{
- bson_iter_t iter;
- bson_t pipeline;
- bson_t match_stage;
- bson_t group_stage;
- bson_t group_stage_doc;
- bson_t sum;
- bson_t empty;
- const char *keys[] = {"0", "1", "2", "3"};
- int key = 0;
-
- bson_init (out);
- bson_append_utf8 (
- out, "aggregate", 9, coll->collection, coll->collectionlen);
- bson_append_document_begin (out, "cursor", 6, &empty);
- bson_append_document_end (out, &empty);
- bson_append_array_begin (out, "pipeline", 8, &pipeline);
-
- bson_append_document_begin (&pipeline, keys[key++], 1, &match_stage);
- bson_append_document (&match_stage, "$match", 6, filter);
- bson_append_document_end (&pipeline, &match_stage);
- /* if @opts includes "skip", or "count", append $skip and $count stages to
- * the aggregate pipeline. */
- if (opts && bson_iter_init_find (&iter, opts, "skip")) {
- bson_t skip_stage;
- bson_append_document_begin (&pipeline, keys[key++], 1, &skip_stage);
- bson_append_value (&skip_stage, "$skip", 5, bson_iter_value (&iter));
- bson_append_document_end (&pipeline, &skip_stage);
- }
- if (opts && bson_iter_init_find (&iter, opts, "limit")) {
- bson_t limit_stage;
- bson_append_document_begin (&pipeline, keys[key++], 1, &limit_stage);
- bson_append_value (&limit_stage, "$limit", 6, bson_iter_value (&iter));
- bson_append_document_end (&pipeline, &limit_stage);
- }
- bson_append_document_begin (&pipeline, keys[key], 1, &group_stage);
- bson_append_document_begin (&group_stage, "$group", 6, &group_stage_doc);
- bson_append_int32 (&group_stage_doc, "_id", 3, 1);
- bson_append_document_begin (&group_stage_doc, "n", 1, &sum);
- bson_append_int32 (&sum, "$sum", 4, 1);
- bson_append_document_end (&group_stage_doc, &sum);
- bson_append_document_end (&group_stage, &group_stage_doc);
- bson_append_document_end (&pipeline, &group_stage);
- bson_append_array_end (out, &pipeline);
-}
-
-
-int64_t
-mongoc_collection_count_documents (mongoc_collection_t *coll,
- const bson_t *filter,
- const bson_t *opts,
- const mongoc_read_prefs_t *read_prefs,
- bson_t *reply,
- bson_error_t *error)
-{
- bson_t aggregate_cmd;
- bson_t aggregate_opts;
- bool ret;
- const bson_t *result;
- mongoc_cursor_t *cursor = NULL;
- int64_t count = -1;
- bson_t cmd_reply;
- bson_iter_t iter;
-
- ENTRY;
-
- BSON_ASSERT_PARAM (coll);
- BSON_ASSERT_PARAM (filter);
-
- _make_aggregate_for_count (coll, filter, opts, &aggregate_cmd);
- bson_init (&aggregate_opts);
- if (opts) {
- bson_copy_to_excluding_noinit (
- opts, &aggregate_opts, "skip", "limit", NULL);
- }
-
- ret = mongoc_collection_read_command_with_opts (
- coll, &aggregate_cmd, read_prefs, &aggregate_opts, &cmd_reply, error);
- bson_destroy (&aggregate_cmd);
- bson_destroy (&aggregate_opts);
- if (reply) {
- bson_copy_to (&cmd_reply, reply);
- }
-
- if (!ret) {
- bson_destroy (&cmd_reply);
- GOTO (done);
- }
-
- /* steals reply */
- cursor = mongoc_cursor_new_from_command_reply_with_opts (
- coll->client, &cmd_reply, NULL);
- BSON_ASSERT (mongoc_cursor_get_id (cursor) == 0);
- ret = mongoc_cursor_next (cursor, &result);
- if (!ret) {
- if (mongoc_cursor_error (cursor, error)) {
- GOTO (done);
- } else {
- count = 0;
- GOTO (done);
- }
- }
-
- if (bson_iter_init_find (&iter, result, "n") &&
- BSON_ITER_HOLDS_INT (&iter)) {
- count = bson_iter_as_int64 (&iter);
- }
-
-done:
- if (cursor) {
- mongoc_cursor_destroy (cursor);
- }
- RETURN (count);
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_collection_drop --
- *
- * Request the MongoDB server drop the collection.
- *
- * Returns:
- * true if successful; otherwise false and @error is set.
- *
- * Side effects:
- * @error is set upon failure.
- *
- *--------------------------------------------------------------------------
- */
-
-bool
-mongoc_collection_drop (mongoc_collection_t *collection, /* IN */
- bson_error_t *error) /* OUT */
-{
- return mongoc_collection_drop_with_opts (collection, NULL, error);
-}
-
-
-bool
-mongoc_collection_drop_with_opts (mongoc_collection_t *collection,
- const bson_t *opts,
- bson_error_t *error)
-{
- bool ret;
- bson_t cmd;
-
- BSON_ASSERT_PARAM (collection);
-
- bson_init (&cmd);
- bson_append_utf8 (
- &cmd, "drop", 4, collection->collection, collection->collectionlen);
-
- ret = _mongoc_client_command_with_opts (collection->client,
- collection->db,
- &cmd,
- MONGOC_CMD_WRITE,
- opts,
- MONGOC_QUERY_NONE,
- NULL, /* user prefs */
- collection->read_prefs,
- collection->read_concern,
- collection->write_concern,
- NULL, /* reply */
- error);
- bson_destroy (&cmd);
-
- return ret;
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_collection_drop_index --
- *
- * Request the MongoDB server drop the named index.
- *
- * Returns:
- * true if successful; otherwise false and @error is set.
- *
- * Side effects:
- * @error is setup upon failure if non-NULL.
- *
- *--------------------------------------------------------------------------
- */
-
-bool
-mongoc_collection_drop_index (mongoc_collection_t *collection, /* IN */
- const char *index_name, /* IN */
- bson_error_t *error) /* OUT */
-{
- return mongoc_collection_drop_index_with_opts (
- collection, index_name, NULL, error);
-}
-
-
-bool
-mongoc_collection_drop_index_with_opts (mongoc_collection_t *collection,
- const char *index_name,
- const bson_t *opts,
- bson_error_t *error)
-{
- bool ret;
- bson_t cmd;
-
- BSON_ASSERT_PARAM (collection);
- BSON_ASSERT_PARAM (index_name);
-
- bson_init (&cmd);
- bson_append_utf8 (&cmd,
- "dropIndexes",
- -1,
- collection->collection,
- collection->collectionlen);
- bson_append_utf8 (&cmd, "index", -1, index_name, -1);
-
- ret = _mongoc_client_command_with_opts (collection->client,
- collection->db,
- &cmd,
- MONGOC_CMD_WRITE,
- opts,
- MONGOC_QUERY_NONE,
- NULL, /* user prefs */
- collection->read_prefs,
- collection->read_concern,
- collection->write_concern,
- NULL, /* reply */
- error);
- bson_destroy (&cmd);
-
- return ret;
-}
-
-
-char *
-mongoc_collection_keys_to_index_string (const bson_t *keys)
-{
- bson_string_t *s;
- bson_iter_t iter;
- bson_type_t type;
- int i = 0;
-
- BSON_ASSERT_PARAM (keys);
-
- if (!bson_iter_init (&iter, keys)) {
- return NULL;
- }
-
- s = bson_string_new (NULL);
-
- while (bson_iter_next (&iter)) {
- /* Index type can be specified as a string ("2d") or as an integer
- * representing direction */
- type = bson_iter_type (&iter);
- if (type == BSON_TYPE_UTF8) {
- bson_string_append_printf (s,
- (i++ ? "_%s_%s" : "%s_%s"),
- bson_iter_key (&iter),
- bson_iter_utf8 (&iter, NULL));
- } else if (type == BSON_TYPE_INT32) {
- bson_string_append_printf (s,
- (i++ ? "_%s_%d" : "%s_%d"),
- bson_iter_key (&iter),
- bson_iter_int32 (&iter));
- } else if (type == BSON_TYPE_INT64) {
- bson_string_append_printf (s,
- (i++ ? "_%s_%" PRId64 : "%s_%" PRId64),
- bson_iter_key (&iter),
- bson_iter_int64 (&iter));
- } else {
- bson_string_free (s, true);
- return NULL;
- }
- }
- return bson_string_free (s, false);
-}
-
-
-bool
-mongoc_collection_create_index (mongoc_collection_t *collection,
- const bson_t *keys,
- const mongoc_index_opt_t *opt,
- bson_error_t *error)
-{
- bson_t reply;
- bool ret;
-
- BEGIN_IGNORE_DEPRECATIONS
-
- ret = mongoc_collection_create_index_with_opts (
- collection, keys, opt, NULL, &reply, error);
-
- END_IGNORE_DEPRECATIONS
-
- bson_destroy (&reply);
- return ret;
-}
-
-static bool
-_mongoc_collection_index_keys_equal (const bson_t *expected,
- const bson_t *actual)
-{
- bson_iter_t iter_expected;
- bson_iter_t iter_actual;
-
- bson_iter_init (&iter_expected, expected);
- bson_iter_init (&iter_actual, actual);
-
- while (bson_iter_next (&iter_expected)) {
- /* If the key document has fewer items than expected, indexes are unequal
- */
- if (!bson_iter_next (&iter_actual)) {
- return false;
- }
-
- /* If key order does not match, indexes are unequal */
- if (strcmp (bson_iter_key (&iter_expected),
- bson_iter_key (&iter_actual)) != 0) {
- return false;
- }
-
- if (BSON_ITER_HOLDS_NUMBER (&iter_expected) &&
- BSON_ITER_HOLDS_NUMBER (&iter_actual)) {
- if (bson_iter_as_int64 (&iter_expected) !=
- bson_iter_as_int64 (&iter_actual)) {
- return false;
- }
- } else if (BSON_ITER_HOLDS_UTF8 (&iter_expected) &&
- BSON_ITER_HOLDS_UTF8 (&iter_actual)) {
- if (strcmp (bson_iter_utf8 (&iter_expected, NULL),
- bson_iter_utf8 (&iter_actual, NULL)) != 0) {
- return false;
- }
- } else {
- return false;
- }
- }
-
- /* If our expected document is exhausted, make sure there are no extra keys
- * in the actual key document */
- if (bson_iter_next (&iter_actual)) {
- return false;
- }
-
- return true;
-}
-
-bool
-_mongoc_collection_create_index_if_not_exists (mongoc_collection_t *collection,
- const bson_t *keys,
- const bson_t *opts,
- bson_error_t *error)
-{
- mongoc_cursor_t *cursor;
- bool index_exists;
- bool r = false;
- const bson_t *doc;
- bson_iter_t iter;
- bson_t inner_doc;
- uint32_t data_len;
- const uint8_t *data;
- bson_t index;
- bson_t command;
-
- BSON_ASSERT (collection);
- BSON_ASSERT (keys);
-
- cursor = mongoc_collection_find_indexes_with_opts (collection, NULL);
-
- index_exists = false;
-
- while (mongoc_cursor_next (cursor, &doc) && !index_exists) {
- r = bson_iter_init_find (&iter, doc, "key");
- if (!r) {
- continue;
- }
-
- bson_iter_document (&iter, &data_len, &data);
- bson_init_static (&inner_doc, data, data_len);
-
- if (_mongoc_collection_index_keys_equal (keys, &inner_doc)) {
- index_exists = true;
- }
-
- bson_destroy (&inner_doc);
- }
-
- if (mongoc_cursor_error (cursor, error)) {
- mongoc_cursor_destroy (cursor);
- return false;
- }
-
- mongoc_cursor_destroy (cursor);
-
- if (index_exists) {
- return true;
- }
-
- if (opts) {
- bson_copy_to (opts, &index);
- } else {
- bson_init (&index);
- }
-
- BSON_APPEND_DOCUMENT (&index, "key", keys);
-
- if (!bson_has_field (&index, "name")) {
- char *alloc_name = mongoc_collection_keys_to_index_string (keys);
-
- if (!alloc_name) {
- bson_set_error (
- error,
- MONGOC_ERROR_BSON,
- MONGOC_ERROR_BSON_INVALID,
- "Cannot generate index name from invalid `keys` argument");
- GOTO (done);
- }
-
- BSON_APPEND_UTF8 (&index, "name", alloc_name);
-
- bson_free (alloc_name);
- }
-
- bson_init (&command);
- BCON_APPEND (&command,
- "createIndexes",
- BCON_UTF8 (mongoc_collection_get_name (collection)),
- "indexes",
- "[",
- BCON_DOCUMENT (&index),
- "]");
-
- r = mongoc_collection_write_command_with_opts (
- collection, &command, NULL, NULL, error);
-
-done:
- bson_destroy (&index);
- bson_destroy (&command);
-
- return r;
-}
-
-bool
-mongoc_collection_create_index_with_opts (mongoc_collection_t *collection,
- const bson_t *keys,
- const mongoc_index_opt_t *opt,
- const bson_t *opts,
- bson_t *reply,
- bson_error_t *error)
-{
- mongoc_create_index_opts_t parsed;
- mongoc_cmd_parts_t parts;
- const mongoc_index_opt_t *def_opt;
- const mongoc_index_opt_geo_t *def_geo;
- const char *name;
- bson_t cmd = BSON_INITIALIZER;
- bson_t ar;
- bson_t doc;
- bson_t storage_doc;
- bson_t wt_doc;
- const mongoc_index_opt_geo_t *geo_opt;
- const mongoc_index_opt_storage_t *storage_opt;
- const mongoc_index_opt_wt_t *wt_opt;
- char *alloc_name = NULL;
- bool ret = false;
- bool reply_initialized = false;
- bool has_collation = false;
- mongoc_server_stream_t *server_stream = NULL;
- mongoc_cluster_t *cluster;
-
- ENTRY;
-
- BSON_ASSERT_PARAM (collection);
- BSON_ASSERT_PARAM (keys);
-
- def_opt = mongoc_index_opt_get_default ();
- opt = opt ? opt : def_opt;
-
- mongoc_cmd_parts_init (
- &parts, collection->client, collection->db, MONGOC_QUERY_NONE, &cmd);
- parts.is_write_command = true;
-
- if (!_mongoc_create_index_opts_parse (
- collection->client, opts, &parsed, error)) {
- GOTO (done);
- }
-
- if (!parsed.writeConcern) {
- parsed.writeConcern = collection->write_concern;
- parsed.write_concern_owned = false;
- }
-
- /*
- * Generate the key name if it was not provided.
- */
- name = (opt->name != def_opt->name) ? opt->name : NULL;
- if (!name) {
- alloc_name = mongoc_collection_keys_to_index_string (keys);
- if (alloc_name) {
- name = alloc_name;
- } else {
- bson_set_error (
- error,
- MONGOC_ERROR_BSON,
- MONGOC_ERROR_BSON_INVALID,
- "Cannot generate index name from invalid `keys` argument");
- GOTO (done);
- }
- }
-
- /*
- * Build our createIndexes command to send to the server.
- */
- BSON_ASSERT (
- BSON_APPEND_UTF8 (&cmd, "createIndexes", collection->collection));
- bson_append_array_begin (&cmd, "indexes", 7, &ar);
- bson_append_document_begin (&ar, "0", 1, &doc);
- BSON_ASSERT (BSON_APPEND_DOCUMENT (&doc, "key", keys));
- BSON_ASSERT (BSON_APPEND_UTF8 (&doc, "name", name));
- if (opt->background) {
- BSON_ASSERT (BSON_APPEND_BOOL (&doc, "background", true));
- }
- if (opt->unique) {
- BSON_ASSERT (BSON_APPEND_BOOL (&doc, "unique", true));
- }
- if (opt->drop_dups) {
- BSON_ASSERT (BSON_APPEND_BOOL (&doc, "dropDups", true));
- }
- if (opt->sparse) {
- BSON_ASSERT (BSON_APPEND_BOOL (&doc, "sparse", true));
- }
- if (opt->expire_after_seconds != def_opt->expire_after_seconds) {
- BSON_ASSERT (BSON_APPEND_INT32 (
- &doc, "expireAfterSeconds", opt->expire_after_seconds));
- }
- if (opt->v != def_opt->v) {
- BSON_ASSERT (BSON_APPEND_INT32 (&doc, "v", opt->v));
- }
- if (opt->weights && (opt->weights != def_opt->weights)) {
- BSON_ASSERT (BSON_APPEND_DOCUMENT (&doc, "weights", opt->weights));
- }
- if (opt->default_language != def_opt->default_language) {
- BSON_ASSERT (
- BSON_APPEND_UTF8 (&doc, "default_language", opt->default_language));
- }
- if (opt->language_override != def_opt->language_override) {
- BSON_ASSERT (
- BSON_APPEND_UTF8 (&doc, "language_override", opt->language_override));
- }
- if (opt->partial_filter_expression) {
- BSON_ASSERT (BSON_APPEND_DOCUMENT (
- &doc, "partialFilterExpression", opt->partial_filter_expression));
- }
- if (opt->collation) {
- BSON_ASSERT (BSON_APPEND_DOCUMENT (&doc, "collation", opt->collation));
- has_collation = true;
- }
- if (opt->geo_options) {
- geo_opt = opt->geo_options;
- def_geo = mongoc_index_opt_geo_get_default ();
- if (geo_opt->twod_sphere_version != def_geo->twod_sphere_version) {
- BSON_ASSERT (BSON_APPEND_INT32 (
- &doc, "2dsphereIndexVersion", geo_opt->twod_sphere_version));
- }
- if (geo_opt->twod_bits_precision != def_geo->twod_bits_precision) {
- BSON_ASSERT (
- BSON_APPEND_INT32 (&doc, "bits", geo_opt->twod_bits_precision));
- }
- if (geo_opt->twod_location_min != def_geo->twod_location_min) {
- BSON_ASSERT (
- BSON_APPEND_DOUBLE (&doc, "min", geo_opt->twod_location_min));
- }
- if (geo_opt->twod_location_max != def_geo->twod_location_max) {
- BSON_ASSERT (
- BSON_APPEND_DOUBLE (&doc, "max", geo_opt->twod_location_max));
- }
- if (geo_opt->haystack_bucket_size != def_geo->haystack_bucket_size) {
- BSON_ASSERT (BSON_APPEND_DOUBLE (
- &doc, "bucketSize", geo_opt->haystack_bucket_size));
- }
- }
-
- if (opt->storage_options) {
- storage_opt = opt->storage_options;
- switch (storage_opt->type) {
- case MONGOC_INDEX_STORAGE_OPT_WIREDTIGER:
- wt_opt = (mongoc_index_opt_wt_t *) storage_opt;
- BSON_APPEND_DOCUMENT_BEGIN (&doc, "storageEngine", &storage_doc);
- BSON_APPEND_DOCUMENT_BEGIN (&storage_doc, "wiredTiger", &wt_doc);
- BSON_ASSERT (
- BSON_APPEND_UTF8 (&wt_doc, "configString", wt_opt->config_str));
- bson_append_document_end (&storage_doc, &wt_doc);
- bson_append_document_end (&doc, &storage_doc);
- break;
- default:
- break;
- }
- }
-
- bson_append_document_end (&ar, &doc);
- bson_append_array_end (&cmd, &ar);
-
- server_stream = mongoc_cluster_stream_for_writes (
- &collection->client->cluster, parsed.client_session, reply, error);
-
- if (!server_stream) {
- reply_initialized = true;
- GOTO (done);
- }
-
- if (!mongoc_cmd_parts_set_write_concern (&parts,
- parsed.writeConcern,
- server_stream->sd->max_wire_version,
- error)) {
- GOTO (done);
- }
-
- if (has_collation &&
- server_stream->sd->max_wire_version < WIRE_VERSION_COLLATION) {
- bson_set_error (error,
- MONGOC_ERROR_COMMAND,
- MONGOC_ERROR_PROTOCOL_BAD_WIRE_VERSION,
- "The selected server does not support collation");
- GOTO (done);
- }
-
- parts.assembled.session = parsed.client_session;
- if (!bson_concat (&parts.extra, &parsed.extra)) {
- bson_set_error (error,
- MONGOC_ERROR_COMMAND,
- MONGOC_ERROR_COMMAND_INVALID_ARG,
- "'opts' is too large");
- GOTO (done);
- }
-
- cluster = &collection->client->cluster;
- if (mongoc_cmd_parts_assemble (&parts, server_stream, error)) {
- ret = mongoc_cluster_run_command_monitored (
- cluster, &parts.assembled, reply, error);
- } else {
- _mongoc_bson_init_if_set (reply);
- }
-
- reply_initialized = true;
-
- if (ret) {
- if (reply) {
- ret = !_mongoc_parse_wc_err (reply, error);
- }
- }
-
-done:
- bson_destroy (&cmd);
- bson_free (alloc_name);
- _mongoc_create_index_opts_cleanup (&parsed);
- mongoc_server_stream_cleanup (server_stream);
- mongoc_cmd_parts_cleanup (&parts);
- if (!reply_initialized && reply) {
- bson_init (reply);
- }
-
- RETURN (ret);
-}
-
-
-bool
-mongoc_collection_ensure_index (mongoc_collection_t *collection,
- const bson_t *keys,
- const mongoc_index_opt_t *opt,
- bson_error_t *error)
-{
- BEGIN_IGNORE_DEPRECATIONS
- return mongoc_collection_create_index (collection, keys, opt, error);
- END_IGNORE_DEPRECATIONS
-}
-
-
-mongoc_cursor_t *
-mongoc_collection_find_indexes (mongoc_collection_t *collection,
- bson_error_t *error)
-{
- mongoc_cursor_t *cursor;
-
- cursor = mongoc_collection_find_indexes_with_opts (collection, NULL);
-
- (void) mongoc_cursor_error (cursor, error);
-
- return cursor;
-}
-
-
-mongoc_cursor_t *
-mongoc_collection_find_indexes_with_opts (mongoc_collection_t *collection,
- const bson_t *opts)
-{
- mongoc_cursor_t *cursor;
- bson_t cmd = BSON_INITIALIZER;
- bson_t child;
- bson_error_t error;
-
- BSON_ASSERT_PARAM (collection);
-
- bson_append_utf8 (&cmd,
- "listIndexes",
- -1,
- collection->collection,
- collection->collectionlen);
-
- BSON_APPEND_DOCUMENT_BEGIN (&cmd, "cursor", &child);
- bson_append_document_end (&cmd, &child);
-
- /* No read preference. Index Enumeration Spec: "run listIndexes on the
- * primary node in replicaSet mode". */
- cursor = _mongoc_cursor_cmd_new (
- collection->client, collection->ns, &cmd, opts, NULL, NULL, NULL);
-
- if (!mongoc_cursor_error (cursor, &error)) {
- _mongoc_cursor_prime (cursor);
- }
-
- if (mongoc_cursor_error (cursor, &error) &&
- error.code == MONGOC_ERROR_COLLECTION_DOES_NOT_EXIST) {
- /* collection does not exist. from spec: return no documents but no err:
- * https://github.com/mongodb/specifications/blob/master/source/enumerate-indexes.rst#enumeration-getting-index-information
- */
- _mongoc_cursor_set_empty (cursor);
- }
-
- bson_destroy (&cmd);
-
- return cursor;
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_collection_insert_bulk --
- *
- * Bulk insert documents into a MongoDB collection.
- *
- * Parameters:
- * @collection: A mongoc_collection_t.
- * @flags: flags for the insert or 0.
- * @documents: The documents to insert.
- * @n_documents: The number of documents to insert.
- * @write_concern: A write concern or NULL.
- * @error: a location for an error or NULL.
- *
- * Returns:
- * true if successful; otherwise false and @error is set.
- *
- * If the write concern does not dictate checking the result of the
- * insert, then true may be returned even though the document was
- * not actually inserted on the MongoDB server or cluster.
- *
- * Side effects:
- * @collection->gle is setup, depending on write_concern->w value.
- * @error may be set upon failure if non-NULL.
- *
- *--------------------------------------------------------------------------
- */
-
-bool
-mongoc_collection_insert_bulk (mongoc_collection_t *collection,
- mongoc_insert_flags_t flags,
- const bson_t **documents,
- uint32_t n_documents,
- const mongoc_write_concern_t *write_concern,
- bson_error_t *error)
-{
- mongoc_write_command_t command;
- mongoc_write_result_t result;
- mongoc_bulk_write_flags_t write_flags = MONGOC_BULK_WRITE_FLAGS_INIT;
- uint32_t i;
- bool ret;
-
- BSON_ASSERT_PARAM (collection);
- BSON_ASSERT_PARAM (documents);
-
- if (!write_concern) {
- write_concern = collection->write_concern;
- }
-
- if (!(flags & MONGOC_INSERT_NO_VALIDATE)) {
- for (i = 0; i < n_documents; i++) {
- if (!_mongoc_validate_new_document (
- documents[i], _mongoc_default_insert_vflags, error)) {
- RETURN (false);
- }
- }
- }
-
- bson_clear (&collection->gle);
-
- _mongoc_write_result_init (&result);
-
- write_flags.ordered = !(flags & MONGOC_INSERT_CONTINUE_ON_ERROR);
-
- _mongoc_write_command_init_insert (
- &command,
- NULL,
- NULL,
- write_flags,
- ++collection->client->cluster.operation_id);
-
- for (i = 0; i < n_documents; i++) {
- _mongoc_write_command_insert_append (&command, documents[i]);
- }
-
- _mongoc_collection_write_command_execute (
- &command, collection, write_concern, NULL, &result);
-
- collection->gle = bson_new ();
- ret = MONGOC_WRITE_RESULT_COMPLETE (&result,
- collection->client->error_api_version,
- write_concern,
- /* no error domain override */
- (mongoc_error_domain_t) 0,
- collection->gle,
- error);
-
- _mongoc_write_result_destroy (&result);
- _mongoc_write_command_destroy (&command);
-
- return ret;
-}
-
-
-bool
-mongoc_collection_insert (mongoc_collection_t *collection,
- mongoc_insert_flags_t flags,
- const bson_t *document,
- const mongoc_write_concern_t *write_concern,
- bson_error_t *error)
-{
- bson_t opts = BSON_INITIALIZER;
- bson_t reply;
- bool r;
-
- bson_clear (&collection->gle);
-
- if (flags & MONGOC_INSERT_NO_VALIDATE) {
- bson_append_bool (&opts, "validate", 8, false);
- }
-
- if (write_concern) {
- mongoc_write_concern_append ((mongoc_write_concern_t *) write_concern,
- &opts);
- }
-
- r =
- mongoc_collection_insert_one (collection, document, &opts, &reply, error);
-
- collection->gle = bson_copy (&reply);
- bson_destroy (&reply);
- bson_destroy (&opts);
-
- return r;
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_collection_insert_one --
- *
- * Insert a document into a MongoDB collection.
- *
- * Parameters:
- * @collection: A mongoc_collection_t.
- * @document: The document to insert.
- * @opts: Standard command options.
- * @reply: Optional. Uninitialized doc to receive the update result.
- * @error: A location for an error or NULL.
- *
- * Returns:
- * true if successful; otherwise false and @error is set.
- *
- * If the write concern does not dictate checking the result of the
- * insert, then true may be returned even though the document was
- * not actually inserted on the MongoDB server or cluster.
- *
- *--------------------------------------------------------------------------
- */
-
-bool
-mongoc_collection_insert_one (mongoc_collection_t *collection,
- const bson_t *document,
- const bson_t *opts,
- bson_t *reply,
- bson_error_t *error)
-{
- mongoc_insert_one_opts_t insert_one_opts;
- mongoc_write_command_t command;
- mongoc_write_result_t result;
- bool ret = false;
-
- ENTRY;
-
- BSON_ASSERT_PARAM (collection);
- BSON_ASSERT_PARAM (document);
-
- _mongoc_bson_init_if_set (reply);
-
- if (!_mongoc_insert_one_opts_parse (
- collection->client, opts, &insert_one_opts, error)) {
- GOTO (done);
- }
-
- if (!_mongoc_validate_new_document (
- document, insert_one_opts.crud.validate, error)) {
- GOTO (done);
- }
-
- _mongoc_write_result_init (&result);
- _mongoc_write_command_init_insert_idl (
- &command,
- document,
- &insert_one_opts.extra,
- ++collection->client->cluster.operation_id);
-
- command.flags.bypass_document_validation = insert_one_opts.bypass;
- _mongoc_collection_write_command_execute_idl (
- &command, collection, &insert_one_opts.crud, &result);
-
- ret = MONGOC_WRITE_RESULT_COMPLETE (&result,
- collection->client->error_api_version,
- insert_one_opts.crud.writeConcern,
- /* no error domain override */
- (mongoc_error_domain_t) 0,
- reply,
- error,
- "insertedCount");
-
- _mongoc_write_result_destroy (&result);
- _mongoc_write_command_destroy (&command);
-
-done:
- _mongoc_insert_one_opts_cleanup (&insert_one_opts);
- RETURN (ret);
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_collection_insert_many --
- *
- * Insert documents into a MongoDB collection. Replaces
- * mongoc_collection_insert_bulk.
- *
- * Parameters:
- * @collection: A mongoc_collection_t.
- * @documents: The documents to insert.
- * @n_documents: Length of @documents array.
- * @opts: Standard command options.
- * @reply: Optional. Uninitialized doc to receive the update result.
- * @error: A location for an error or NULL.
- *
- * Returns:
- * true if successful; otherwise false and @error is set.
- *
- * If the write concern does not dictate checking the result of the
- * insert, then true may be returned even though the document was
- * not actually inserted on the MongoDB server or cluster.
- *
- *--------------------------------------------------------------------------
- */
-
-bool
-mongoc_collection_insert_many (mongoc_collection_t *collection,
- const bson_t **documents,
- size_t n_documents,
- const bson_t *opts,
- bson_t *reply,
- bson_error_t *error)
-{
- mongoc_insert_many_opts_t insert_many_opts;
- mongoc_write_command_t command;
- mongoc_write_result_t result;
- size_t i;
- bool ret;
-
- ENTRY;
-
- BSON_ASSERT_PARAM (collection);
- BSON_ASSERT_PARAM (documents);
-
- _mongoc_bson_init_if_set (reply);
-
- if (!_mongoc_insert_many_opts_parse (
- collection->client, opts, &insert_many_opts, error)) {
- _mongoc_insert_many_opts_cleanup (&insert_many_opts);
- return false;
- }
-
- _mongoc_write_result_init (&result);
- _mongoc_write_command_init_insert_idl (
- &command,
- NULL,
- &insert_many_opts.extra,
- ++collection->client->cluster.operation_id);
-
- command.flags.ordered = insert_many_opts.ordered;
- command.flags.bypass_document_validation = insert_many_opts.bypass;
-
- for (i = 0; i < n_documents; i++) {
- if (!_mongoc_validate_new_document (
- documents[i], insert_many_opts.crud.validate, error)) {
- ret = false;
- GOTO (done);
- }
-
- _mongoc_write_command_insert_append (&command, documents[i]);
- }
-
- _mongoc_collection_write_command_execute_idl (
- &command, collection, &insert_many_opts.crud, &result);
-
- ret = MONGOC_WRITE_RESULT_COMPLETE (&result,
- collection->client->error_api_version,
- insert_many_opts.crud.writeConcern,
- /* no error domain override */
- (mongoc_error_domain_t) 0,
- reply,
- error,
- "insertedCount");
-
-done:
- _mongoc_write_result_destroy (&result);
- _mongoc_write_command_destroy (&command);
- _mongoc_insert_many_opts_cleanup (&insert_many_opts);
-
- RETURN (ret);
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_collection_update --
- *
- * Updates one or more documents matching @selector with @update.
- *
- * Parameters:
- * @collection: A mongoc_collection_t.
- * @flags: The flags for the update.
- * @selector: A bson_t containing your selector.
- * @update: A bson_t containing your update document.
- * @write_concern: The write concern or NULL.
- * @error: A location for an error or NULL.
- *
- * Returns:
- * true if successful; otherwise false and @error is set.
- *
- * Side effects:
- * @collection->gle is setup, depending on write_concern->w value.
- * @error is setup upon failure.
- *
- *--------------------------------------------------------------------------
- */
-
-bool
-mongoc_collection_update (mongoc_collection_t *collection,
- mongoc_update_flags_t uflags,
- const bson_t *selector,
- const bson_t *update,
- const mongoc_write_concern_t *write_concern,
- bson_error_t *error)
-{
- mongoc_bulk_write_flags_t write_flags = MONGOC_BULK_WRITE_FLAGS_INIT;
- mongoc_write_command_t command;
- mongoc_write_result_t result;
- bson_iter_t iter;
- bool ret;
- int flags = uflags;
- bson_t opts;
-
- ENTRY;
-
- BSON_ASSERT_PARAM (collection);
- BSON_ASSERT_PARAM (selector);
- BSON_ASSERT_PARAM (update);
-
- bson_clear (&collection->gle);
-
- if (!write_concern) {
- write_concern = collection->write_concern;
- }
-
- if (!((uint32_t) flags & MONGOC_UPDATE_NO_VALIDATE) &&
- bson_iter_init (&iter, update) && bson_iter_next (&iter)) {
- if (bson_iter_key (&iter)[0] == '$') {
- /* update document, all keys must be $-operators */
- if (!_mongoc_validate_update (
- update, _mongoc_default_update_vflags, error)) {
- return false;
- }
- } else {
- if (!_mongoc_validate_replace (
- update, _mongoc_default_replace_vflags, error)) {
- return false;
- }
- }
- }
-
- bson_init (&opts);
- BSON_APPEND_BOOL (&opts, "upsert", !!(flags & MONGOC_UPDATE_UPSERT));
- BSON_APPEND_BOOL (&opts, "multi", !!(flags & MONGOC_UPDATE_MULTI_UPDATE));
-
- _mongoc_write_result_init (&result);
- _mongoc_write_command_init_update (
- &command,
- selector,
- update,
- &opts,
- write_flags,
- ++collection->client->cluster.operation_id);
- bson_destroy (&opts);
-
- command.flags.has_multi_write = !!(flags & MONGOC_UPDATE_MULTI_UPDATE);
-
- _mongoc_collection_write_command_execute (
- &command, collection, write_concern, NULL, &result);
-
- collection->gle = bson_new ();
- ret = MONGOC_WRITE_RESULT_COMPLETE (&result,
- collection->client->error_api_version,
- write_concern,
- /* no error domain override */
- (mongoc_error_domain_t) 0,
- collection->gle,
- error);
-
- _mongoc_write_result_destroy (&result);
- _mongoc_write_command_destroy (&command);
-
- RETURN (ret);
-}
-
-static bool
-_mongoc_collection_update_or_replace (mongoc_collection_t *collection,
- const bson_t *selector,
- const bson_t *update,
- mongoc_update_opts_t *update_opts,
- bool multi,
- bool bypass,
- const bson_t *array_filters,
- bson_t *extra,
- bson_t *reply,
- bson_error_t *error)
-{
- mongoc_write_command_t command;
- mongoc_write_result_t result;
- mongoc_server_stream_t *server_stream = NULL;
- bool reply_initialized = false;
- bool ret = false;
-
- ENTRY;
-
- BSON_ASSERT_PARAM (collection);
- BSON_ASSERT_PARAM (selector);
- BSON_ASSERT_PARAM (update);
-
- if (update_opts->upsert) {
- bson_append_bool (extra, "upsert", 6, true);
- }
-
- if (!bson_empty (&update_opts->collation)) {
- bson_append_document (extra, "collation", 9, &update_opts->collation);
- }
-
- if (update_opts->hint.value_type) {
- bson_append_value (extra, "hint", 4, &update_opts->hint);
- }
-
- if (!bson_empty0 (array_filters)) {
- bson_append_array (extra, "arrayFilters", 12, array_filters);
- }
-
- if (multi) {
- bson_append_bool (extra, "multi", 5, true);
- }
-
- _mongoc_write_result_init (&result);
- _mongoc_write_command_init_update_idl (
- &command,
- selector,
- update,
- extra,
- ++collection->client->cluster.operation_id);
-
- command.flags.has_multi_write = multi;
- command.flags.bypass_document_validation = bypass;
- if (!bson_empty (&update_opts->collation)) {
- command.flags.has_collation = true;
- }
- if (update_opts->hint.value_type) {
- command.flags.has_update_hint = true;
- }
-
- server_stream =
- mongoc_cluster_stream_for_writes (&collection->client->cluster,
- update_opts->crud.client_session,
- reply,
- error);
-
- if (!server_stream) {
- /* mongoc_cluster_stream_for_writes inits reply on error */
- reply_initialized = true;
- GOTO (done);
- }
-
- if (!bson_empty0 (array_filters)) {
- if (server_stream->sd->max_wire_version < WIRE_VERSION_ARRAY_FILTERS) {
- bson_set_error (error,
- MONGOC_ERROR_COMMAND,
- MONGOC_ERROR_PROTOCOL_BAD_WIRE_VERSION,
- "The selected server does not support array filters");
- GOTO (done);
- }
-
- if (!mongoc_write_concern_is_acknowledged (
- update_opts->crud.writeConcern)) {
- bson_set_error (error,
- MONGOC_ERROR_COMMAND,
- MONGOC_ERROR_PROTOCOL_BAD_WIRE_VERSION,
- "Cannot use array filters with unacknowledged writes");
- GOTO (done);
- }
- }
-
- if (_mongoc_client_session_in_txn (update_opts->crud.client_session) &&
- update_opts->crud.writeConcern) {
- bson_set_error (error,
- MONGOC_ERROR_COMMAND,
- MONGOC_ERROR_COMMAND_INVALID_ARG,
- "Cannot set write concern after starting transaction");
- GOTO (done);
- }
-
- if (!update_opts->crud.writeConcern &&
- !_mongoc_client_session_in_txn (update_opts->crud.client_session)) {
- update_opts->crud.writeConcern = collection->write_concern;
- update_opts->crud.write_concern_owned = false;
- }
-
- _mongoc_write_command_execute_idl (&command,
- collection->client,
- server_stream,
- collection->db,
- collection->collection,
- 0 /* offset */,
- &update_opts->crud,
- &result);
-
- _mongoc_bson_init_if_set (reply);
- reply_initialized = true;
-
- /* set fields described in CRUD spec for the UpdateResult */
- ret = MONGOC_WRITE_RESULT_COMPLETE (&result,
- collection->client->error_api_version,
- update_opts->crud.writeConcern,
- /* no error domain override */
- (mongoc_error_domain_t) 0,
- reply,
- error,
- "modifiedCount",
- "matchedCount",
- "upsertedCount",
- "upsertedId");
-
-done:
- _mongoc_write_result_destroy (&result);
- mongoc_server_stream_cleanup (server_stream);
- _mongoc_write_command_destroy (&command);
-
- if (!reply_initialized) {
- _mongoc_bson_init_if_set (reply);
- }
-
- RETURN (ret);
-}
-
-bool
-mongoc_collection_update_one (mongoc_collection_t *collection,
- const bson_t *selector,
- const bson_t *update,
- const bson_t *opts,
- bson_t *reply,
- bson_error_t *error)
-{
- mongoc_update_one_opts_t update_one_opts;
- bool ret;
-
- ENTRY;
-
- BSON_ASSERT_PARAM (collection);
- BSON_ASSERT_PARAM (update);
-
- if (!_mongoc_update_one_opts_parse (
- collection->client, opts, &update_one_opts, error)) {
- _mongoc_update_one_opts_cleanup (&update_one_opts);
- _mongoc_bson_init_if_set (reply);
- return false;
- }
-
- if (!_mongoc_validate_update (
- update, update_one_opts.update.crud.validate, error)) {
- _mongoc_update_one_opts_cleanup (&update_one_opts);
- _mongoc_bson_init_if_set (reply);
- return false;
- }
-
- ret = _mongoc_collection_update_or_replace (collection,
- selector,
- update,
- &update_one_opts.update,
- false /* multi */,
- update_one_opts.update.bypass,
- &update_one_opts.arrayFilters,
- &update_one_opts.extra,
- reply,
- error);
-
- _mongoc_update_one_opts_cleanup (&update_one_opts);
-
- RETURN (ret);
-}
-
-bool
-mongoc_collection_update_many (mongoc_collection_t *collection,
- const bson_t *selector,
- const bson_t *update,
- const bson_t *opts,
- bson_t *reply,
- bson_error_t *error)
-{
- mongoc_update_many_opts_t update_many_opts;
- bool ret;
-
- ENTRY;
-
- BSON_ASSERT_PARAM (collection);
- BSON_ASSERT_PARAM (update);
-
- if (!_mongoc_update_many_opts_parse (
- collection->client, opts, &update_many_opts, error)) {
- _mongoc_update_many_opts_cleanup (&update_many_opts);
- _mongoc_bson_init_if_set (reply);
- return false;
- }
-
- if (!_mongoc_validate_update (
- update, update_many_opts.update.crud.validate, error)) {
- _mongoc_update_many_opts_cleanup (&update_many_opts);
- _mongoc_bson_init_if_set (reply);
- return false;
- }
-
- ret = _mongoc_collection_update_or_replace (collection,
- selector,
- update,
- &update_many_opts.update,
- true /* multi */,
- update_many_opts.update.bypass,
- &update_many_opts.arrayFilters,
- &update_many_opts.extra,
- reply,
- error);
-
- _mongoc_update_many_opts_cleanup (&update_many_opts);
-
- RETURN (ret);
-}
-
-bool
-mongoc_collection_replace_one (mongoc_collection_t *collection,
- const bson_t *selector,
- const bson_t *replacement,
- const bson_t *opts,
- bson_t *reply,
- bson_error_t *error)
-{
- mongoc_replace_one_opts_t replace_one_opts;
- bool ret;
-
- ENTRY;
-
- BSON_ASSERT_PARAM (collection);
- BSON_ASSERT_PARAM (replacement);
-
- if (!_mongoc_replace_one_opts_parse (
- collection->client, opts, &replace_one_opts, error)) {
- _mongoc_replace_one_opts_cleanup (&replace_one_opts);
- _mongoc_bson_init_if_set (reply);
- return false;
- }
-
- if (!_mongoc_validate_replace (
- replacement, replace_one_opts.update.crud.validate, error)) {
- _mongoc_replace_one_opts_cleanup (&replace_one_opts);
- _mongoc_bson_init_if_set (reply);
- return false;
- }
-
- ret = _mongoc_collection_update_or_replace (collection,
- selector,
- replacement,
- &replace_one_opts.update,
- false /* multi */,
- replace_one_opts.update.bypass,
- NULL,
- &replace_one_opts.extra,
- reply,
- error);
-
- _mongoc_replace_one_opts_cleanup (&replace_one_opts);
-
- RETURN (ret);
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_collection_save --
- *
- * Save @document to @collection.
- *
- * If the document has an _id field, it will be updated. Otherwise,
- * the document will be inserted into the collection.
- *
- * Returns:
- * true if successful; otherwise false and @error is set.
- *
- * Side effects:
- * @error is set upon failure if non-NULL.
- *
- *--------------------------------------------------------------------------
- */
-
-bool
-mongoc_collection_save (mongoc_collection_t *collection,
- const bson_t *document,
- const mongoc_write_concern_t *write_concern,
- bson_error_t *error)
-{
- bson_iter_t iter;
- bool ret;
- bson_t selector;
-
- BSON_ASSERT_PARAM (collection);
- BSON_ASSERT_PARAM (document);
-
- BEGIN_IGNORE_DEPRECATIONS
- if (!bson_iter_init_find (&iter, document, "_id")) {
- return mongoc_collection_insert (
- collection, MONGOC_INSERT_NONE, document, write_concern, error);
- }
-
- bson_init (&selector);
- if (!bson_append_iter (&selector, NULL, 0, &iter)) {
- bson_set_error (error,
- MONGOC_ERROR_COMMAND,
- MONGOC_ERROR_COMMAND_INVALID_ARG,
- "Failed to append bson to create update.");
- bson_destroy (&selector);
- return false;
- }
-
- /* this document will be inserted, validate same as for inserts */
- if (!_mongoc_validate_new_document (
- document, _mongoc_default_insert_vflags, error)) {
- return false;
- }
-
- ret = mongoc_collection_update (collection,
- MONGOC_UPDATE_UPSERT |
- MONGOC_UPDATE_NO_VALIDATE,
- &selector,
- document,
- write_concern,
- error);
- END_IGNORE_DEPRECATIONS
-
- bson_destroy (&selector);
-
- return ret;
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_collection_remove --
- *
- * Delete one or more items from a collection. If you want to
- * limit to a single delete, provided MONGOC_REMOVE_SINGLE_REMOVE
- * for @flags.
- *
- * Superseded by mongoc_collection_delete_one/many.
- *
- * Parameters:
- * @collection: A mongoc_collection_t.
- * @flags: the delete flags or 0.
- * @selector: A selector of documents to delete.
- * @write_concern: A write concern or NULL. If NULL, the default
- * write concern for the collection will be used.
- * @error: A location for an error or NULL.
- *
- * Returns:
- * true if successful; otherwise false and error is set.
- *
- * If the write concern does not dictate checking the result, this
- * function may return true even if it failed.
- *
- * Side effects:
- * @collection->gle is setup, depending on write_concern->w value.
- * @error is setup upon failure.
- *
- *--------------------------------------------------------------------------
- */
-
-bool
-mongoc_collection_remove (mongoc_collection_t *collection,
- mongoc_remove_flags_t flags,
- const bson_t *selector,
- const mongoc_write_concern_t *write_concern,
- bson_error_t *error)
-{
- mongoc_bulk_write_flags_t write_flags = MONGOC_BULK_WRITE_FLAGS_INIT;
- mongoc_write_command_t command;
- mongoc_write_result_t result;
- bson_t opts;
- bool ret;
-
- ENTRY;
-
- BSON_ASSERT_PARAM (collection);
- BSON_ASSERT_PARAM (selector);
-
- bson_clear (&collection->gle);
-
- if (!write_concern) {
- write_concern = collection->write_concern;
- }
-
- bson_init (&opts);
- BSON_APPEND_INT32 (
- &opts, "limit", flags & MONGOC_REMOVE_SINGLE_REMOVE ? 1 : 0);
- _mongoc_write_result_init (&result);
- ++collection->client->cluster.operation_id;
- _mongoc_write_command_init_delete (&command,
- selector,
- NULL,
- &opts,
- write_flags,
- collection->client->cluster.operation_id);
- bson_destroy (&opts);
-
- command.flags.has_multi_write = !(flags & MONGOC_REMOVE_SINGLE_REMOVE);
-
- _mongoc_collection_write_command_execute (
- &command, collection, write_concern, NULL, &result);
-
- collection->gle = bson_new ();
- ret = MONGOC_WRITE_RESULT_COMPLETE (&result,
- collection->client->error_api_version,
- write_concern,
- 0 /* no error domain override */,
- collection->gle,
- error);
-
- _mongoc_write_result_destroy (&result);
- _mongoc_write_command_destroy (&command);
-
- RETURN (ret);
-}
-
-
-bool
-mongoc_collection_delete (mongoc_collection_t *collection,
- mongoc_delete_flags_t flags,
- const bson_t *selector,
- const mongoc_write_concern_t *write_concern,
- bson_error_t *error)
-{
- return mongoc_collection_remove (collection,
- (mongoc_remove_flags_t) flags,
- selector,
- write_concern,
- error);
-}
-
-
-static bool
-_mongoc_delete_one_or_many (mongoc_collection_t *collection,
- bool multi,
- const bson_t *selector,
- mongoc_delete_opts_t *delete_opts,
- const bson_t *cmd_opts,
- bson_t *opts,
- bson_t *reply,
- bson_error_t *error)
-{
- mongoc_write_command_t command;
- mongoc_write_result_t result;
- bool ret;
-
- ENTRY;
-
- BSON_ASSERT_PARAM (collection);
- BSON_ASSERT_PARAM (selector);
- BSON_ASSERT (bson_empty0 (reply));
-
- _mongoc_write_result_init (&result);
- bson_append_int32 (opts, "limit", 5, multi ? 0 : 1);
-
- if (!bson_empty (&delete_opts->collation)) {
- bson_append_document (opts, "collation", 9, &delete_opts->collation);
- }
-
- if (delete_opts->hint.value_type) {
- bson_append_value (opts, "hint", 4, &delete_opts->hint);
- }
-
- _mongoc_write_command_init_delete_idl (
- &command,
- selector,
- cmd_opts,
- opts,
- ++collection->client->cluster.operation_id);
-
- command.flags.has_multi_write = multi;
- if (!bson_empty (&delete_opts->collation)) {
- command.flags.has_collation = true;
- }
- if (delete_opts->hint.value_type) {
- command.flags.has_delete_hint = true;
- }
-
- _mongoc_collection_write_command_execute_idl (
- &command, collection, &delete_opts->crud, &result);
-
- /* set field described in CRUD spec for the DeleteResult */
- ret = MONGOC_WRITE_RESULT_COMPLETE (&result,
- collection->client->error_api_version,
- delete_opts->crud.writeConcern,
- /* no error domain override */
- (mongoc_error_domain_t) 0,
- reply,
- error,
- "deletedCount");
-
- _mongoc_write_result_destroy (&result);
- _mongoc_write_command_destroy (&command);
-
- RETURN (ret);
-}
-
-
-bool
-mongoc_collection_delete_one (mongoc_collection_t *collection,
- const bson_t *selector,
- const bson_t *opts,
- bson_t *reply,
- bson_error_t *error)
-{
- mongoc_delete_one_opts_t delete_one_opts;
- bson_t limit = BSON_INITIALIZER;
- bool ret = false;
-
- ENTRY;
-
- BSON_ASSERT_PARAM (collection);
- BSON_ASSERT_PARAM (selector);
-
- _mongoc_bson_init_if_set (reply);
- if (!_mongoc_delete_one_opts_parse (
- collection->client, opts, &delete_one_opts, error)) {
- GOTO (done);
- }
-
- ret = _mongoc_delete_one_or_many (collection,
- false /* multi */,
- selector,
- &delete_one_opts.delete,
- &delete_one_opts.extra,
- &limit,
- reply,
- error);
-
-done:
- _mongoc_delete_one_opts_cleanup (&delete_one_opts);
- bson_destroy (&limit);
-
- RETURN (ret);
-}
-
-bool
-mongoc_collection_delete_many (mongoc_collection_t *collection,
- const bson_t *selector,
- const bson_t *opts,
- bson_t *reply,
- bson_error_t *error)
-{
- mongoc_delete_many_opts_t delete_many_opts;
- bson_t limit = BSON_INITIALIZER;
- bool ret = false;
-
- ENTRY;
-
- BSON_ASSERT_PARAM (collection);
- BSON_ASSERT_PARAM (selector);
-
- _mongoc_bson_init_if_set (reply);
- if (!_mongoc_delete_many_opts_parse (
- collection->client, opts, &delete_many_opts, error)) {
- GOTO (done);
- }
-
- ret = _mongoc_delete_one_or_many (collection,
- true /* multi */,
- selector,
- &delete_many_opts.delete,
- &delete_many_opts.extra,
- &limit,
- reply,
- error);
-
-done:
- _mongoc_delete_many_opts_cleanup (&delete_many_opts);
- bson_destroy (&limit);
-
- RETURN (ret);
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_collection_get_read_prefs --
- *
- * Fetch the default read preferences for the collection.
- *
- * Returns:
- * A mongoc_read_prefs_t that should not be modified or freed.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-const mongoc_read_prefs_t *
-mongoc_collection_get_read_prefs (const mongoc_collection_t *collection)
-{
- BSON_ASSERT_PARAM (collection);
- return collection->read_prefs;
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_collection_set_read_prefs --
- *
- * Sets the default read preferences for the collection instance.
- *
- * Returns:
- * None.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-void
-mongoc_collection_set_read_prefs (mongoc_collection_t *collection,
- const mongoc_read_prefs_t *read_prefs)
-{
- BSON_ASSERT_PARAM (collection);
-
- if (collection->read_prefs) {
- mongoc_read_prefs_destroy (collection->read_prefs);
- collection->read_prefs = NULL;
- }
-
- if (read_prefs) {
- collection->read_prefs = mongoc_read_prefs_copy (read_prefs);
- }
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_collection_get_read_concern --
- *
- * Fetches the default read concern for the collection instance.
- *
- * Returns:
- * A mongoc_read_concern_t that should not be modified or freed.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-const mongoc_read_concern_t *
-mongoc_collection_get_read_concern (const mongoc_collection_t *collection)
-{
- BSON_ASSERT_PARAM (collection);
-
- return collection->read_concern;
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_collection_set_read_concern --
- *
- * Sets the default read concern for the collection instance.
- *
- * Returns:
- * None.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-void
-mongoc_collection_set_read_concern (mongoc_collection_t *collection,
- const mongoc_read_concern_t *read_concern)
-{
- BSON_ASSERT_PARAM (collection);
-
- if (collection->read_concern) {
- mongoc_read_concern_destroy (collection->read_concern);
- collection->read_concern = NULL;
- }
-
- if (read_concern) {
- collection->read_concern = mongoc_read_concern_copy (read_concern);
- }
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_collection_get_write_concern --
- *
- * Fetches the default write concern for the collection instance.
- *
- * Returns:
- * A mongoc_write_concern_t that should not be modified or freed.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-const mongoc_write_concern_t *
-mongoc_collection_get_write_concern (const mongoc_collection_t *collection)
-{
- BSON_ASSERT_PARAM (collection);
-
- return collection->write_concern;
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_collection_set_write_concern --
- *
- * Sets the default write concern for the collection instance.
- *
- * Returns:
- * None.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-void
-mongoc_collection_set_write_concern (
- mongoc_collection_t *collection, const mongoc_write_concern_t *write_concern)
-{
- BSON_ASSERT_PARAM (collection);
-
- if (collection->write_concern) {
- mongoc_write_concern_destroy (collection->write_concern);
- collection->write_concern = NULL;
- }
-
- if (write_concern) {
- collection->write_concern = mongoc_write_concern_copy (write_concern);
- }
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_collection_get_name --
- *
- * Returns the name of the collection, excluding the database name.
- *
- * Returns:
- * A string which should not be modified or freed.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-const char *
-mongoc_collection_get_name (mongoc_collection_t *collection)
-{
- BSON_ASSERT_PARAM (collection);
-
- return collection->collection;
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_collection_get_last_error --
- *
- * Returns a bulk result.
- *
- * Returns:
- * NULL or a bson_t that should not be modified or freed. This value
- * is not guaranteed to be persistent between calls into the
- * mongoc_collection_t instance, and therefore must be copied if
- * you would like to keep it around.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-const bson_t *
-mongoc_collection_get_last_error (
- const mongoc_collection_t *collection) /* IN */
-{
- BSON_ASSERT_PARAM (collection);
-
- return collection->gle;
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_collection_validate --
- *
- * Helper to call the validate command on the MongoDB server to
- * validate the collection.
- *
- * Options may be additional options, or NULL.
- * Currently supported options are:
- *
- * "full": Boolean
- *
- * If full is true, then perform a more resource intensive
- * validation.
- *
- * The result is stored in reply.
- *
- * Returns:
- * true if successful; otherwise false and @error is set.
- *
- * Side effects:
- * @reply is set if successful.
- * @error may be set.
- *
- *--------------------------------------------------------------------------
- */
-
-bool
-mongoc_collection_validate (mongoc_collection_t *collection, /* IN */
- const bson_t *options, /* IN */
- bson_t *reply, /* OUT */
- bson_error_t *error) /* IN */
-{
- bson_iter_t iter;
- bson_t cmd = BSON_INITIALIZER;
- bool ret = false;
- bool reply_initialized = false;
-
- BSON_ASSERT_PARAM (collection);
-
- if (options && bson_iter_init_find (&iter, options, "full") &&
- !BSON_ITER_HOLDS_BOOL (&iter)) {
- bson_set_error (error,
- MONGOC_ERROR_BSON,
- MONGOC_ERROR_BSON_INVALID,
- "'full' must be a boolean value.");
- goto cleanup;
- }
-
- bson_append_utf8 (
- &cmd, "validate", 8, collection->collection, collection->collectionlen);
-
- if (options) {
- bson_concat (&cmd, options);
- }
-
- ret =
- mongoc_collection_command_simple (collection, &cmd, NULL, reply, error);
- reply_initialized = true;
-
-cleanup:
- bson_destroy (&cmd);
-
- if (reply && !reply_initialized) {
- bson_init (reply);
- }
-
- return ret;
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_collection_rename --
- *
- * Rename the collection to @new_name.
- *
- * If @new_db is NULL, the same db will be used.
- *
- * If @drop_target_before_rename is true, then a collection named
- * @new_name will be dropped before renaming @collection to
- * @new_name.
- *
- * Returns:
- * true on success; false on failure and @error is set.
- *
- * Side effects:
- * @error is set on failure.
- *
- *--------------------------------------------------------------------------
- */
-
-bool
-mongoc_collection_rename (mongoc_collection_t *collection,
- const char *new_db,
- const char *new_name,
- bool drop_target_before_rename,
- bson_error_t *error)
-{
- return mongoc_collection_rename_with_opts (
- collection, new_db, new_name, drop_target_before_rename, NULL, error);
-}
-
-
-bool
-mongoc_collection_rename_with_opts (mongoc_collection_t *collection,
- const char *new_db,
- const char *new_name,
- bool drop_target_before_rename,
- const bson_t *opts,
- bson_error_t *error)
-{
- bson_t cmd = BSON_INITIALIZER;
- char *newns;
- bool ret;
-
- BSON_ASSERT_PARAM (collection);
- BSON_ASSERT_PARAM (new_name);
-
- if (strchr (new_name, '$')) {
- bson_set_error (error,
- MONGOC_ERROR_NAMESPACE,
- MONGOC_ERROR_NAMESPACE_INVALID,
- "\"%s\" is an invalid collection name.",
- new_name);
- return false;
- }
-
- newns =
- bson_strdup_printf ("%s.%s", new_db ? new_db : collection->db, new_name);
-
- BSON_APPEND_UTF8 (&cmd, "renameCollection", collection->ns);
- BSON_APPEND_UTF8 (&cmd, "to", newns);
-
- if (drop_target_before_rename) {
- BSON_APPEND_BOOL (&cmd, "dropTarget", true);
- }
-
- ret = _mongoc_client_command_with_opts (collection->client,
- "admin",
- &cmd,
- MONGOC_CMD_WRITE,
- opts,
- MONGOC_QUERY_NONE,
- NULL, /* user prefs */
- collection->read_prefs,
- collection->read_concern,
- collection->write_concern,
- NULL, /* reply */
- error);
-
- if (ret) {
- if (new_db) {
- bson_free (collection->db);
- collection->db = bson_strdup (new_db);
- }
-
- bson_free (collection->collection);
- collection->collection = bson_strdup (new_name);
- collection->collectionlen = (int) strlen (collection->collection);
-
- bson_free (collection->ns);
- collection->ns = bson_strdup_printf ("%s.%s", collection->db, new_name);
- collection->nslen = (int) strlen (collection->ns);
- }
-
- bson_free (newns);
- bson_destroy (&cmd);
-
- return ret;
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_collection_stats --
- *
- * Fetches statistics about the collection.
- *
- * The result is stored in @stats, which should NOT be an initialized
- * bson_t or a leak will occur.
- *
- * @stats, @options, and @error are optional.
- *
- * Returns:
- * true on success and @stats is set.
- * false on failure and @error is set.
- *
- * Side effects:
- * @stats and @error.
- *
- *--------------------------------------------------------------------------
- */
-
-bool
-mongoc_collection_stats (mongoc_collection_t *collection,
- const bson_t *options,
- bson_t *stats,
- bson_error_t *error)
-{
- bson_iter_t iter;
- bson_t cmd = BSON_INITIALIZER;
- bool ret;
-
- BSON_ASSERT_PARAM (collection);
-
- if (options && bson_iter_init_find (&iter, options, "scale") &&
- !BSON_ITER_HOLDS_INT32 (&iter)) {
- bson_set_error (error,
- MONGOC_ERROR_BSON,
- MONGOC_ERROR_BSON_INVALID,
- "'scale' must be an int32 value.");
- return false;
- }
-
- BSON_APPEND_UTF8 (&cmd, "collStats", collection->collection);
-
- if (options) {
- bson_concat (&cmd, options);
- }
-
- /* Server Selection Spec: "may-use-secondary" commands SHOULD take a read
- * preference argument and otherwise MUST use the default read preference
- * from client, database or collection configuration. */
- ret = mongoc_collection_command_simple (
- collection, &cmd, collection->read_prefs, stats, error);
-
- bson_destroy (&cmd);
-
- return ret;
-}
-
-
-mongoc_bulk_operation_t *
-mongoc_collection_create_bulk_operation (
- mongoc_collection_t *collection,
- bool ordered,
- const mongoc_write_concern_t *write_concern)
-{
- bson_t opts = BSON_INITIALIZER;
- mongoc_bulk_operation_t *bulk;
- bool wc_ok = true;
-
- bson_append_bool (&opts, "ordered", 7, ordered);
- if (write_concern) {
- wc_ok = mongoc_write_concern_append (
- (mongoc_write_concern_t *) write_concern, &opts);
- }
-
- bulk = mongoc_collection_create_bulk_operation_with_opts (collection, &opts);
-
- bson_destroy (&opts);
-
- if (!wc_ok) {
- bson_set_error (&bulk->result.error,
- MONGOC_ERROR_COMMAND,
- MONGOC_ERROR_COMMAND_INVALID_ARG,
- "invalid writeConcern");
- }
-
- return bulk;
-}
-
-
-mongoc_bulk_operation_t *
-mongoc_collection_create_bulk_operation_with_opts (
- mongoc_collection_t *collection, const bson_t *opts)
-{
- mongoc_bulk_opts_t bulk_opts;
- mongoc_bulk_write_flags_t write_flags = MONGOC_BULK_WRITE_FLAGS_INIT;
- mongoc_write_concern_t *wc = NULL;
- mongoc_bulk_operation_t *bulk;
- bson_error_t err = {0};
-
- BSON_ASSERT_PARAM (collection);
-
- (void) _mongoc_bulk_opts_parse (collection->client, opts, &bulk_opts, &err);
- if (!_mongoc_client_session_in_txn (bulk_opts.client_session)) {
- wc = COALESCE (bulk_opts.writeConcern, collection->write_concern);
- }
- write_flags.ordered = bulk_opts.ordered;
- bulk = _mongoc_bulk_operation_new (collection->client,
- collection->db,
- collection->collection,
- write_flags,
- wc);
-
- bulk->session = bulk_opts.client_session;
- if (err.domain) {
- /* _mongoc_bulk_opts_parse failed, above */
- memcpy (&bulk->result.error, &err, sizeof (bson_error_t));
- } else if (_mongoc_client_session_in_txn (bulk_opts.client_session) &&
- !mongoc_write_concern_is_default (bulk_opts.writeConcern)) {
- bson_set_error (&bulk->result.error,
- MONGOC_ERROR_COMMAND,
- MONGOC_ERROR_COMMAND_INVALID_ARG,
- "Cannot set write concern after starting transaction");
- }
-
- _mongoc_bulk_opts_cleanup (&bulk_opts);
-
- return bulk;
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_collection_find_and_modify_with_opts --
- *
- * Find a document in @collection matching @query, applying @opts.
- *
- * If @reply is not NULL, then the result document will be placed
- * in reply and should be released with bson_destroy().
- *
- * See http://docs.mongodb.org/manual/reference/command/findAndModify/
- * for more information.
- *
- * Returns:
- * true on success; false on failure.
- *
- * Side effects:
- * reply is initialized.
- * error is set if false is returned.
- *
- *--------------------------------------------------------------------------
- */
-bool
-mongoc_collection_find_and_modify_with_opts (
- mongoc_collection_t *collection,
- const bson_t *query,
- const mongoc_find_and_modify_opts_t *opts,
- bson_t *reply,
- bson_error_t *error)
-{
- mongoc_cluster_t *cluster;
- mongoc_cmd_parts_t parts;
- bool is_retryable;
- bson_iter_t iter;
- bson_iter_t inner;
- const char *name;
- bson_t ss_reply;
- bson_t reply_local;
- bson_t *reply_ptr;
- bool ret = false;
- bson_t command = BSON_INITIALIZER;
- mongoc_server_stream_t *server_stream = NULL;
- mongoc_server_stream_t *retry_server_stream = NULL;
- mongoc_find_and_modify_appended_opts_t appended_opts;
- mongoc_write_concern_t *write_concern = NULL;
-
- ENTRY;
-
- BSON_ASSERT_PARAM (collection);
- BSON_ASSERT_PARAM (query);
- BSON_ASSERT_PARAM (opts);
-
- reply_ptr = reply ? reply : &reply_local;
- cluster = &collection->client->cluster;
-
- mongoc_cmd_parts_init (
- &parts, collection->client, collection->db, MONGOC_QUERY_NONE, &command);
- parts.is_read_command = true;
- parts.is_write_command = true;
-
- bson_init (reply_ptr);
-
- if (!_mongoc_find_and_modify_appended_opts_parse (
- cluster->client, &opts->extra, &appended_opts, error)) {
- GOTO (done);
- }
-
- server_stream = mongoc_cluster_stream_for_writes (
- cluster, appended_opts.client_session, &ss_reply, error);
-
- if (!server_stream) {
- bson_concat (reply_ptr, &ss_reply);
- bson_destroy (&ss_reply);
- GOTO (done);
- }
-
- name = mongoc_collection_get_name (collection);
- BSON_APPEND_UTF8 (&command, "findAndModify", name);
- BSON_APPEND_DOCUMENT (&command, "query", query);
-
- if (opts->sort) {
- BSON_APPEND_DOCUMENT (&command, "sort", opts->sort);
- }
-
- if (opts->update) {
- if (_mongoc_document_is_pipeline (opts->update)) {
- BSON_APPEND_ARRAY (&command, "update", opts->update);
- } else {
- BSON_APPEND_DOCUMENT (&command, "update", opts->update);
- }
- }
-
- if (opts->fields) {
- BSON_APPEND_DOCUMENT (&command, "fields", opts->fields);
- }
-
- if (opts->flags & MONGOC_FIND_AND_MODIFY_REMOVE) {
- BSON_APPEND_BOOL (&command, "remove", true);
- }
-
- if (opts->flags & MONGOC_FIND_AND_MODIFY_UPSERT) {
- BSON_APPEND_BOOL (&command, "upsert", true);
- }
-
- if (opts->flags & MONGOC_FIND_AND_MODIFY_RETURN_NEW) {
- BSON_APPEND_BOOL (&command, "new", true);
- }
-
- if (opts->bypass_document_validation) {
- BSON_APPEND_BOOL (&command,
- "bypassDocumentValidation",
- opts->bypass_document_validation);
- }
-
- if (opts->max_time_ms > 0) {
- BSON_APPEND_INT32 (&command, "maxTimeMS", opts->max_time_ms);
- }
-
- /* Some options set via mongoc_find_and_modify_opts_append were parsed. Set
- * them on the command parts. */
- if (appended_opts.client_session) {
- mongoc_cmd_parts_set_session (&parts, appended_opts.client_session);
- }
-
- if (appended_opts.writeConcern) {
- if (_mongoc_client_session_in_txn (parts.assembled.session)) {
- bson_set_error (error,
- MONGOC_ERROR_COMMAND,
- MONGOC_ERROR_COMMAND_INVALID_ARG,
- "Cannot set write concern after starting transaction");
- GOTO (done);
- }
-
- write_concern = appended_opts.writeConcern;
- }
- /* inherit write concern from collection if not in transaction */
- else if (server_stream->sd->max_wire_version >=
- WIRE_VERSION_FAM_WRITE_CONCERN &&
- !_mongoc_client_session_in_txn (parts.assembled.session)) {
- if (!mongoc_write_concern_is_valid (collection->write_concern)) {
- bson_set_error (error,
- MONGOC_ERROR_COMMAND,
- MONGOC_ERROR_COMMAND_INVALID_ARG,
- "The write concern is invalid.");
- GOTO (done);
- }
-
- write_concern = collection->write_concern;
- }
-
- if (appended_opts.hint.value_type) {
- int max_wire_version =
- mongoc_write_concern_is_acknowledged (write_concern)
- ? WIRE_VERSION_FIND_AND_MODIFY_HINT_SERVER_SIDE_ERROR
- : WIRE_VERSION_FIND_AND_MODIFY_HINT;
-
- if (server_stream->sd->max_wire_version < max_wire_version) {
- bson_set_error (
- error,
- MONGOC_ERROR_COMMAND,
- MONGOC_ERROR_PROTOCOL_BAD_WIRE_VERSION,
- "selected server does not support hint on findAndModify");
- GOTO (done);
- }
-
- bson_append_value (&parts.extra, "hint", 4, &appended_opts.hint);
- }
-
- /* Append any remaining unparsed options set via
- * mongoc_find_and_modify_opts_append to the command part. */
- if (bson_iter_init (&iter, &appended_opts.extra)) {
- bool ok = mongoc_cmd_parts_append_opts (
- &parts, &iter, server_stream->sd->max_wire_version, error);
- if (!ok) {
- GOTO (done);
- }
- }
-
- /* An empty write concern amounts to a no-op, so there's no need to guard
- * against it. */
- if (!mongoc_cmd_parts_set_write_concern (
- &parts, write_concern, server_stream->sd->max_wire_version, error)) {
- GOTO (done);
- }
-
- parts.assembled.operation_id = ++cluster->operation_id;
- if (!mongoc_cmd_parts_assemble (&parts, server_stream, error)) {
- GOTO (done);
- }
-
- is_retryable = parts.is_retryable_write;
-
- /* increment the transaction number for the first attempt of each retryable
- * write command */
- if (is_retryable) {
- bson_iter_t txn_number_iter;
- BSON_ASSERT (bson_iter_init_find (
- &txn_number_iter, parts.assembled.command, "txnNumber"));
- bson_iter_overwrite_int64 (
- &txn_number_iter,
- ++parts.assembled.session->server_session->txn_number);
- }
-retry:
- bson_destroy (reply_ptr);
- ret = mongoc_cluster_run_command_monitored (
- cluster, &parts.assembled, reply_ptr, error);
-
- if (parts.is_retryable_write) {
- _mongoc_write_error_handle_labels (
- ret, error, reply_ptr, server_stream->sd->max_wire_version);
- }
-
- if (is_retryable) {
- _mongoc_write_error_update_if_unsupported_storage_engine (
- ret, error, reply_ptr);
- }
-
- /* If a retryable error is encountered and the write is retryable, select
- * a new writable stream and retry. If server selection fails or the selected
- * server does not support retryable writes, fall through and allow the
- * original error to be reported. */
- if (is_retryable &&
- _mongoc_write_error_get_type (reply_ptr) == MONGOC_WRITE_ERR_RETRY) {
- bson_error_t ignored_error;
-
- /* each write command may be retried at most once */
- is_retryable = false;
- retry_server_stream = mongoc_cluster_stream_for_writes (
- cluster, parts.assembled.session, NULL /* reply */, &ignored_error);
-
- if (retry_server_stream && retry_server_stream->sd->max_wire_version >=
- WIRE_VERSION_RETRY_WRITES) {
- parts.assembled.server_stream = retry_server_stream;
- GOTO (retry);
- }
- }
-
- if (bson_iter_init_find (&iter, reply_ptr, "writeConcernError") &&
- BSON_ITER_HOLDS_DOCUMENT (&iter)) {
- const char *errmsg = NULL;
- int32_t code = 0;
-
- BSON_ASSERT (bson_iter_recurse (&iter, &inner));
- while (bson_iter_next (&inner)) {
- if (BSON_ITER_IS_KEY (&inner, "code")) {
- code = (uint32_t) bson_iter_as_int64 (&inner);
- } else if (BSON_ITER_IS_KEY (&inner, "errmsg")) {
- errmsg = bson_iter_utf8 (&inner, NULL);
- }
- }
- bson_set_error (error,
- MONGOC_ERROR_WRITE_CONCERN,
- code,
- "Write Concern error: %s",
- errmsg);
- ret = false;
- }
-
-
-done:
- mongoc_server_stream_cleanup (server_stream);
- mongoc_server_stream_cleanup (retry_server_stream);
-
- if (ret && error) {
- /* if a retry succeeded, clear the initial error */
- memset (error, 0, sizeof (bson_error_t));
- }
- mongoc_cmd_parts_cleanup (&parts);
- bson_destroy (&command);
- if (&reply_local == reply_ptr) {
- bson_destroy (&reply_local);
- }
- _mongoc_find_and_modify_appended_opts_cleanup (&appended_opts);
- RETURN (ret);
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_collection_find_and_modify --
- *
- * Find a document in @collection matching @query and update it with
- * the update document @update.
- *
- * If @reply is not NULL, then the result document will be placed
- * in reply and should be released with bson_destroy().
- *
- * If @remove is true, then the matching documents will be removed.
- *
- * If @fields is not NULL, it will be used to select the desired
- * resulting fields.
- *
- * If @_new is true, then the new version of the document is returned
- * instead of the old document.
- *
- * See http://docs.mongodb.org/manual/reference/command/findAndModify/
- * for more information.
- *
- * Returns:
- * true on success; false on failure.
- *
- * Side effects:
- * reply is initialized.
- * error is set if false is returned.
- *
- *--------------------------------------------------------------------------
- */
-
-bool
-mongoc_collection_find_and_modify (mongoc_collection_t *collection,
- const bson_t *query,
- const bson_t *sort,
- const bson_t *update,
- const bson_t *fields,
- bool _remove,
- bool upsert,
- bool _new,
- bson_t *reply,
- bson_error_t *error)
-{
- mongoc_find_and_modify_opts_t *opts;
- int flags = 0;
- bool ret;
-
- ENTRY;
-
- BSON_ASSERT_PARAM (collection);
- BSON_ASSERT_PARAM (query);
- BSON_ASSERT (update || _remove);
-
-
- if (_remove) {
- flags |= MONGOC_FIND_AND_MODIFY_REMOVE;
- }
- if (upsert) {
- flags |= MONGOC_FIND_AND_MODIFY_UPSERT;
- }
- if (_new) {
- flags |= MONGOC_FIND_AND_MODIFY_RETURN_NEW;
- }
-
- opts = mongoc_find_and_modify_opts_new ();
-
- mongoc_find_and_modify_opts_set_sort (opts, sort);
- mongoc_find_and_modify_opts_set_update (opts, update);
- mongoc_find_and_modify_opts_set_fields (opts, fields);
- mongoc_find_and_modify_opts_set_flags (opts, flags);
-
- ret = mongoc_collection_find_and_modify_with_opts (
- collection, query, opts, reply, error);
- mongoc_find_and_modify_opts_destroy (opts);
-
- return ret;
-}
-
-mongoc_change_stream_t *
-mongoc_collection_watch (const mongoc_collection_t *coll,
- const bson_t *pipeline,
- const bson_t *opts)
-{
- return _mongoc_change_stream_new_from_collection (coll, pipeline, opts);
-}
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-config.h b/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-config.h
deleted file mode 100644
index 6d8a9535..00000000
--- a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-config.h
+++ /dev/null
@@ -1,414 +0,0 @@
-/*
- * Copyright 2013 MongoDB Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#if !defined(MONGOC_INSIDE) && !defined(MONGOC_COMPILATION)
-#error "Only <mongoc/mongoc.h> can be included directly."
-#endif
-
-
-#ifndef MONGOC_CONFIG_H
-#define MONGOC_CONFIG_H
-
-/* MONGOC_USER_SET_CFLAGS is set from config based on what compiler flags were
- * used to compile mongoc */
-#define MONGOC_USER_SET_CFLAGS ""
-
-#define MONGOC_USER_SET_LDFLAGS ""
-
-/* MONGOC_CC is used to determine what C compiler was used to compile mongoc */
-#define MONGOC_CC "cc"
-
-/*
- * MONGOC_ENABLE_SSL_SECURE_CHANNEL is set from configure to determine if we are
- * compiled with Native SSL support on Windows
- */
-#define MONGOC_ENABLE_SSL_SECURE_CHANNEL 0
-
-#if MONGOC_ENABLE_SSL_SECURE_CHANNEL != 1
-# undef MONGOC_ENABLE_SSL_SECURE_CHANNEL
-#endif
-
-
-/*
- * MONGOC_ENABLE_CRYPTO_CNG is set from configure to determine if we are
- * compiled with Native Crypto support on Windows
- */
-#define MONGOC_ENABLE_CRYPTO_CNG 0
-
-#if MONGOC_ENABLE_CRYPTO_CNG != 1
-# undef MONGOC_ENABLE_CRYPTO_CNG
-#endif
-
-
-/*
- * MONGOC_ENABLE_SSL_SECURE_TRANSPORT is set from configure to determine if we are
- * compiled with Native SSL support on Darwin
- */
-#define MONGOC_ENABLE_SSL_SECURE_TRANSPORT 0
-
-#if MONGOC_ENABLE_SSL_SECURE_TRANSPORT != 1
-# undef MONGOC_ENABLE_SSL_SECURE_TRANSPORT
-#endif
-
-
-/*
- * MONGOC_ENABLE_CRYPTO_COMMON_CRYPTO is set from configure to determine if we are
- * compiled with Native Crypto support on Darwin
- */
-#define MONGOC_ENABLE_CRYPTO_COMMON_CRYPTO 0
-
-#if MONGOC_ENABLE_CRYPTO_COMMON_CRYPTO != 1
-# undef MONGOC_ENABLE_CRYPTO_COMMON_CRYPTO
-#endif
-
-
-/*
- * MONGOC_ENABLE_SSL_LIBRESSL is set from configure to determine if we are
- * compiled with LibreSSL support.
- */
-#define MONGOC_ENABLE_SSL_LIBRESSL 0
-
-#if MONGOC_ENABLE_SSL_LIBRESSL != 1
-# undef MONGOC_ENABLE_SSL_LIBRESSL
-#endif
-
-
-/*
- * MONGOC_ENABLE_SSL_OPENSSL is set from configure to determine if we are
- * compiled with OpenSSL support.
- */
-#define MONGOC_ENABLE_SSL_OPENSSL 1
-
-#if MONGOC_ENABLE_SSL_OPENSSL != 1
-# undef MONGOC_ENABLE_SSL_OPENSSL
-#endif
-
-
-/*
- * MONGOC_ENABLE_CRYPTO_LIBCRYPTO is set from configure to determine if we are
- * compiled with OpenSSL support.
- */
-#define MONGOC_ENABLE_CRYPTO_LIBCRYPTO 1
-
-#if MONGOC_ENABLE_CRYPTO_LIBCRYPTO != 1
-# undef MONGOC_ENABLE_CRYPTO_LIBCRYPTO
-#endif
-
-
-/*
- * MONGOC_ENABLE_SSL is set from configure to determine if we are
- * compiled with any SSL support.
- */
-#define MONGOC_ENABLE_SSL 1
-
-#if MONGOC_ENABLE_SSL != 1
-# undef MONGOC_ENABLE_SSL
-#endif
-
-
-/*
- * MONGOC_ENABLE_CRYPTO is set from configure to determine if we are
- * compiled with any crypto support.
- */
-#define MONGOC_ENABLE_CRYPTO 1
-
-#if MONGOC_ENABLE_CRYPTO != 1
-# undef MONGOC_ENABLE_CRYPTO
-#endif
-
-
-/*
- * Use system crypto profile
- */
-#define MONGOC_ENABLE_CRYPTO_SYSTEM_PROFILE 0
-
-#if MONGOC_ENABLE_CRYPTO_SYSTEM_PROFILE != 1
-# undef MONGOC_ENABLE_CRYPTO_SYSTEM_PROFILE
-#endif
-
-
-/*
- * Use ASN1_STRING_get0_data () rather than the deprecated ASN1_STRING_data
- */
-#define MONGOC_HAVE_ASN1_STRING_GET0_DATA 1
-
-#if MONGOC_HAVE_ASN1_STRING_GET0_DATA != 1
-# undef MONGOC_HAVE_ASN1_STRING_GET0_DATA
-#endif
-
-
-/*
- * MONGOC_ENABLE_SASL is set from configure to determine if we are
- * compiled with SASL support.
- */
-#define MONGOC_ENABLE_SASL 0
-
-#if MONGOC_ENABLE_SASL != 1
-# undef MONGOC_ENABLE_SASL
-#endif
-
-
-/*
- * MONGOC_ENABLE_SASL_CYRUS is set from configure to determine if we are
- * compiled with Cyrus SASL support.
- */
-#define MONGOC_ENABLE_SASL_CYRUS 0
-
-#if MONGOC_ENABLE_SASL_CYRUS != 1
-# undef MONGOC_ENABLE_SASL_CYRUS
-#endif
-
-
-/*
- * MONGOC_ENABLE_SASL_SSPI is set from configure to determine if we are
- * compiled with SSPI support.
- */
-#define MONGOC_ENABLE_SASL_SSPI 0
-
-#if MONGOC_ENABLE_SASL_SSPI != 1
-# undef MONGOC_ENABLE_SASL_SSPI
-#endif
-
-/*
- * MONGOC_HAVE_SASL_CLIENT_DONE is set from configure to determine if we
- * have SASL and its version is new enough to use sasl_client_done (),
- * which supersedes sasl_done ().
- */
-#define MONGOC_HAVE_SASL_CLIENT_DONE 0
-
-#if MONGOC_HAVE_SASL_CLIENT_DONE != 1
-# undef MONGOC_HAVE_SASL_CLIENT_DONE
-#endif
-
-
-/*
- * Disable automatic calls to mongoc_init() and mongoc_cleanup()
- * before main() is called, and after exit() (respectively).
- */
-#define MONGOC_NO_AUTOMATIC_GLOBALS 1
-
-#if MONGOC_NO_AUTOMATIC_GLOBALS != 1
-# undef MONGOC_NO_AUTOMATIC_GLOBALS
-#endif
-
-/*
- * MONGOC_HAVE_SOCKLEN is set from configure to determine if we
- * need to emulate the type.
- */
-#define MONGOC_HAVE_SOCKLEN 1
-
-#if MONGOC_HAVE_SOCKLEN != 1
-# undef MONGOC_HAVE_SOCKLEN
-#endif
-
-
-/*
- * MONGOC_HAVE_DNSAPI is set from configure to determine if we should use the
- * Windows dnsapi for SRV record lookups.
- */
-#define MONGOC_HAVE_DNSAPI 0
-
-#if MONGOC_HAVE_DNSAPI != 1
-# undef MONGOC_HAVE_DNSAPI
-#endif
-
-
-/*
- * MONGOC_HAVE_RES_NSEARCH is set from configure to determine if we
- * have thread-safe res_nsearch().
- */
-#define MONGOC_HAVE_RES_NSEARCH 1
-
-#if MONGOC_HAVE_RES_NSEARCH != 1
-# undef MONGOC_HAVE_RES_NSEARCH
-#endif
-
-
-/*
- * MONGOC_HAVE_RES_NDESTROY is set from configure to determine if we
- * have BSD / Darwin's res_ndestroy().
- */
-#define MONGOC_HAVE_RES_NDESTROY 0
-
-#if MONGOC_HAVE_RES_NDESTROY != 1
-# undef MONGOC_HAVE_RES_NDESTROY
-#endif
-
-
-/*
- * MONGOC_HAVE_RES_NCLOSE is set from configure to determine if we
- * have Linux's res_nclose().
- */
-#define MONGOC_HAVE_RES_NCLOSE 1
-
-#if MONGOC_HAVE_RES_NCLOSE != 1
-# undef MONGOC_HAVE_RES_NCLOSE
-#endif
-
-
-/*
- * MONGOC_HAVE_RES_SEARCH is set from configure to determine if we
- * have thread-unsafe res_search(). It's unset if we have the preferred
- * res_nsearch().
- */
-#define MONGOC_HAVE_RES_SEARCH 0
-
-#if MONGOC_HAVE_RES_SEARCH != 1
-# undef MONGOC_HAVE_RES_SEARCH
-#endif
-
-
-/*
- * Set from configure, see
- * https://curl.haxx.se/mail/lib-2009-04/0287.html
- */
-#define MONGOC_SOCKET_ARG2 struct sockaddr
-#define MONGOC_SOCKET_ARG3 socklen_t
-
-/*
- * Enable wire protocol compression negotiation
- *
- */
-#define MONGOC_ENABLE_COMPRESSION 1
-
-#if MONGOC_ENABLE_COMPRESSION != 1
-# undef MONGOC_ENABLE_COMPRESSION
-#endif
-
-/*
- * Set if we have snappy compression support
- *
- */
-#define MONGOC_ENABLE_COMPRESSION_SNAPPY 1
-
-#if MONGOC_ENABLE_COMPRESSION_SNAPPY != 1
-# undef MONGOC_ENABLE_COMPRESSION_SNAPPY
-#endif
-
-
-/*
- * Set if we have zlib compression support
- *
- */
-#define MONGOC_ENABLE_COMPRESSION_ZLIB 1
-
-#if MONGOC_ENABLE_COMPRESSION_ZLIB != 1
-# undef MONGOC_ENABLE_COMPRESSION_ZLIB
-#endif
-
-/*
- * Set if we have zstd compression support
- *
- */
-#define MONGOC_ENABLE_COMPRESSION_ZSTD 1
-
-#if MONGOC_ENABLE_COMPRESSION_ZSTD != 1
-# undef MONGOC_ENABLE_COMPRESSION_ZSTD
-#endif
-
-/*
- * Set if performance counters are available and not disabled.
- *
- */
-#define MONGOC_ENABLE_SHM_COUNTERS 0
-
-#if MONGOC_ENABLE_SHM_COUNTERS != 1
-# undef MONGOC_ENABLE_SHM_COUNTERS
-#endif
-
-/*
- * Set if we have enabled fast counters on Intel using the RDTSCP instruction
- *
- */
-#define MONGOC_ENABLE_RDTSCP 0
-
-#if MONGOC_ENABLE_RDTSCP != 1
-# undef MONGOC_ENABLE_RDTSCP
-#endif
-
-
-/*
- * Set if we have the sched_getcpu() function for use with counters
- *
- */
-#define MONGOC_HAVE_SCHED_GETCPU 1
-
-#if MONGOC_HAVE_SCHED_GETCPU != 1
-# undef MONGOC_HAVE_SCHED_GETCPU
-#endif
-
-/*
- * Set if tracing is enabled. Logs things like network communication and
- * entry/exit of certain functions.
- *
- */
-#define MONGOC_TRACE 1
-
-#if MONGOC_TRACE != 1
-# undef MONGOC_TRACE
-#endif
-
-/*
- * Set if we have ICU support.
- */
-#define MONGOC_ENABLE_ICU 1
-
-#if MONGOC_ENABLE_ICU != 1
-# undef MONGOC_ENABLE_ICU
-#endif
-
-
-/*
- * Set if we have Client Side Encryption support.
- */
-
-#define MONGOC_ENABLE_CLIENT_SIDE_ENCRYPTION 1
-
-#if MONGOC_ENABLE_CLIENT_SIDE_ENCRYPTION != 1
-# undef MONGOC_ENABLE_CLIENT_SIDE_ENCRYPTION
-#endif
-
-
-/*
- * Set if struct sockaddr_storage has __ss_family (instead of ss_family)
- */
-
-#define MONGOC_HAVE_SS_FAMILY 1
-
-#if MONGOC_HAVE_SS_FAMILY != 1
-# undef MONGOC_HAVE_SS_FAMILY
-#endif
-
-/*
- * Set if building with AWS IAM support.
- */
-#define MONGOC_ENABLE_MONGODB_AWS_AUTH 1
-
-#if MONGOC_ENABLE_MONGODB_AWS_AUTH != 1
-# undef MONGOC_ENABLE_MONGODB_AWS_AUTH
-#endif
-
-/*
- * NOTICE:
- * If you're about to update this file and add a config flag, make sure to
- * update:
- * o The bitfield in mongoc-handshake-private.h
- * o _mongoc_handshake_get_config_hex_string() in mongoc-handshake.c
- * o examples/parse_handshake_cfg.py
- * o test_handshake_config_string in test-mongoc-handshake.c
- */
-
-#endif /* MONGOC_CONFIG_H */
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-config.h.in b/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-config.h.in
deleted file mode 100644
index a797c205..00000000
--- a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-config.h.in
+++ /dev/null
@@ -1,414 +0,0 @@
-/*
- * Copyright 2013 MongoDB Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#if !defined(MONGOC_INSIDE) && !defined(MONGOC_COMPILATION)
-#error "Only <mongoc/mongoc.h> can be included directly."
-#endif
-
-
-#ifndef MONGOC_CONFIG_H
-#define MONGOC_CONFIG_H
-
-/* MONGOC_USER_SET_CFLAGS is set from config based on what compiler flags were
- * used to compile mongoc */
-#define MONGOC_USER_SET_CFLAGS "@MONGOC_USER_SET_CFLAGS@"
-
-#define MONGOC_USER_SET_LDFLAGS "@MONGOC_USER_SET_LDFLAGS@"
-
-/* MONGOC_CC is used to determine what C compiler was used to compile mongoc */
-#define MONGOC_CC "@MONGOC_CC@"
-
-/*
- * MONGOC_ENABLE_SSL_SECURE_CHANNEL is set from configure to determine if we are
- * compiled with Native SSL support on Windows
- */
-#define MONGOC_ENABLE_SSL_SECURE_CHANNEL @MONGOC_ENABLE_SSL_SECURE_CHANNEL@
-
-#if MONGOC_ENABLE_SSL_SECURE_CHANNEL != 1
-# undef MONGOC_ENABLE_SSL_SECURE_CHANNEL
-#endif
-
-
-/*
- * MONGOC_ENABLE_CRYPTO_CNG is set from configure to determine if we are
- * compiled with Native Crypto support on Windows
- */
-#define MONGOC_ENABLE_CRYPTO_CNG @MONGOC_ENABLE_CRYPTO_CNG@
-
-#if MONGOC_ENABLE_CRYPTO_CNG != 1
-# undef MONGOC_ENABLE_CRYPTO_CNG
-#endif
-
-
-/*
- * MONGOC_ENABLE_SSL_SECURE_TRANSPORT is set from configure to determine if we are
- * compiled with Native SSL support on Darwin
- */
-#define MONGOC_ENABLE_SSL_SECURE_TRANSPORT @MONGOC_ENABLE_SSL_SECURE_TRANSPORT@
-
-#if MONGOC_ENABLE_SSL_SECURE_TRANSPORT != 1
-# undef MONGOC_ENABLE_SSL_SECURE_TRANSPORT
-#endif
-
-
-/*
- * MONGOC_ENABLE_CRYPTO_COMMON_CRYPTO is set from configure to determine if we are
- * compiled with Native Crypto support on Darwin
- */
-#define MONGOC_ENABLE_CRYPTO_COMMON_CRYPTO @MONGOC_ENABLE_CRYPTO_COMMON_CRYPTO@
-
-#if MONGOC_ENABLE_CRYPTO_COMMON_CRYPTO != 1
-# undef MONGOC_ENABLE_CRYPTO_COMMON_CRYPTO
-#endif
-
-
-/*
- * MONGOC_ENABLE_SSL_LIBRESSL is set from configure to determine if we are
- * compiled with LibreSSL support.
- */
-#define MONGOC_ENABLE_SSL_LIBRESSL @MONGOC_ENABLE_SSL_LIBRESSL@
-
-#if MONGOC_ENABLE_SSL_LIBRESSL != 1
-# undef MONGOC_ENABLE_SSL_LIBRESSL
-#endif
-
-
-/*
- * MONGOC_ENABLE_SSL_OPENSSL is set from configure to determine if we are
- * compiled with OpenSSL support.
- */
-#define MONGOC_ENABLE_SSL_OPENSSL @MONGOC_ENABLE_SSL_OPENSSL@
-
-#if MONGOC_ENABLE_SSL_OPENSSL != 1
-# undef MONGOC_ENABLE_SSL_OPENSSL
-#endif
-
-
-/*
- * MONGOC_ENABLE_CRYPTO_LIBCRYPTO is set from configure to determine if we are
- * compiled with OpenSSL support.
- */
-#define MONGOC_ENABLE_CRYPTO_LIBCRYPTO @MONGOC_ENABLE_CRYPTO_LIBCRYPTO@
-
-#if MONGOC_ENABLE_CRYPTO_LIBCRYPTO != 1
-# undef MONGOC_ENABLE_CRYPTO_LIBCRYPTO
-#endif
-
-
-/*
- * MONGOC_ENABLE_SSL is set from configure to determine if we are
- * compiled with any SSL support.
- */
-#define MONGOC_ENABLE_SSL @MONGOC_ENABLE_SSL@
-
-#if MONGOC_ENABLE_SSL != 1
-# undef MONGOC_ENABLE_SSL
-#endif
-
-
-/*
- * MONGOC_ENABLE_CRYPTO is set from configure to determine if we are
- * compiled with any crypto support.
- */
-#define MONGOC_ENABLE_CRYPTO @MONGOC_ENABLE_CRYPTO@
-
-#if MONGOC_ENABLE_CRYPTO != 1
-# undef MONGOC_ENABLE_CRYPTO
-#endif
-
-
-/*
- * Use system crypto profile
- */
-#define MONGOC_ENABLE_CRYPTO_SYSTEM_PROFILE @MONGOC_ENABLE_CRYPTO_SYSTEM_PROFILE@
-
-#if MONGOC_ENABLE_CRYPTO_SYSTEM_PROFILE != 1
-# undef MONGOC_ENABLE_CRYPTO_SYSTEM_PROFILE
-#endif
-
-
-/*
- * Use ASN1_STRING_get0_data () rather than the deprecated ASN1_STRING_data
- */
-#define MONGOC_HAVE_ASN1_STRING_GET0_DATA @MONGOC_HAVE_ASN1_STRING_GET0_DATA@
-
-#if MONGOC_HAVE_ASN1_STRING_GET0_DATA != 1
-# undef MONGOC_HAVE_ASN1_STRING_GET0_DATA
-#endif
-
-
-/*
- * MONGOC_ENABLE_SASL is set from configure to determine if we are
- * compiled with SASL support.
- */
-#define MONGOC_ENABLE_SASL @MONGOC_ENABLE_SASL@
-
-#if MONGOC_ENABLE_SASL != 1
-# undef MONGOC_ENABLE_SASL
-#endif
-
-
-/*
- * MONGOC_ENABLE_SASL_CYRUS is set from configure to determine if we are
- * compiled with Cyrus SASL support.
- */
-#define MONGOC_ENABLE_SASL_CYRUS @MONGOC_ENABLE_SASL_CYRUS@
-
-#if MONGOC_ENABLE_SASL_CYRUS != 1
-# undef MONGOC_ENABLE_SASL_CYRUS
-#endif
-
-
-/*
- * MONGOC_ENABLE_SASL_SSPI is set from configure to determine if we are
- * compiled with SSPI support.
- */
-#define MONGOC_ENABLE_SASL_SSPI @MONGOC_ENABLE_SASL_SSPI@
-
-#if MONGOC_ENABLE_SASL_SSPI != 1
-# undef MONGOC_ENABLE_SASL_SSPI
-#endif
-
-/*
- * MONGOC_HAVE_SASL_CLIENT_DONE is set from configure to determine if we
- * have SASL and its version is new enough to use sasl_client_done (),
- * which supersedes sasl_done ().
- */
-#define MONGOC_HAVE_SASL_CLIENT_DONE @MONGOC_HAVE_SASL_CLIENT_DONE@
-
-#if MONGOC_HAVE_SASL_CLIENT_DONE != 1
-# undef MONGOC_HAVE_SASL_CLIENT_DONE
-#endif
-
-
-/*
- * Disable automatic calls to mongoc_init() and mongoc_cleanup()
- * before main() is called, and after exit() (respectively).
- */
-#define MONGOC_NO_AUTOMATIC_GLOBALS @MONGOC_NO_AUTOMATIC_GLOBALS@
-
-#if MONGOC_NO_AUTOMATIC_GLOBALS != 1
-# undef MONGOC_NO_AUTOMATIC_GLOBALS
-#endif
-
-/*
- * MONGOC_HAVE_SOCKLEN is set from configure to determine if we
- * need to emulate the type.
- */
-#define MONGOC_HAVE_SOCKLEN @MONGOC_HAVE_SOCKLEN@
-
-#if MONGOC_HAVE_SOCKLEN != 1
-# undef MONGOC_HAVE_SOCKLEN
-#endif
-
-
-/*
- * MONGOC_HAVE_DNSAPI is set from configure to determine if we should use the
- * Windows dnsapi for SRV record lookups.
- */
-#define MONGOC_HAVE_DNSAPI @MONGOC_HAVE_DNSAPI@
-
-#if MONGOC_HAVE_DNSAPI != 1
-# undef MONGOC_HAVE_DNSAPI
-#endif
-
-
-/*
- * MONGOC_HAVE_RES_NSEARCH is set from configure to determine if we
- * have thread-safe res_nsearch().
- */
-#define MONGOC_HAVE_RES_NSEARCH @MONGOC_HAVE_RES_NSEARCH@
-
-#if MONGOC_HAVE_RES_NSEARCH != 1
-# undef MONGOC_HAVE_RES_NSEARCH
-#endif
-
-
-/*
- * MONGOC_HAVE_RES_NDESTROY is set from configure to determine if we
- * have BSD / Darwin's res_ndestroy().
- */
-#define MONGOC_HAVE_RES_NDESTROY @MONGOC_HAVE_RES_NDESTROY@
-
-#if MONGOC_HAVE_RES_NDESTROY != 1
-# undef MONGOC_HAVE_RES_NDESTROY
-#endif
-
-
-/*
- * MONGOC_HAVE_RES_NCLOSE is set from configure to determine if we
- * have Linux's res_nclose().
- */
-#define MONGOC_HAVE_RES_NCLOSE @MONGOC_HAVE_RES_NCLOSE@
-
-#if MONGOC_HAVE_RES_NCLOSE != 1
-# undef MONGOC_HAVE_RES_NCLOSE
-#endif
-
-
-/*
- * MONGOC_HAVE_RES_SEARCH is set from configure to determine if we
- * have thread-unsafe res_search(). It's unset if we have the preferred
- * res_nsearch().
- */
-#define MONGOC_HAVE_RES_SEARCH @MONGOC_HAVE_RES_SEARCH@
-
-#if MONGOC_HAVE_RES_SEARCH != 1
-# undef MONGOC_HAVE_RES_SEARCH
-#endif
-
-
-/*
- * Set from configure, see
- * https://curl.haxx.se/mail/lib-2009-04/0287.html
- */
-#define MONGOC_SOCKET_ARG2 @MONGOC_SOCKET_ARG2@
-#define MONGOC_SOCKET_ARG3 @MONGOC_SOCKET_ARG3@
-
-/*
- * Enable wire protocol compression negotiation
- *
- */
-#define MONGOC_ENABLE_COMPRESSION @MONGOC_ENABLE_COMPRESSION@
-
-#if MONGOC_ENABLE_COMPRESSION != 1
-# undef MONGOC_ENABLE_COMPRESSION
-#endif
-
-/*
- * Set if we have snappy compression support
- *
- */
-#define MONGOC_ENABLE_COMPRESSION_SNAPPY @MONGOC_ENABLE_COMPRESSION_SNAPPY@
-
-#if MONGOC_ENABLE_COMPRESSION_SNAPPY != 1
-# undef MONGOC_ENABLE_COMPRESSION_SNAPPY
-#endif
-
-
-/*
- * Set if we have zlib compression support
- *
- */
-#define MONGOC_ENABLE_COMPRESSION_ZLIB @MONGOC_ENABLE_COMPRESSION_ZLIB@
-
-#if MONGOC_ENABLE_COMPRESSION_ZLIB != 1
-# undef MONGOC_ENABLE_COMPRESSION_ZLIB
-#endif
-
-/*
- * Set if we have zstd compression support
- *
- */
-#define MONGOC_ENABLE_COMPRESSION_ZSTD @MONGOC_ENABLE_COMPRESSION_ZSTD@
-
-#if MONGOC_ENABLE_COMPRESSION_ZSTD != 1
-# undef MONGOC_ENABLE_COMPRESSION_ZSTD
-#endif
-
-/*
- * Set if performance counters are available and not disabled.
- *
- */
-#define MONGOC_ENABLE_SHM_COUNTERS @MONGOC_ENABLE_SHM_COUNTERS@
-
-#if MONGOC_ENABLE_SHM_COUNTERS != 1
-# undef MONGOC_ENABLE_SHM_COUNTERS
-#endif
-
-/*
- * Set if we have enabled fast counters on Intel using the RDTSCP instruction
- *
- */
-#define MONGOC_ENABLE_RDTSCP @MONGOC_ENABLE_RDTSCP@
-
-#if MONGOC_ENABLE_RDTSCP != 1
-# undef MONGOC_ENABLE_RDTSCP
-#endif
-
-
-/*
- * Set if we have the sched_getcpu() function for use with counters
- *
- */
-#define MONGOC_HAVE_SCHED_GETCPU @MONGOC_HAVE_SCHED_GETCPU@
-
-#if MONGOC_HAVE_SCHED_GETCPU != 1
-# undef MONGOC_HAVE_SCHED_GETCPU
-#endif
-
-/*
- * Set if tracing is enabled. Logs things like network communication and
- * entry/exit of certain functions.
- *
- */
-#define MONGOC_TRACE @MONGOC_TRACE@
-
-#if MONGOC_TRACE != 1
-# undef MONGOC_TRACE
-#endif
-
-/*
- * Set if we have ICU support.
- */
-#define MONGOC_ENABLE_ICU @MONGOC_ENABLE_ICU@
-
-#if MONGOC_ENABLE_ICU != 1
-# undef MONGOC_ENABLE_ICU
-#endif
-
-
-/*
- * Set if we have Client Side Encryption support.
- */
-
-#define MONGOC_ENABLE_CLIENT_SIDE_ENCRYPTION @MONGOC_ENABLE_CLIENT_SIDE_ENCRYPTION@
-
-#if MONGOC_ENABLE_CLIENT_SIDE_ENCRYPTION != 1
-# undef MONGOC_ENABLE_CLIENT_SIDE_ENCRYPTION
-#endif
-
-
-/*
- * Set if struct sockaddr_storage has __ss_family (instead of ss_family)
- */
-
-#define MONGOC_HAVE_SS_FAMILY @MONGOC_HAVE_SS_FAMILY@
-
-#if MONGOC_HAVE_SS_FAMILY != 1
-# undef MONGOC_HAVE_SS_FAMILY
-#endif
-
-/*
- * Set if building with AWS IAM support.
- */
-#define MONGOC_ENABLE_MONGODB_AWS_AUTH @MONGOC_ENABLE_MONGODB_AWS_AUTH@
-
-#if MONGOC_ENABLE_MONGODB_AWS_AUTH != 1
-# undef MONGOC_ENABLE_MONGODB_AWS_AUTH
-#endif
-
-/*
- * NOTICE:
- * If you're about to update this file and add a config flag, make sure to
- * update:
- * o The bitfield in mongoc-handshake-private.h
- * o _mongoc_handshake_get_config_hex_string() in mongoc-handshake.c
- * o examples/parse_handshake_cfg.py
- * o test_handshake_config_string in test-mongoc-handshake.c
- */
-
-#endif /* MONGOC_CONFIG_H */
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-counters-private.h b/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-counters-private.h
deleted file mode 100644
index ec4cdf03..00000000
--- a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-counters-private.h
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * Copyright 2013 MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "mongoc-prelude.h"
-
-#ifndef MONGOC_COUNTERS_PRIVATE_H
-#define MONGOC_COUNTERS_PRIVATE_H
-
-#include <bson/bson.h>
-
-#include "mongoc.h"
-
-#ifdef __linux__
-#include <sched.h>
-#include <sys/sysinfo.h>
-#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || \
- defined(__OpenBSD__)
-#include <sys/types.h>
-#include <sys/sysctl.h>
-#include <sys/param.h>
-#elif defined(__hpux__)
-#include <sys/pstat.h>
-#endif
-
-
-BSON_BEGIN_DECLS
-
-
-void
-_mongoc_counters_init (void);
-void
-_mongoc_counters_cleanup (void);
-
-
-static BSON_INLINE unsigned
-_mongoc_get_cpu_count (void)
-{
-#if defined(__linux__)
- return get_nprocs ();
-#elif defined(__hpux__)
- struct pst_dynamic psd;
-
- if (pstat_getdynamic (&psd, sizeof (psd), (size_t) 1, 0) != -1) {
- return psd.psd_max_proc_cnt;
- }
- return 1;
-#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || \
- defined(__OpenBSD__)
- int mib[2];
- int maxproc;
- size_t len;
-
- mib[0] = CTL_HW;
- mib[1] = HW_NCPU;
- len = sizeof (maxproc);
-
- if (-1 == sysctl (mib, 2, &maxproc, &len, NULL, 0)) {
- return 1;
- }
-
- return len;
-#elif defined(__APPLE__) || defined(__sun) || defined(_AIX)
- int ncpu;
-
- ncpu = (int) sysconf (_SC_NPROCESSORS_ONLN);
- return (ncpu > 0) ? ncpu : 1;
-#elif defined(_MSC_VER) || defined(_WIN32)
- SYSTEM_INFO si;
- GetSystemInfo (&si);
- return si.dwNumberOfProcessors;
-#else
-#warning "_mongoc_get_cpu_count() not supported, defaulting to 1."
- return 1;
-#endif
-}
-
-
-#if defined(MONGOC_ENABLE_RDTSCP)
-static BSON_INLINE unsigned
-_mongoc_sched_getcpu (void)
-{
- volatile uint32_t rax, rdx, rcx;
- __asm__ volatile("rdtscp\n" : "=a"(rax), "=d"(rdx), "=c"(rcx) : :);
- unsigned node_id, core_id;
- // node_id = (rcx & 0xFFF000)>>12; // node_id is unused
- core_id = rcx & 0xFFF;
- return core_id;
-}
-#elif defined(MONGOC_HAVE_SCHED_GETCPU)
-#define _mongoc_sched_getcpu sched_getcpu
-#else
-#define _mongoc_sched_getcpu() (0)
-#endif
-
-
-#ifndef SLOTS_PER_CACHELINE
-#define SLOTS_PER_CACHELINE 8
-#endif
-
-
-typedef struct {
- int64_t slots[SLOTS_PER_CACHELINE];
-} mongoc_counter_slots_t;
-
-
-typedef struct {
- mongoc_counter_slots_t *cpus;
-} mongoc_counter_t;
-
-
-#define COUNTER(ident, Category, Name, Description) \
- extern mongoc_counter_t __mongoc_counter_##ident;
-#include "mongoc-counters.defs"
-#undef COUNTER
-
-
-enum {
-#define COUNTER(ident, Category, Name, Description) COUNTER_##ident,
-#include "mongoc-counters.defs"
-#undef COUNTER
- LAST_COUNTER
-};
-
-#ifdef MONGOC_ENABLE_SHM_COUNTERS
-#define COUNTER(ident, Category, Name, Description) \
- static BSON_INLINE void mongoc_counter_##ident##_add (int64_t val) \
- { \
- int64_t *counter = \
- &BSON_CONCAT (__mongoc_counter_, ident) \
- .cpus[_mongoc_sched_getcpu ()] \
- .slots[BSON_CONCAT (COUNTER_, ident) % SLOTS_PER_CACHELINE]; \
- bson_atomic_int64_fetch_add (counter, val, bson_memory_order_seq_cst); \
- } \
- static BSON_INLINE void mongoc_counter_##ident##_inc (void) \
- { \
- mongoc_counter_##ident##_add (1); \
- } \
- static BSON_INLINE void mongoc_counter_##ident##_dec (void) \
- { \
- mongoc_counter_##ident##_add (-1); \
- } \
- static BSON_INLINE void mongoc_counter_##ident##_reset (void) \
- { \
- uint32_t i; \
- for (i = 0; i < _mongoc_get_cpu_count (); i++) { \
- int64_t *counter = &__mongoc_counter_##ident.cpus[i] \
- .slots[COUNTER_##ident % SLOTS_PER_CACHELINE]; \
- bson_atomic_int64_exchange (counter, 0, bson_memory_order_seq_cst); \
- } \
- bson_atomic_thread_fence (); \
- }
-#include "mongoc-counters.defs"
-#undef COUNTER
-#else
-/* when counters are disabled, these functions are no-ops */
-#define COUNTER(ident, Category, Name, Description) \
- static BSON_INLINE void mongoc_counter_##ident##_add (int64_t val) \
- { \
- } \
- static BSON_INLINE void mongoc_counter_##ident##_inc (void) \
- { \
- } \
- static BSON_INLINE void mongoc_counter_##ident##_dec (void) \
- { \
- } \
- static BSON_INLINE void mongoc_counter_##ident##_reset (void) \
- { \
- }
-#include "mongoc-counters.defs"
-#undef COUNTER
-#endif
-
-BSON_END_DECLS
-
-
-#endif /* MONGOC_COUNTERS_PRIVATE_H */
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-crypto-openssl.c b/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-crypto-openssl.c
deleted file mode 100644
index 26254ea2..00000000
--- a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-crypto-openssl.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright 2016 MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "mongoc-config.h"
-#include <bson/bson.h>
-
-#ifdef MONGOC_ENABLE_CRYPTO_LIBCRYPTO
-#include "mongoc-crypto-openssl-private.h"
-#include "mongoc-crypto-private.h"
-
-#include <openssl/sha.h>
-#include <openssl/evp.h>
-#include <openssl/hmac.h>
-
-
-void
-mongoc_crypto_openssl_hmac_sha1 (mongoc_crypto_t *crypto,
- const void *key,
- int key_len,
- const unsigned char *data,
- int data_len,
- unsigned char *hmac_out)
-{
- /* U1 = HMAC(input, salt + 0001) */
- HMAC (EVP_sha1 (), key, key_len, data, data_len, hmac_out, NULL);
-}
-
-#if OPENSSL_VERSION_NUMBER < 0x10100000L || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000L)
-EVP_MD_CTX *
-EVP_MD_CTX_new (void)
-{
- return bson_malloc0 (sizeof (EVP_MD_CTX));
-}
-
-void
-EVP_MD_CTX_free (EVP_MD_CTX *ctx)
-{
- EVP_MD_CTX_cleanup (ctx);
- bson_free (ctx);
-}
-#endif
-
-bool
-mongoc_crypto_openssl_sha1 (mongoc_crypto_t *crypto,
- const unsigned char *input,
- const size_t input_len,
- unsigned char *hash_out)
-{
- EVP_MD_CTX *digest_ctxp = EVP_MD_CTX_new ();
- bool rval = false;
-
- if (1 != EVP_DigestInit_ex (digest_ctxp, EVP_sha1 (), NULL)) {
- goto cleanup;
- }
-
- if (1 != EVP_DigestUpdate (digest_ctxp, input, input_len)) {
- goto cleanup;
- }
-
- rval = (1 == EVP_DigestFinal_ex (digest_ctxp, hash_out, NULL));
-
-cleanup:
- EVP_MD_CTX_free (digest_ctxp);
-
- return rval;
-}
-
-void
-mongoc_crypto_openssl_hmac_sha256 (mongoc_crypto_t *crypto,
- const void *key,
- int key_len,
- const unsigned char *data,
- int data_len,
- unsigned char *hmac_out)
-{
- /* U1 = HMAC(input, salt + 0001) */
- HMAC (EVP_sha256 (), key, key_len, data, data_len, hmac_out, NULL);
-}
-
-bool
-mongoc_crypto_openssl_sha256 (mongoc_crypto_t *crypto,
- const unsigned char *input,
- const size_t input_len,
- unsigned char *hash_out)
-{
- EVP_MD_CTX *digest_ctxp = EVP_MD_CTX_new ();
- bool rval = false;
-
- if (1 != EVP_DigestInit_ex (digest_ctxp, EVP_sha256 (), NULL)) {
- goto cleanup;
- }
-
- if (1 != EVP_DigestUpdate (digest_ctxp, input, input_len)) {
- goto cleanup;
- }
-
- rval = (1 == EVP_DigestFinal_ex (digest_ctxp, hash_out, NULL));
-
-cleanup:
- EVP_MD_CTX_free (digest_ctxp);
-
- return rval;
-}
-
-#endif
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor-cmd.c b/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor-cmd.c
deleted file mode 100644
index f32d6257..00000000
--- a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor-cmd.c
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * Copyright 2018-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include "mongoc.h"
-#include "mongoc-cursor-private.h"
-#include "mongoc-client-private.h"
-
-typedef enum { NONE, CMD_RESPONSE, OP_GETMORE_RESPONSE } reading_from_t;
-typedef enum { UNKNOWN, GETMORE_CMD, OP_GETMORE } getmore_type_t;
-typedef struct _data_cmd_t {
- /* Two paths:
- * - Mongo 3.2+, sent "getMore" cmd, we're reading reply's "nextBatch" array
- * - Mongo 2.6 to 3, after "aggregate" or similar command we sent OP_GETMORE,
- * we're reading the raw reply from a stream
- */
- mongoc_cursor_response_t response;
- mongoc_cursor_response_legacy_t response_legacy;
- reading_from_t reading_from;
- getmore_type_t getmore_type; /* cache after first getmore. */
- bson_t cmd;
-} data_cmd_t;
-
-
-static getmore_type_t
-_getmore_type (mongoc_cursor_t *cursor)
-{
- mongoc_server_stream_t *server_stream;
- bool use_cmd;
- data_cmd_t *data = (data_cmd_t *) cursor->impl.data;
- if (data->getmore_type != UNKNOWN) {
- return data->getmore_type;
- }
- server_stream = _mongoc_cursor_fetch_stream (cursor);
- if (!server_stream) {
- return UNKNOWN;
- }
- use_cmd = server_stream->sd->max_wire_version >= WIRE_VERSION_FIND_CMD &&
- !_mongoc_cursor_get_opt_bool (cursor, MONGOC_CURSOR_EXHAUST);
- data->getmore_type = use_cmd ? GETMORE_CMD : OP_GETMORE;
- mongoc_server_stream_cleanup (server_stream);
- return data->getmore_type;
-}
-
-
-static mongoc_cursor_state_t
-_prime (mongoc_cursor_t *cursor)
-{
- data_cmd_t *data = (data_cmd_t *) cursor->impl.data;
- bson_t copied_opts;
- bson_init (&copied_opts);
-
- cursor->operation_id = ++cursor->client->cluster.operation_id;
- /* commands like agg have a cursor field, so copy opts without "batchSize" */
- bson_copy_to_excluding_noinit (
- &cursor->opts, &copied_opts, "batchSize", "tailable", NULL);
-
- /* server replies to aggregate/listIndexes/listCollections with:
- * {cursor: {id: N, firstBatch: []}} */
- _mongoc_cursor_response_refresh (
- cursor, &data->cmd, &copied_opts, &data->response);
- data->reading_from = CMD_RESPONSE;
- bson_destroy (&copied_opts);
- return IN_BATCH;
-}
-
-
-static mongoc_cursor_state_t
-_pop_from_batch (mongoc_cursor_t *cursor)
-{
- data_cmd_t *data = (data_cmd_t *) cursor->impl.data;
-
- switch (data->reading_from) {
- case CMD_RESPONSE:
- _mongoc_cursor_response_read (cursor, &data->response, &cursor->current);
- break;
- case OP_GETMORE_RESPONSE:
- cursor->current = bson_reader_read (data->response_legacy.reader, NULL);
- break;
- case NONE:
- default:
- fprintf (stderr, "trying to pop from an uninitialized cursor reader.\n");
- BSON_ASSERT (false);
- }
- if (cursor->current) {
- return IN_BATCH;
- } else {
- return cursor->cursor_id ? END_OF_BATCH : DONE;
- }
-}
-
-
-static mongoc_cursor_state_t
-_get_next_batch (mongoc_cursor_t *cursor)
-{
- data_cmd_t *data = (data_cmd_t *) cursor->impl.data;
- bson_t getmore_cmd;
- getmore_type_t getmore_type = _getmore_type (cursor);
-
- switch (getmore_type) {
- case GETMORE_CMD:
- _mongoc_cursor_prepare_getmore_command (cursor, &getmore_cmd);
- _mongoc_cursor_response_refresh (
- cursor, &getmore_cmd, NULL /* opts */, &data->response);
- bson_destroy (&getmore_cmd);
- data->reading_from = CMD_RESPONSE;
- return IN_BATCH;
- case OP_GETMORE:
- _mongoc_cursor_op_getmore (cursor, &data->response_legacy);
- data->reading_from = OP_GETMORE_RESPONSE;
- return IN_BATCH;
- case UNKNOWN:
- default:
- return DONE;
- }
-}
-
-
-static void
-_destroy (mongoc_cursor_impl_t *impl)
-{
- data_cmd_t *data = (data_cmd_t *) impl->data;
- bson_destroy (&data->response.reply);
- bson_destroy (&data->cmd);
- _mongoc_cursor_response_legacy_destroy (&data->response_legacy);
- bson_free (data);
-}
-
-
-static void
-_clone (mongoc_cursor_impl_t *dst, const mongoc_cursor_impl_t *src)
-{
- data_cmd_t *data_src = (data_cmd_t *) src->data;
- data_cmd_t *data_dst = bson_malloc0 (sizeof (data_cmd_t));
- bson_init (&data_dst->response.reply);
- _mongoc_cursor_response_legacy_init (&data_dst->response_legacy);
- bson_copy_to (&data_src->cmd, &data_dst->cmd);
- dst->data = data_dst;
-}
-
-
-mongoc_cursor_t *
-_mongoc_cursor_cmd_new (mongoc_client_t *client,
- const char *db_and_coll,
- const bson_t *cmd,
- const bson_t *opts,
- const mongoc_read_prefs_t *user_prefs,
- const mongoc_read_prefs_t *default_prefs,
- const mongoc_read_concern_t *read_concern)
-{
- mongoc_cursor_t *cursor;
- data_cmd_t *data = bson_malloc0 (sizeof (*data));
-
- cursor = _mongoc_cursor_new_with_opts (
- client, db_and_coll, opts, user_prefs, default_prefs, read_concern);
- _mongoc_cursor_response_legacy_init (&data->response_legacy);
- _mongoc_cursor_check_and_copy_to (cursor, "command", cmd, &data->cmd);
- bson_init (&data->response.reply);
- cursor->impl.prime = _prime;
- cursor->impl.pop_from_batch = _pop_from_batch;
- cursor->impl.get_next_batch = _get_next_batch;
- cursor->impl.destroy = _destroy;
- cursor->impl.clone = _clone;
- cursor->impl.data = (void *) data;
- return cursor;
-}
-
-
-mongoc_cursor_t *
-_mongoc_cursor_cmd_new_from_reply (mongoc_client_t *client,
- const bson_t *cmd,
- const bson_t *opts,
- bson_t *reply)
-{
- mongoc_cursor_t *cursor =
- _mongoc_cursor_cmd_new (client, NULL, cmd, opts, NULL, NULL, NULL);
- data_cmd_t *data = (data_cmd_t *) cursor->impl.data;
-
- data->reading_from = CMD_RESPONSE;
- cursor->state = IN_BATCH;
-
- bson_destroy (&data->response.reply);
- if (!bson_steal (&data->response.reply, reply)) {
- bson_destroy (&data->response.reply);
- BSON_ASSERT (bson_steal (&data->response.reply, bson_copy (reply)));
- }
-
- if (!_mongoc_cursor_start_reading_response (cursor, &data->response)) {
- bson_set_error (&cursor->error,
- MONGOC_ERROR_CURSOR,
- MONGOC_ERROR_CURSOR_INVALID_CURSOR,
- "Couldn't parse cursor document");
- }
- return cursor;
-}
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor-find.c b/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor-find.c
deleted file mode 100644
index 88134370..00000000
--- a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor-find.c
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright 2018-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "mongoc.h"
-#include "mongoc-cursor-private.h"
-#include "mongoc-client-private.h"
-
-typedef struct _data_find_t {
- bson_t filter;
-} data_find_t;
-
-
-extern void
-_mongoc_cursor_impl_find_cmd_init (mongoc_cursor_t *cursor, bson_t *filter);
-extern void
-_mongoc_cursor_impl_find_opquery_init (mongoc_cursor_t *cursor, bson_t *filter);
-
-
-static mongoc_cursor_state_t
-_prime (mongoc_cursor_t *cursor)
-{
- bool use_find_command;
- mongoc_server_stream_t *server_stream;
- data_find_t *data = (data_find_t *) cursor->impl.data;
-
- /* determine if this should be a command or op_query cursor. */
- server_stream = _mongoc_cursor_fetch_stream (cursor);
- if (!server_stream) {
- return DONE;
- }
- /* find_getmore_killcursors spec:
- * "The find command does not support the exhaust flag from OP_QUERY." */
- use_find_command =
- server_stream->sd->max_wire_version >= WIRE_VERSION_FIND_CMD &&
- !_mongoc_cursor_get_opt_bool (cursor, MONGOC_CURSOR_EXHAUST);
- mongoc_server_stream_cleanup (server_stream);
-
- /* set all mongoc_impl_t function pointers. */
- if (use_find_command) {
- _mongoc_cursor_impl_find_cmd_init (cursor, &data->filter /* stolen */);
- } else {
- _mongoc_cursor_impl_find_opquery_init (cursor,
- &data->filter /* stolen */);
- }
- /* destroy this impl data since impl functions have been replaced. */
- bson_free (data);
- /* prime with the new implementation. */
- return cursor->impl.prime (cursor);
-}
-
-
-static void
-_clone (mongoc_cursor_impl_t *dst, const mongoc_cursor_impl_t *src)
-{
- data_find_t *data_dst = bson_malloc0 (sizeof (data_find_t));
- data_find_t *data_src = (data_find_t *) src->data;
- bson_copy_to (&data_src->filter, &data_dst->filter);
- dst->data = data_dst;
-}
-
-
-static void
-_destroy (mongoc_cursor_impl_t *impl)
-{
- data_find_t *data = (data_find_t *) impl->data;
- bson_destroy (&data->filter);
- bson_free (data);
-}
-
-
-mongoc_cursor_t *
-_mongoc_cursor_find_new (mongoc_client_t *client,
- const char *db_and_coll,
- const bson_t *filter,
- const bson_t *opts,
- const mongoc_read_prefs_t *user_prefs,
- const mongoc_read_prefs_t *default_prefs,
- const mongoc_read_concern_t *read_concern)
-{
- mongoc_cursor_t *cursor;
- data_find_t *data = bson_malloc0 (sizeof (data_find_t));
- cursor = _mongoc_cursor_new_with_opts (
- client, db_and_coll, opts, user_prefs, default_prefs, read_concern);
- _mongoc_cursor_check_and_copy_to (cursor, "filter", filter, &data->filter);
- cursor->impl.prime = _prime;
- cursor->impl.clone = _clone;
- cursor->impl.destroy = _destroy;
- cursor->impl.data = data;
- return cursor;
-}
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor-private.h b/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor-private.h
deleted file mode 100644
index e8bddeab..00000000
--- a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor-private.h
+++ /dev/null
@@ -1,326 +0,0 @@
-/*
- * Copyright 2013 MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "mongoc-prelude.h"
-
-#ifndef MONGOC_CURSOR_PRIVATE_H
-#define MONGOC_CURSOR_PRIVATE_H
-
-#include <bson/bson.h>
-
-#include "mongoc-client.h"
-#include "mongoc-buffer-private.h"
-#include "mongoc-rpc-private.h"
-#include "mongoc-server-stream-private.h"
-
-
-BSON_BEGIN_DECLS
-
-#define MONGOC_CURSOR_ALLOW_PARTIAL_RESULTS "allowPartialResults"
-#define MONGOC_CURSOR_ALLOW_PARTIAL_RESULTS_LEN 19
-#define MONGOC_CURSOR_AWAIT_DATA "awaitData"
-#define MONGOC_CURSOR_AWAIT_DATA_LEN 9
-#define MONGOC_CURSOR_BATCH_SIZE "batchSize"
-#define MONGOC_CURSOR_BATCH_SIZE_LEN 9
-#define MONGOC_CURSOR_COLLATION "collation"
-#define MONGOC_CURSOR_COLLATION_LEN 9
-#define MONGOC_CURSOR_COMMENT "comment"
-#define MONGOC_CURSOR_COMMENT_LEN 7
-#define MONGOC_CURSOR_EXHAUST "exhaust"
-#define MONGOC_CURSOR_EXHAUST_LEN 7
-#define MONGOC_CURSOR_FILTER "filter"
-#define MONGOC_CURSOR_FILTER_LEN 6
-#define MONGOC_CURSOR_FIND "find"
-#define MONGOC_CURSOR_FIND_LEN 4
-#define MONGOC_CURSOR_HINT "hint"
-#define MONGOC_CURSOR_HINT_LEN 4
-#define MONGOC_CURSOR_LIMIT "limit"
-#define MONGOC_CURSOR_LIMIT_LEN 5
-#define MONGOC_CURSOR_MAX "max"
-#define MONGOC_CURSOR_MAX_LEN 3
-#define MONGOC_CURSOR_MAX_AWAIT_TIME_MS "maxAwaitTimeMS"
-#define MONGOC_CURSOR_MAX_AWAIT_TIME_MS_LEN 14
-#define MONGOC_CURSOR_MAX_SCAN "maxScan"
-#define MONGOC_CURSOR_MAX_SCAN_LEN 7
-#define MONGOC_CURSOR_MAX_TIME_MS "maxTimeMS"
-#define MONGOC_CURSOR_MAX_TIME_MS_LEN 9
-#define MONGOC_CURSOR_MIN "min"
-#define MONGOC_CURSOR_MIN_LEN 3
-#define MONGOC_CURSOR_NO_CURSOR_TIMEOUT "noCursorTimeout"
-#define MONGOC_CURSOR_NO_CURSOR_TIMEOUT_LEN 15
-#define MONGOC_CURSOR_OPLOG_REPLAY "oplogReplay"
-#define MONGOC_CURSOR_OPLOG_REPLAY_LEN 11
-#define MONGOC_CURSOR_ORDERBY "orderby"
-#define MONGOC_CURSOR_ORDERBY_LEN 7
-#define MONGOC_CURSOR_PROJECTION "projection"
-#define MONGOC_CURSOR_PROJECTION_LEN 10
-#define MONGOC_CURSOR_QUERY "query"
-#define MONGOC_CURSOR_QUERY_LEN 5
-#define MONGOC_CURSOR_READ_CONCERN "readConcern"
-#define MONGOC_CURSOR_READ_CONCERN_LEN 11
-#define MONGOC_CURSOR_RETURN_KEY "returnKey"
-#define MONGOC_CURSOR_RETURN_KEY_LEN 9
-#define MONGOC_CURSOR_SHOW_DISK_LOC "showDiskLoc"
-#define MONGOC_CURSOR_SHOW_DISK_LOC_LEN 11
-#define MONGOC_CURSOR_SHOW_RECORD_ID "showRecordId"
-#define MONGOC_CURSOR_SHOW_RECORD_ID_LEN 12
-#define MONGOC_CURSOR_SINGLE_BATCH "singleBatch"
-#define MONGOC_CURSOR_SINGLE_BATCH_LEN 11
-#define MONGOC_CURSOR_SKIP "skip"
-#define MONGOC_CURSOR_SKIP_LEN 4
-#define MONGOC_CURSOR_SNAPSHOT "snapshot"
-#define MONGOC_CURSOR_SNAPSHOT_LEN 8
-#define MONGOC_CURSOR_SORT "sort"
-#define MONGOC_CURSOR_SORT_LEN 4
-#define MONGOC_CURSOR_TAILABLE "tailable"
-#define MONGOC_CURSOR_TAILABLE_LEN 8
-
-typedef struct _mongoc_cursor_impl_t mongoc_cursor_impl_t;
-typedef enum { UNPRIMED, IN_BATCH, END_OF_BATCH, DONE } mongoc_cursor_state_t;
-typedef mongoc_cursor_state_t (*_mongoc_cursor_impl_transition_t) (
- mongoc_cursor_t *cursor);
-struct _mongoc_cursor_impl_t {
- void (*clone) (mongoc_cursor_impl_t *dst, const mongoc_cursor_impl_t *src);
- void (*destroy) (mongoc_cursor_impl_t *ctx);
- _mongoc_cursor_impl_transition_t prime;
- _mongoc_cursor_impl_transition_t pop_from_batch;
- _mongoc_cursor_impl_transition_t get_next_batch;
- void *data;
-};
-
-/* pre-3.2 and exhaust cursor responses -- read documents from stream. */
-typedef struct _mongoc_cursor_response_legacy {
- mongoc_rpc_t rpc;
- mongoc_buffer_t buffer;
- bson_reader_t *reader;
-} mongoc_cursor_response_legacy_t;
-
-/* 3.2+ responses -- read batch docs like {cursor:{id: 123, firstBatch: []}} */
-typedef struct _mongoc_cursor_response_t {
- bson_t reply; /* the entire command reply */
- bson_iter_t batch_iter; /* iterates over the batch array */
- bson_t current_doc; /* the current doc inside the batch array */
-} mongoc_cursor_response_t;
-
-struct _mongoc_cursor_t {
- mongoc_client_t *client;
- uint32_t client_generation;
-
- uint32_t server_id;
- bool secondary_ok;
-
- mongoc_cursor_state_t state;
- bool in_exhaust;
-
- bson_t opts;
-
- mongoc_read_concern_t *read_concern;
- mongoc_read_prefs_t *read_prefs;
- mongoc_write_concern_t *write_concern;
-
- bool explicit_session;
- mongoc_client_session_t *client_session;
-
- uint32_t count;
-
- char *ns;
- uint32_t nslen;
- uint32_t dblen;
-
- bson_error_t error;
- bson_t error_doc; /* always initialized, and set with server errors. */
-
- const bson_t *current;
-
- mongoc_cursor_impl_t impl;
-
- int64_t operation_id;
- int64_t cursor_id;
-};
-
-int32_t
-_mongoc_n_return (mongoc_cursor_t *cursor);
-void
-_mongoc_set_cursor_ns (mongoc_cursor_t *cursor, const char *ns, uint32_t nslen);
-bool
-_mongoc_cursor_get_opt_bool (const mongoc_cursor_t *cursor, const char *option);
-void
-_mongoc_cursor_flags_to_opts (mongoc_query_flags_t qflags,
- bson_t *opts,
- bool *secondary_ok);
-bool
-_mongoc_cursor_translate_dollar_query_opts (const bson_t *query,
- bson_t *opts,
- bson_t *unwrapped,
- bson_error_t *error);
-mongoc_server_stream_t *
-_mongoc_cursor_fetch_stream (mongoc_cursor_t *cursor);
-void
-_mongoc_cursor_collection (const mongoc_cursor_t *cursor,
- const char **collection,
- int *collection_len);
-bool
-_mongoc_cursor_run_command (mongoc_cursor_t *cursor,
- const bson_t *command,
- const bson_t *opts,
- bson_t *reply,
- bool retry_prohibited);
-bool
-_mongoc_cursor_more (mongoc_cursor_t *cursor);
-
-bool
-_mongoc_cursor_set_opt_int64 (mongoc_cursor_t *cursor,
- const char *option,
- int64_t value);
-void
-_mongoc_cursor_monitor_failed (mongoc_cursor_t *cursor,
- int64_t duration,
- mongoc_server_stream_t *stream,
- const char *cmd_name);
-bool
-_mongoc_cursor_monitor_command (mongoc_cursor_t *cursor,
- mongoc_server_stream_t *server_stream,
- const bson_t *cmd,
- const char *cmd_name);
-void
-_mongoc_cursor_prepare_find_command (mongoc_cursor_t *cursor,
- const bson_t *filter,
- bson_t *command);
-const bson_t *
-_mongoc_cursor_initial_query (mongoc_cursor_t *cursor);
-const bson_t *
-_mongoc_cursor_get_more (mongoc_cursor_t *cursor);
-bool
-_mongoc_cursor_opts_to_flags (mongoc_cursor_t *cursor,
- mongoc_server_stream_t *stream,
- mongoc_query_flags_t *flags /* OUT */);
-void
-_mongoc_cursor_monitor_succeeded (mongoc_cursor_t *cursor,
- mongoc_cursor_response_legacy_t *response,
- int64_t duration,
- bool first_batch,
- mongoc_server_stream_t *stream,
- const char *cmd_name);
-/* start iterating a reply like
- * {cursor: {id: 1234, ns: "db.collection", firstBatch: [...]}} or
- * {cursor: {id: 1234, ns: "db.collection", nextBatch: [...]}} */
-void
-_mongoc_cursor_response_refresh (mongoc_cursor_t *cursor,
- const bson_t *command,
- const bson_t *opts,
- mongoc_cursor_response_t *response);
-bool
-_mongoc_cursor_start_reading_response (mongoc_cursor_t *cursor,
- mongoc_cursor_response_t *response);
-void
-_mongoc_cursor_response_read (mongoc_cursor_t *cursor,
- mongoc_cursor_response_t *response,
- const bson_t **bson);
-void
-_mongoc_cursor_prepare_getmore_command (mongoc_cursor_t *cursor,
- bson_t *command);
-void
-_mongoc_cursor_set_empty (mongoc_cursor_t *cursor);
-bool
-_mongoc_cursor_check_and_copy_to (mongoc_cursor_t *cursor,
- const char *err_prefix,
- const bson_t *src,
- bson_t *dst);
-void
-_mongoc_cursor_prime (mongoc_cursor_t *cursor);
-/* legacy functions defined in mongoc-cursor-legacy.c */
-bool
-_mongoc_cursor_next (mongoc_cursor_t *cursor, const bson_t **bson);
-bool
-_mongoc_cursor_op_query_find (mongoc_cursor_t *cursor,
- bson_t *filter,
- mongoc_cursor_response_legacy_t *response);
-void
-_mongoc_cursor_op_getmore (mongoc_cursor_t *cursor,
- mongoc_cursor_response_legacy_t *response);
-mongoc_cursor_t *
-_mongoc_cursor_new_with_opts (mongoc_client_t *client,
- const char *db_and_collection,
- const bson_t *opts,
- const mongoc_read_prefs_t *user_prefs,
- const mongoc_read_prefs_t *default_prefs,
- const mongoc_read_concern_t *read_concern);
-void
-_mongoc_cursor_response_legacy_init (mongoc_cursor_response_legacy_t *response);
-void
-_mongoc_cursor_response_legacy_destroy (
- mongoc_cursor_response_legacy_t *response);
-/* cursor constructors. */
-mongoc_cursor_t *
-_mongoc_cursor_find_new (mongoc_client_t *client,
- const char *db_and_coll,
- const bson_t *filter,
- const bson_t *opts,
- const mongoc_read_prefs_t *user_prefs,
- const mongoc_read_prefs_t *default_prefs,
- const mongoc_read_concern_t *read_concern);
-
-mongoc_cursor_t *
-_mongoc_cursor_cmd_new (mongoc_client_t *client,
- const char *db_and_coll,
- const bson_t *cmd,
- const bson_t *opts,
- const mongoc_read_prefs_t *user_prefs,
- const mongoc_read_prefs_t *default_prefs,
- const mongoc_read_concern_t *read_concern);
-
-mongoc_cursor_t *
-_mongoc_cursor_cmd_new_from_reply (mongoc_client_t *client,
- const bson_t *cmd,
- const bson_t *opts,
- bson_t *reply);
-
-mongoc_cursor_t *
-_mongoc_cursor_cmd_deprecated_new (mongoc_client_t *client,
- const char *db_and_coll,
- const bson_t *cmd,
- const mongoc_read_prefs_t *read_prefs);
-
-mongoc_cursor_t *
-_mongoc_cursor_array_new (mongoc_client_t *client,
- const char *db_and_coll,
- const bson_t *cmd,
- const bson_t *opts,
- const char *field_name);
-
-mongoc_cursor_t *
-_mongoc_cursor_change_stream_new (mongoc_client_t *client,
- bson_t *reply,
- const bson_t *opts);
-
-bool
-_mongoc_cursor_change_stream_end_of_batch (mongoc_cursor_t *cursor);
-
-const bson_t *
-_mongoc_cursor_change_stream_get_post_batch_resume_token (
- mongoc_cursor_t *cursor);
-
-bool
-_mongoc_cursor_change_stream_has_post_batch_resume_token (
- mongoc_cursor_t *cursor);
-
-const bson_t *
-_mongoc_cursor_change_stream_get_reply (mongoc_cursor_t *cursor);
-
-BSON_END_DECLS
-
-
-#endif /* MONGOC_CURSOR_PRIVATE_H */
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor.c b/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor.c
deleted file mode 100644
index 1314cd8e..00000000
--- a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor.c
+++ /dev/null
@@ -1,1759 +0,0 @@
-/*
- * Copyright 2013 MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-#include "mongoc-cursor.h"
-#include "mongoc-cursor-private.h"
-#include "mongoc-client-private.h"
-#include "mongoc-client-session-private.h"
-#include "mongoc-counters-private.h"
-#include "mongoc-error.h"
-#include "mongoc-error-private.h"
-#include "mongoc-log.h"
-#include "mongoc-trace-private.h"
-#include "mongoc-read-concern-private.h"
-#include "mongoc-util-private.h"
-#include "mongoc-write-concern-private.h"
-#include "mongoc-read-prefs-private.h"
-#include "mongoc-aggregate-private.h"
-
-#undef MONGOC_LOG_DOMAIN
-#define MONGOC_LOG_DOMAIN "cursor"
-
-
-#define CURSOR_FAILED(cursor_) ((cursor_)->error.domain != 0)
-
-static bool
-_translate_query_opt (const char *query_field,
- const char **cmd_field,
- int *len);
-
-
-bool
-_mongoc_cursor_set_opt_int64 (mongoc_cursor_t *cursor,
- const char *option,
- int64_t value)
-{
- bson_iter_t iter;
-
- if (bson_iter_init_find (&iter, &cursor->opts, option)) {
- if (!BSON_ITER_HOLDS_INT64 (&iter)) {
- return false;
- }
-
- bson_iter_overwrite_int64 (&iter, value);
- return true;
- }
-
- return BSON_APPEND_INT64 (&cursor->opts, option, value);
-}
-
-
-static int64_t
-_mongoc_cursor_get_opt_int64 (const mongoc_cursor_t *cursor,
- const char *option,
- int64_t default_value)
-{
- bson_iter_t iter;
-
- if (bson_iter_init_find (&iter, &cursor->opts, option)) {
- return bson_iter_as_int64 (&iter);
- }
-
- return default_value;
-}
-
-
-static bool
-_mongoc_cursor_set_opt_bool (mongoc_cursor_t *cursor,
- const char *option,
- bool value)
-{
- bson_iter_t iter;
-
- if (bson_iter_init_find (&iter, &cursor->opts, option)) {
- if (!BSON_ITER_HOLDS_BOOL (&iter)) {
- return false;
- }
-
- bson_iter_overwrite_bool (&iter, value);
- return true;
- }
-
- return BSON_APPEND_BOOL (&cursor->opts, option, value);
-}
-
-
-bool
-_mongoc_cursor_get_opt_bool (const mongoc_cursor_t *cursor, const char *option)
-{
- bson_iter_t iter;
-
- if (bson_iter_init_find (&iter, &cursor->opts, option)) {
- return bson_iter_as_bool (&iter);
- }
-
- return false;
-}
-
-
-int32_t
-_mongoc_n_return (mongoc_cursor_t *cursor)
-{
- int64_t limit;
- int64_t batch_size;
- int64_t n_return;
-
- /* calculate numberToReturn according to:
- * https://github.com/mongodb/specifications/blob/master/source/crud/crud.rst#combining-limit-and-batch-size-for-the-wire-protocol
- */
- limit = mongoc_cursor_get_limit (cursor);
- batch_size = mongoc_cursor_get_batch_size (cursor);
-
- if (limit < 0) {
- n_return = limit;
- } else if (limit == 0) {
- n_return = batch_size;
- } else if (batch_size == 0) {
- n_return = limit;
- } else if (limit < batch_size) {
- n_return = limit;
- } else {
- n_return = batch_size;
- }
-
- /* if a specified limit exists, account for documents already returned. */
- if (limit > 0 && cursor->count) {
- int64_t remaining = limit - cursor->count;
- /* remaining can be 0 if we have retrieved "limit" documents, but still
- * have a cursor id: SERVER-21086. use nonzero batchSize to fetch final
- * empty batch and trigger server to close cursor. */
- if (remaining <= 0) {
- return 1;
- }
-
- n_return = BSON_MIN (n_return, remaining);
- }
-
- /* check boundary conditions */
- if (n_return < INT32_MIN) {
- return INT32_MIN;
- } else if (n_return > INT32_MAX) {
- return INT32_MAX;
- } else {
- return (int32_t) n_return;
- }
-}
-
-
-void
-_mongoc_set_cursor_ns (mongoc_cursor_t *cursor, const char *ns, uint32_t nslen)
-{
- const char *dot;
-
- bson_free (cursor->ns);
- cursor->ns = bson_strndup (ns, nslen);
- cursor->nslen = nslen;
- dot = strstr (cursor->ns, ".");
-
- if (dot) {
- cursor->dblen = (uint32_t) (dot - cursor->ns);
- } else {
- /* a database name with no collection name */
- cursor->dblen = cursor->nslen;
- }
-}
-
-
-/* return first key beginning with $, or NULL. precondition: bson is valid. */
-static const char *
-_first_dollar_field (const bson_t *bson)
-{
- bson_iter_t iter;
- const char *key;
-
- BSON_ASSERT (bson_iter_init (&iter, bson));
- while (bson_iter_next (&iter)) {
- key = bson_iter_key (&iter);
-
- if (key[0] == '$') {
- return key;
- }
- }
-
- return NULL;
-}
-
-
-/* if src is non-NULL, it is validated and copied to dst. returns false and
- * sets the cursor error if validation fails. */
-bool
-_mongoc_cursor_check_and_copy_to (mongoc_cursor_t *cursor,
- const char *err_prefix,
- const bson_t *src,
- bson_t *dst)
-{
- bson_error_t validate_err;
- bson_init (dst);
- if (src) {
- if (!bson_validate_with_error (
- src, BSON_VALIDATE_EMPTY_KEYS, &validate_err)) {
- bson_set_error (&cursor->error,
- MONGOC_ERROR_CURSOR,
- MONGOC_ERROR_CURSOR_INVALID_CURSOR,
- "Invalid %s: %s",
- err_prefix,
- validate_err.message);
- return false;
- }
-
- bson_destroy (dst);
- bson_copy_to (src, dst);
- }
- return true;
-}
-
-
-mongoc_cursor_t *
-_mongoc_cursor_new_with_opts (mongoc_client_t *client,
- const char *db_and_collection,
- const bson_t *opts,
- const mongoc_read_prefs_t *user_prefs,
- const mongoc_read_prefs_t *default_prefs,
- const mongoc_read_concern_t *read_concern)
-{
- mongoc_cursor_t *cursor;
- mongoc_topology_description_type_t td_type;
- uint32_t server_id;
- mongoc_read_concern_t *read_concern_local = NULL;
- bson_error_t validate_err;
- const char *dollar_field;
- bson_iter_t iter;
-
- ENTRY;
-
- BSON_ASSERT (client);
-
- cursor = (mongoc_cursor_t *) bson_malloc0 (sizeof *cursor);
- cursor->client = client;
- cursor->state = UNPRIMED;
- cursor->client_generation = client->generation;
-
- bson_init (&cursor->opts);
- bson_init (&cursor->error_doc);
-
- if (opts) {
- if (!bson_validate_with_error (
- opts, BSON_VALIDATE_EMPTY_KEYS, &validate_err)) {
- bson_set_error (&cursor->error,
- MONGOC_ERROR_CURSOR,
- MONGOC_ERROR_CURSOR_INVALID_CURSOR,
- "Invalid opts: %s",
- validate_err.message);
- GOTO (finish);
- }
-
- dollar_field = _first_dollar_field (opts);
- if (dollar_field) {
- bson_set_error (&cursor->error,
- MONGOC_ERROR_CURSOR,
- MONGOC_ERROR_CURSOR_INVALID_CURSOR,
- "Cannot use $-modifiers in opts: \"%s\"",
- dollar_field);
- GOTO (finish);
- }
-
- if (bson_iter_init_find (&iter, opts, "sessionId")) {
- if (!_mongoc_client_session_from_iter (
- client, &iter, &cursor->client_session, &cursor->error)) {
- GOTO (finish);
- }
-
- cursor->explicit_session = true;
- }
-
- if (bson_iter_init_find (&iter, opts, "readConcern")) {
- read_concern_local =
- _mongoc_read_concern_new_from_iter (&iter, &cursor->error);
-
- if (!read_concern_local) {
- /* invalid read concern */
- GOTO (finish);
- }
-
- read_concern = read_concern_local;
- }
-
- /* true if there's a valid serverId or no serverId, false on err */
- if (!_mongoc_get_server_id_from_opts (opts,
- MONGOC_ERROR_CURSOR,
- MONGOC_ERROR_CURSOR_INVALID_CURSOR,
- &server_id,
- &cursor->error)) {
- GOTO (finish);
- }
-
- if (server_id) {
- (void) mongoc_cursor_set_hint (cursor, server_id);
- }
-
- bson_copy_to_excluding_noinit (opts,
- &cursor->opts,
- "serverId",
- "sessionId",
- "bypassDocumentValidation",
- NULL);
-
-
- /* only include bypassDocumentValidation if it's true */
- if (bson_iter_init_find (&iter, opts, "bypassDocumentValidation") &&
- bson_iter_as_bool (&iter)) {
- BSON_APPEND_BOOL (&cursor->opts, "bypassDocumentValidation", true);
- }
- }
-
- if (_mongoc_client_session_in_txn (cursor->client_session)) {
- if (!IS_PREF_PRIMARY (user_prefs)) {
- bson_set_error (&cursor->error,
- MONGOC_ERROR_CURSOR,
- MONGOC_ERROR_CURSOR_INVALID_CURSOR,
- "Read preference in a transaction must be primary");
- GOTO (finish);
- }
-
- cursor->read_prefs =
- mongoc_read_prefs_copy (cursor->client_session->txn.opts.read_prefs);
-
- if (bson_has_field (opts, "readConcern")) {
- bson_set_error (&cursor->error,
- MONGOC_ERROR_CURSOR,
- MONGOC_ERROR_CURSOR_INVALID_CURSOR,
- "Cannot set read concern after starting transaction");
- GOTO (finish);
- }
- } else if (user_prefs) {
- cursor->read_prefs = mongoc_read_prefs_copy (user_prefs);
- } else if (default_prefs) {
- cursor->read_prefs = mongoc_read_prefs_copy (default_prefs);
- } else {
- cursor->read_prefs = mongoc_read_prefs_new (MONGOC_READ_PRIMARY);
- }
-
- cursor->read_concern = read_concern ? mongoc_read_concern_copy (read_concern)
- : mongoc_read_concern_new ();
-
- if (db_and_collection) {
- _mongoc_set_cursor_ns (
- cursor, db_and_collection, (uint32_t) strlen (db_and_collection));
- }
-
- if (_mongoc_cursor_get_opt_bool (cursor, MONGOC_CURSOR_EXHAUST)) {
- if (_mongoc_cursor_get_opt_int64 (cursor, MONGOC_CURSOR_LIMIT, 0)) {
- bson_set_error (&cursor->error,
- MONGOC_ERROR_CURSOR,
- MONGOC_ERROR_CURSOR_INVALID_CURSOR,
- "Cannot specify both 'exhaust' and 'limit'.");
- GOTO (finish);
- }
-
- td_type = _mongoc_topology_get_type (client->topology);
-
- if (td_type == MONGOC_TOPOLOGY_SHARDED) {
- bson_set_error (&cursor->error,
- MONGOC_ERROR_CURSOR,
- MONGOC_ERROR_CURSOR_INVALID_CURSOR,
- "Cannot use exhaust cursor with sharded cluster.");
- GOTO (finish);
- }
- }
-
- (void) _mongoc_read_prefs_validate (cursor->read_prefs, &cursor->error);
-
-finish:
- mongoc_read_concern_destroy (read_concern_local);
- mongoc_counter_cursors_active_inc ();
-
- RETURN (cursor);
-}
-
-
-static bool
-_translate_query_opt (const char *query_field, const char **cmd_field, int *len)
-{
- if (query_field[0] != '$') {
- *cmd_field = query_field;
- *len = -1;
- return true;
- }
-
- /* strip the leading '$' */
- query_field++;
-
- if (!strcmp (MONGOC_CURSOR_ORDERBY, query_field)) {
- *cmd_field = MONGOC_CURSOR_SORT;
- *len = MONGOC_CURSOR_SORT_LEN;
- } else if (!strcmp (MONGOC_CURSOR_SHOW_DISK_LOC,
- query_field)) { /* <= MongoDb 3.0 */
- *cmd_field = MONGOC_CURSOR_SHOW_RECORD_ID;
- *len = MONGOC_CURSOR_SHOW_RECORD_ID_LEN;
- } else if (!strcmp (MONGOC_CURSOR_HINT, query_field)) {
- *cmd_field = MONGOC_CURSOR_HINT;
- *len = MONGOC_CURSOR_HINT_LEN;
- } else if (!strcmp (MONGOC_CURSOR_COMMENT, query_field)) {
- *cmd_field = MONGOC_CURSOR_COMMENT;
- *len = MONGOC_CURSOR_COMMENT_LEN;
- } else if (!strcmp (MONGOC_CURSOR_MAX_SCAN, query_field)) {
- *cmd_field = MONGOC_CURSOR_MAX_SCAN;
- *len = MONGOC_CURSOR_MAX_SCAN_LEN;
- } else if (!strcmp (MONGOC_CURSOR_MAX_TIME_MS, query_field)) {
- *cmd_field = MONGOC_CURSOR_MAX_TIME_MS;
- *len = MONGOC_CURSOR_MAX_TIME_MS_LEN;
- } else if (!strcmp (MONGOC_CURSOR_MAX, query_field)) {
- *cmd_field = MONGOC_CURSOR_MAX;
- *len = MONGOC_CURSOR_MAX_LEN;
- } else if (!strcmp (MONGOC_CURSOR_MIN, query_field)) {
- *cmd_field = MONGOC_CURSOR_MIN;
- *len = MONGOC_CURSOR_MIN_LEN;
- } else if (!strcmp (MONGOC_CURSOR_RETURN_KEY, query_field)) {
- *cmd_field = MONGOC_CURSOR_RETURN_KEY;
- *len = MONGOC_CURSOR_RETURN_KEY_LEN;
- } else if (!strcmp (MONGOC_CURSOR_SNAPSHOT, query_field)) {
- *cmd_field = MONGOC_CURSOR_SNAPSHOT;
- *len = MONGOC_CURSOR_SNAPSHOT_LEN;
- } else {
- /* not a special command field, must be a query operator like $or */
- return false;
- }
-
- return true;
-}
-
-
-/* set up a new opt bson from older ways of specifying options.
- * secondary_ok may be NULL.
- * error may be NULL.
- */
-void
-_mongoc_cursor_flags_to_opts (mongoc_query_flags_t qflags,
- bson_t *opts, /* IN/OUT */
- bool *secondary_ok /* OUT */)
-{
- ENTRY;
- BSON_ASSERT (opts);
-
- if (secondary_ok) {
- *secondary_ok = !!(qflags & MONGOC_QUERY_SECONDARY_OK);
- }
-
- if (qflags & MONGOC_QUERY_TAILABLE_CURSOR) {
- bson_append_bool (
- opts, MONGOC_CURSOR_TAILABLE, MONGOC_CURSOR_TAILABLE_LEN, true);
- }
-
- if (qflags & MONGOC_QUERY_OPLOG_REPLAY) {
- bson_append_bool (opts,
- MONGOC_CURSOR_OPLOG_REPLAY,
- MONGOC_CURSOR_OPLOG_REPLAY_LEN,
- true);
- }
-
- if (qflags & MONGOC_QUERY_NO_CURSOR_TIMEOUT) {
- bson_append_bool (opts,
- MONGOC_CURSOR_NO_CURSOR_TIMEOUT,
- MONGOC_CURSOR_NO_CURSOR_TIMEOUT_LEN,
- true);
- }
-
- if (qflags & MONGOC_QUERY_AWAIT_DATA) {
- bson_append_bool (
- opts, MONGOC_CURSOR_AWAIT_DATA, MONGOC_CURSOR_AWAIT_DATA_LEN, true);
- }
-
- if (qflags & MONGOC_QUERY_EXHAUST) {
- bson_append_bool (
- opts, MONGOC_CURSOR_EXHAUST, MONGOC_CURSOR_EXHAUST_LEN, true);
- }
-
- if (qflags & MONGOC_QUERY_PARTIAL) {
- bson_append_bool (opts,
- MONGOC_CURSOR_ALLOW_PARTIAL_RESULTS,
- MONGOC_CURSOR_ALLOW_PARTIAL_RESULTS_LEN,
- true);
- }
-}
-
-/* Checks if the passed query was wrapped in a $query, and if so, parses the
- * query modifiers:
- * https://docs.mongodb.com/manual/reference/operator/query-modifier/
- * and translates them to find command options:
- * https://docs.mongodb.com/manual/reference/command/find/
- * opts must be initialized, and may already have options set.
- * unwrapped must be uninitialized, and will be initialized at return.
- * Returns true if query was unwrapped. */
-bool
-_mongoc_cursor_translate_dollar_query_opts (const bson_t *query,
- bson_t *opts,
- bson_t *unwrapped,
- bson_error_t *error)
-{
- bool has_filter = false;
- const char *key;
- bson_iter_t iter;
- const char *opt_key;
- int len;
- uint32_t data_len;
- const uint8_t *data;
- bson_error_t error_local = {0};
-
- ENTRY;
- BSON_ASSERT (query);
- BSON_ASSERT (opts);
- /* If the query is explicitly specified wrapped in $query, unwrap it and
- * translate the options to new options. */
- if (bson_has_field (query, "$query")) {
- /* like "{$query: {a: 1}, $orderby: {b: 1}, $otherModifier: true}" */
- if (!bson_iter_init (&iter, query)) {
- bson_set_error (&error_local,
- MONGOC_ERROR_BSON,
- MONGOC_ERROR_BSON_INVALID,
- "Invalid BSON in query document");
- GOTO (done);
- }
- while (bson_iter_next (&iter)) {
- key = bson_iter_key (&iter);
- if (key[0] != '$') {
- bson_set_error (&error_local,
- MONGOC_ERROR_CURSOR,
- MONGOC_ERROR_CURSOR_INVALID_CURSOR,
- "Cannot mix $query with non-dollar field '%s'",
- key);
- GOTO (done);
- }
- if (!strcmp (key, "$query")) {
- /* set "filter" to the incoming document's "$query" */
- bson_iter_document (&iter, &data_len, &data);
- if (!bson_init_static (unwrapped, data, (size_t) data_len)) {
- bson_set_error (&error_local,
- MONGOC_ERROR_BSON,
- MONGOC_ERROR_BSON_INVALID,
- "Invalid BSON in $query subdocument");
- GOTO (done);
- }
- has_filter = true;
- } else if (_translate_query_opt (key, &opt_key, &len)) {
- /* "$orderby" becomes "sort", etc., "$unknown" -> "unknown" */
- if (!bson_append_iter (opts, opt_key, len, &iter)) {
- bson_set_error (&error_local,
- MONGOC_ERROR_BSON,
- MONGOC_ERROR_BSON_INVALID,
- "Error adding \"%s\" to query",
- opt_key);
- }
- } else {
- /* strip leading "$" */
- if (!bson_append_iter (opts, key + 1, -1, &iter)) {
- bson_set_error (&error_local,
- MONGOC_ERROR_BSON,
- MONGOC_ERROR_BSON_INVALID,
- "Error adding \"%s\" to query",
- key);
- }
- }
- }
- }
-done:
- if (error) {
- memcpy (error, &error_local, sizeof (bson_error_t));
- }
- if (!has_filter) {
- bson_init (unwrapped);
- }
- RETURN (has_filter);
-}
-
-
-void
-mongoc_cursor_destroy (mongoc_cursor_t *cursor)
-{
- char *db;
- ENTRY;
-
- if (!cursor) {
- EXIT;
- }
-
- if (cursor->impl.destroy) {
- cursor->impl.destroy (&cursor->impl);
- }
-
- /* Always close the socket for an exhaust cursor, even if the client was
- * reset with mongoc_client_reset. That prevents further use of that socket.
- */
- if (cursor->in_exhaust) {
- cursor->client->in_exhaust = false;
- if (cursor->state != DONE) {
- /* The only way to stop an exhaust cursor is to kill the connection
- */
- mongoc_cluster_disconnect_node (&cursor->client->cluster,
- cursor->server_id);
- }
- } else if (cursor->client_generation == cursor->client->generation) {
- if (cursor->cursor_id) {
- db = bson_strndup (cursor->ns, cursor->dblen);
-
- _mongoc_client_kill_cursor (cursor->client,
- cursor->server_id,
- cursor->cursor_id,
- cursor->operation_id,
- db,
- cursor->ns + cursor->dblen + 1,
- cursor->client_session);
- bson_free (db);
- }
- }
-
- if (cursor->client_session && !cursor->explicit_session) {
- mongoc_client_session_destroy (cursor->client_session);
- }
-
- mongoc_read_prefs_destroy (cursor->read_prefs);
- mongoc_read_concern_destroy (cursor->read_concern);
- mongoc_write_concern_destroy (cursor->write_concern);
-
- bson_destroy (&cursor->opts);
- bson_destroy (&cursor->error_doc);
- bson_free (cursor->ns);
- bson_free (cursor);
-
- mongoc_counter_cursors_active_dec ();
- mongoc_counter_cursors_disposed_inc ();
-
- EXIT;
-}
-
-
-mongoc_server_stream_t *
-_mongoc_cursor_fetch_stream (mongoc_cursor_t *cursor)
-{
- mongoc_server_stream_t *server_stream;
- bson_t reply;
-
- ENTRY;
-
- if (cursor->server_id) {
- server_stream =
- mongoc_cluster_stream_for_server (&cursor->client->cluster,
- cursor->server_id,
- true /* reconnect_ok */,
- cursor->client_session,
- &reply,
- &cursor->error);
- } else {
- server_stream = mongoc_cluster_stream_for_reads (&cursor->client->cluster,
- cursor->read_prefs,
- cursor->client_session,
- &reply,
- &cursor->error);
-
- if (server_stream) {
- cursor->server_id = server_stream->sd->id;
- }
- }
-
- if (!server_stream) {
- bson_destroy (&cursor->error_doc);
- bson_copy_to (&reply, &cursor->error_doc);
- bson_destroy (&reply);
- }
-
- RETURN (server_stream);
-}
-
-
-bool
-_mongoc_cursor_monitor_command (mongoc_cursor_t *cursor,
- mongoc_server_stream_t *server_stream,
- const bson_t *cmd,
- const char *cmd_name)
-{
- mongoc_client_t *client;
- mongoc_apm_command_started_t event;
- char *db;
-
- ENTRY;
-
- client = cursor->client;
- if (!client->apm_callbacks.started) {
- /* successful */
- RETURN (true);
- }
-
- db = bson_strndup (cursor->ns, cursor->dblen);
-
- mongoc_apm_command_started_init (&event,
- cmd,
- db,
- cmd_name,
- client->cluster.request_id,
- cursor->operation_id,
- &server_stream->sd->host,
- server_stream->sd->id,
- &server_stream->sd->service_id,
- NULL,
- client->apm_context);
-
- client->apm_callbacks.started (&event);
- mongoc_apm_command_started_cleanup (&event);
- bson_free (db);
-
- RETURN (true);
-}
-
-
-/* append array of docs from current cursor batch */
-static void
-_mongoc_cursor_append_docs_array (mongoc_cursor_t *cursor,
- bson_t *docs,
- mongoc_cursor_response_legacy_t *response)
-{
- bool eof = false;
- char str[16];
- const char *key;
- uint32_t i = 0;
- size_t keylen;
- const bson_t *doc;
-
- while ((doc = bson_reader_read (response->reader, &eof))) {
- keylen = bson_uint32_to_string (i, &key, str, sizeof str);
- bson_append_document (docs, key, (int) keylen, doc);
- }
-
- bson_reader_reset (response->reader);
-}
-
-
-void
-_mongoc_cursor_monitor_succeeded (mongoc_cursor_t *cursor,
- mongoc_cursor_response_legacy_t *response,
- int64_t duration,
- bool first_batch,
- mongoc_server_stream_t *stream,
- const char *cmd_name)
-{
- bson_t docs_array;
- mongoc_apm_command_succeeded_t event;
- mongoc_client_t *client;
- bson_t reply;
- bson_t reply_cursor;
-
- ENTRY;
-
- client = cursor->client;
-
- if (!client->apm_callbacks.succeeded) {
- EXIT;
- }
-
- /* we sent OP_QUERY/OP_GETMORE, fake a reply to find/getMore command:
- * {ok: 1, cursor: {id: 17, ns: "...", first/nextBatch: [ ... docs ... ]}}
- */
- bson_init (&docs_array);
- _mongoc_cursor_append_docs_array (cursor, &docs_array, response);
-
- bson_init (&reply);
- bson_append_int32 (&reply, "ok", 2, 1);
- bson_append_document_begin (&reply, "cursor", 6, &reply_cursor);
- bson_append_int64 (&reply_cursor, "id", 2, mongoc_cursor_get_id (cursor));
- bson_append_utf8 (&reply_cursor, "ns", 2, cursor->ns, cursor->nslen);
- bson_append_array (&reply_cursor,
- first_batch ? "firstBatch" : "nextBatch",
- first_batch ? 10 : 9,
- &docs_array);
- bson_append_document_end (&reply, &reply_cursor);
- bson_destroy (&docs_array);
-
- mongoc_apm_command_succeeded_init (&event,
- duration,
- &reply,
- cmd_name,
- client->cluster.request_id,
- cursor->operation_id,
- &stream->sd->host,
- stream->sd->id,
- &stream->sd->service_id,
- false,
- client->apm_context);
-
- client->apm_callbacks.succeeded (&event);
-
- mongoc_apm_command_succeeded_cleanup (&event);
- bson_destroy (&reply);
-
- EXIT;
-}
-
-
-void
-_mongoc_cursor_monitor_failed (mongoc_cursor_t *cursor,
- int64_t duration,
- mongoc_server_stream_t *stream,
- const char *cmd_name)
-{
- mongoc_apm_command_failed_t event;
- mongoc_client_t *client;
- bson_t reply;
-
- ENTRY;
-
- client = cursor->client;
-
- if (!client->apm_callbacks.failed) {
- EXIT;
- }
-
- /* we sent OP_QUERY/OP_GETMORE, fake a reply to find/getMore command:
- * {ok: 0}
- */
- bson_init (&reply);
- bson_append_int32 (&reply, "ok", 2, 0);
-
- mongoc_apm_command_failed_init (&event,
- duration,
- cmd_name,
- &cursor->error,
- &reply,
- client->cluster.request_id,
- cursor->operation_id,
- &stream->sd->host,
- stream->sd->id,
- &stream->sd->service_id,
- false,
- client->apm_context);
-
- client->apm_callbacks.failed (&event);
-
- mongoc_apm_command_failed_cleanup (&event);
- bson_destroy (&reply);
-
- EXIT;
-}
-
-
-#define ADD_FLAG(_flags, _value) \
- do { \
- if (!BSON_ITER_HOLDS_BOOL (&iter)) { \
- bson_set_error (&cursor->error, \
- MONGOC_ERROR_COMMAND, \
- MONGOC_ERROR_COMMAND_INVALID_ARG, \
- "invalid option %s, should be type bool", \
- key); \
- return false; \
- } \
- if (bson_iter_as_bool (&iter)) { \
- *_flags |= _value; \
- } \
- } while (false);
-
-bool
-_mongoc_cursor_opts_to_flags (mongoc_cursor_t *cursor,
- mongoc_server_stream_t *stream,
- mongoc_query_flags_t *flags /* OUT */)
-{
- bson_iter_t iter;
- const char *key;
-
- *flags = MONGOC_QUERY_NONE;
-
- if (!bson_iter_init (&iter, &cursor->opts)) {
- bson_set_error (&cursor->error,
- MONGOC_ERROR_BSON,
- MONGOC_ERROR_BSON_INVALID,
- "Invalid 'opts' parameter.");
- return false;
- }
-
- while (bson_iter_next (&iter)) {
- key = bson_iter_key (&iter);
-
- if (!strcmp (key, MONGOC_CURSOR_ALLOW_PARTIAL_RESULTS)) {
- ADD_FLAG (flags, MONGOC_QUERY_PARTIAL);
- } else if (!strcmp (key, MONGOC_CURSOR_AWAIT_DATA)) {
- ADD_FLAG (flags, MONGOC_QUERY_AWAIT_DATA);
- } else if (!strcmp (key, MONGOC_CURSOR_EXHAUST)) {
- ADD_FLAG (flags, MONGOC_QUERY_EXHAUST);
- } else if (!strcmp (key, MONGOC_CURSOR_NO_CURSOR_TIMEOUT)) {
- ADD_FLAG (flags, MONGOC_QUERY_NO_CURSOR_TIMEOUT);
- } else if (!strcmp (key, MONGOC_CURSOR_OPLOG_REPLAY)) {
- ADD_FLAG (flags, MONGOC_QUERY_OPLOG_REPLAY);
- } else if (!strcmp (key, MONGOC_CURSOR_TAILABLE)) {
- ADD_FLAG (flags, MONGOC_QUERY_TAILABLE_CURSOR);
- }
- }
-
- if (cursor->secondary_ok) {
- *flags |= MONGOC_QUERY_SECONDARY_OK;
- } else if (cursor->server_id &&
- (stream->topology_type == MONGOC_TOPOLOGY_RS_WITH_PRIMARY ||
- stream->topology_type == MONGOC_TOPOLOGY_RS_NO_PRIMARY) &&
- stream->sd->type != MONGOC_SERVER_RS_PRIMARY) {
- *flags |= MONGOC_QUERY_SECONDARY_OK;
- }
-
- return true;
-}
-
-bool
-_mongoc_cursor_run_command (mongoc_cursor_t *cursor,
- const bson_t *command,
- const bson_t *opts,
- bson_t *reply,
- bool retry_prohibited)
-{
- mongoc_server_stream_t *server_stream;
- bson_iter_t iter;
- mongoc_cmd_parts_t parts;
- const char *cmd_name;
- bool is_primary;
- mongoc_read_prefs_t *prefs = NULL;
- char *db = NULL;
- mongoc_session_opt_t *session_opts;
- bool ret = false;
- bool is_retryable = true;
-
- ENTRY;
-
- mongoc_cmd_parts_init (
- &parts, cursor->client, db, MONGOC_QUERY_NONE, command);
- parts.is_read_command = true;
- parts.read_prefs = cursor->read_prefs;
- parts.assembled.operation_id = cursor->operation_id;
- server_stream = _mongoc_cursor_fetch_stream (cursor);
-
- if (!server_stream) {
- _mongoc_bson_init_if_set (reply);
- GOTO (done);
- }
-
- if (opts) {
- if (!bson_iter_init (&iter, opts)) {
- _mongoc_bson_init_if_set (reply);
- bson_set_error (&cursor->error,
- MONGOC_ERROR_BSON,
- MONGOC_ERROR_BSON_INVALID,
- "Invalid BSON in opts document");
- GOTO (done);
- }
- if (!mongoc_cmd_parts_append_opts (&parts,
- &iter,
- server_stream->sd->max_wire_version,
- &cursor->error)) {
- _mongoc_bson_init_if_set (reply);
- GOTO (done);
- }
- }
-
- if (parts.assembled.session) {
- /* initial query/aggregate/etc, and opts contains "sessionId" */
- BSON_ASSERT (!cursor->client_session);
- BSON_ASSERT (!cursor->explicit_session);
- cursor->client_session = parts.assembled.session;
- cursor->explicit_session = true;
- } else if (cursor->client_session) {
- /* a getMore with implicit or explicit session already acquired */
- mongoc_cmd_parts_set_session (&parts, cursor->client_session);
- } else {
- /* try to create an implicit session. not causally consistent. we keep
- * the session but leave cursor->explicit_session as 0, so we use the
- * same lsid for getMores but destroy the session when the cursor dies.
- */
- session_opts = mongoc_session_opts_new ();
- mongoc_session_opts_set_causal_consistency (session_opts, false);
- /* returns NULL if sessions aren't supported. ignore errors. */
- cursor->client_session =
- mongoc_client_start_session (cursor->client, session_opts, NULL);
- mongoc_cmd_parts_set_session (&parts, cursor->client_session);
- mongoc_session_opts_destroy (session_opts);
- }
-
- if (!mongoc_cmd_parts_set_read_concern (&parts,
- cursor->read_concern,
- server_stream->sd->max_wire_version,
- &cursor->error)) {
- _mongoc_bson_init_if_set (reply);
- GOTO (done);
- }
-
- db = bson_strndup (cursor->ns, cursor->dblen);
- parts.assembled.db_name = db;
-
- if (!_mongoc_cursor_opts_to_flags (
- cursor, server_stream, &parts.user_query_flags)) {
- _mongoc_bson_init_if_set (reply);
- GOTO (done);
- }
-
- /* we might use mongoc_cursor_set_hint to target a secondary but have no
- * read preference, so the secondary rejects the read. same if we have a
- * direct connection to a secondary (topology type "single"). with
- * OP_QUERY we handle this by setting secondaryOk. here we use
- * $readPreference.
- */
- cmd_name = _mongoc_get_command_name (command);
- is_primary =
- !cursor->read_prefs || cursor->read_prefs->mode == MONGOC_READ_PRIMARY;
-
- if (strcmp (cmd_name, "getMore") != 0 &&
- server_stream->sd->max_wire_version >= WIRE_VERSION_OP_MSG &&
- is_primary && parts.user_query_flags & MONGOC_QUERY_SECONDARY_OK) {
- parts.read_prefs = prefs =
- mongoc_read_prefs_new (MONGOC_READ_PRIMARY_PREFERRED);
- } else {
- parts.read_prefs = cursor->read_prefs;
- }
-
- is_retryable = _is_retryable_read (&parts, server_stream);
- if (!strcmp (cmd_name, "getMore")) {
- is_retryable = false;
- }
- if (!strcmp (cmd_name, "aggregate")) {
- bson_iter_t pipeline_iter;
- if (bson_iter_init_find (&pipeline_iter, command, "pipeline") &&
- BSON_ITER_HOLDS_ARRAY (&pipeline_iter) &&
- bson_iter_recurse (&pipeline_iter, &pipeline_iter)) {
- if (_has_write_key (&pipeline_iter)) {
- is_retryable = false;
- }
- }
- }
- if (is_retryable && retry_prohibited) {
- is_retryable = false;
- }
-
- if (cursor->write_concern &&
- !mongoc_write_concern_is_default (cursor->write_concern) &&
- server_stream->sd->max_wire_version >= WIRE_VERSION_CMD_WRITE_CONCERN) {
- parts.assembled.is_acknowledged =
- mongoc_write_concern_is_acknowledged (cursor->write_concern);
- mongoc_write_concern_append (cursor->write_concern, &parts.extra);
- }
-
- if (!mongoc_cmd_parts_assemble (&parts, server_stream, &cursor->error)) {
- _mongoc_bson_init_if_set (reply);
- GOTO (done);
- }
-
-retry:
- ret = mongoc_cluster_run_command_monitored (
- &cursor->client->cluster, &parts.assembled, reply, &cursor->error);
-
- if (ret) {
- memset (&cursor->error, 0, sizeof (bson_error_t));
- }
-
- if (is_retryable &&
- _mongoc_read_error_get_type (ret, &cursor->error, reply) ==
- MONGOC_READ_ERR_RETRY) {
- is_retryable = false;
-
- mongoc_server_stream_cleanup (server_stream);
-
- server_stream = mongoc_cluster_stream_for_reads (&cursor->client->cluster,
- cursor->read_prefs,
- cursor->client_session,
- reply,
- &cursor->error);
-
- if (server_stream &&
- server_stream->sd->max_wire_version >= WIRE_VERSION_RETRY_READS) {
- cursor->server_id = server_stream->sd->id;
- parts.assembled.server_stream = server_stream;
- bson_destroy (reply);
- GOTO (retry);
- }
- }
-
- if (cursor->error.domain) {
- bson_destroy (&cursor->error_doc);
- bson_copy_to (reply, &cursor->error_doc);
- }
-
- /* Read and Write Concern Spec: "Drivers SHOULD parse server replies for a
- * "writeConcernError" field and report the error only in command-specific
- * helper methods that take a separate write concern parameter or an options
- * parameter that may contain a write concern option.
- *
- * Only command helpers with names like "_with_write_concern" can create
- * cursors with a non-NULL write_concern field.
- */
- if (ret && cursor->write_concern) {
- ret = !_mongoc_parse_wc_err (reply, &cursor->error);
- }
-
-done:
- mongoc_server_stream_cleanup (server_stream);
- mongoc_cmd_parts_cleanup (&parts);
- mongoc_read_prefs_destroy (prefs);
- bson_free (db);
-
- return ret;
-}
-
-
-void
-_mongoc_cursor_collection (const mongoc_cursor_t *cursor,
- const char **collection,
- int *collection_len)
-{
- /* ns is like "db.collection". Collection name is located past the ".". */
- *collection = cursor->ns + (cursor->dblen + 1);
- /* Collection name's length is ns length, minus length of db name and ".". */
- *collection_len = cursor->nslen - cursor->dblen - 1;
-
- BSON_ASSERT (*collection_len > 0);
-}
-
-
-void
-_mongoc_cursor_prepare_find_command (mongoc_cursor_t *cursor,
- const bson_t *filter,
- bson_t *command)
-{
- const char *collection;
- int collection_len;
-
- _mongoc_cursor_collection (cursor, &collection, &collection_len);
- bson_append_utf8 (command,
- MONGOC_CURSOR_FIND,
- MONGOC_CURSOR_FIND_LEN,
- collection,
- collection_len);
- bson_append_document (
- command, MONGOC_CURSOR_FILTER, MONGOC_CURSOR_FILTER_LEN, filter);
-}
-
-
-bool
-mongoc_cursor_error (mongoc_cursor_t *cursor, bson_error_t *error)
-{
- ENTRY;
-
- RETURN (mongoc_cursor_error_document (cursor, error, NULL));
-}
-
-
-bool
-mongoc_cursor_error_document (mongoc_cursor_t *cursor,
- bson_error_t *error,
- const bson_t **doc)
-{
- ENTRY;
-
- BSON_ASSERT (cursor);
-
- if (BSON_UNLIKELY (CURSOR_FAILED (cursor))) {
- bson_set_error (error,
- cursor->error.domain,
- cursor->error.code,
- "%s",
- cursor->error.message);
-
- if (doc) {
- *doc = &cursor->error_doc;
- }
-
- RETURN (true);
- }
-
- if (doc) {
- *doc = NULL;
- }
-
- RETURN (false);
-}
-
-
-static mongoc_cursor_state_t
-_call_transition (mongoc_cursor_t *cursor)
-{
- mongoc_cursor_state_t state = cursor->state;
- _mongoc_cursor_impl_transition_t fn = NULL;
- switch (state) {
- case UNPRIMED:
- fn = cursor->impl.prime;
- break;
- case IN_BATCH:
- fn = cursor->impl.pop_from_batch;
- break;
- case END_OF_BATCH:
- fn = cursor->impl.get_next_batch;
- break;
- case DONE:
- default:
- fn = NULL;
- break;
- }
- if (!fn) {
- return DONE;
- }
- state = fn (cursor);
- if (cursor->error.domain) {
- state = DONE;
- }
- return state;
-}
-
-
-bool
-mongoc_cursor_next (mongoc_cursor_t *cursor, const bson_t **bson)
-{
- bool ret = false;
- bool attempted_refresh = false;
-
- ENTRY;
-
- BSON_ASSERT (cursor);
- BSON_ASSERT (bson);
-
- TRACE ("cursor_id(%" PRId64 ")", cursor->cursor_id);
-
- if (cursor->client_generation != cursor->client->generation) {
- bson_set_error (&cursor->error,
- MONGOC_ERROR_CURSOR,
- MONGOC_ERROR_CURSOR_INVALID_CURSOR,
- "Cannot advance cursor after client reset");
- RETURN (false);
- }
-
- if (bson) {
- *bson = NULL;
- }
-
- if (CURSOR_FAILED (cursor)) {
- RETURN (false);
- }
-
- if (cursor->state == DONE) {
- bson_set_error (&cursor->error,
- MONGOC_ERROR_CURSOR,
- MONGOC_ERROR_CURSOR_INVALID_CURSOR,
- "Cannot advance a completed or failed cursor.");
- RETURN (false);
- }
-
- /*
- * We cannot proceed if another cursor is receiving results in exhaust mode.
- */
- if (cursor->client->in_exhaust && !cursor->in_exhaust) {
- bson_set_error (&cursor->error,
- MONGOC_ERROR_CLIENT,
- MONGOC_ERROR_CLIENT_IN_EXHAUST,
- "Another cursor derived from this client is in exhaust.");
- RETURN (false);
- }
-
- cursor->current = NULL;
-
- /* if an error was set on this cursor before calling next, transition to DONE
- * immediately. */
- if (cursor->error.domain) {
- cursor->state = DONE;
- GOTO (done);
- }
-
- while (cursor->state != DONE) {
- /* even when there is no data to return, some cursors remain open and
- * continue sending empty batches (e.g. a tailable or change stream
- * cursor). in that case, do not attempt to get another batch. */
- if (cursor->state == END_OF_BATCH) {
- if (attempted_refresh) {
- RETURN (false);
- }
- attempted_refresh = true;
- }
-
- cursor->state = _call_transition (cursor);
-
- /* check if we received a document. */
- if (cursor->current) {
- *bson = cursor->current;
- ret = true;
- GOTO (done);
- }
-
- if (cursor->state == DONE) {
- GOTO (done);
- }
- }
-
-done:
- cursor->count++;
- RETURN (ret);
-}
-
-
-bool
-mongoc_cursor_more (mongoc_cursor_t *cursor)
-{
- ENTRY;
-
- BSON_ASSERT (cursor);
-
- if (CURSOR_FAILED (cursor)) {
- RETURN (false);
- }
-
- RETURN (cursor->state != DONE);
-}
-
-
-void
-mongoc_cursor_get_host (mongoc_cursor_t *cursor, mongoc_host_list_t *host)
-{
- mongoc_server_description_t const *description;
- mc_shared_tpld td;
-
- BSON_ASSERT (cursor);
- BSON_ASSERT (host);
-
- memset (host, 0, sizeof *host);
-
- if (!cursor->server_id) {
- MONGOC_WARNING ("%s(): Must send query before fetching peer.", BSON_FUNC);
- return;
- }
-
- td = mc_tpld_take_ref (cursor->client->topology);
- description = mongoc_topology_description_server_by_id_const (
- td.ptr, cursor->server_id, &cursor->error);
- mc_tpld_drop_ref (&td);
- if (!description) {
- return;
- }
-
- *host = description->host;
-
- EXIT;
-}
-
-
-mongoc_cursor_t *
-mongoc_cursor_clone (const mongoc_cursor_t *cursor)
-{
- mongoc_cursor_t *_clone;
-
- BSON_ASSERT (cursor);
-
- _clone = (mongoc_cursor_t *) bson_malloc0 (sizeof *_clone);
-
- _clone->client = cursor->client;
- _clone->nslen = cursor->nslen;
- _clone->dblen = cursor->dblen;
- _clone->explicit_session = cursor->explicit_session;
-
- if (cursor->read_prefs) {
- _clone->read_prefs = mongoc_read_prefs_copy (cursor->read_prefs);
- }
-
- if (cursor->read_concern) {
- _clone->read_concern = mongoc_read_concern_copy (cursor->read_concern);
- }
-
- if (cursor->write_concern) {
- _clone->write_concern = mongoc_write_concern_copy (cursor->write_concern);
- }
-
- if (cursor->explicit_session) {
- _clone->client_session = cursor->client_session;
- }
-
- bson_copy_to (&cursor->opts, &_clone->opts);
- bson_init (&_clone->error_doc);
-
- _clone->ns = bson_strdup (cursor->ns);
-
- /* copy the context functions by default. */
- memcpy (&_clone->impl, &cursor->impl, sizeof (cursor->impl));
- if (cursor->impl.clone) {
- cursor->impl.clone (&_clone->impl, &cursor->impl);
- }
-
- mongoc_counter_cursors_active_inc ();
-
- RETURN (_clone);
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_cursor_is_alive --
- *
- * Deprecated for mongoc_cursor_more.
- *
- *--------------------------------------------------------------------------
- */
-
-bool
-mongoc_cursor_is_alive (const mongoc_cursor_t *cursor) /* IN */
-{
- return mongoc_cursor_more ((mongoc_cursor_t *) cursor);
-}
-
-
-const bson_t *
-mongoc_cursor_current (const mongoc_cursor_t *cursor) /* IN */
-{
- BSON_ASSERT (cursor);
-
- return cursor->current;
-}
-
-
-void
-mongoc_cursor_set_batch_size (mongoc_cursor_t *cursor, uint32_t batch_size)
-{
- BSON_ASSERT (cursor);
-
- _mongoc_cursor_set_opt_int64 (
- cursor, MONGOC_CURSOR_BATCH_SIZE, (int64_t) batch_size);
-}
-
-
-uint32_t
-mongoc_cursor_get_batch_size (const mongoc_cursor_t *cursor)
-{
- BSON_ASSERT (cursor);
-
- return (uint32_t) _mongoc_cursor_get_opt_int64 (
- cursor, MONGOC_CURSOR_BATCH_SIZE, 0);
-}
-
-
-bool
-mongoc_cursor_set_limit (mongoc_cursor_t *cursor, int64_t limit)
-{
- BSON_ASSERT (cursor);
-
- if (cursor->state == UNPRIMED) {
- if (limit < 0) {
- return _mongoc_cursor_set_opt_int64 (
- cursor, MONGOC_CURSOR_LIMIT, -limit) &&
- _mongoc_cursor_set_opt_bool (
- cursor, MONGOC_CURSOR_SINGLE_BATCH, true);
- } else {
- return _mongoc_cursor_set_opt_int64 (
- cursor, MONGOC_CURSOR_LIMIT, limit);
- }
- } else {
- return false;
- }
-}
-
-
-int64_t
-mongoc_cursor_get_limit (const mongoc_cursor_t *cursor)
-{
- int64_t limit;
- bool single_batch;
-
- BSON_ASSERT (cursor);
-
- limit = _mongoc_cursor_get_opt_int64 (cursor, MONGOC_CURSOR_LIMIT, 0);
- single_batch =
- _mongoc_cursor_get_opt_bool (cursor, MONGOC_CURSOR_SINGLE_BATCH);
-
- if (limit > 0 && single_batch) {
- limit = -limit;
- }
-
- return limit;
-}
-
-
-bool
-mongoc_cursor_set_hint (mongoc_cursor_t *cursor, uint32_t server_id)
-{
- BSON_ASSERT (cursor);
-
- if (cursor->server_id) {
- MONGOC_ERROR ("mongoc_cursor_set_hint: server_id already set");
- return false;
- }
-
- if (!server_id) {
- MONGOC_ERROR ("mongoc_cursor_set_hint: cannot set server_id to 0");
- return false;
- }
-
- cursor->server_id = server_id;
-
- return true;
-}
-
-
-uint32_t
-mongoc_cursor_get_hint (const mongoc_cursor_t *cursor)
-{
- BSON_ASSERT (cursor);
-
- return cursor->server_id;
-}
-
-
-int64_t
-mongoc_cursor_get_id (const mongoc_cursor_t *cursor)
-{
- BSON_ASSERT (cursor);
-
- return cursor->cursor_id;
-}
-
-
-void
-mongoc_cursor_set_max_await_time_ms (mongoc_cursor_t *cursor,
- uint32_t max_await_time_ms)
-{
- BSON_ASSERT (cursor);
-
- if (cursor->state == UNPRIMED) {
- _mongoc_cursor_set_opt_int64 (
- cursor, MONGOC_CURSOR_MAX_AWAIT_TIME_MS, (int64_t) max_await_time_ms);
- }
-}
-
-
-uint32_t
-mongoc_cursor_get_max_await_time_ms (const mongoc_cursor_t *cursor)
-{
- bson_iter_t iter;
-
- BSON_ASSERT (cursor);
-
- if (bson_iter_init_find (
- &iter, &cursor->opts, MONGOC_CURSOR_MAX_AWAIT_TIME_MS)) {
- return (uint32_t) bson_iter_as_int64 (&iter);
- }
-
- return 0;
-}
-
-
-/* deprecated for mongoc_cursor_new_from_command_reply_with_opts */
-mongoc_cursor_t *
-mongoc_cursor_new_from_command_reply (mongoc_client_t *client,
- bson_t *reply,
- uint32_t server_id)
-{
- mongoc_cursor_t *cursor;
- bson_t cmd = BSON_INITIALIZER;
- bson_t opts = BSON_INITIALIZER;
-
- BSON_ASSERT (client);
- BSON_ASSERT (reply);
- /* options are passed through by adding them to reply. */
- bson_copy_to_excluding_noinit (reply,
- &opts,
- "cursor",
- "ok",
- "operationTime",
- "$clusterTime",
- "$gleStats",
- NULL);
-
- if (server_id) {
- bson_append_int64 (&opts, "serverId", 8, server_id);
- }
-
- cursor = _mongoc_cursor_cmd_new_from_reply (client, &cmd, &opts, reply);
- bson_destroy (&cmd);
- bson_destroy (&opts);
-
- return cursor;
-}
-
-
-mongoc_cursor_t *
-mongoc_cursor_new_from_command_reply_with_opts (mongoc_client_t *client,
- bson_t *reply,
- const bson_t *opts)
-{
- mongoc_cursor_t *cursor;
- bson_t cmd = BSON_INITIALIZER;
-
- BSON_ASSERT (client);
- BSON_ASSERT (reply);
-
- cursor = _mongoc_cursor_cmd_new_from_reply (client, &cmd, opts, reply);
- bson_destroy (&cmd);
-
- return cursor;
-}
-
-
-bool
-_mongoc_cursor_start_reading_response (mongoc_cursor_t *cursor,
- mongoc_cursor_response_t *response)
-{
- bson_iter_t iter;
- bson_iter_t child;
- const char *ns;
- uint32_t nslen;
- bool in_batch = false;
-
- if (bson_iter_init_find (&iter, &response->reply, "cursor") &&
- BSON_ITER_HOLDS_DOCUMENT (&iter) && bson_iter_recurse (&iter, &child)) {
- while (bson_iter_next (&child)) {
- if (BSON_ITER_IS_KEY (&child, "id")) {
- cursor->cursor_id = bson_iter_as_int64 (&child);
- } else if (BSON_ITER_IS_KEY (&child, "ns")) {
- ns = bson_iter_utf8 (&child, &nslen);
- _mongoc_set_cursor_ns (cursor, ns, nslen);
- } else if (BSON_ITER_IS_KEY (&child, "firstBatch") ||
- BSON_ITER_IS_KEY (&child, "nextBatch")) {
- if (BSON_ITER_HOLDS_ARRAY (&child) &&
- bson_iter_recurse (&child, &response->batch_iter)) {
- in_batch = true;
- }
- }
- }
- }
-
- /* Driver Sessions Spec: "When an implicit session is associated with a
- * cursor for use with getMore operations, the session MUST be returned to
- * the pool immediately following a getMore operation that indicates that the
- * cursor has been exhausted." */
- if (cursor->cursor_id == 0 && cursor->client_session &&
- !cursor->explicit_session) {
- mongoc_client_session_destroy (cursor->client_session);
- cursor->client_session = NULL;
- }
-
- return in_batch;
-}
-
-
-void
-_mongoc_cursor_response_read (mongoc_cursor_t *cursor,
- mongoc_cursor_response_t *response,
- const bson_t **bson)
-{
- const uint8_t *data = NULL;
- uint32_t data_len = 0;
-
- ENTRY;
-
- if (bson_iter_next (&response->batch_iter) &&
- BSON_ITER_HOLDS_DOCUMENT (&response->batch_iter)) {
- bson_iter_document (&response->batch_iter, &data_len, &data);
-
- /* bson_iter_next guarantees valid BSON, so this must succeed */
- BSON_ASSERT (bson_init_static (&response->current_doc, data, data_len));
- *bson = &response->current_doc;
- }
-}
-
-/* sets cursor error if could not get the next batch. */
-void
-_mongoc_cursor_response_refresh (mongoc_cursor_t *cursor,
- const bson_t *command,
- const bson_t *opts,
- mongoc_cursor_response_t *response)
-{
- ENTRY;
-
- bson_destroy (&response->reply);
-
- /* server replies to find / aggregate with {cursor: {id: N, firstBatch: []}},
- * to getMore command with {cursor: {id: N, nextBatch: []}}. */
- if (_mongoc_cursor_run_command (
- cursor, command, opts, &response->reply, false) &&
- _mongoc_cursor_start_reading_response (cursor, response)) {
- return;
- }
- if (!cursor->error.domain) {
- bson_set_error (&cursor->error,
- MONGOC_ERROR_PROTOCOL,
- MONGOC_ERROR_PROTOCOL_INVALID_REPLY,
- "Invalid reply to %s command.",
- _mongoc_get_command_name (command));
- }
-}
-
-void
-_mongoc_cursor_prepare_getmore_command (mongoc_cursor_t *cursor,
- bson_t *command)
-{
- const char *collection;
- int collection_len;
- int64_t batch_size;
- bool await_data;
- int64_t max_await_time_ms;
-
- ENTRY;
-
- _mongoc_cursor_collection (cursor, &collection, &collection_len);
-
- bson_init (command);
- bson_append_int64 (command, "getMore", 7, mongoc_cursor_get_id (cursor));
- bson_append_utf8 (command, "collection", 10, collection, collection_len);
-
- batch_size = mongoc_cursor_get_batch_size (cursor);
-
- /* See find, getMore, and killCursors Spec for batchSize rules */
- if (batch_size) {
- bson_append_int64 (command,
- MONGOC_CURSOR_BATCH_SIZE,
- MONGOC_CURSOR_BATCH_SIZE_LEN,
- abs (_mongoc_n_return (cursor)));
- }
-
- /* Find, getMore And killCursors Commands Spec: "In the case of a tailable
- cursor with awaitData == true the driver MUST provide a Cursor level
- option named maxAwaitTimeMS (See CRUD specification for details). The
- maxTimeMS option on the getMore command MUST be set to the value of the
- option maxAwaitTimeMS. If no maxAwaitTimeMS is specified, the driver
- SHOULD not set maxTimeMS on the getMore command."
- */
- await_data = _mongoc_cursor_get_opt_bool (cursor, MONGOC_CURSOR_TAILABLE) &&
- _mongoc_cursor_get_opt_bool (cursor, MONGOC_CURSOR_AWAIT_DATA);
-
- if (await_data) {
- max_await_time_ms = _mongoc_cursor_get_opt_int64 (
- cursor, MONGOC_CURSOR_MAX_AWAIT_TIME_MS, 0);
- if (max_await_time_ms) {
- bson_append_int64 (command,
- MONGOC_CURSOR_MAX_TIME_MS,
- MONGOC_CURSOR_MAX_TIME_MS_LEN,
- max_await_time_ms);
- }
- }
-}
-
-/* sets the cursor to be empty so it returns NULL on the first call to
- * cursor_next but does not return an error. */
-void
-_mongoc_cursor_set_empty (mongoc_cursor_t *cursor)
-{
- memset (&cursor->error, 0, sizeof (bson_error_t));
- bson_reinit (&cursor->error_doc);
- cursor->state = IN_BATCH;
-}
-
-void
-_mongoc_cursor_prime (mongoc_cursor_t *cursor)
-{
- cursor->state = cursor->impl.prime (cursor);
-}
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-handshake.c b/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-handshake.c
deleted file mode 100644
index 477f11ea..00000000
--- a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-handshake.c
+++ /dev/null
@@ -1,712 +0,0 @@
-/*
- * Copyright 2016-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <bson/bson.h>
-
-#ifdef _POSIX_VERSION
-#include <sys/utsname.h>
-#endif
-
-#ifdef _WIN32
-#include <windows.h>
-#endif
-
-#include "mongoc-linux-distro-scanner-private.h"
-#include "mongoc-handshake.h"
-#include "mongoc-handshake-compiler-private.h"
-#include "mongoc-handshake-os-private.h"
-#include "mongoc-handshake-private.h"
-#include "mongoc-client.h"
-#include "mongoc-client-private.h"
-#include "mongoc-error.h"
-#include "mongoc-log.h"
-#include "mongoc-version.h"
-#include "mongoc-util-private.h"
-
-/*
- * Global handshake data instance. Initialized at startup from mongoc_init
- *
- * Can be modified by calls to mongoc_handshake_data_append
- */
-static mongoc_handshake_t gMongocHandshake;
-
-/*
- * Used for thread-safety in mongoc_handshake_data_append
- */
-static bson_mutex_t gHandshakeLock;
-
-static void
-_set_bit (uint8_t *bf, uint32_t byte_count, uint32_t bit)
-{
- uint32_t byte = bit / 8;
- uint32_t bit_of_byte = (bit) % 8;
- /* byte 0 is the last location in bf. */
- bf[(byte_count - 1) - byte] |= 1u << bit_of_byte;
-}
-
-/* returns a hex string for all config flag bits, which must be freed. */
-char *
-_mongoc_handshake_get_config_hex_string (void)
-{
- uint32_t byte_count;
- uint8_t *bf;
- bson_string_t *str;
- int i;
-
- byte_count = (LAST_MONGOC_MD_FLAG + 7) / 8; /* ceil (num_bits / 8) */
- /* allocate enough bytes to fit all config bits. */
- bf = (uint8_t *) bson_malloc0 (byte_count);
-
-#ifdef MONGOC_ENABLE_SSL_SECURE_CHANNEL
- _set_bit (bf, byte_count, MONGOC_ENABLE_SSL_SECURE_CHANNEL);
-#endif
-
-#ifdef MONGOC_ENABLE_CRYPTO_CNG
- _set_bit (bf, byte_count, MONGOC_ENABLE_CRYPTO_CNG);
-#endif
-
-#ifdef MONGOC_ENABLE_SSL_SECURE_TRANSPORT
- _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_SSL_SECURE_TRANSPORT);
-#endif
-
-#ifdef MONGOC_ENABLE_CRYPTO_COMMON_CRYPTO
- _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_CRYPTO_COMMON_CRYPTO);
-#endif
-
-#ifdef MONGOC_ENABLE_SSL_OPENSSL
- _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_SSL_OPENSSL);
-#endif
-
-#ifdef MONGOC_ENABLE_CRYPTO_LIBCRYPTO
- _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_CRYPTO_LIBCRYPTO);
-#endif
-
-#ifdef MONGOC_ENABLE_SSL
- _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_SSL);
-#endif
-
-#ifdef MONGOC_ENABLE_CRYPTO
- _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_CRYPTO);
-#endif
-
-#ifdef MONGOC_ENABLE_CRYPTO_SYSTEM_PROFILE
- _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_CRYPTO_SYSTEM_PROFILE);
-#endif
-
-#ifdef MONGOC_ENABLE_SASL
- _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_SASL);
-#endif
-
-#ifdef MONGOC_HAVE_SASL_CLIENT_DONE
- _set_bit (bf, byte_count, MONGOC_MD_FLAG_HAVE_SASL_CLIENT_DONE);
-#endif
-
-#ifdef MONGOC_NO_AUTOMATIC_GLOBALS
- _set_bit (bf, byte_count, MONGOC_MD_FLAG_NO_AUTOMATIC_GLOBALS);
-#endif
-
-#ifdef MONGOC_EXPERIMENTAL_FEATURES
- _set_bit (bf, byte_count, MONGOC_MD_FLAG_EXPERIMENTAL_FEATURES);
-#endif
-
-#ifdef MONGOC_ENABLE_SSL_LIBRESSL
- _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_SSL_LIBRESSL);
-#endif
-
-#ifdef MONGOC_ENABLE_SASL_CYRUS
- _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_SASL_CYRUS);
-#endif
-
-#ifdef MONGOC_ENABLE_SASL_SSPI
- _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_SASL_SSPI);
-#endif
-
-#ifdef MONGOC_HAVE_SOCKLEN
- _set_bit (bf, byte_count, MONGOC_MD_FLAG_HAVE_SOCKLEN);
-#endif
-
-#ifdef MONGOC_ENABLE_COMPRESSION
- _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_COMPRESSION);
-#endif
-
-#ifdef MONGOC_ENABLE_COMPRESSION_SNAPPY
- _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_COMPRESSION_SNAPPY);
-#endif
-
-#ifdef MONGOC_ENABLE_COMPRESSION_ZLIB
- _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_COMPRESSION_ZLIB);
-#endif
-
-#ifdef MONGOC_HAVE_RES_NSEARCH
- _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_RES_NSEARCH);
-#endif
-
-#ifdef MONGOC_HAVE_RES_NDESTROY
- _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_RES_NDESTROY);
-#endif
-
-#ifdef MONGOC_HAVE_RES_NCLOSE
- _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_RES_NCLOSE);
-#endif
-
-#ifdef MONGOC_HAVE_RES_SEARCH
- _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_RES_SEARCH);
-#endif
-
-#ifdef MONGOC_HAVE_DNSAPI
- _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_DNSAPI);
-#endif
-
-#ifdef MONGOC_HAVE_RDTSCP
- _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_RDTSCP);
-#endif
-
-#ifdef MONGOC_HAVE_SCHED_GETCPU
- _set_bit (bf, byte_count, MONGOC_MD_FLAG_HAVE_SCHED_GETCPU);
-#endif
-
-#ifdef MONGOC_ENABLE_SHM_COUNTERS
- _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_SHM_COUNTERS);
-#endif
-
-#ifdef MONGOC_TRACE
- _set_bit (bf, byte_count, MONGOC_MD_FLAG_TRACE);
-#endif
-
-#ifdef MONGOC_ENABLE_ICU
- _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_ICU);
-#endif
-
-#ifdef MONGOC_ENABLE_CLIENT_SIDE_ENCRYPTION
- _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_CLIENT_SIDE_ENCRYPTION);
-#endif
-
-#ifdef MONGOC_ENABLE_MONGODB_AWS_AUTH
- _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_MONGODB_AWS_AUTH);
-#endif
-
- str = bson_string_new ("0x");
- for (i = 0; i < byte_count; i++) {
- bson_string_append_printf (str, "%02x", bf[i]);
- }
- bson_free (bf);
- /* free the bson_string_t, but keep the underlying char* alive. */
- return bson_string_free (str, false);
-}
-
-static char *
-_get_os_type (void)
-{
-#ifdef MONGOC_OS_TYPE
- return bson_strndup (MONGOC_OS_TYPE, HANDSHAKE_OS_TYPE_MAX);
-#else
- return bson_strndup ("unknown", HANDSHAKE_OS_TYPE_MAX);
-#endif
-}
-
-static char *
-_get_os_architecture (void)
-{
- const char *ret = NULL;
-
-#ifdef _WIN32
- SYSTEM_INFO system_info;
- DWORD arch;
- GetSystemInfo (&system_info);
-
- arch = system_info.wProcessorArchitecture;
-
- switch (arch) {
- case PROCESSOR_ARCHITECTURE_AMD64:
- ret = "x86_64";
- break;
- case PROCESSOR_ARCHITECTURE_ARM:
- ret = "ARM";
- break;
- case PROCESSOR_ARCHITECTURE_IA64:
- ret = "IA64";
- break;
- case PROCESSOR_ARCHITECTURE_INTEL:
- ret = "x86";
- break;
- case PROCESSOR_ARCHITECTURE_UNKNOWN:
- ret = "Unknown";
- break;
- default:
- ret = "Other";
- break;
- }
-
-#elif defined(_POSIX_VERSION)
- struct utsname system_info;
-
- if (uname (&system_info) >= 0) {
- ret = system_info.machine;
- }
-
-#endif
-
- if (ret) {
- return bson_strndup (ret, HANDSHAKE_OS_ARCHITECTURE_MAX);
- }
-
- return NULL;
-}
-
-#ifndef MONGOC_OS_IS_LINUX
-static char *
-_get_os_name (void)
-{
-#ifdef MONGOC_OS_NAME
- return bson_strndup (MONGOC_OS_NAME, HANDSHAKE_OS_NAME_MAX);
-#elif defined(_POSIX_VERSION)
- struct utsname system_info;
-
- if (uname (&system_info) >= 0) {
- return bson_strndup (system_info.sysname, HANDSHAKE_OS_NAME_MAX);
- }
-
-#endif
-
- return NULL;
-}
-
-static char *
-_get_os_version (void)
-{
- char *ret = bson_malloc (HANDSHAKE_OS_VERSION_MAX);
- bool found = false;
-
-#ifdef _WIN32
- OSVERSIONINFO osvi;
- ZeroMemory (&osvi, sizeof (OSVERSIONINFO));
- osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
-
- if (GetVersionEx (&osvi)) {
- bson_snprintf (ret,
- HANDSHAKE_OS_VERSION_MAX,
- "%lu.%lu (%lu)",
- osvi.dwMajorVersion,
- osvi.dwMinorVersion,
- osvi.dwBuildNumber);
- found = true;
- } else {
- MONGOC_WARNING ("Error with GetVersionEx(): %lu", GetLastError ());
- }
-
-#elif defined(_POSIX_VERSION)
- struct utsname system_info;
-
- if (uname (&system_info) >= 0) {
- bson_strncpy (ret, system_info.release, HANDSHAKE_OS_VERSION_MAX);
- found = true;
- } else {
- MONGOC_WARNING ("Error with uname(): %d", errno);
- }
-
-#endif
-
- if (!found) {
- bson_free (ret);
- ret = NULL;
- }
-
- return ret;
-}
-#endif
-
-static void
-_get_system_info (mongoc_handshake_t *handshake)
-{
- handshake->os_type = _get_os_type ();
-
-#ifdef MONGOC_OS_IS_LINUX
- _mongoc_linux_distro_scanner_get_distro (&handshake->os_name,
- &handshake->os_version);
-#else
- handshake->os_name = _get_os_name ();
- handshake->os_version = _get_os_version ();
-#endif
-
- handshake->os_architecture = _get_os_architecture ();
-}
-
-static void
-_free_system_info (mongoc_handshake_t *handshake)
-{
- bson_free (handshake->os_type);
- bson_free (handshake->os_name);
- bson_free (handshake->os_version);
- bson_free (handshake->os_architecture);
-}
-
-static void
-_get_driver_info (mongoc_handshake_t *handshake)
-{
- handshake->driver_name = bson_strndup ("mongoc", HANDSHAKE_DRIVER_NAME_MAX);
- handshake->driver_version =
- bson_strndup (MONGOC_VERSION_S, HANDSHAKE_DRIVER_VERSION_MAX);
-}
-
-static void
-_free_driver_info (mongoc_handshake_t *handshake)
-{
- bson_free (handshake->driver_name);
- bson_free (handshake->driver_version);
-}
-
-static void
-_set_platform_string (mongoc_handshake_t *handshake)
-{
- bson_string_t *str;
-
- str = bson_string_new ("");
-
- handshake->platform = bson_string_free (str, false);
-}
-
-static void
-_set_compiler_info (mongoc_handshake_t *handshake)
-{
- bson_string_t *str;
- char *config_str;
-
- str = bson_string_new ("");
-
- config_str = _mongoc_handshake_get_config_hex_string ();
- bson_string_append_printf (str, "cfg=%s", config_str);
- bson_free (config_str);
-
-#ifdef _POSIX_VERSION
- bson_string_append_printf (str, " posix=%ld", _POSIX_VERSION);
-#endif
-
-#ifdef __STDC_VERSION__
- bson_string_append_printf (str, " stdc=%ld", __STDC_VERSION__);
-#endif
-
- bson_string_append_printf (str, " CC=%s", MONGOC_COMPILER);
-
-#ifdef MONGOC_COMPILER_VERSION
- bson_string_append_printf (str, " %s", MONGOC_COMPILER_VERSION);
-#endif
- handshake->compiler_info = bson_string_free (str, false);
-}
-
-static void
-_set_flags (mongoc_handshake_t *handshake)
-{
- bson_string_t *str;
-
- str = bson_string_new ("");
-
- if (strlen (MONGOC_EVALUATE_STR (MONGOC_USER_SET_CFLAGS)) > 0) {
- bson_string_append_printf (
- str, " CFLAGS=%s", MONGOC_EVALUATE_STR (MONGOC_USER_SET_CFLAGS));
- }
-
- if (strlen (MONGOC_EVALUATE_STR (MONGOC_USER_SET_LDFLAGS)) > 0) {
- bson_string_append_printf (
- str, " LDFLAGS=%s", MONGOC_EVALUATE_STR (MONGOC_USER_SET_LDFLAGS));
- }
-
- handshake->flags = bson_string_free (str, false);
-}
-
-static void
-_free_platform_string (mongoc_handshake_t *handshake)
-{
- bson_free (handshake->platform);
- bson_free (handshake->compiler_info);
- bson_free (handshake->flags);
-}
-
-void
-_mongoc_handshake_init (void)
-{
- _get_system_info (_mongoc_handshake_get ());
- _get_driver_info (_mongoc_handshake_get ());
- _set_platform_string (_mongoc_handshake_get ());
- _set_compiler_info (_mongoc_handshake_get ());
- _set_flags (_mongoc_handshake_get ());
-
- _mongoc_handshake_get ()->frozen = false;
- bson_mutex_init (&gHandshakeLock);
-}
-
-void
-_mongoc_handshake_cleanup (void)
-{
- _free_system_info (_mongoc_handshake_get ());
- _free_driver_info (_mongoc_handshake_get ());
- _free_platform_string (_mongoc_handshake_get ());
-
- bson_mutex_destroy (&gHandshakeLock);
-}
-
-static void
-_append_platform_field (bson_t *doc, const char *platform)
-{
- int max_platform_str_size;
-
- char *compiler_info = _mongoc_handshake_get ()->compiler_info;
- char *flags = _mongoc_handshake_get ()->flags;
- bson_string_t *combined_platform = bson_string_new (platform);
-
- /* Compute space left for platform field */
- max_platform_str_size =
- HANDSHAKE_MAX_SIZE - ((int) doc->len +
- /* 1 byte for utf8 tag */
- 1 +
-
- /* key size */
- (int) strlen (HANDSHAKE_PLATFORM_FIELD) + 1 +
-
- /* 4 bytes for length of string */
- 4);
-
- if (max_platform_str_size <= 0) {
- bson_string_free (combined_platform, true);
- return;
- }
-
- /* We opt to drop compiler info and flags if they can't fit, while the
- * platform information is truncated
- * Try to drop flags first, and if there is still not enough space also drop
- * compiler info */
- if (max_platform_str_size >
- combined_platform->len + strlen (compiler_info) + 1) {
- bson_string_append (combined_platform, compiler_info);
- }
- if (max_platform_str_size > combined_platform->len + strlen (flags) + 1) {
- bson_string_append (combined_platform, flags);
- }
-
- /* We use the flags_index field to check if the CLAGS/LDFLAGS need to be
- * truncated, and if so we drop them altogether */
- bson_append_utf8 (
- doc,
- HANDSHAKE_PLATFORM_FIELD,
- -1,
- combined_platform->str,
- BSON_MIN (max_platform_str_size - 1, combined_platform->len));
-
- bson_string_free (combined_platform, true);
- BSON_ASSERT (doc->len <= HANDSHAKE_MAX_SIZE);
-}
-
-/*
- * Return true if we build the document, and it's not too big
- * false if there's no way to prevent the doc from being too big. In this
- * case, the caller shouldn't include it with hello
- */
-bool
-_mongoc_handshake_build_doc_with_application (bson_t *doc, const char *appname)
-{
- const mongoc_handshake_t *md = _mongoc_handshake_get ();
- bson_t child;
-
- if (appname) {
- BSON_APPEND_DOCUMENT_BEGIN (doc, "application", &child);
- BSON_APPEND_UTF8 (&child, "name", appname);
- bson_append_document_end (doc, &child);
- }
-
- BSON_APPEND_DOCUMENT_BEGIN (doc, "driver", &child);
- BSON_APPEND_UTF8 (&child, "name", md->driver_name);
- BSON_APPEND_UTF8 (&child, "version", md->driver_version);
- bson_append_document_end (doc, &child);
-
- BSON_APPEND_DOCUMENT_BEGIN (doc, "os", &child);
-
- BSON_ASSERT (md->os_type);
- BSON_APPEND_UTF8 (&child, "type", md->os_type);
-
- if (md->os_name) {
- BSON_APPEND_UTF8 (&child, "name", md->os_name);
- }
-
- if (md->os_version) {
- BSON_APPEND_UTF8 (&child, "version", md->os_version);
- }
-
- if (md->os_architecture) {
- BSON_APPEND_UTF8 (&child, "architecture", md->os_architecture);
- }
-
- bson_append_document_end (doc, &child);
-
- if (doc->len > HANDSHAKE_MAX_SIZE) {
- /* We've done all we can possibly do to ensure the current
- * document is below the maxsize, so if it overflows there is
- * nothing else we can do, so we fail */
- return false;
- }
-
- if (md->platform) {
- _append_platform_field (doc, md->platform);
- }
-
- return true;
-}
-
-void
-_mongoc_handshake_freeze (void)
-{
- _mongoc_handshake_get ()->frozen = true;
-}
-
-/*
- * free (*s) and make *s point to *s concated with suffix.
- * If *s is NULL it's treated like it's an empty string.
- */
-static void
-_append_and_truncate (char **s, const char *suffix, int max_len)
-{
- char *old_str = *s;
- char *prefix;
- const int delim_len = (int) strlen (" / ");
- int space_for_suffix;
-
- BSON_ASSERT_PARAM (s);
- BSON_ASSERT_PARAM (suffix);
-
- prefix = old_str ? old_str : "";
-
- space_for_suffix = max_len - (int) strlen (prefix) - delim_len;
-
- if (space_for_suffix <= 0) {
- /* the old string already takes the whole allotted space */
- return;
- }
-
- *s = bson_strdup_printf ("%s / %.*s", prefix, space_for_suffix, suffix);
- BSON_ASSERT (strlen (*s) <= max_len);
-
- bson_free (old_str);
-}
-
-
-/*
- * Set some values in our global handshake struct. These values will be sent
- * to the server as part of the initial connection handshake (hello).
- * If this function is called more than once, or after we've connected to a
- * mongod, then it will do nothing and return false. It will return true if it
- * successfully sets the values.
- *
- * All arguments are optional.
- */
-bool
-mongoc_handshake_data_append (const char *driver_name,
- const char *driver_version,
- const char *platform)
-{
- int platform_space;
-
- bson_mutex_lock (&gHandshakeLock);
-
- if (_mongoc_handshake_get ()->frozen) {
- bson_mutex_unlock (&gHandshakeLock);
- return false;
- }
-
- BSON_ASSERT (_mongoc_handshake_get ()->platform);
-
- /* allow practically any size for "platform", we'll trim it down in
- * _mongoc_handshake_build_doc_with_application */
- platform_space =
- HANDSHAKE_MAX_SIZE - (int) strlen (_mongoc_handshake_get ()->platform);
-
- if (platform) {
- /* we check for an empty string as a special case to avoid an unnecessary
- * delimiter being added in front of the string by _append_and_truncate */
- if (_mongoc_handshake_get ()->platform[0] == '\0') {
- bson_free (_mongoc_handshake_get ()->platform);
- _mongoc_handshake_get ()->platform =
- bson_strdup_printf ("%.*s", platform_space, platform);
- } else {
- _append_and_truncate (
- &_mongoc_handshake_get ()->platform, platform, HANDSHAKE_MAX_SIZE);
- }
- }
-
- if (driver_name) {
- _append_and_truncate (&_mongoc_handshake_get ()->driver_name,
- driver_name,
- HANDSHAKE_DRIVER_NAME_MAX);
- }
-
- if (driver_version) {
- _append_and_truncate (&_mongoc_handshake_get ()->driver_version,
- driver_version,
- HANDSHAKE_DRIVER_VERSION_MAX);
- }
-
- _mongoc_handshake_freeze ();
- bson_mutex_unlock (&gHandshakeLock);
-
- return true;
-}
-
-mongoc_handshake_t *
-_mongoc_handshake_get (void)
-{
- return &gMongocHandshake;
-}
-
-bool
-_mongoc_handshake_appname_is_valid (const char *appname)
-{
- return strlen (appname) <= MONGOC_HANDSHAKE_APPNAME_MAX;
-}
-
-void
-_mongoc_handshake_append_sasl_supported_mechs (const mongoc_uri_t *uri,
- bson_t *cmd)
-{
- const char *username;
- char *db_user;
- username = mongoc_uri_get_username (uri);
- db_user =
- bson_strdup_printf ("%s.%s", mongoc_uri_get_auth_source (uri), username);
- bson_append_utf8 (cmd, "saslSupportedMechs", 18, db_user, -1);
- bson_free (db_user);
-}
-
-void
-_mongoc_handshake_parse_sasl_supported_mechs (
- const bson_t *hello,
- mongoc_handshake_sasl_supported_mechs_t *sasl_supported_mechs)
-{
- bson_iter_t iter;
- memset (sasl_supported_mechs, 0, sizeof (*sasl_supported_mechs));
- if (bson_iter_init_find (&iter, hello, "saslSupportedMechs")) {
- bson_iter_t array_iter;
- if (BSON_ITER_HOLDS_ARRAY (&iter) &&
- bson_iter_recurse (&iter, &array_iter)) {
- while (bson_iter_next (&array_iter)) {
- if (BSON_ITER_HOLDS_UTF8 (&array_iter)) {
- const char *mechanism_name = bson_iter_utf8 (&array_iter, NULL);
- if (0 == strcmp (mechanism_name, "SCRAM-SHA-256")) {
- sasl_supported_mechs->scram_sha_256 = true;
- } else if (0 == strcmp (mechanism_name, "SCRAM-SHA-1")) {
- sasl_supported_mechs->scram_sha_1 = true;
- }
- }
- }
- }
- }
-}
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-host-list-private.h b/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-host-list-private.h
deleted file mode 100644
index b830a7e5..00000000
--- a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-host-list-private.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright 2013 MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "mongoc-prelude.h"
-
-#ifndef MONGOC_HOST_LIST_PRIVATE_H
-#define MONGOC_HOST_LIST_PRIVATE_H
-
-#include "mongoc-host-list.h"
-
-
-BSON_BEGIN_DECLS
-
-mongoc_host_list_t *
-_mongoc_host_list_push (const char *host,
- uint16_t port,
- int family,
- mongoc_host_list_t *next);
-
-void
-_mongoc_host_list_upsert (mongoc_host_list_t **list,
- const mongoc_host_list_t *new_host);
-
-mongoc_host_list_t *
-_mongoc_host_list_copy_all (const mongoc_host_list_t *src);
-
-bool
-_mongoc_host_list_from_string (mongoc_host_list_t *host_list,
- const char *host_and_port);
-
-bool
-_mongoc_host_list_from_string_with_err (mongoc_host_list_t *host_list,
- const char *host_and_port,
- bson_error_t *error);
-
-bool
-_mongoc_host_list_from_hostport_with_err (mongoc_host_list_t *host_list,
- const char *host,
- uint16_t port,
- bson_error_t *error);
-
-int
-_mongoc_host_list_length (mongoc_host_list_t *list);
-
-bool
-_mongoc_host_list_compare_one (const mongoc_host_list_t *host_a,
- const mongoc_host_list_t *host_b);
-
-void
-_mongoc_host_list_remove_host (mongoc_host_list_t **phosts,
- const char *host,
- uint16_t port);
-
-void
-_mongoc_host_list_destroy_all (mongoc_host_list_t *host);
-
-bool
-_mongoc_host_list_contains_one (mongoc_host_list_t *host_list,
- mongoc_host_list_t *host);
-
-BSON_END_DECLS
-
-
-#endif /* MONGOC_HOST_LIST_PRIVATE_H */
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-host-list.c b/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-host-list.c
deleted file mode 100644
index 2d17f846..00000000
--- a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-host-list.c
+++ /dev/null
@@ -1,397 +0,0 @@
-/*
- * Copyright 2015 MongoDB Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "mongoc-host-list-private.h"
-/* strcasecmp on windows */
-#include "mongoc-util-private.h"
-#include "utlist.h"
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_host_list_push --
- *
- * Add a host to the front of the list and return it.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-mongoc_host_list_t *
-_mongoc_host_list_push (const char *host,
- uint16_t port,
- int family,
- mongoc_host_list_t *next)
-{
- mongoc_host_list_t *h;
-
- BSON_ASSERT (host);
-
- h = bson_malloc0 (sizeof (mongoc_host_list_t));
- bson_strncpy (h->host, host, sizeof h->host);
- h->port = port;
- bson_snprintf (
- h->host_and_port, sizeof h->host_and_port, "%s:%hu", host, port);
-
- h->family = family;
- h->next = next;
-
- return h;
-}
-
-static mongoc_host_list_t *
-_mongoc_host_list_find_host_and_port (mongoc_host_list_t *hosts,
- const char *host_and_port)
-{
- mongoc_host_list_t *iter;
- LL_FOREACH (hosts, iter)
- {
- BSON_ASSERT (iter);
-
- if (strcasecmp (iter->host_and_port, host_and_port) == 0) {
- return iter;
- }
- }
-
- return NULL;
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_host_list_upsert --
- *
- * If new_host is not already in list, copy and add it to the end of list.
- * If *list == NULL, then it will be set to a new host.
- *
- * Returns:
- * Nothing.
- *
- *--------------------------------------------------------------------------
- */
-void
-_mongoc_host_list_upsert (mongoc_host_list_t **list,
- const mongoc_host_list_t *new_host)
-{
- mongoc_host_list_t *link = NULL;
- mongoc_host_list_t *next_link = NULL;
-
- BSON_ASSERT (list);
- if (!new_host) {
- return;
- }
-
- link = _mongoc_host_list_find_host_and_port (*list, new_host->host_and_port);
-
- if (!link) {
- link = bson_malloc0 (sizeof (mongoc_host_list_t));
- LL_APPEND (*list, link);
- } else {
- /* Make sure linking is preserved when copying data into final. */
- next_link = link->next;
- }
-
- memcpy (link, new_host, sizeof (mongoc_host_list_t));
- link->next = next_link;
-}
-
-
-/* Duplicates a host list.
- */
-mongoc_host_list_t *
-_mongoc_host_list_copy_all (const mongoc_host_list_t *src)
-{
- mongoc_host_list_t *tail = NULL;
- const mongoc_host_list_t *src_iter;
- mongoc_host_list_t *head = NULL;
-
- LL_FOREACH (src, src_iter)
- {
- tail = bson_malloc0 (sizeof (mongoc_host_list_t));
- memcpy (tail, src_iter, sizeof (mongoc_host_list_t));
-
- LL_PREPEND (head, tail);
- }
-
- return head;
-}
-
-int
-_mongoc_host_list_length (mongoc_host_list_t *list)
-{
- mongoc_host_list_t *tmp;
- int counter = 0;
-
- tmp = list;
- while (tmp) {
- tmp = tmp->next;
- counter++;
- }
-
- return counter;
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_host_list_compare_one --
- *
- * Check two hosts have the same domain (case-insensitive), port,
- * and address family.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-bool
-_mongoc_host_list_compare_one (const mongoc_host_list_t *host_a,
- const mongoc_host_list_t *host_b)
-{
- return (0 == strcasecmp (host_a->host_and_port, host_b->host_and_port) &&
- host_a->family == host_b->family);
-}
-
-bool
-_mongoc_host_list_contains_one (mongoc_host_list_t *host_list,
- mongoc_host_list_t *host)
-{
- return NULL !=
- _mongoc_host_list_find_host_and_port (host_list, host->host_and_port);
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_host_list_destroy_all --
- *
- * Destroy whole linked list of hosts.
- *
- *--------------------------------------------------------------------------
- */
-void
-_mongoc_host_list_destroy_all (mongoc_host_list_t *host)
-{
- mongoc_host_list_t *tmp;
-
- while (host) {
- tmp = host->next;
- bson_free (host);
- host = tmp;
- }
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_host_list_from_string --
- *
- * Populate a mongoc_host_list_t from a fully qualified address
- *
- *--------------------------------------------------------------------------
- */
-bool
-_mongoc_host_list_from_string (mongoc_host_list_t *link_, const char *address)
-{
- bson_error_t error = {0};
- bool r = _mongoc_host_list_from_string_with_err (link_, address, &error);
- if (!r) {
- MONGOC_ERROR ("Could not parse address %s: %s", address, error.message);
- return false;
- }
- return true;
-}
-
-bool
-_mongoc_host_list_from_string_with_err (mongoc_host_list_t *link_,
- const char *address,
- bson_error_t *error)
-{
- char *close_bracket;
- char *sport;
- uint16_t port;
- char *host;
- bool ret;
- bool ipv6 = false;
-
- close_bracket = strchr (address, ']');
-
- /* if this is an ipv6 address. */
- if (close_bracket) {
- /* if present, the port should immediately follow after ] */
- sport = strchr (close_bracket, ':');
- if (sport > close_bracket + 1) {
- bson_set_error (error,
- MONGOC_ERROR_COMMAND,
- MONGOC_ERROR_COMMAND_INVALID_ARG,
- "If present, port should immediately follow the \"]\""
- "in an IPv6 address"
- );
- return false;
- }
-
- /* otherwise ] should be the last char. */
- if (!sport && *(close_bracket + 1) != '\0') {
- bson_set_error (error,
- MONGOC_ERROR_COMMAND,
- MONGOC_ERROR_COMMAND_INVALID_ARG,
- "If port is not supplied, \"[\" should be the last"
- "character");
- return false;
- }
-
- if (*address != '[') {
- bson_set_error (error,
- MONGOC_ERROR_COMMAND,
- MONGOC_ERROR_COMMAND_INVALID_ARG,
- "Missing matching bracket \"[\""
- );
- return false;
- }
-
- ipv6 = true;
- }
- /* otherwise, just find the first : */
- else {
- sport = strchr (address, ':');
- }
-
- /* like "example.com:27019" or "[fe80::1]:27019", but not "[fe80::1]" */
- if (sport) {
- if (sport == address) {
- /* bad address like ":27017" */
- bson_set_error (error,
- MONGOC_ERROR_COMMAND,
- MONGOC_ERROR_COMMAND_INVALID_ARG,
- "Bad address, \":\" should not be first character"
- );
- return false;
- }
-
- if (!mongoc_parse_port (&port, sport + 1)) {
- bson_set_error (error,
- MONGOC_ERROR_COMMAND,
- MONGOC_ERROR_COMMAND_INVALID_ARG,
- "Port could not be parsed"
- );
- return false;
- }
-
- /* if this is an ipv6 address, strip the [ and ] */
- if (ipv6) {
- host = bson_strndup (address + 1, close_bracket - address - 1);
- } else {
- host = bson_strndup (address, sport - address);
- }
- } else {
- /* if this is an ipv6 address, strip the [ and ] */
- if (ipv6) {
- host = bson_strndup (address + 1, close_bracket - address - 1);
- } else {
- host = bson_strdup (address);
- }
- port = MONGOC_DEFAULT_PORT;
- }
-
- ret = _mongoc_host_list_from_hostport_with_err (link_, host, port, error);
-
- bson_free (host);
-
- return ret;
-}
-
-bool
-_mongoc_host_list_from_hostport_with_err (mongoc_host_list_t *link_,
- const char *host,
- uint16_t port,
- bson_error_t *error)
-{
- size_t host_len = strlen (host);
- link_->port = port;
-
- if (host_len == 0) {
- bson_set_error (error,
- MONGOC_ERROR_STREAM,
- MONGOC_ERROR_STREAM_NAME_RESOLUTION,
- "Empty hostname in URI");
- return false;
- }
-
- if (host_len > BSON_HOST_NAME_MAX) {
- bson_set_error (error,
- MONGOC_ERROR_STREAM,
- MONGOC_ERROR_STREAM_NAME_RESOLUTION,
- "Hostname provided in URI is too long, max is %d chars",
- BSON_HOST_NAME_MAX);
- return false;
- }
-
- bson_strncpy (link_->host, host, host_len + 1);
-
- /* like "fe80::1" or "::1" */
- if (strchr (host, ':')) {
- link_->family = AF_INET6;
-
- mongoc_lowercase (link_->host, link_->host);
- bson_snprintf (link_->host_and_port,
- sizeof link_->host_and_port,
- "[%s]:%hu",
- link_->host,
- link_->port);
-
- } else if (strchr (host, '/') && strstr (host, ".sock")) {
- link_->family = AF_UNIX;
- bson_strncpy (link_->host_and_port, link_->host, host_len + 1);
- } else {
- /* This is either an IPv4 or hostname. */
- link_->family = AF_UNSPEC;
-
- mongoc_lowercase (link_->host, link_->host);
- bson_snprintf (link_->host_and_port,
- sizeof link_->host_and_port,
- "%s:%hu",
- link_->host,
- link_->port);
- }
-
- link_->next = NULL;
- return true;
-}
-
-void
-_mongoc_host_list_remove_host (mongoc_host_list_t **hosts,
- const char *host,
- uint16_t port)
-{
- mongoc_host_list_t *current;
- mongoc_host_list_t *prev = NULL;
-
- for (current = *hosts; current; prev = current, current = current->next) {
- if ((current->port == port) && (strcmp (current->host, host) == 0)) {
- /* Node found, unlink. */
- if (prev) {
- prev->next = current->next;
- } else {
- /* No previous, unlinking at head. */
- *hosts = current->next;
- }
- bson_free (current);
- break;
- }
- }
-}
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-log.c b/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-log.c
deleted file mode 100644
index 54c84828..00000000
--- a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-log.c
+++ /dev/null
@@ -1,344 +0,0 @@
-/*
- * Copyright 2013 MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-#if defined(__linux__)
-#include <sys/syscall.h>
-#elif defined(_WIN32)
-#include <process.h>
-#elif defined(__APPLE__)
-#include <pthread.h>
-#elif defined(__FreeBSD__)
-#include <sys/thr.h>
-#elif defined(__NetBSD__)
-#include <lwp.h>
-#else
-#include <unistd.h>
-#endif
-#include <stdarg.h>
-#include <time.h>
-
-#include "mongoc-log.h"
-#include "mongoc-log-private.h"
-#include "mongoc-thread-private.h"
-
-
-static bson_once_t once = BSON_ONCE_INIT;
-static bson_mutex_t gLogMutex;
-static mongoc_log_func_t gLogFunc = mongoc_log_default_handler;
-#ifdef MONGOC_TRACE
-static bool gLogTrace = true;
-#endif
-static void *gLogData;
-
-static BSON_ONCE_FUN (_mongoc_ensure_mutex_once)
-{
- bson_mutex_init (&gLogMutex);
-
- BSON_ONCE_RETURN;
-}
-
-void
-mongoc_log_set_handler (mongoc_log_func_t log_func, void *user_data)
-{
- bson_once (&once, &_mongoc_ensure_mutex_once);
-
- bson_mutex_lock (&gLogMutex);
- gLogFunc = log_func;
- gLogData = user_data;
- bson_mutex_unlock (&gLogMutex);
-}
-
-
-/* just for testing */
-void
-_mongoc_log_get_handler (mongoc_log_func_t *log_func, void **user_data)
-{
- *log_func = gLogFunc;
- *user_data = gLogData;
-}
-
-
-void
-mongoc_log (mongoc_log_level_t log_level,
- const char *log_domain,
- const char *format,
- ...)
-{
- va_list args;
- char *message;
- int stop_logging;
-
- bson_once (&once, &_mongoc_ensure_mutex_once);
-
- stop_logging = !gLogFunc;
-#ifdef MONGOC_TRACE
- stop_logging =
- stop_logging || (log_level == MONGOC_LOG_LEVEL_TRACE && !gLogTrace);
-#endif
- if (stop_logging) {
- return;
- }
-
- BSON_ASSERT (format);
-
- va_start (args, format);
- message = bson_strdupv_printf (format, args);
- va_end (args);
-
- bson_mutex_lock (&gLogMutex);
- gLogFunc (log_level, log_domain, message, gLogData);
- bson_mutex_unlock (&gLogMutex);
-
- bson_free (message);
-}
-
-
-const char *
-mongoc_log_level_str (mongoc_log_level_t log_level)
-{
- switch (log_level) {
- case MONGOC_LOG_LEVEL_ERROR:
- return "ERROR";
- case MONGOC_LOG_LEVEL_CRITICAL:
- return "CRITICAL";
- case MONGOC_LOG_LEVEL_WARNING:
- return "WARNING";
- case MONGOC_LOG_LEVEL_MESSAGE:
- return "MESSAGE";
- case MONGOC_LOG_LEVEL_INFO:
- return "INFO";
- case MONGOC_LOG_LEVEL_DEBUG:
- return "DEBUG";
- case MONGOC_LOG_LEVEL_TRACE:
- return "TRACE";
- default:
- return "UNKNOWN";
- }
-}
-
-
-void
-mongoc_log_default_handler (mongoc_log_level_t log_level,
- const char *log_domain,
- const char *message,
- void *user_data)
-{
- struct timeval tv;
- struct tm tt;
- time_t t;
- FILE *stream;
- char nowstr[32];
- int pid;
-
- bson_gettimeofday (&tv);
- t = tv.tv_sec;
-
-#ifdef _WIN32
-#ifdef _MSC_VER
- localtime_s (&tt, &t);
-#else
- tt = *(localtime (&t));
-#endif
-#else
- localtime_r (&t, &tt);
-#endif
-
- strftime (nowstr, sizeof nowstr, "%Y/%m/%d %H:%M:%S", &tt);
-
- switch (log_level) {
- case MONGOC_LOG_LEVEL_ERROR:
- case MONGOC_LOG_LEVEL_CRITICAL:
- case MONGOC_LOG_LEVEL_WARNING:
- stream = stderr;
- break;
- case MONGOC_LOG_LEVEL_MESSAGE:
- case MONGOC_LOG_LEVEL_INFO:
- case MONGOC_LOG_LEVEL_DEBUG:
- case MONGOC_LOG_LEVEL_TRACE:
- default:
- stream = stdout;
- }
-
-#ifdef __linux__
- pid = syscall (SYS_gettid);
-#elif defined(_WIN32)
- pid = (int) _getpid ();
-#elif defined(__FreeBSD__)
- long tid;
- thr_self (&tid);
- pid = (int) tid;
-#elif defined(__OpenBSD__)
- pid = (int) getthrid ();
-#elif defined(__NetBSD__)
- pid = (int) _lwp_self ();
-#elif defined(__APPLE__)
- uint64_t tid;
- pthread_threadid_np (0, &tid);
- pid = (int) tid;
-#else
- pid = (int) getpid ();
-#endif
-
- fprintf (stream,
- "%s.%04ld: [%5d]: %8s: %12s: %s\n",
- nowstr,
- tv.tv_usec / 1000L,
- pid,
- mongoc_log_level_str (log_level),
- log_domain,
- message);
-}
-
-bool
-_mongoc_log_trace_is_enabled (void)
-{
-#ifdef MONGOC_TRACE
- return gLogTrace;
-#else
- return false;
-#endif
-}
-
-void
-mongoc_log_trace_enable (void)
-{
-#ifdef MONGOC_TRACE
- gLogTrace = true;
-#endif
-}
-
-void
-mongoc_log_trace_disable (void)
-{
-#ifdef MONGOC_TRACE
- gLogTrace = false;
-#endif
-}
-
-void
-mongoc_log_trace_bytes (const char *domain, const uint8_t *_b, size_t _l)
-{
- bson_string_t *str, *astr;
- int32_t _i;
- uint8_t _v;
-
-#ifdef MONGOC_TRACE
- if (!gLogTrace) {
- return;
- }
-#endif
-
- str = bson_string_new (NULL);
- astr = bson_string_new (NULL);
- for (_i = 0; _i < _l; _i++) {
- _v = *(_b + _i);
-
- if ((_i % 16) == 0) {
- bson_string_append_printf (str, "%05x: ", _i);
- }
-
- bson_string_append_printf (str, " %02x", _v);
- if (isprint (_v)) {
- bson_string_append_printf (astr, " %c", _v);
- } else {
- bson_string_append (astr, " .");
- }
-
- if ((_i % 16) == 15) {
- mongoc_log (
- MONGOC_LOG_LEVEL_TRACE, domain, "%s %s", str->str, astr->str);
- bson_string_truncate (str, 0);
- bson_string_truncate (astr, 0);
- } else if ((_i % 16) == 7) {
- bson_string_append (str, " ");
- bson_string_append (astr, " ");
- }
- }
-
- if (_i != 16) {
- mongoc_log (
- MONGOC_LOG_LEVEL_TRACE, domain, "%-56s %s", str->str, astr->str);
- }
-
- bson_string_free (str, true);
- bson_string_free (astr, true);
-}
-
-void
-mongoc_log_trace_iovec (const char *domain,
- const mongoc_iovec_t *_iov,
- size_t _iovcnt)
-{
- bson_string_t *str, *astr;
- const char *_b;
- unsigned _i = 0;
- unsigned _j = 0;
- unsigned _k = 0;
- size_t _l = 0;
- uint8_t _v;
-
-#ifdef MONGOC_TRACE
- if (!gLogTrace) {
- return;
- }
-#endif
-
- for (_i = 0; _i < _iovcnt; _i++) {
- _l += _iov[_i].iov_len;
- }
-
- _i = 0;
- str = bson_string_new (NULL);
- astr = bson_string_new (NULL);
-
- for (_j = 0; _j < _iovcnt; _j++) {
- _b = (char *) _iov[_j].iov_base;
- _l = _iov[_j].iov_len;
-
- for (_k = 0; _k < _l; _k++, _i++) {
- _v = *(_b + _k);
- if ((_i % 16) == 0) {
- bson_string_append_printf (str, "%05x: ", _i);
- }
-
- bson_string_append_printf (str, " %02x", _v);
- if (isprint (_v)) {
- bson_string_append_printf (astr, " %c", _v);
- } else {
- bson_string_append (astr, " .");
- }
-
- if ((_i % 16) == 15) {
- mongoc_log (
- MONGOC_LOG_LEVEL_TRACE, domain, "%s %s", str->str, astr->str);
- bson_string_truncate (str, 0);
- bson_string_truncate (astr, 0);
- } else if ((_i % 16) == 7) {
- bson_string_append (str, " ");
- bson_string_append (astr, " ");
- }
- }
- }
-
- if (_i != 16) {
- mongoc_log (
- MONGOC_LOG_LEVEL_TRACE, domain, "%-56s %s", str->str, astr->str);
- }
-
- bson_string_free (str, true);
- bson_string_free (astr, true);
-}
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-read-prefs.c b/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-read-prefs.c
deleted file mode 100644
index 492c23cf..00000000
--- a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-read-prefs.c
+++ /dev/null
@@ -1,422 +0,0 @@
-/*
- * Copyright 2013 MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-#include "mongoc-error.h"
-#include "mongoc-read-prefs-private.h"
-#include "mongoc-trace-private.h"
-
-
-mongoc_read_prefs_t *
-mongoc_read_prefs_new (mongoc_read_mode_t mode)
-{
- mongoc_read_prefs_t *read_prefs;
-
- read_prefs = (mongoc_read_prefs_t *) bson_malloc0 (sizeof *read_prefs);
- read_prefs->mode = mode;
- bson_init (&read_prefs->tags);
- read_prefs->max_staleness_seconds = MONGOC_NO_MAX_STALENESS;
- bson_init (&read_prefs->hedge);
-
- return read_prefs;
-}
-
-
-mongoc_read_mode_t
-mongoc_read_prefs_get_mode (const mongoc_read_prefs_t *read_prefs)
-{
- return read_prefs ? read_prefs->mode : MONGOC_READ_PRIMARY;
-}
-
-
-void
-mongoc_read_prefs_set_mode (mongoc_read_prefs_t *read_prefs,
- mongoc_read_mode_t mode)
-{
- BSON_ASSERT (read_prefs);
- BSON_ASSERT (mode <= MONGOC_READ_NEAREST);
-
- read_prefs->mode = mode;
-}
-
-
-const bson_t *
-mongoc_read_prefs_get_tags (const mongoc_read_prefs_t *read_prefs)
-{
- BSON_ASSERT (read_prefs);
- return &read_prefs->tags;
-}
-
-
-void
-mongoc_read_prefs_set_tags (mongoc_read_prefs_t *read_prefs, const bson_t *tags)
-{
- BSON_ASSERT (read_prefs);
-
- bson_destroy (&read_prefs->tags);
-
- if (tags) {
- bson_copy_to (tags, &read_prefs->tags);
- } else {
- bson_init (&read_prefs->tags);
- }
-}
-
-
-void
-mongoc_read_prefs_add_tag (mongoc_read_prefs_t *read_prefs, const bson_t *tag)
-{
- bson_t empty = BSON_INITIALIZER;
- char str[16];
- int key;
-
- BSON_ASSERT (read_prefs);
-
- key = bson_count_keys (&read_prefs->tags);
- bson_snprintf (str, sizeof str, "%d", key);
-
- if (tag) {
- bson_append_document (&read_prefs->tags, str, -1, tag);
- } else {
- bson_append_document (&read_prefs->tags, str, -1, &empty);
- }
-
- bson_destroy (&empty);
-}
-
-
-int64_t
-mongoc_read_prefs_get_max_staleness_seconds (
- const mongoc_read_prefs_t *read_prefs)
-{
- BSON_ASSERT (read_prefs);
-
- return read_prefs->max_staleness_seconds;
-}
-
-
-void
-mongoc_read_prefs_set_max_staleness_seconds (mongoc_read_prefs_t *read_prefs,
- int64_t max_staleness_seconds)
-{
- BSON_ASSERT (read_prefs);
-
- read_prefs->max_staleness_seconds = max_staleness_seconds;
-}
-
-
-const bson_t *
-mongoc_read_prefs_get_hedge (const mongoc_read_prefs_t *read_prefs)
-{
- BSON_ASSERT (read_prefs);
-
- return &read_prefs->hedge;
-}
-
-
-void
-mongoc_read_prefs_set_hedge (mongoc_read_prefs_t *read_prefs,
- const bson_t *hedge)
-{
- BSON_ASSERT (read_prefs);
-
- bson_destroy (&read_prefs->hedge);
-
- if (hedge) {
- bson_copy_to (hedge, &read_prefs->hedge);
- } else {
- bson_init (&read_prefs->hedge);
- }
-}
-
-
-bool
-mongoc_read_prefs_is_valid (const mongoc_read_prefs_t *read_prefs)
-{
- BSON_ASSERT (read_prefs);
-
- /*
- * Tags, maxStalenessSeconds, and hedge are not supported with PRIMARY mode.
- */
- if (read_prefs->mode == MONGOC_READ_PRIMARY) {
- if (!bson_empty (&read_prefs->tags) ||
- read_prefs->max_staleness_seconds != MONGOC_NO_MAX_STALENESS ||
- !bson_empty (&read_prefs->hedge)) {
- return false;
- }
- }
-
- if (read_prefs->max_staleness_seconds != MONGOC_NO_MAX_STALENESS &&
- read_prefs->max_staleness_seconds <= 0) {
- return false;
- }
-
- return true;
-}
-
-
-void
-mongoc_read_prefs_destroy (mongoc_read_prefs_t *read_prefs)
-{
- if (read_prefs) {
- bson_destroy (&read_prefs->tags);
- bson_destroy (&read_prefs->hedge);
- bson_free (read_prefs);
- }
-}
-
-
-mongoc_read_prefs_t *
-mongoc_read_prefs_copy (const mongoc_read_prefs_t *read_prefs)
-{
- mongoc_read_prefs_t *ret = NULL;
-
- if (read_prefs) {
- ret = mongoc_read_prefs_new (read_prefs->mode);
- bson_destroy (&ret->tags);
- bson_copy_to (&read_prefs->tags, &ret->tags);
- ret->max_staleness_seconds = read_prefs->max_staleness_seconds;
- bson_destroy (&ret->hedge);
- bson_copy_to (&read_prefs->hedge, &ret->hedge);
- }
-
- return ret;
-}
-
-
-const char *
-_mongoc_read_mode_as_str (mongoc_read_mode_t mode)
-{
- switch (mode) {
- case MONGOC_READ_PRIMARY:
- return "primary";
- case MONGOC_READ_PRIMARY_PREFERRED:
- return "primaryPreferred";
- case MONGOC_READ_SECONDARY:
- return "secondary";
- case MONGOC_READ_SECONDARY_PREFERRED:
- return "secondaryPreferred";
- case MONGOC_READ_NEAREST:
- return "nearest";
- default:
- return "";
- }
-}
-
-
-/* Update result with the read prefs, following Server Selection Spec.
- * The driver must have discovered the server is a mongos.
- */
-static void
-_apply_read_preferences_mongos (
- const mongoc_read_prefs_t *read_prefs,
- const bson_t *query_bson,
- mongoc_assemble_query_result_t *result /* OUT */)
-{
- mongoc_read_mode_t mode;
- const bson_t *tags = NULL;
- bson_t child;
- const char *mode_str;
- int64_t max_staleness_seconds = MONGOC_NO_MAX_STALENESS;
- const bson_t *hedge = NULL;
-
- mode = mongoc_read_prefs_get_mode (read_prefs);
- if (read_prefs) {
- max_staleness_seconds =
- mongoc_read_prefs_get_max_staleness_seconds (read_prefs);
-
- tags = mongoc_read_prefs_get_tags (read_prefs);
- hedge = mongoc_read_prefs_get_hedge (read_prefs);
- }
-
- /* Server Selection Spec says:
- *
- * For mode 'primary', drivers MUST NOT set the secondaryOk wire protocol flag
- * and MUST NOT use $readPreference
- *
- * For mode 'secondary', drivers MUST set the secondaryOk wire protocol flag and
- * MUST also use $readPreference
- *
- * For mode 'primaryPreferred', drivers MUST set the secondaryOk wire protocol
- * flag and MUST also use $readPreference
- *
- * For mode 'secondaryPreferred', drivers MUST set the secondaryOk wire protocol
- * flag. If the read preference contains a non-empty tag_sets parameter,
- * maxStalenessSeconds is a positive integer, or the hedge parameter is
- * non-empty, drivers MUST use $readPreference; otherwise, drivers MUST NOT
- * use $readPreference
- *
- * For mode 'nearest', drivers MUST set the secondaryOk wire protocol flag and
- * MUST also use $readPreference
- */
- if (mode == MONGOC_READ_SECONDARY_PREFERRED &&
- (bson_empty0 (tags) && max_staleness_seconds <= 0 && bson_empty0 (hedge))) {
- result->flags |= MONGOC_QUERY_SECONDARY_OK;
-
- } else if (mode != MONGOC_READ_PRIMARY) {
- result->flags |= MONGOC_QUERY_SECONDARY_OK;
-
- /* Server Selection Spec: "When any $ modifier is used, including the
- * $readPreference modifier, the query MUST be provided using the $query
- * modifier".
- *
- * This applies to commands, too.
- */
- result->assembled_query = bson_new ();
- result->query_owned = true;
-
- if (bson_has_field (query_bson, "$query")) {
- bson_concat (result->assembled_query, query_bson);
- } else {
- bson_append_document (
- result->assembled_query, "$query", 6, query_bson);
- }
-
- bson_append_document_begin (
- result->assembled_query, "$readPreference", 15, &child);
- mode_str = _mongoc_read_mode_as_str (mode);
- bson_append_utf8 (&child, "mode", 4, mode_str, -1);
- if (!bson_empty0 (tags)) {
- bson_append_array (&child, "tags", 4, tags);
- }
-
- if (max_staleness_seconds != MONGOC_NO_MAX_STALENESS) {
- bson_append_int64 (
- &child, "maxStalenessSeconds", 19, max_staleness_seconds);
- }
-
- if (!bson_empty0 (hedge)) {
- bson_append_document (&child, "hedge", 5, hedge);
- }
-
- bson_append_document_end (result->assembled_query, &child);
- }
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * assemble_query --
- *
- * Update @result based on @read_prefs, following the Server Selection
- * Spec.
- *
- * Side effects:
- * Sets @result->assembled_query and @result->flags.
- *
- * Note:
- * This function, the mongoc_assemble_query_result_t struct, and all
- * related functions are only used for find operations with OP_QUERY.
- * Remove them once we have implemented exhaust cursors with OP_MSG in
- * the server, and all previous server versions are EOL.
- *
- *--------------------------------------------------------------------------
- */
-
-void
-assemble_query (const mongoc_read_prefs_t *read_prefs,
- const mongoc_server_stream_t *server_stream,
- const bson_t *query_bson,
- mongoc_query_flags_t initial_flags,
- mongoc_assemble_query_result_t *result /* OUT */)
-{
- mongoc_server_description_type_t server_type;
-
- ENTRY;
-
- BSON_ASSERT (server_stream);
- BSON_ASSERT (query_bson);
- BSON_ASSERT (result);
-
- /* default values */
- result->assembled_query = (bson_t *) query_bson;
- result->query_owned = false;
- result->flags = initial_flags;
-
- server_type = server_stream->sd->type;
-
- switch (server_stream->topology_type) {
- case MONGOC_TOPOLOGY_SINGLE:
- if (server_type == MONGOC_SERVER_MONGOS) {
- _apply_read_preferences_mongos (read_prefs, query_bson, result);
- } else {
- /* Server Selection Spec: for topology type single and server types
- * besides mongos, "clients MUST always set the secondaryOk wire protocol
- * flag on reads to ensure that any server type can handle the
- * request."
- */
- result->flags |= MONGOC_QUERY_SECONDARY_OK;
- }
-
- break;
-
- case MONGOC_TOPOLOGY_RS_NO_PRIMARY:
- case MONGOC_TOPOLOGY_RS_WITH_PRIMARY:
- /* Server Selection Spec: for RS topology types, "For all read
- * preferences modes except primary, clients MUST set the secondaryOk wire
- * protocol flag to ensure that any suitable server can handle the
- * request. Clients MUST NOT set the secondaryOk wire protocol flag if the
- * read preference mode is primary.
- */
- if (read_prefs && read_prefs->mode != MONGOC_READ_PRIMARY) {
- result->flags |= MONGOC_QUERY_SECONDARY_OK;
- }
-
- break;
-
- case MONGOC_TOPOLOGY_SHARDED:
- case MONGOC_TOPOLOGY_LOAD_BALANCED:
- _apply_read_preferences_mongos (read_prefs, query_bson, result);
- break;
-
- case MONGOC_TOPOLOGY_UNKNOWN:
- case MONGOC_TOPOLOGY_DESCRIPTION_TYPES:
- default:
- /* must not call _apply_read_preferences with unknown topology type */
- BSON_ASSERT (false);
- }
-
- EXIT;
-}
-
-
-void
-assemble_query_result_cleanup (mongoc_assemble_query_result_t *result)
-{
- ENTRY;
-
- BSON_ASSERT (result);
-
- if (result->query_owned) {
- bson_destroy (result->assembled_query);
- }
-
- EXIT;
-}
-
-bool
-_mongoc_read_prefs_validate (const mongoc_read_prefs_t *read_prefs,
- bson_error_t *error)
-{
- if (read_prefs && !mongoc_read_prefs_is_valid (read_prefs)) {
- bson_set_error (error,
- MONGOC_ERROR_COMMAND,
- MONGOC_ERROR_COMMAND_INVALID_ARG,
- "Invalid mongoc_read_prefs_t");
- return false;
- }
- return true;
-}
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-read-prefs.h b/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-read-prefs.h
deleted file mode 100644
index 7180548b..00000000
--- a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-read-prefs.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright 2013 MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "mongoc-prelude.h"
-
-#ifndef MONGOC_READ_PREFS_H
-#define MONGOC_READ_PREFS_H
-
-#include <bson/bson.h>
-
-#include "mongoc-macros.h"
-#include "mongoc-config.h"
-
-BSON_BEGIN_DECLS
-
-
-#define MONGOC_NO_MAX_STALENESS -1
-#define MONGOC_SMALLEST_MAX_STALENESS_SECONDS 90
-
-typedef struct _mongoc_read_prefs_t mongoc_read_prefs_t;
-
-
-typedef enum {
- MONGOC_READ_PRIMARY = (1 << 0),
- MONGOC_READ_SECONDARY = (1 << 1),
- MONGOC_READ_PRIMARY_PREFERRED = (1 << 2) | MONGOC_READ_PRIMARY,
- MONGOC_READ_SECONDARY_PREFERRED = (1 << 2) | MONGOC_READ_SECONDARY,
- MONGOC_READ_NEAREST = (1 << 3) | MONGOC_READ_SECONDARY,
-} mongoc_read_mode_t;
-
-
-MONGOC_EXPORT (mongoc_read_prefs_t *)
-mongoc_read_prefs_new (mongoc_read_mode_t read_mode)
- BSON_GNUC_WARN_UNUSED_RESULT;
-MONGOC_EXPORT (mongoc_read_prefs_t *)
-mongoc_read_prefs_copy (const mongoc_read_prefs_t *read_prefs)
- BSON_GNUC_WARN_UNUSED_RESULT;
-MONGOC_EXPORT (void)
-mongoc_read_prefs_destroy (mongoc_read_prefs_t *read_prefs);
-MONGOC_EXPORT (mongoc_read_mode_t)
-mongoc_read_prefs_get_mode (const mongoc_read_prefs_t *read_prefs);
-MONGOC_EXPORT (void)
-mongoc_read_prefs_set_mode (mongoc_read_prefs_t *read_prefs,
- mongoc_read_mode_t mode);
-MONGOC_EXPORT (const bson_t *)
-mongoc_read_prefs_get_tags (const mongoc_read_prefs_t *read_prefs);
-MONGOC_EXPORT (void)
-mongoc_read_prefs_set_tags (mongoc_read_prefs_t *read_prefs,
- const bson_t *tags);
-MONGOC_EXPORT (void)
-mongoc_read_prefs_add_tag (mongoc_read_prefs_t *read_prefs, const bson_t *tag);
-MONGOC_EXPORT (int64_t)
-mongoc_read_prefs_get_max_staleness_seconds (
- const mongoc_read_prefs_t *read_prefs);
-MONGOC_EXPORT (void)
-mongoc_read_prefs_set_max_staleness_seconds (mongoc_read_prefs_t *read_prefs,
- int64_t max_staleness_seconds);
-MONGOC_EXPORT (const bson_t *)
-mongoc_read_prefs_get_hedge (const mongoc_read_prefs_t *read_prefs);
-MONGOC_EXPORT (void)
-mongoc_read_prefs_set_hedge (mongoc_read_prefs_t *read_prefs,
- const bson_t *hedge);
-MONGOC_EXPORT (bool)
-mongoc_read_prefs_is_valid (const mongoc_read_prefs_t *read_prefs);
-
-
-BSON_END_DECLS
-
-
-#endif /* MONGOC_READ_PREFS_H */
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-monitor.c b/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-monitor.c
deleted file mode 100644
index f69043f4..00000000
--- a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-monitor.c
+++ /dev/null
@@ -1,1273 +0,0 @@
-/*
- * Copyright 2020-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "common-thread-private.h"
-#include "mongoc-server-monitor-private.h"
-
-#include "mongoc/mongoc-client-private.h"
-#include "mongoc/mongoc-error-private.h"
-#include "mongoc/mongoc-flags-private.h"
-#include "mongoc/mongoc-ssl-private.h"
-#include "mongoc/mongoc-stream-private.h"
-#include "mongoc/mongoc-topology-background-monitoring-private.h"
-#include "mongoc/mongoc-topology-private.h"
-#include "mongoc/mongoc-trace-private.h"
-
-#undef MONGOC_LOG_DOMAIN
-#define MONGOC_LOG_DOMAIN "monitor"
-
-typedef enum {
- MONGOC_THREAD_OFF = 0,
- MONGOC_THREAD_RUNNING,
- MONGOC_THREAD_SHUTTING_DOWN,
- MONGOC_THREAD_JOINABLE
-} thread_state_t;
-
-/* Use a signed and wide return type for timeouts as long as you can. Cast only
- * when you know what you're doing with it. */
-static int64_t
-_now_us (void)
-{
- return bson_get_monotonic_time ();
-}
-
-static int64_t
-_now_ms (void)
-{
- return _now_us () / 1000;
-}
-
-struct _mongoc_server_monitor_t {
- mongoc_topology_t *topology;
- bson_thread_t thread;
-
- /* State accessed from multiple threads. */
- struct {
- bson_mutex_t mutex;
- mongoc_cond_t cond;
- thread_state_t state;
- bool scan_requested;
- bool cancel_requested;
- } shared;
-
- /* Default time to sleep between hello checks (reduced when a scan is
- * requested) */
- uint64_t heartbeat_frequency_ms;
- /* The minimum time to sleep between hello checks. */
- uint64_t min_heartbeat_frequency_ms;
- int64_t connect_timeout_ms;
- bool use_tls;
-#ifdef MONGOC_ENABLE_SSL
- mongoc_ssl_opt_t *ssl_opts;
-#endif
- mongoc_uri_t *uri;
- /* A custom initiator may be set if a user provides overrides to create a
- * stream. */
- mongoc_stream_initiator_t initiator;
- void *initiator_context;
- int64_t request_id;
- mongoc_apm_callbacks_t apm_callbacks;
- void *apm_context;
-
- mongoc_stream_t *stream;
- bool more_to_come;
- mongoc_server_description_t *description;
- uint32_t server_id;
- bool is_rtt;
-};
-
-static BSON_GNUC_PRINTF (3, 4) void _server_monitor_log (
- mongoc_server_monitor_t *server_monitor,
- mongoc_log_level_t level,
- const char *format,
- ...)
-{
- va_list ap;
- char *msg;
-
- va_start (ap, format);
- msg = bson_strdupv_printf (format, ap);
- va_end (ap);
-
- mongoc_log (level,
- MONGOC_LOG_DOMAIN,
- "[%s%s] %s",
- server_monitor->description->host.host_and_port,
- server_monitor->is_rtt ? "-RTT" : "",
- msg);
- bson_free (msg);
-}
-
-#ifdef MONGOC_TRACE
-#define MONITOR_LOG(sm, ...) \
- _server_monitor_log (sm, MONGOC_LOG_LEVEL_TRACE, __VA_ARGS__)
-#else
-#define MONITOR_LOG(sm, ...) (void) 0
-#endif
-
-/* TODO CDRIVER-3710 use MONGOC_LOG_LEVEL_ERROR */
-#define MONITOR_LOG_ERROR(sm, ...) \
- _server_monitor_log (sm, MONGOC_LOG_LEVEL_DEBUG, __VA_ARGS__)
-/* TODO CDRIVER-3710 use MONGOC_LOG_LEVEL_WARNING */
-#define MONITOR_LOG_WARNING(sm, ...) \
- _server_monitor_log (sm, MONGOC_LOG_LEVEL_DEBUG, __VA_ARGS__)
-
-static void
-_server_monitor_heartbeat_started (mongoc_server_monitor_t *server_monitor,
- bool awaited)
-{
- mongoc_apm_server_heartbeat_started_t event;
- MONGOC_DEBUG_ASSERT (
- !COMMON_PREFIX (mutex_is_locked) (&server_monitor->topology->apm_mutex));
-
- if (!server_monitor->apm_callbacks.server_heartbeat_started) {
- return;
- }
-
- event.host = &server_monitor->description->host;
- event.context = server_monitor->apm_context;
- MONITOR_LOG (server_monitor,
- "%s heartbeat started",
- awaited ? "awaitable" : "regular");
- event.awaited = awaited;
- bson_mutex_lock (&server_monitor->topology->apm_mutex);
- server_monitor->apm_callbacks.server_heartbeat_started (&event);
- bson_mutex_unlock (&server_monitor->topology->apm_mutex);
-}
-
-static void
-_server_monitor_heartbeat_succeeded (mongoc_server_monitor_t *server_monitor,
- const bson_t *reply,
- int64_t duration_usec,
- bool awaited)
-{
- mongoc_apm_server_heartbeat_succeeded_t event;
-
- if (!server_monitor->apm_callbacks.server_heartbeat_succeeded) {
- return;
- }
-
- event.host = &server_monitor->description->host;
- event.context = server_monitor->apm_context;
- event.reply = reply;
- event.duration_usec = duration_usec;
- MONITOR_LOG (server_monitor,
- "%s heartbeat succeeded",
- awaited ? "awaitable" : "regular");
- event.awaited = awaited;
- bson_mutex_lock (&server_monitor->topology->apm_mutex);
- server_monitor->apm_callbacks.server_heartbeat_succeeded (&event);
- bson_mutex_unlock (&server_monitor->topology->apm_mutex);
-}
-
-static void
-_server_monitor_heartbeat_failed (mongoc_server_monitor_t *server_monitor,
- const bson_error_t *error,
- int64_t duration_usec,
- bool awaited)
-{
- mongoc_apm_server_heartbeat_failed_t event;
-
- if (!server_monitor->apm_callbacks.server_heartbeat_failed) {
- return;
- }
-
- event.host = &server_monitor->description->host;
- event.context = server_monitor->apm_context;
- event.error = error;
- event.duration_usec = duration_usec;
- MONITOR_LOG (
- server_monitor, "%s heartbeat failed", awaited ? "awaitable" : "regular");
- event.awaited = awaited;
- bson_mutex_lock (&server_monitor->topology->apm_mutex);
- server_monitor->apm_callbacks.server_heartbeat_failed (&event);
- bson_mutex_unlock (&server_monitor->topology->apm_mutex);
-}
-
-static void
-_server_monitor_append_cluster_time (mongoc_server_monitor_t *server_monitor,
- bson_t *cmd)
-{
- mc_shared_tpld td =
- mc_tpld_take_ref (BSON_ASSERT_PTR_INLINE (server_monitor)->topology);
-
- /* Cluster time is updated on every reply. */
- if (!bson_empty (&td.ptr->cluster_time)) {
- bson_append_document (cmd, "$clusterTime", 12, &td.ptr->cluster_time);
- }
- mc_tpld_drop_ref (&td);
-}
-
-static bool
-_server_monitor_send_and_recv_opquery (mongoc_server_monitor_t *server_monitor,
- const bson_t *cmd,
- bson_t *reply,
- bson_error_t *error)
-{
- mongoc_rpc_t rpc;
- mongoc_array_t array_to_write;
- mongoc_iovec_t *iovec;
- int niovec;
- mongoc_buffer_t buffer;
- uint32_t reply_len;
- bson_t temp_reply;
- bool ret = false;
-
- rpc.header.msg_len = 0;
- rpc.header.request_id = server_monitor->request_id++;
- rpc.header.response_to = 0;
- rpc.header.opcode = MONGOC_OPCODE_QUERY;
- rpc.query.flags = MONGOC_QUERY_SECONDARY_OK;
- rpc.query.collection = "admin.$cmd";
- rpc.query.skip = 0;
- rpc.query.n_return = -1;
- rpc.query.query = bson_get_data (cmd);
- rpc.query.fields = NULL;
-
- _mongoc_buffer_init (&buffer, NULL, 0, NULL, NULL);
- _mongoc_array_init (&array_to_write, sizeof (mongoc_iovec_t));
- _mongoc_rpc_gather (&rpc, &array_to_write);
- iovec = (mongoc_iovec_t *) array_to_write.data;
- niovec = array_to_write.len;
- _mongoc_rpc_swab_to_le (&rpc);
-
- if (!_mongoc_stream_writev_full (server_monitor->stream,
- iovec,
- niovec,
- server_monitor->connect_timeout_ms,
- error)) {
- GOTO (fail);
- }
-
- if (!_mongoc_buffer_append_from_stream (&buffer,
- server_monitor->stream,
- 4,
- server_monitor->connect_timeout_ms,
- error)) {
- GOTO (fail);
- }
-
- memcpy (&reply_len, buffer.data, 4);
- reply_len = BSON_UINT32_FROM_LE (reply_len);
-
- if (!_mongoc_buffer_append_from_stream (&buffer,
- server_monitor->stream,
- reply_len - buffer.len,
- server_monitor->connect_timeout_ms,
- error)) {
- GOTO (fail);
- }
-
- if (!_mongoc_rpc_scatter (&rpc, buffer.data, buffer.len)) {
- bson_set_error (error,
- MONGOC_ERROR_PROTOCOL,
- MONGOC_ERROR_PROTOCOL_INVALID_REPLY,
- "Invalid reply from server.");
-
- GOTO (fail);
- }
-
- if (!_mongoc_rpc_decompress_if_necessary (&rpc, &buffer, error)) {
- GOTO (fail);
- }
- _mongoc_rpc_swab_from_le (&rpc);
-
- if (!_mongoc_rpc_get_first_document (&rpc, &temp_reply)) {
- bson_set_error (error,
- MONGOC_ERROR_PROTOCOL,
- MONGOC_ERROR_PROTOCOL_INVALID_REPLY,
- "Invalid reply from server");
- GOTO (fail);
- }
- bson_copy_to (&temp_reply, reply);
-
- ret = true;
-fail:
- if (!ret) {
- bson_init (reply);
- }
- _mongoc_array_destroy (&array_to_write);
- _mongoc_buffer_destroy (&buffer);
- return ret;
-}
-
-static bool
-_server_monitor_polling_hello (mongoc_server_monitor_t *server_monitor,
- bool hello_ok,
- bson_t *hello_response,
- bson_error_t *error)
-{
- bson_t cmd;
- const bson_t *hello;
- bool ret;
-
- hello = _mongoc_topology_scanner_get_monitoring_cmd (
- server_monitor->topology->scanner, hello_ok);
- bson_copy_to (hello, &cmd);
-
- _server_monitor_append_cluster_time (server_monitor, &cmd);
- ret = _server_monitor_send_and_recv_opquery (
- server_monitor, &cmd, hello_response, error);
- bson_destroy (&cmd);
- return ret;
-}
-
-static bool
-_server_monitor_awaitable_hello_send (mongoc_server_monitor_t *server_monitor,
- bson_t *cmd,
- bson_error_t *error)
-{
- mongoc_rpc_t rpc = {0};
- mongoc_array_t array_to_write;
- mongoc_iovec_t *iovec;
- int niovec;
-
- rpc.header.msg_len = 0;
- rpc.header.request_id = server_monitor->request_id++;
- rpc.header.response_to = 0;
- rpc.header.opcode = MONGOC_OPCODE_MSG;
- rpc.msg.flags = MONGOC_MSG_EXHAUST_ALLOWED;
- rpc.msg.n_sections = 1;
- rpc.msg.sections[0].payload_type = 0;
- rpc.msg.sections[0].payload.bson_document = bson_get_data (cmd);
-
- _mongoc_array_init (&array_to_write, sizeof (mongoc_iovec_t));
- _mongoc_rpc_gather (&rpc, &array_to_write);
-
- iovec = (mongoc_iovec_t *) array_to_write.data;
- niovec = array_to_write.len;
- _mongoc_rpc_swab_to_le (&rpc);
-
- MONITOR_LOG (server_monitor,
- "sending with timeout %" PRId64,
- server_monitor->connect_timeout_ms);
-
- if (!_mongoc_stream_writev_full (server_monitor->stream,
- iovec,
- niovec,
- server_monitor->connect_timeout_ms,
- error)) {
- MONITOR_LOG_ERROR (
- server_monitor, "failed to write awaitable hello: %s", error->message);
- _mongoc_array_destroy (&array_to_write);
- return false;
- }
- _mongoc_array_destroy (&array_to_write);
- return true;
-}
-
-/* Poll the server monitor stream for reading. Allows cancellation.
- *
- * Called only from server monitor thread.
- * Locks server monitor mutex.
- * Returns true if stream is readable. False on error or cancellation.
- * On cancellation, no error is set, but cancelled is set to true.
- */
-static bool
-_server_monitor_poll_with_interrupt (mongoc_server_monitor_t *server_monitor,
- int64_t expire_at_ms,
- bool *cancelled,
- bson_error_t *error)
-{
- /* How many milliseconds we should poll for on each tick.
- * On every tick, check whether the awaitable hello was cancelled. */
- const int32_t monitor_tick_ms = MONGOC_TOPOLOGY_MIN_HEARTBEAT_FREQUENCY_MS;
- int64_t timeleft_ms;
-
- while ((timeleft_ms = expire_at_ms - _now_ms ()) > 0) {
- ssize_t ret;
- mongoc_stream_poll_t poller[1];
-
- MONITOR_LOG (server_monitor,
- "_server_monitor_poll_with_interrupt expires in: %" PRIu64
- "ms",
- timeleft_ms);
- poller[0].stream = server_monitor->stream;
- poller[0].events =
- POLLIN; /* POLLERR and POLLHUP are added in mongoc_socket_poll. */
- poller[0].revents = 0;
-
- MONITOR_LOG (
- server_monitor,
- "polling for awaitable hello reply with timeleft_ms: %" PRId64,
- timeleft_ms);
- ret = mongoc_stream_poll (
- poller, 1, (int32_t) BSON_MIN (timeleft_ms, monitor_tick_ms));
- if (ret == -1) {
- MONITOR_LOG (server_monitor, "mongoc_stream_poll error");
- bson_set_error (error,
- MONGOC_ERROR_STREAM,
- MONGOC_ERROR_STREAM_SOCKET,
- "poll error");
- return false;
- }
-
- if (poller[0].revents & (POLLERR | POLLHUP)) {
- bson_set_error (error,
- MONGOC_ERROR_STREAM,
- MONGOC_ERROR_STREAM_SOCKET,
- "connection closed while polling");
- return false;
- }
-
- /* Check for cancellation. */
- bson_mutex_lock (&server_monitor->shared.mutex);
- *cancelled = server_monitor->shared.cancel_requested;
- server_monitor->shared.cancel_requested = false;
- bson_mutex_unlock (&server_monitor->shared.mutex);
-
- if (*cancelled) {
- MONITOR_LOG (server_monitor, "polling cancelled");
- return false;
- }
-
- if (poller[0].revents & POLLIN) {
- MONITOR_LOG (server_monitor, "mongoc_stream_poll ready to read");
- return true;
- }
- }
- bson_set_error (error,
- MONGOC_ERROR_STREAM,
- MONGOC_ERROR_STREAM_SOCKET,
- "connection timeout while polling");
- return false;
-}
-
-/* Calculate the timeout between the current time and an absolute expiration
- * time in milliseconds.
- *
- * Returns 0 and sets error if time expired.
- */
-int64_t
-_get_timeout_ms (int64_t expire_at_ms, bson_error_t *error)
-{
- int64_t timeout_ms;
-
- timeout_ms = expire_at_ms - _now_ms ();
- if (timeout_ms <= 0) {
- bson_set_error (error,
- MONGOC_ERROR_STREAM,
- MONGOC_ERROR_STREAM_SOCKET,
- "connection timed out reading message length");
- return 0;
- }
- return timeout_ms;
-}
-
-/* Receive an awaitable hello reply.
- *
- * May be used to receive additional replies when moreToCome is set.
- * Called only from server monitor thread.
- * May lock server monitor mutex in functions that are called.
- * May block for up to heartbeatFrequencyMS + connectTimeoutMS waiting for
- * reply.
- * Returns true if a reply was received. False on error or cancellation.
- * On cancellation, no error is set, but cancelled is set to true.
- */
-static bool
-_server_monitor_awaitable_hello_recv (mongoc_server_monitor_t *server_monitor,
- bson_t *hello_response,
- bool *cancelled,
- bson_error_t *error)
-{
- bool ret = false;
- mongoc_buffer_t buffer;
- int32_t msg_len;
- mongoc_rpc_t rpc;
- bson_t reply_local;
- int64_t expire_at_ms;
- int64_t timeout_ms;
-
- expire_at_ms = _now_ms () + server_monitor->heartbeat_frequency_ms +
- server_monitor->connect_timeout_ms;
- _mongoc_buffer_init (&buffer, NULL, 0, NULL, NULL);
- if (!_server_monitor_poll_with_interrupt (
- server_monitor, expire_at_ms, cancelled, error)) {
- GOTO (fail);
- }
-
- timeout_ms = _get_timeout_ms (expire_at_ms, error);
- if (!timeout_ms) {
- GOTO (fail);
- }
- MONITOR_LOG (server_monitor,
- "reading first 4 bytes with timeout: %" PRId64,
- timeout_ms);
- if (!_mongoc_buffer_append_from_stream (
- &buffer, server_monitor->stream, 4, (int32_t) timeout_ms, error)) {
- GOTO (fail);
- }
-
- BSON_ASSERT (buffer.len == 4);
- memcpy (&msg_len, buffer.data, 4);
- msg_len = BSON_UINT32_FROM_LE (msg_len);
-
- if ((msg_len < 16) ||
- (msg_len > server_monitor->description->max_msg_size)) {
- bson_set_error (
- error,
- MONGOC_ERROR_PROTOCOL,
- MONGOC_ERROR_PROTOCOL_INVALID_REPLY,
- "Message size %d is not within expected range 16-%d bytes",
- msg_len,
- server_monitor->description->max_msg_size);
- GOTO (fail);
- }
-
- timeout_ms = _get_timeout_ms (expire_at_ms, error);
- if (!timeout_ms) {
- GOTO (fail);
- }
- MONITOR_LOG (server_monitor,
- "reading remaining %d bytes. Timeout %" PRId64,
- (int) (msg_len - 4),
- timeout_ms);
- if (!_mongoc_buffer_append_from_stream (
- &buffer, server_monitor->stream, msg_len - 4, timeout_ms, error)) {
- GOTO (fail);
- }
-
- if (!_mongoc_rpc_scatter (&rpc, buffer.data, buffer.len)) {
- bson_set_error (error,
- MONGOC_ERROR_PROTOCOL,
- MONGOC_ERROR_PROTOCOL_INVALID_REPLY,
- "Malformed message from server");
- GOTO (fail);
- }
-
- if (!_mongoc_rpc_decompress_if_necessary (&rpc, &buffer, error)) {
- GOTO (fail);
- }
-
- _mongoc_rpc_swab_from_le (&rpc);
- memcpy (&msg_len, rpc.msg.sections[0].payload.bson_document, 4);
- msg_len = BSON_UINT32_FROM_LE (msg_len);
- if (!bson_init_static (
- &reply_local, rpc.msg.sections[0].payload.bson_document, msg_len)) {
- bson_set_error (error,
- MONGOC_ERROR_PROTOCOL,
- MONGOC_ERROR_PROTOCOL_INVALID_REPLY,
- "Malformed BSON payload from server");
- GOTO (fail);
- }
-
- bson_copy_to (&reply_local, hello_response);
- server_monitor->more_to_come =
- (rpc.msg.flags & MONGOC_MSG_MORE_TO_COME) != 0;
-
- ret = true;
-fail:
- if (!ret) {
- bson_init (hello_response);
- }
- _mongoc_buffer_destroy (&buffer);
- return ret;
-}
-
-/* Send and receive an awaitable hello.
- *
- * Called only from server monitor thread.
- * May lock server monitor mutex in functions that are called.
- * May block for up to heartbeatFrequencyMS waiting for reply.
- */
-static bool
-_server_monitor_awaitable_hello (mongoc_server_monitor_t *server_monitor,
- const mongoc_server_description_t *description,
- bson_t *hello_response,
- bool *cancelled,
- bson_error_t *error)
-{
- bson_t cmd;
- const bson_t *hello;
- bool ret = false;
-
- hello = _mongoc_topology_scanner_get_monitoring_cmd (
- server_monitor->topology->scanner, description->hello_ok);
- bson_copy_to (hello, &cmd);
-
- _server_monitor_append_cluster_time (server_monitor, &cmd);
- bson_append_document (
- &cmd, "topologyVersion", 15, &description->topology_version);
- bson_append_int32 (
- &cmd, "maxAwaitTimeMS", 14, server_monitor->heartbeat_frequency_ms);
- bson_append_utf8 (&cmd, "$db", 3, "admin", 5);
-
- if (!_server_monitor_awaitable_hello_send (server_monitor, &cmd, error)) {
- GOTO (fail);
- }
-
- if (!_server_monitor_awaitable_hello_recv (
- server_monitor, hello_response, cancelled, error)) {
- bson_destroy (hello_response);
- GOTO (fail);
- }
-
- ret = true;
-fail:
- if (!ret) {
- bson_init (hello_response);
- }
- bson_destroy (&cmd);
- return ret;
-}
-
-/* Update the topology description with a reply or an error.
- *
- * Called only from server monitor thread.
- * Caller must hold no locks.
- * Locks server monitor mutex.
- */
-static void
-_update_topology_description (mongoc_server_monitor_t *server_monitor,
- mongoc_server_description_t *description)
-{
- mongoc_topology_t *topology;
- bson_t *hello_response = NULL;
- mc_tpld_modification tdmod;
-
- topology = server_monitor->topology;
- if (description->has_hello_response) {
- hello_response = &description->last_hello_response;
- }
-
- if (hello_response) {
- _mongoc_topology_update_cluster_time (topology, hello_response);
- }
-
- if (bson_atomic_int_fetch (&topology->scanner_state,
- bson_memory_order_relaxed) ==
- MONGOC_TOPOLOGY_SCANNER_SHUTTING_DOWN) {
- return;
- }
-
- tdmod = mc_tpld_modify_begin (topology);
- bson_mutex_lock (&server_monitor->shared.mutex);
- server_monitor->shared.scan_requested = false;
- bson_mutex_unlock (&server_monitor->shared.mutex);
- mongoc_topology_description_handle_hello (tdmod.new_td,
- server_monitor->server_id,
- hello_response,
- description->round_trip_time_msec,
- &description->error);
- /* Reconcile server monitors. */
- _mongoc_topology_background_monitoring_reconcile (topology, tdmod.new_td);
- /* Wake threads performing server selection. */
- mongoc_cond_broadcast (&server_monitor->topology->cond_client);
- mc_tpld_modify_commit (tdmod);
-}
-
-/* Create a new server monitor.
- *
- * Called during reconcile.
- * Caller must hold topology lock.
- */
-mongoc_server_monitor_t *
-mongoc_server_monitor_new (mongoc_topology_t *topology,
- mongoc_topology_description_t *td,
- mongoc_server_description_t *init_description)
-{
- mongoc_server_monitor_t *server_monitor =
- bson_malloc0 (sizeof (*server_monitor));
- server_monitor->description =
- mongoc_server_description_new_copy (init_description);
- server_monitor->server_id = init_description->id;
- server_monitor->topology = topology;
- server_monitor->heartbeat_frequency_ms = td->heartbeat_msec;
- server_monitor->min_heartbeat_frequency_ms =
- topology->min_heartbeat_frequency_msec;
- server_monitor->connect_timeout_ms = topology->connect_timeout_msec;
- server_monitor->uri = mongoc_uri_copy (topology->uri);
-/* TODO CDRIVER-3682: Do not retrieve ssl opts from topology scanner. They
- * should be stored somewhere else. */
-#ifdef MONGOC_ENABLE_SSL
- if (topology->scanner->ssl_opts) {
- server_monitor->ssl_opts = bson_malloc0 (sizeof (mongoc_ssl_opt_t));
-
- _mongoc_ssl_opts_copy_to (
- topology->scanner->ssl_opts, server_monitor->ssl_opts, true);
- }
-#endif
- memcpy (&server_monitor->apm_callbacks,
- &td->apm_callbacks,
- sizeof (mongoc_apm_callbacks_t));
- server_monitor->apm_context = td->apm_context;
- server_monitor->initiator = topology->scanner->initiator;
- server_monitor->initiator_context = topology->scanner->initiator_context;
- mongoc_cond_init (&server_monitor->shared.cond);
- bson_mutex_init (&server_monitor->shared.mutex);
- return server_monitor;
-}
-
-/* Creates a stream and performs the initial hello handshake.
- *
- * Called only by server monitor thread.
- * Returns true if both connection and handshake succeeds.
- * Returns false and sets error otherwise.
- * hello_response is always initialized.
- */
-static bool
-_server_monitor_setup_connection (mongoc_server_monitor_t *server_monitor,
- bson_t *hello_response,
- int64_t *start_us,
- bson_error_t *error)
-{
- bson_t cmd = BSON_INITIALIZER;
- bool ret = false;
-
- ENTRY;
-
- BSON_ASSERT (!server_monitor->stream);
- bson_init (hello_response);
-
- server_monitor->more_to_come = false;
-
- /* Using an initiator isn't really necessary. Users can't set them on
- * pools. But it is used for tests. */
- if (server_monitor->initiator) {
- server_monitor->stream =
- server_monitor->initiator (server_monitor->uri,
- &server_monitor->description->host,
- server_monitor->initiator_context,
- error);
- } else {
- void *ssl_opts_void = NULL;
-
-#ifdef MONGOC_ENABLE_SSL
- ssl_opts_void = server_monitor->ssl_opts;
-#endif
- server_monitor->stream =
- mongoc_client_connect (false,
- ssl_opts_void != NULL,
- ssl_opts_void,
- server_monitor->uri,
- &server_monitor->description->host,
- error);
- }
-
- if (!server_monitor->stream) {
- GOTO (fail);
- }
-
- /* Update the start time just before the handshake. */
- *start_us = _now_us ();
- /* Perform handshake. */
- bson_destroy (&cmd);
- _mongoc_topology_dup_handshake_cmd (server_monitor->topology, &cmd);
- _server_monitor_append_cluster_time (server_monitor, &cmd);
- bson_destroy (hello_response);
- if (!_server_monitor_send_and_recv_opquery (
- server_monitor, &cmd, hello_response, error)) {
- GOTO (fail);
- }
-
- ret = true;
-fail:
- bson_destroy (&cmd);
- RETURN (ret);
-}
-
-/**
- * @brief Perform a hello check on a server
- *
- * @param server_monitor The server monitor for this server.
- * @param previous_description The most recent view of the description of this
- * server.
- * @param cancelled Output parameter: Whether the monitor check is cancelled.
- * @return mongoc_server_description_t* The newly created updated server
- * description.
- *
- * @note May update the topology description associated with the server monitor.
- *
- * @note In case of error, returns a new server description with the error
- * information, but with no hello reply.
- */
-static mongoc_server_description_t *
-_server_monitor_check_server (
- mongoc_server_monitor_t *server_monitor,
- const mongoc_server_description_t *previous_description,
- bool *cancelled)
-{
- bool ret = false;
- bson_error_t error;
- bson_t hello_response;
- int64_t duration_us;
- int64_t start_us;
- bool command_or_network_error = false;
- bool awaited = false;
- mongoc_server_description_t *description;
- mc_tpld_modification tdmod;
-
- ENTRY;
-
- *cancelled = false;
- memset (&error, 0, sizeof (bson_error_t));
- description = bson_malloc0 (sizeof (mongoc_server_description_t));
- mongoc_server_description_init (
- description,
- server_monitor->description->connection_address,
- server_monitor->description->id);
- start_us = _now_us ();
-
- if (!server_monitor->stream) {
- MONITOR_LOG (server_monitor, "setting up connection");
- awaited = false;
- _server_monitor_heartbeat_started (server_monitor, awaited);
- ret = _server_monitor_setup_connection (
- server_monitor, &hello_response, &start_us, &error);
- GOTO (exit);
- }
-
- if (server_monitor->more_to_come) {
- awaited = true;
- /* Publish a heartbeat started for each additional response read. */
- _server_monitor_heartbeat_started (server_monitor, awaited);
- MONITOR_LOG (server_monitor, "more to come");
- ret = _server_monitor_awaitable_hello_recv (
- server_monitor, &hello_response, cancelled, &error);
- GOTO (exit);
- }
-
- if (!bson_empty (&previous_description->topology_version)) {
- awaited = true;
- _server_monitor_heartbeat_started (server_monitor, awaited);
- MONITOR_LOG (server_monitor, "awaitable hello");
- ret = _server_monitor_awaitable_hello (server_monitor,
- previous_description,
- &hello_response,
- cancelled,
- &error);
- GOTO (exit);
- }
-
- MONITOR_LOG (server_monitor, "polling hello");
- awaited = false;
- _server_monitor_heartbeat_started (server_monitor, awaited);
- ret = _server_monitor_polling_hello (
- server_monitor, previous_description->hello_ok, &hello_response, &error);
-
-exit:
- duration_us = _now_us () - start_us;
- MONITOR_LOG (
- server_monitor, "server check duration (us): %" PRId64, duration_us);
-
- /* If ret is true, we have a reply. Check if "ok": 1. */
- if (ret && _mongoc_cmd_check_ok (
- &hello_response, MONGOC_ERROR_API_VERSION_2, &error)) {
- int64_t rtt_ms = MONGOC_RTT_UNSET;
-
- /* rtt remains MONGOC_RTT_UNSET if awaited. */
- if (!awaited) {
- rtt_ms = duration_us / 1000;
- }
-
- mongoc_server_description_handle_hello (
- description, &hello_response, rtt_ms, NULL);
- /* If the hello reply could not be parsed, consider this a command
- * error. */
- if (description->error.code) {
- MONITOR_LOG_ERROR (server_monitor,
- "error parsing server reply: %s",
- description->error.message);
- command_or_network_error = true;
- _server_monitor_heartbeat_failed (
- server_monitor, &description->error, duration_us, awaited);
- } else {
- _server_monitor_heartbeat_succeeded (
- server_monitor, &hello_response, duration_us, awaited);
- }
- } else if (*cancelled) {
- MONITOR_LOG (server_monitor, "server monitor cancelled");
- if (server_monitor->stream) {
- mongoc_stream_destroy (server_monitor->stream);
- }
- server_monitor->stream = NULL;
- server_monitor->more_to_come = false;
- _server_monitor_heartbeat_failed (
- server_monitor, &description->error, duration_us, awaited);
- } else {
- /* The hello reply had "ok":0 or a network error occurred. */
- MONITOR_LOG_ERROR (server_monitor,
- "command or network error occurred: %s",
- error.message);
- command_or_network_error = true;
- mongoc_server_description_handle_hello (
- description, NULL, MONGOC_RTT_UNSET, &error);
- _server_monitor_heartbeat_failed (
- server_monitor, &description->error, duration_us, awaited);
- }
-
- if (command_or_network_error) {
- if (server_monitor->stream) {
- mongoc_stream_failed (server_monitor->stream);
- }
- server_monitor->stream = NULL;
- server_monitor->more_to_come = false;
- tdmod = mc_tpld_modify_begin (server_monitor->topology);
- /* clear_connection_pool() is a no-op if 'description->id' was already
- * removed. */
- _mongoc_topology_description_clear_connection_pool (
- tdmod.new_td,
- server_monitor->description->id,
- &server_monitor->description->service_id);
- mc_tpld_modify_commit (tdmod);
- }
-
- bson_destroy (&hello_response);
- return description;
-}
-
-/* Request scan of a single server.
- *
- * Locks server monitor mutex to deliver scan_requested.
- */
-void
-mongoc_server_monitor_request_scan (mongoc_server_monitor_t *server_monitor)
-{
- MONITOR_LOG (server_monitor, "requesting scan");
- bson_mutex_lock (&server_monitor->shared.mutex);
- server_monitor->shared.scan_requested = true;
- mongoc_cond_signal (&server_monitor->shared.cond);
- bson_mutex_unlock (&server_monitor->shared.mutex);
-}
-
-/* Request cancellation of an in progress awaitable hello.
- *
- * Called from app threads on network errors and during shutdown.
- * Locks server monitor mutex.
- */
-void
-mongoc_server_monitor_request_cancel (mongoc_server_monitor_t *server_monitor)
-{
- MONITOR_LOG (server_monitor, "requesting cancel");
- bson_mutex_lock (&server_monitor->shared.mutex);
- server_monitor->shared.cancel_requested = true;
- mongoc_cond_signal (&server_monitor->shared.cond);
- bson_mutex_unlock (&server_monitor->shared.mutex);
-}
-
-/* Wait for heartbeatFrequencyMS or minHeartbeatFrequencyMS if a scan is
- * requested.
- *
- * Locks server monitor mutex.
- */
-void
-mongoc_server_monitor_wait (mongoc_server_monitor_t *server_monitor)
-{
- int64_t start_ms;
- int64_t scan_due_ms;
-
- start_ms = _now_ms ();
- scan_due_ms = start_ms + server_monitor->heartbeat_frequency_ms;
-
- bson_mutex_lock (&server_monitor->shared.mutex);
- while (true) {
- int64_t sleep_duration_ms;
- int cond_ret;
-
- if (server_monitor->shared.state != MONGOC_THREAD_RUNNING) {
- break;
- }
-
- if (server_monitor->shared.scan_requested) {
- server_monitor->shared.scan_requested = false;
- scan_due_ms = start_ms + server_monitor->min_heartbeat_frequency_ms;
- }
-
- sleep_duration_ms = scan_due_ms - _now_ms ();
-
- if (sleep_duration_ms <= 0) {
- break;
- }
-
- MONITOR_LOG (server_monitor, "sleeping for %" PRId64, sleep_duration_ms);
- cond_ret = mongoc_cond_timedwait (&server_monitor->shared.cond,
- &server_monitor->shared.mutex,
- sleep_duration_ms);
- if (mongo_cond_ret_is_timedout (cond_ret)) {
- break;
- }
- }
- bson_mutex_unlock (&server_monitor->shared.mutex);
-}
-
-/* The server monitor thread function.
- *
- * Server monitor must be in state MONGOC_THREAD_OFF.
- */
-static BSON_THREAD_FUN (_server_monitor_thread, server_monitor_void)
-{
- mongoc_server_monitor_t *server_monitor;
- mongoc_server_description_t *description;
- mongoc_server_description_t *previous_description;
-
- server_monitor = (mongoc_server_monitor_t *) server_monitor_void;
- description =
- mongoc_server_description_new_copy (server_monitor->description);
- previous_description = NULL;
-
- while (true) {
- bool cancelled = false;
-
- bson_mutex_lock (&server_monitor->shared.mutex);
- if (server_monitor->shared.state != MONGOC_THREAD_RUNNING) {
- bson_mutex_unlock (&server_monitor->shared.mutex);
- break;
- }
- bson_mutex_unlock (&server_monitor->shared.mutex);
-
- mongoc_server_description_destroy (previous_description);
- previous_description = mongoc_server_description_new_copy (description);
- mongoc_server_description_destroy (description);
- description = _server_monitor_check_server (
- server_monitor, previous_description, &cancelled);
-
- if (cancelled) {
- mongoc_server_monitor_wait (server_monitor);
- continue;
- }
-
- _update_topology_description (server_monitor, description);
-
- /* Immediately proceed to the next check if the previous response was
- * successful and included the topologyVersion field. */
- if (description->type != MONGOC_SERVER_UNKNOWN &&
- !bson_empty (&description->topology_version)) {
- MONITOR_LOG (server_monitor,
- "immediately proceeding due to topologyVersion");
- continue;
- }
-
- /* ... or the previous response included the moreToCome flag */
- if (server_monitor->more_to_come) {
- MONITOR_LOG (server_monitor,
- "immediately proceeding due to moreToCome");
- continue;
- }
-
- /* ... or the server has just transitioned to Unknown due to a network
- * error. */
- if (_mongoc_error_is_network (&description->error) &&
- previous_description->type != MONGOC_SERVER_UNKNOWN) {
- MONITOR_LOG (server_monitor,
- "immediately proceeding due to network error");
- continue;
- }
-
- mongoc_server_monitor_wait (server_monitor);
- }
-
- bson_mutex_lock (&server_monitor->shared.mutex);
- server_monitor->shared.state = MONGOC_THREAD_JOINABLE;
- bson_mutex_unlock (&server_monitor->shared.mutex);
- mongoc_server_description_destroy (previous_description);
- mongoc_server_description_destroy (description);
- BSON_THREAD_RETURN;
-}
-
-static bool
-_server_monitor_ping_server (mongoc_server_monitor_t *server_monitor,
- bool hello_ok,
- int64_t *rtt_ms)
-{
- bool ret = false;
- int64_t start_us = _now_us ();
- bson_t hello_response;
- bson_error_t error;
-
- *rtt_ms = MONGOC_RTT_UNSET;
-
- if (!server_monitor->stream) {
- MONITOR_LOG (server_monitor, "rtt setting up connection");
- ret = _server_monitor_setup_connection (
- server_monitor, &hello_response, &start_us, &error);
- bson_destroy (&hello_response);
- }
-
- if (server_monitor->stream) {
- MONITOR_LOG (server_monitor, "rtt polling hello");
- ret = _server_monitor_polling_hello (
- server_monitor, hello_ok, &hello_response, &error);
- if (ret) {
- *rtt_ms = (_now_us () - start_us) / 1000;
- }
- bson_destroy (&hello_response);
- }
- return ret;
-}
-
-/* The RTT monitor thread function.
- *
- * Server monitor must be in state MONGOC_THREAD_OFF.
- */
-static BSON_THREAD_FUN (_server_monitor_rtt_thread, server_monitor_void)
-{
- mongoc_server_monitor_t *server_monitor = server_monitor_void;
-
- while (true) {
- int64_t rtt_ms;
- bson_error_t error;
- bool hello_ok;
-
- bson_mutex_lock (&server_monitor->shared.mutex);
- if (server_monitor->shared.state != MONGOC_THREAD_RUNNING) {
- bson_mutex_unlock (&server_monitor->shared.mutex);
- break;
- }
- bson_mutex_unlock (&server_monitor->shared.mutex);
-
- {
- mc_shared_tpld td = mc_tpld_take_ref (server_monitor->topology);
- const mongoc_server_description_t *sd =
- mongoc_topology_description_server_by_id_const (
- td.ptr, server_monitor->description->id, &error);
- hello_ok = sd ? sd->hello_ok : false;
- mc_tpld_drop_ref (&td);
- }
-
- _server_monitor_ping_server (server_monitor, hello_ok, &rtt_ms);
- if (rtt_ms != MONGOC_RTT_UNSET) {
- mc_tpld_modification tdmod =
- mc_tpld_modify_begin (server_monitor->topology);
- mongoc_server_description_t *const mut_sd =
- mongoc_topology_description_server_by_id (
- tdmod.new_td, server_monitor->description->id, &error);
- if (mut_sd) {
- mongoc_server_description_update_rtt (mut_sd, rtt_ms);
- mc_tpld_modify_commit (tdmod);
- } else {
- /* If the server description has been removed, the RTT thread will
- * be terminated by background monitoring soon, so we have nothing
- * to do but wait until we are about to be stopped. */
- mc_tpld_modify_drop (tdmod);
- }
- }
- mongoc_server_monitor_wait (server_monitor);
- }
-
- bson_mutex_lock (&server_monitor->shared.mutex);
- server_monitor->shared.state = MONGOC_THREAD_JOINABLE;
- bson_mutex_unlock (&server_monitor->shared.mutex);
- BSON_THREAD_RETURN;
-}
-
-void
-mongoc_server_monitor_run (mongoc_server_monitor_t *server_monitor)
-{
- bson_mutex_lock (&server_monitor->shared.mutex);
- if (server_monitor->shared.state == MONGOC_THREAD_OFF) {
- server_monitor->is_rtt = false;
- server_monitor->shared.state = MONGOC_THREAD_RUNNING;
- COMMON_PREFIX (thread_create)
- (&server_monitor->thread, _server_monitor_thread, server_monitor);
- }
- bson_mutex_unlock (&server_monitor->shared.mutex);
-}
-
-void
-mongoc_server_monitor_run_as_rtt (mongoc_server_monitor_t *server_monitor)
-{
- bson_mutex_lock (&server_monitor->shared.mutex);
- if (server_monitor->shared.state == MONGOC_THREAD_OFF) {
- server_monitor->is_rtt = true;
- server_monitor->shared.state = MONGOC_THREAD_RUNNING;
- COMMON_PREFIX (thread_create)
- (&server_monitor->thread, _server_monitor_rtt_thread, server_monitor);
- }
- bson_mutex_unlock (&server_monitor->shared.mutex);
-}
-
-/* Request thread shutdown.
- *
- * Returns true if in state MONGOC_THREAD_OFF and the server monitor can be
- * safely destroyed.
- * Called during topology description reconcile.
- * Locks server monitor mutex.
- */
-bool
-mongoc_server_monitor_request_shutdown (mongoc_server_monitor_t *server_monitor)
-{
- bool off = false;
-
- bson_mutex_lock (&server_monitor->shared.mutex);
- if (server_monitor->shared.state == MONGOC_THREAD_RUNNING) {
- server_monitor->shared.state = MONGOC_THREAD_SHUTTING_DOWN;
- }
- if (server_monitor->shared.state == MONGOC_THREAD_JOINABLE) {
- COMMON_PREFIX (thread_join) (server_monitor->thread);
- server_monitor->shared.state = MONGOC_THREAD_OFF;
- }
- if (server_monitor->shared.state == MONGOC_THREAD_OFF) {
- off = true;
- }
- mongoc_cond_signal (&server_monitor->shared.cond);
- bson_mutex_unlock (&server_monitor->shared.mutex);
- /* Cancel an in-progress hello check. */
- if (!off) {
- mongoc_server_monitor_request_cancel (server_monitor);
- }
- return off;
-}
-
-/* Request thread shutdown and block until the server monitor thread terminates.
- *
- * Called by one thread.
- * Locks the server monitor mutex.
- */
-void
-mongoc_server_monitor_wait_for_shutdown (
- mongoc_server_monitor_t *server_monitor)
-{
- if (mongoc_server_monitor_request_shutdown (server_monitor)) {
- return;
- }
-
- /* Shutdown requested, but thread is not yet off. Wait. */
- COMMON_PREFIX (thread_join) (server_monitor->thread);
- bson_mutex_lock (&server_monitor->shared.mutex);
- server_monitor->shared.state = MONGOC_THREAD_OFF;
- bson_mutex_unlock (&server_monitor->shared.mutex);
-}
-
-/* Destroy a server monitor.
- *
- * Called only by one thread.
- * Caller must not hold server monitor lock.
- * Server monitor thread is in state MONGOC_THREAD_OFF.
- */
-void
-mongoc_server_monitor_destroy (mongoc_server_monitor_t *server_monitor)
-{
- if (!server_monitor) {
- return;
- }
-
- /* Locking not necessary since this is only called by one thread, and server
- * monitor thread is no longer running. */
- BSON_ASSERT (server_monitor->shared.state == MONGOC_THREAD_OFF);
-
- mongoc_server_description_destroy (server_monitor->description);
- mongoc_stream_destroy (server_monitor->stream);
- mongoc_uri_destroy (server_monitor->uri);
- mongoc_cond_destroy (&server_monitor->shared.cond);
- bson_mutex_destroy (&server_monitor->shared.mutex);
-#ifdef MONGOC_ENABLE_SSL
- if (server_monitor->ssl_opts) {
- _mongoc_ssl_opts_cleanup (server_monitor->ssl_opts, true);
- bson_free (server_monitor->ssl_opts);
- }
-#endif
- bson_free (server_monitor);
-}
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-stream-private.h b/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-stream-private.h
deleted file mode 100644
index 6a1c61dd..00000000
--- a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-stream-private.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright 2015 MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "mongoc-prelude.h"
-
-#ifndef MONGOC_SERVER_STREAM_H
-#define MONGOC_SERVER_STREAM_H
-
-#include "mongoc-config.h"
-
-#include <bson/bson.h>
-
-#include "mongoc-topology-description-private.h"
-#include "mongoc-server-description-private.h"
-#include "mongoc-stream.h"
-
-BSON_BEGIN_DECLS
-
-typedef struct _mongoc_server_stream_t {
- mongoc_topology_description_type_t topology_type;
- mongoc_server_description_t *sd; /* owned */
- bson_t cluster_time; /* owned */
- mongoc_stream_t *stream; /* borrowed */
-} mongoc_server_stream_t;
-
-
-mongoc_server_stream_t *
-mongoc_server_stream_new (const mongoc_topology_description_t *td,
- mongoc_server_description_t *sd,
- mongoc_stream_t *stream);
-
-int32_t
-mongoc_server_stream_max_bson_obj_size (mongoc_server_stream_t *server_stream);
-
-int32_t
-mongoc_server_stream_max_msg_size (mongoc_server_stream_t *server_stream);
-
-int32_t
-mongoc_server_stream_max_write_batch_size (
- mongoc_server_stream_t *server_stream);
-
-void
-mongoc_server_stream_cleanup (mongoc_server_stream_t *server_stream);
-
-BSON_END_DECLS
-
-
-#endif /* MONGOC_SERVER_STREAM_H */
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-stream.c b/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-stream.c
deleted file mode 100644
index 305db509..00000000
--- a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-stream.c
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright 2015 MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-#include "mongoc-cluster-private.h"
-#include "mongoc-server-stream-private.h"
-#include "mongoc-util-private.h"
-
-#undef MONGOC_LOG_DOMAIN
-#define MONGOC_LOG_DOMAIN "server-stream"
-
-mongoc_server_stream_t *
-mongoc_server_stream_new (const mongoc_topology_description_t *td,
- mongoc_server_description_t *sd,
- mongoc_stream_t *stream)
-{
- mongoc_server_stream_t *server_stream;
-
- BSON_ASSERT (sd);
- BSON_ASSERT (stream);
-
- server_stream = bson_malloc (sizeof (mongoc_server_stream_t));
- server_stream->topology_type = td->type;
- bson_copy_to (&td->cluster_time, &server_stream->cluster_time);
- server_stream->sd = sd; /* becomes owned */
- server_stream->stream = stream; /* merely borrowed */
-
- return server_stream;
-}
-
-void
-mongoc_server_stream_cleanup (mongoc_server_stream_t *server_stream)
-{
- if (server_stream) {
- mongoc_server_description_destroy (server_stream->sd);
- bson_destroy (&server_stream->cluster_time);
- bson_free (server_stream);
- }
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_server_stream_max_bson_obj_size --
- *
- * Return the max bson object size for the given server stream.
- *
- *--------------------------------------------------------------------------
- */
-
-int32_t
-mongoc_server_stream_max_bson_obj_size (mongoc_server_stream_t *server_stream)
-{
- return COALESCE (server_stream->sd->max_bson_obj_size,
- MONGOC_DEFAULT_BSON_OBJ_SIZE);
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_server_stream_max_msg_size --
- *
- * Return the max message size for the given server stream.
- *
- *--------------------------------------------------------------------------
- */
-
-int32_t
-mongoc_server_stream_max_msg_size (mongoc_server_stream_t *server_stream)
-{
- return COALESCE (server_stream->sd->max_msg_size,
- MONGOC_DEFAULT_MAX_MSG_SIZE);
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_server_stream_max_write_batch_size --
- *
- * Return the max write batch size for the given server stream.
- *
- *--------------------------------------------------------------------------
- */
-
-int32_t
-mongoc_server_stream_max_write_batch_size (
- mongoc_server_stream_t *server_stream)
-{
- return COALESCE (server_stream->sd->max_write_batch_size,
- MONGOC_DEFAULT_WRITE_BATCH_SIZE);
-}
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-socket.c b/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-socket.c
deleted file mode 100644
index 21e094bf..00000000
--- a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-socket.c
+++ /dev/null
@@ -1,1578 +0,0 @@
-/*
- * Copyright 2014 MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-#include <errno.h>
-#include <string.h>
-
-#include "mongoc-counters-private.h"
-#include "mongoc-errno-private.h"
-#include "mongoc-socket-private.h"
-#include "mongoc-host-list.h"
-#include "mongoc-socket-private.h"
-#include "mongoc-trace-private.h"
-#ifdef _WIN32
-#include <Mstcpip.h>
-#include <process.h>
-#endif
-
-#undef MONGOC_LOG_DOMAIN
-#define MONGOC_LOG_DOMAIN "socket"
-
-
-#define OPERATION_EXPIRED(expire_at) \
- ((expire_at >= 0) && (expire_at < (bson_get_monotonic_time ())))
-
-
-/* either struct sockaddr or void, depending on platform */
-typedef MONGOC_SOCKET_ARG2 mongoc_sockaddr_t;
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_socket_capture_errno --
- *
- * Save the errno state for contextual use.
- *
- * Returns:
- * None.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-static void
-_mongoc_socket_capture_errno (mongoc_socket_t *sock) /* IN */
-{
-#ifdef _WIN32
- errno = sock->errno_ = WSAGetLastError ();
-#else
- sock->errno_ = errno;
-#endif
- TRACE ("setting errno: %d %s", sock->errno_, strerror (sock->errno_));
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_socket_setflags --
- *
- * A helper to set socket flags. Sets to nonblocking mode. On
- * POSIX sets closeonexec.
- *
- *
- * Returns:
- * true if successful; otherwise false.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-static bool
-#ifdef _WIN32
-_mongoc_socket_setflags (SOCKET sd)
-#else
-_mongoc_socket_setflags (int sd)
-#endif
-{
-#ifdef _WIN32
- u_long io_mode = 1;
- return (NO_ERROR == ioctlsocket (sd, FIONBIO, &io_mode));
-#else
- int flags;
-
- flags = fcntl (sd, F_GETFL);
-
- if (-1 == fcntl (sd, F_SETFL, (flags | O_NONBLOCK))) {
- return false;
- }
-
-#ifdef FD_CLOEXEC
- flags = fcntl (sd, F_GETFD);
- if (-1 == fcntl (sd, F_SETFD, (flags | FD_CLOEXEC))) {
- return false;
- }
-#endif
- return true;
-#endif
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_socket_wait --
- *
- * A single socket poll helper.
- *
- * @events: in most cases should be POLLIN or POLLOUT.
- *
- * @expire_at should be an absolute time at which to expire using
- * the monotonic clock (bson_get_monotonic_time(), which is in
- * microseconds). Or zero to not block at all. Or -1 to block
- * forever.
- *
- * Returns:
- * true if an event matched. otherwise false.
- * a timeout will return false.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-static bool
-_mongoc_socket_wait (mongoc_socket_t *sock, /* IN */
- int events, /* IN */
- int64_t expire_at) /* IN */
-{
-#ifdef _WIN32
- fd_set read_fds;
- fd_set write_fds;
- fd_set error_fds;
- struct timeval timeout_tv;
-#else
- struct pollfd pfd;
-#endif
- int ret;
- int timeout;
- int64_t now;
-
- ENTRY;
-
- BSON_ASSERT (sock);
- BSON_ASSERT (events);
-
-#ifdef _WIN32
- FD_ZERO (&read_fds);
- FD_ZERO (&write_fds);
- FD_ZERO (&error_fds);
-
- if (events & POLLIN) {
- FD_SET (sock->sd, &read_fds);
- }
-
- if (events & POLLOUT) {
- FD_SET (sock->sd, &write_fds);
- }
-
- FD_SET (sock->sd, &error_fds);
-#else
- pfd.fd = sock->sd;
- pfd.events = events | POLLERR | POLLHUP;
- pfd.revents = 0;
-#endif
- now = bson_get_monotonic_time ();
-
- for (;;) {
- if (expire_at < 0) {
- timeout = -1;
- } else if (expire_at == 0) {
- timeout = 0;
- } else {
- timeout = (int) ((expire_at - now) / 1000L);
- if (timeout < 0) {
- timeout = 0;
- }
- }
-
-#ifdef _WIN32
- if (timeout == -1) {
- /* not WSAPoll: daniel.haxx.se/blog/2012/10/10/wsapoll-is-broken */
- ret = select (0 /*unused*/, &read_fds, &write_fds, &error_fds, NULL);
- } else {
- timeout_tv.tv_sec = timeout / 1000;
- timeout_tv.tv_usec = (timeout % 1000) * 1000;
- ret = select (
- 0 /*unused*/, &read_fds, &write_fds, &error_fds, &timeout_tv);
- }
- if (ret == SOCKET_ERROR) {
- _mongoc_socket_capture_errno (sock);
- ret = -1;
- } else if (FD_ISSET (sock->sd, &error_fds)) {
- errno = WSAECONNRESET;
- ret = -1;
- }
-#else
- ret = poll (&pfd, 1, timeout);
-#endif
-
- if (ret > 0) {
-/* Something happened, so return that */
-#ifdef _WIN32
- return (FD_ISSET (sock->sd, &read_fds) ||
- FD_ISSET (sock->sd, &write_fds));
-#else
- RETURN (0 != (pfd.revents & events));
-#endif
- } else if (ret < 0) {
- /* poll itself failed */
-
- TRACE ("errno is: %d", errno);
- if (MONGOC_ERRNO_IS_AGAIN (errno)) {
- if (OPERATION_EXPIRED (expire_at)) {
- _mongoc_socket_capture_errno (sock);
- RETURN (false);
- } else {
- continue;
- }
- } else {
- /* poll failed for some non-transient reason */
- _mongoc_socket_capture_errno (sock);
- RETURN (false);
- }
- } else {
- /* ret == 0, poll timed out */
- if (timeout) {
- mongoc_counter_streams_timeout_inc ();
- }
-#ifdef _WIN32
- sock->errno_ = timeout ? WSAETIMEDOUT : EAGAIN;
-#else
- sock->errno_ = timeout ? ETIMEDOUT : EAGAIN;
-#endif
- RETURN (false);
- }
- }
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_socket_poll --
- *
- * A multi-socket poll helper.
- *
- * @expire_at should be an absolute time at which to expire using
- * the monotonic clock (bson_get_monotonic_time(), which is in
- * microseconds). Or zero to not block at all. Or -1 to block
- * forever.
- *
- * Returns:
- * The number of sockets ready.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-ssize_t
-mongoc_socket_poll (mongoc_socket_poll_t *sds, /* IN */
- size_t nsds, /* IN */
- int32_t timeout) /* IN */
-{
-#ifdef _WIN32
- fd_set read_fds;
- fd_set write_fds;
- fd_set error_fds;
- struct timeval timeout_tv;
-#else
- struct pollfd *pfds;
-#endif
- int ret;
- int i;
-
- ENTRY;
-
- BSON_ASSERT (sds);
-
-#ifdef _WIN32
- FD_ZERO (&read_fds);
- FD_ZERO (&write_fds);
- FD_ZERO (&error_fds);
-
- for (i = 0; i < nsds; i++) {
- if (sds[i].events & POLLIN) {
- FD_SET (sds[i].socket->sd, &read_fds);
- }
-
- if (sds[i].events & POLLOUT) {
- FD_SET (sds[i].socket->sd, &write_fds);
- }
-
- FD_SET (sds[i].socket->sd, &error_fds);
- }
-
- timeout_tv.tv_sec = timeout / 1000;
- timeout_tv.tv_usec = (timeout % 1000) * 1000;
-
- /* not WSAPoll: daniel.haxx.se/blog/2012/10/10/wsapoll-is-broken */
- ret = select (0 /*unused*/, &read_fds, &write_fds, &error_fds, &timeout_tv);
- if (ret == SOCKET_ERROR) {
- errno = WSAGetLastError ();
- return -1;
- }
-
- for (i = 0; i < nsds; i++) {
- if (FD_ISSET (sds[i].socket->sd, &read_fds)) {
- sds[i].revents = POLLIN;
- } else if (FD_ISSET (sds[i].socket->sd, &write_fds)) {
- sds[i].revents = POLLOUT;
- } else if (FD_ISSET (sds[i].socket->sd, &error_fds)) {
- sds[i].revents = POLLHUP;
- } else {
- sds[i].revents = 0;
- }
- }
-#else
- pfds = (struct pollfd *) bson_malloc (sizeof (*pfds) * nsds);
-
- for (i = 0; i < nsds; i++) {
- pfds[i].fd = sds[i].socket->sd;
- pfds[i].events = sds[i].events | POLLERR | POLLHUP;
- pfds[i].revents = 0;
- }
-
- ret = poll (pfds, nsds, timeout);
- for (i = 0; i < nsds; i++) {
- sds[i].revents = pfds[i].revents;
- }
-
- bson_free (pfds);
-#endif
-
- return ret;
-}
-
-
-/* https://jira.mongodb.org/browse/CDRIVER-2176 */
-#define MONGODB_KEEPALIVEINTVL 10
-#define MONGODB_KEEPIDLE 120
-#define MONGODB_KEEPALIVECNT 9
-
-#ifdef _WIN32
-static void
-_mongoc_socket_setkeepalive_windows (SOCKET sd)
-{
- struct tcp_keepalive keepalive;
- DWORD lpcbBytesReturned = 0;
- HKEY hKey;
- DWORD type;
- DWORD data;
- DWORD data_size = sizeof data;
- const char *reg_key =
- "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters";
- keepalive.onoff = true;
- keepalive.keepalivetime = MONGODB_KEEPIDLE * 1000;
- keepalive.keepaliveinterval = MONGODB_KEEPALIVEINTVL * 1000;
- /*
- * Windows hardcodes probes to 10:
- * https://msdn.microsoft.com/en-us/library/windows/desktop/dd877220(v=vs.85).aspx
- * "On Windows Vista and later, the number of keep-alive probes (data
- * retransmissions) is set to 10 and cannot be changed."
- *
- * Note that win2k (and seeminly all versions thereafter) do not set the
- * registry value by default so there is no way to derive the default value
- * programmatically. It is however listed in the docs. A user can however
- * change the default value by setting the registry values.
- */
-
- if (RegOpenKeyExA (HKEY_LOCAL_MACHINE, reg_key, 0, KEY_QUERY_VALUE, &hKey) ==
- ERROR_SUCCESS) {
- /* https://technet.microsoft.com/en-us/library/cc957549.aspx */
- DWORD default_keepalivetime = 7200000; /* 2 hours */
- /* https://technet.microsoft.com/en-us/library/cc957548.aspx */
- DWORD default_keepaliveinterval = 1000; /* 1 second */
-
- if (RegQueryValueEx (
- hKey, "KeepAliveTime", NULL, &type, (LPBYTE) &data, &data_size) ==
- ERROR_SUCCESS) {
- if (type == REG_DWORD && data < keepalive.keepalivetime) {
- keepalive.keepalivetime = data;
- }
- } else if (default_keepalivetime < keepalive.keepalivetime) {
- keepalive.keepalivetime = default_keepalivetime;
- }
-
- if (RegQueryValueEx (hKey,
- "KeepAliveInterval",
- NULL,
- &type,
- (LPBYTE) &data,
- &data_size) == ERROR_SUCCESS) {
- if (type == REG_DWORD && data < keepalive.keepaliveinterval) {
- keepalive.keepaliveinterval = data;
- }
- } else if (default_keepaliveinterval < keepalive.keepaliveinterval) {
- keepalive.keepaliveinterval = default_keepaliveinterval;
- }
- RegCloseKey (hKey);
- }
- if (WSAIoctl (sd,
- SIO_KEEPALIVE_VALS,
- &keepalive,
- sizeof keepalive,
- NULL,
- 0,
- &lpcbBytesReturned,
- NULL,
- NULL) == SOCKET_ERROR) {
- TRACE ("%s", "Could not set keepalive values");
- } else {
- TRACE ("%s", "KeepAlive values updated");
- TRACE ("KeepAliveTime: %d", keepalive.keepalivetime);
- TRACE ("KeepAliveInterval: %d", keepalive.keepaliveinterval);
- }
-}
-#else
-#ifdef MONGOC_TRACE
-static const char *
-_mongoc_socket_sockopt_value_to_name (int value)
-{
- switch (value) {
-#ifdef TCP_KEEPIDLE
- case TCP_KEEPIDLE:
- return "TCP_KEEPIDLE";
-#endif
-#ifdef TCP_KEEPALIVE
- case TCP_KEEPALIVE:
- return "TCP_KEEPALIVE";
-#endif
-#ifdef TCP_KEEPINTVL
- case TCP_KEEPINTVL:
- return "TCP_KEEPINTVL";
-#endif
-#ifdef TCP_KEEPCNT
- case TCP_KEEPCNT:
- return "TCP_KEEPCNT";
-#endif
- default:
- MONGOC_WARNING ("Don't know what socketopt %d is", value);
- return "Unknown option name";
- }
-}
-#endif
-static void
-_mongoc_socket_set_sockopt_if_less (int sd, int name, int value)
-{
- int optval = 1;
- mongoc_socklen_t optlen;
-
- optlen = sizeof optval;
- if (getsockopt (sd, IPPROTO_TCP, name, (char *) &optval, &optlen)) {
- TRACE ("Getting '%s' failed, errno: %d",
- _mongoc_socket_sockopt_value_to_name (name),
- errno);
- } else {
- TRACE ("'%s' is %d, target value is %d",
- _mongoc_socket_sockopt_value_to_name (name),
- optval,
- value);
- if (optval > value) {
- optval = value;
- if (setsockopt (
- sd, IPPROTO_TCP, name, (char *) &optval, sizeof optval)) {
- TRACE ("Setting '%s' failed, errno: %d",
- _mongoc_socket_sockopt_value_to_name (name),
- errno);
- } else {
- TRACE ("'%s' value changed to %d",
- _mongoc_socket_sockopt_value_to_name (name),
- optval);
- }
- }
- }
-}
-
-static void
-_mongoc_socket_setkeepalive_nix (int sd)
-{
-#if defined(TCP_KEEPIDLE)
- _mongoc_socket_set_sockopt_if_less (sd, TCP_KEEPIDLE, MONGODB_KEEPIDLE);
-#elif defined(TCP_KEEPALIVE)
- _mongoc_socket_set_sockopt_if_less (sd, TCP_KEEPALIVE, MONGODB_KEEPIDLE);
-#else
- TRACE ("%s", "Neither TCP_KEEPIDLE nor TCP_KEEPALIVE available");
-#endif
-
-#ifdef TCP_KEEPINTVL
- _mongoc_socket_set_sockopt_if_less (
- sd, TCP_KEEPINTVL, MONGODB_KEEPALIVEINTVL);
-#else
- TRACE ("%s", "TCP_KEEPINTVL not available");
-#endif
-
-#ifdef TCP_KEEPCNT
- _mongoc_socket_set_sockopt_if_less (sd, TCP_KEEPCNT, MONGODB_KEEPALIVECNT);
-#else
- TRACE ("%s", "TCP_KEEPCNT not available");
-#endif
-}
-
-#endif
-static void
-#ifdef _WIN32
-_mongoc_socket_setkeepalive (SOCKET sd) /* IN */
-#else
-_mongoc_socket_setkeepalive (int sd) /* IN */
-#endif
-{
-#ifdef SO_KEEPALIVE
- int optval = 1;
-
- ENTRY;
-#ifdef SO_KEEPALIVE
- if (!setsockopt (
- sd, SOL_SOCKET, SO_KEEPALIVE, (char *) &optval, sizeof optval)) {
- TRACE ("%s", "Setting SO_KEEPALIVE");
-#ifdef _WIN32
- _mongoc_socket_setkeepalive_windows (sd);
-#else
- _mongoc_socket_setkeepalive_nix (sd);
-#endif
- } else {
- TRACE ("%s", "Failed setting SO_KEEPALIVE");
- }
-#else
- TRACE ("%s", "SO_KEEPALIVE not available");
-#endif
- EXIT;
-#endif
-}
-
-
-static bool
-#ifdef _WIN32
-_mongoc_socket_setnodelay (SOCKET sd) /* IN */
-#else
-_mongoc_socket_setnodelay (int sd) /* IN */
-#endif
-{
-#ifdef _WIN32
- BOOL optval = 1;
-#else
- int optval = 1;
-#endif
- int ret;
-
- ENTRY;
-
- errno = 0;
- ret = setsockopt (
- sd, IPPROTO_TCP, TCP_NODELAY, (char *) &optval, sizeof optval);
-
-#ifdef _WIN32
- if (ret == SOCKET_ERROR) {
- MONGOC_WARNING ("WSAGetLastError(): %d", (int) WSAGetLastError ());
- }
-#endif
-
- RETURN (ret == 0);
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_socket_errno --
- *
- * Returns the last error on the socket.
- *
- * Returns:
- * An integer errno, or 0 on no error.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-int
-mongoc_socket_errno (mongoc_socket_t *sock) /* IN */
-{
- BSON_ASSERT (sock);
- TRACE ("Current errno: %d", sock->errno_);
- return sock->errno_;
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_socket_errno_is_again --
- *
- * Check to see if we should attempt to make further progress
- * based on the error of the last operation.
- *
- * Returns:
- * true if we should try again. otherwise false.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-static bool
-_mongoc_socket_errno_is_again (mongoc_socket_t *sock) /* IN */
-{
- TRACE ("errno is: %d", sock->errno_);
- return MONGOC_ERRNO_IS_AGAIN (sock->errno_);
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_socket_accept --
- *
- * Wrapper for BSD socket accept(). Handles portability between
- * BSD sockets and WinSock2 on Windows Vista and newer.
- *
- * Returns:
- * NULL upon failure to accept or timeout.
- * A newly allocated mongoc_socket_t on success.
- *
- * Side effects:
- * *port contains the client port number.
- *
- *--------------------------------------------------------------------------
- */
-
-mongoc_socket_t *
-mongoc_socket_accept (mongoc_socket_t *sock, /* IN */
- int64_t expire_at) /* IN */
-{
- return mongoc_socket_accept_ex (sock, expire_at, NULL);
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_socket_accept_ex --
- *
- * Private synonym for mongoc_socket_accept, returning client port.
- *
- * Returns:
- * NULL upon failure to accept or timeout.
- * A newly allocated mongoc_socket_t on success.
- *
- * Side effects:
- * *port contains the client port number.
- *
- *--------------------------------------------------------------------------
- */
-
-mongoc_socket_t *
-mongoc_socket_accept_ex (mongoc_socket_t *sock, /* IN */
- int64_t expire_at, /* IN */
- uint16_t *port) /* OUT */
-{
- mongoc_socket_t *client;
- struct sockaddr_storage addr = {0};
- mongoc_socklen_t addrlen = sizeof addr;
- bool try_again = false;
- bool failed = false;
-#ifdef _WIN32
- SOCKET sd;
-#else
- int sd;
-#endif
-
- ENTRY;
-
- BSON_ASSERT (sock);
-
-again:
- errno = 0;
- sd = accept (sock->sd, (mongoc_sockaddr_t *) &addr, &addrlen);
-
- _mongoc_socket_capture_errno (sock);
-#ifdef _WIN32
- failed = (sd == INVALID_SOCKET);
-#else
- failed = (sd == -1);
-#endif
- try_again = (failed && _mongoc_socket_errno_is_again (sock));
-
- if (failed && try_again) {
- if (_mongoc_socket_wait (sock, POLLIN, expire_at)) {
- GOTO (again);
- }
- RETURN (NULL);
- } else if (failed) {
- RETURN (NULL);
- } else if (!_mongoc_socket_setflags (sd)) {
-#ifdef _WIN32
- closesocket (sd);
-#else
- close (sd);
-#endif
- RETURN (NULL);
- }
-
- client = (mongoc_socket_t *) bson_malloc0 (sizeof *client);
- client->sd = sd;
-
- if (port) {
- if (addr.ss_family == AF_INET) {
- struct sockaddr_in *tmp = (struct sockaddr_in *) &addr;
- *port = ntohs (tmp->sin_port);
- } else {
- struct sockaddr_in6 *tmp = (struct sockaddr_in6 *) &addr;
- *port = ntohs (tmp->sin6_port);
- }
- }
-
- if (!_mongoc_socket_setnodelay (client->sd)) {
- MONGOC_WARNING ("Failed to enable TCP_NODELAY.");
- }
-
- RETURN (client);
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongo_socket_bind --
- *
- * A wrapper around bind().
- *
- * Returns:
- * 0 on success, -1 on failure and errno is set.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-int
-mongoc_socket_bind (mongoc_socket_t *sock, /* IN */
- const struct sockaddr *addr, /* IN */
- mongoc_socklen_t addrlen) /* IN */
-{
- int ret;
-
- ENTRY;
-
- BSON_ASSERT (sock);
- BSON_ASSERT (addr);
- BSON_ASSERT (addrlen);
-
- ret = bind (sock->sd, addr, addrlen);
-
- _mongoc_socket_capture_errno (sock);
-
- RETURN (ret);
-}
-
-
-int
-mongoc_socket_close (mongoc_socket_t *sock) /* IN */
-{
- bool owned;
-
- ENTRY;
-
- BSON_ASSERT (sock);
-
-#ifdef _WIN32
- owned = (sock->pid == (int) _getpid ());
-
- if (sock->sd != INVALID_SOCKET) {
- if (owned) {
- shutdown (sock->sd, SD_BOTH);
- }
-
- if (0 == closesocket (sock->sd)) {
- sock->sd = INVALID_SOCKET;
- } else {
- _mongoc_socket_capture_errno (sock);
- RETURN (-1);
- }
- }
- RETURN (0);
-#else
- owned = (sock->pid == (int) getpid ());
-
- if (sock->sd != -1) {
- if (owned) {
- shutdown (sock->sd, SHUT_RDWR);
- }
-
- if (0 == close (sock->sd)) {
- sock->sd = -1;
- } else {
- _mongoc_socket_capture_errno (sock);
- RETURN (-1);
- }
- }
- RETURN (0);
-#endif
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_socket_connect --
- *
- * Performs a socket connection but will fail if @expire_at is
- * reached by the monotonic clock.
- *
- * Returns:
- * 0 if success, otherwise -1 and errno is set.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-int
-mongoc_socket_connect (mongoc_socket_t *sock, /* IN */
- const struct sockaddr *addr, /* IN */
- mongoc_socklen_t addrlen, /* IN */
- int64_t expire_at) /* IN */
-{
- bool try_again = false;
- bool failed = false;
- int ret;
- int optval;
- /* getsockopt parameter types vary, we check in CheckCompiler.m4 */
- mongoc_socklen_t optlen = (mongoc_socklen_t) sizeof optval;
-
- ENTRY;
-
- BSON_ASSERT (sock);
- BSON_ASSERT (addr);
- BSON_ASSERT (addrlen);
-
- ret = connect (sock->sd, addr, addrlen);
-
-#ifdef _WIN32
- if (ret == SOCKET_ERROR) {
-#else
- if (ret == -1) {
-#endif
- _mongoc_socket_capture_errno (sock);
-
- failed = true;
- try_again = _mongoc_socket_errno_is_again (sock);
- }
-
- if (failed && try_again) {
- if (_mongoc_socket_wait (sock, POLLOUT, expire_at)) {
- optval = -1;
- ret = getsockopt (
- sock->sd, SOL_SOCKET, SO_ERROR, (char *) &optval, &optlen);
- if ((ret == 0) && (optval == 0)) {
- RETURN (0);
- } else {
- errno = sock->errno_ = optval;
- }
- }
- RETURN (-1);
- } else if (failed) {
- RETURN (-1);
- } else {
- RETURN (0);
- }
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_socket_destroy --
- *
- * Cleanup after a mongoc_socket_t structure, possibly closing
- * underlying sockets.
- *
- * Returns:
- * None.
- *
- * Side effects:
- * @sock is freed and should be considered invalid.
- *
- *--------------------------------------------------------------------------
- */
-
-void
-mongoc_socket_destroy (mongoc_socket_t *sock) /* IN */
-{
- if (sock) {
- mongoc_socket_close (sock);
- bson_free (sock);
- }
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_socket_listen --
- *
- * Listen for incoming requests with a backlog up to @backlog.
- *
- * If @backlog is zero, a sensible default will be chosen.
- *
- * Returns:
- * true if successful; otherwise false.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-int
-mongoc_socket_listen (mongoc_socket_t *sock, /* IN */
- unsigned int backlog) /* IN */
-{
- int ret;
-
- ENTRY;
-
- BSON_ASSERT (sock);
-
- if (backlog == 0) {
- backlog = 10;
- }
-
- ret = listen (sock->sd, backlog);
-
- _mongoc_socket_capture_errno (sock);
-
- RETURN (ret);
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_socket_new --
- *
- * Create a new socket and store the current process id on it.
- *
- * Free the result with mongoc_socket_destroy().
- *
- * Returns:
- * A newly allocated socket.
- * NULL on failure.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-mongoc_socket_t *
-mongoc_socket_new (int domain, /* IN */
- int type, /* IN */
- int protocol) /* IN */
-{
- mongoc_socket_t *sock;
-#ifdef _WIN32
- SOCKET sd;
-#else
- int sd;
-#endif
-#ifdef SO_NOSIGPIPE
- int on = 1;
-#endif
-
- ENTRY;
-
- sd = socket (domain, type, protocol);
-
-#ifdef _WIN32
- if (sd == INVALID_SOCKET) {
-#else
- if (sd == -1) {
-#endif
- RETURN (NULL);
- }
-
- if (!_mongoc_socket_setflags (sd)) {
- GOTO (fail);
- }
-
- if (domain != AF_UNIX) {
- if (!_mongoc_socket_setnodelay (sd)) {
- MONGOC_WARNING ("Failed to enable TCP_NODELAY.");
- }
- _mongoc_socket_setkeepalive (sd);
- }
-
- /* Set SO_NOSIGPIPE, to ignore SIGPIPE on writes for platforms where
- setting MSG_NOSIGNAL on writes is not supported (primarily OSX). */
-#ifdef SO_NOSIGPIPE
- setsockopt(sd, SOL_SOCKET, SO_NOSIGPIPE, &on, sizeof(on));
-#endif
-
- sock = (mongoc_socket_t *) bson_malloc0 (sizeof *sock);
- sock->sd = sd;
- sock->domain = domain;
-#ifdef _WIN32
- sock->pid = (int) _getpid ();
-#else
- sock->pid = (int) getpid ();
-#endif
-
- RETURN (sock);
-
-fail:
-#ifdef _WIN32
- closesocket (sd);
-#else
- close (sd);
-#endif
-
- RETURN (NULL);
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_socket_recv --
- *
- * A portable wrapper around recv() that also respects an absolute
- * timeout.
- *
- * @expire_at is 0 for no blocking, -1 for infinite blocking,
- * or a time using the monotonic clock to expire. Calculate this
- * using bson_get_monotonic_time() + N_MICROSECONDS.
- *
- * Returns:
- * The number of bytes received on success.
- * 0 on end of stream.
- * -1 on failure.
- *
- * Side effects:
- * @buf will be read into.
- *
- *--------------------------------------------------------------------------
- */
-
-ssize_t
-mongoc_socket_recv (mongoc_socket_t *sock, /* IN */
- void *buf, /* OUT */
- size_t buflen, /* IN */
- int flags, /* IN */
- int64_t expire_at) /* IN */
-{
- ssize_t ret = 0;
- bool failed = false;
-
- ENTRY;
-
- BSON_ASSERT (sock);
- BSON_ASSERT (buf);
- BSON_ASSERT (buflen);
-
-again:
- sock->errno_ = 0;
-#ifdef _WIN32
- ret = recv (sock->sd, (char *) buf, (int) buflen, flags);
- failed = (ret == SOCKET_ERROR);
-#else
- ret = recv (sock->sd, buf, buflen, flags);
- failed = (ret == -1);
-#endif
- if (failed) {
- _mongoc_socket_capture_errno (sock);
- if (_mongoc_socket_errno_is_again (sock) &&
- _mongoc_socket_wait (sock, POLLIN, expire_at)) {
- GOTO (again);
- }
- }
-
- if (failed) {
- RETURN (-1);
- }
-
- mongoc_counter_streams_ingress_add (ret);
-
- RETURN (ret);
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_socket_setsockopt --
- *
- * A wrapper around setsockopt().
- *
- * Returns:
- * 0 on success, -1 on failure.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-int
-mongoc_socket_setsockopt (mongoc_socket_t *sock, /* IN */
- int level, /* IN */
- int optname, /* IN */
- const void *optval, /* IN */
- mongoc_socklen_t optlen) /* IN */
-{
- int ret;
-
- ENTRY;
-
- BSON_ASSERT (sock);
-
- ret = setsockopt (sock->sd, level, optname, optval, optlen);
-
- _mongoc_socket_capture_errno (sock);
-
- RETURN (ret);
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_socket_send --
- *
- * A simplified wrapper around mongoc_socket_sendv().
- *
- * @expire_at is 0 for no blocking, -1 for infinite blocking,
- * or a time using the monotonic clock to expire. Calculate this
- * using bson_get_monotonic_time() + N_MICROSECONDS.
- *
- * Returns:
- * -1 on failure. number of bytes written on success.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-ssize_t
-mongoc_socket_send (mongoc_socket_t *sock, /* IN */
- const void *buf, /* IN */
- size_t buflen, /* IN */
- int64_t expire_at) /* IN */
-{
- mongoc_iovec_t iov;
-
- BSON_ASSERT (sock);
- BSON_ASSERT (buf);
- BSON_ASSERT (buflen);
-
- iov.iov_base = (void *) buf;
- iov.iov_len = buflen;
-
- return mongoc_socket_sendv (sock, &iov, 1, expire_at);
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_socket_try_sendv_slow --
- *
- * A slow variant of _mongoc_socket_try_sendv() that sends each
- * iovec entry one by one. This can happen if we hit EMSGSIZE
- * with sendmsg() on various POSIX systems or WSASend()+WSAEMSGSIZE
- * on Windows.
- *
- * Returns:
- * the number of bytes sent or -1 and errno is set.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-static ssize_t
-_mongoc_socket_try_sendv_slow (mongoc_socket_t *sock, /* IN */
- mongoc_iovec_t *iov, /* IN */
- size_t iovcnt) /* IN */
-{
- ssize_t ret = 0;
- size_t i;
- ssize_t wrote;
-
- ENTRY;
-
- BSON_ASSERT (sock);
- BSON_ASSERT (iov);
- BSON_ASSERT (iovcnt);
-
- for (i = 0; i < iovcnt; i++) {
- wrote = send (sock->sd, iov[i].iov_base, iov[i].iov_len, 0);
-#ifdef _WIN32
- if (wrote == SOCKET_ERROR) {
-#else
- if (wrote == -1) {
-#endif
- _mongoc_socket_capture_errno (sock);
-
- if (!_mongoc_socket_errno_is_again (sock)) {
- RETURN (-1);
- }
- RETURN (ret ? ret : -1);
- }
-
- ret += wrote;
-
- if (wrote != iov[i].iov_len) {
- RETURN (ret);
- }
- }
-
- RETURN (ret);
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_socket_try_sendv --
- *
- * Helper used by mongoc_socket_sendv() to try to write as many
- * bytes to the underlying socket until the socket buffer is full.
- *
- * This is performed in a non-blocking fashion.
- *
- * Returns:
- * -1 on failure. the number of bytes written on success.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-static ssize_t
-_mongoc_socket_try_sendv (mongoc_socket_t *sock, /* IN */
- mongoc_iovec_t *iov, /* IN */
- size_t iovcnt) /* IN */
-{
-#ifdef _WIN32
- DWORD dwNumberofBytesSent = 0;
- int ret;
-#else
- struct msghdr msg;
- ssize_t ret;
-#endif
-
- ENTRY;
-
- BSON_ASSERT (sock);
- BSON_ASSERT (iov);
- BSON_ASSERT (iovcnt);
-
- DUMP_IOVEC (sendbuf, iov, iovcnt);
-
-#ifdef _WIN32
- ret = WSASend (
- sock->sd, (LPWSABUF) iov, iovcnt, &dwNumberofBytesSent, 0, NULL, NULL);
- TRACE ("WSASend sent: %ld (out of: %ld), ret: %d",
- dwNumberofBytesSent,
- iov->iov_len,
- ret);
-#else
- memset (&msg, 0, sizeof msg);
- msg.msg_iov = iov;
- msg.msg_iovlen = (int) iovcnt;
- ret = sendmsg (sock->sd,
- &msg,
-#ifdef MSG_NOSIGNAL
- MSG_NOSIGNAL);
-#else
- 0);
-#endif
- TRACE ("Send %ld out of %ld bytes", ret, iov->iov_len);
-#endif
-
-
-#ifdef _WIN32
- if (ret == SOCKET_ERROR) {
-#else
- if (ret == -1) {
-#endif
- _mongoc_socket_capture_errno (sock);
-
-/*
- * Check to see if we have sent an iovec too large for sendmsg to
- * complete. If so, we need to fallback to the slow path of multiple
- * send() commands.
- */
-#ifdef _WIN32
- if (mongoc_socket_errno (sock) == WSAEMSGSIZE) {
-#else
- if (mongoc_socket_errno (sock) == EMSGSIZE) {
-#endif
- RETURN (_mongoc_socket_try_sendv_slow (sock, iov, iovcnt));
- }
-
- RETURN (-1);
- }
-
-#ifdef _WIN32
- RETURN (dwNumberofBytesSent);
-#else
- RETURN (ret);
-#endif
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_socket_sendv --
- *
- * A wrapper around using sendmsg() to send an iovec.
- * This also deals with the structure differences between
- * WSABUF and struct iovec.
- *
- * @expire_at is 0 for no blocking, -1 for infinite blocking,
- * or a time using the monotonic clock to expire. Calculate this
- * using bson_get_monotonic_time() + N_MICROSECONDS.
- *
- * Returns:
- * -1 on failure.
- * the number of bytes written on success.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-ssize_t
-mongoc_socket_sendv (mongoc_socket_t *sock, /* IN */
- mongoc_iovec_t *in_iov, /* IN */
- size_t iovcnt, /* IN */
- int64_t expire_at) /* IN */
-{
- ssize_t ret = 0;
- ssize_t sent;
- size_t cur = 0;
- mongoc_iovec_t *iov;
-
- ENTRY;
-
- BSON_ASSERT (sock);
- BSON_ASSERT (in_iov);
- BSON_ASSERT (iovcnt);
-
- iov = bson_malloc (sizeof (*iov) * iovcnt);
- memcpy (iov, in_iov, sizeof (*iov) * iovcnt);
-
- for (;;) {
- sent = _mongoc_socket_try_sendv (sock, &iov[cur], iovcnt - cur);
- TRACE (
- "Sent %ld (of %ld) out of iovcnt=%ld", sent, iov[cur].iov_len, iovcnt);
-
- /*
- * If we failed with anything other than EAGAIN or EWOULDBLOCK,
- * we should fail immediately as there is another issue with the
- * underlying socket.
- */
- if (sent == -1) {
- if (!_mongoc_socket_errno_is_again (sock)) {
- ret = -1;
- GOTO (CLEANUP);
- }
- }
-
- /*
- * Update internal stream counters.
- */
- if (sent > 0) {
- ret += sent;
- mongoc_counter_streams_egress_add (sent);
-
- /*
- * Subtract the sent amount from what we still need to send.
- */
- while ((cur < iovcnt) && (sent >= (ssize_t) iov[cur].iov_len)) {
- TRACE ("still got bytes left: sent -= iov_len: %ld -= %ld",
- sent,
- iov[cur].iov_len);
- sent -= iov[cur++].iov_len;
- }
-
- /*
- * Check if that made us finish all of the iovecs. If so, we are done
- * sending data over the socket.
- */
- if (cur == iovcnt) {
- TRACE ("%s", "Finished the iovecs");
- break;
- }
-
- /*
- * Increment the current iovec buffer to its proper offset and adjust
- * the number of bytes to write.
- */
- TRACE ("Seeked io_base+%ld", sent);
- TRACE (
- "Subtracting iov_len -= sent; %ld -= %ld", iov[cur].iov_len, sent);
- iov[cur].iov_base = ((char *) iov[cur].iov_base) + sent;
- iov[cur].iov_len -= sent;
- TRACE ("iov_len remaining %ld", iov[cur].iov_len);
-
- BSON_ASSERT (iovcnt - cur);
- BSON_ASSERT (iov[cur].iov_len);
- } else if (OPERATION_EXPIRED (expire_at)) {
- if (expire_at > 0) {
- mongoc_counter_streams_timeout_inc ();
- }
- GOTO (CLEANUP);
- }
-
- /*
- * Block on poll() until our desired condition is met.
- */
- if (!_mongoc_socket_wait (sock, POLLOUT, expire_at)) {
- GOTO (CLEANUP);
- }
- }
-
-CLEANUP:
- bson_free (iov);
-
- RETURN (ret);
-}
-
-
-int
-mongoc_socket_getsockname (mongoc_socket_t *sock, /* IN */
- struct sockaddr *addr, /* OUT */
- mongoc_socklen_t *addrlen) /* INOUT */
-{
- int ret;
-
- ENTRY;
-
- BSON_ASSERT (sock);
-
- ret = getsockname (sock->sd, addr, addrlen);
-
- _mongoc_socket_capture_errno (sock);
-
- RETURN (ret);
-}
-
-
-char *
-mongoc_socket_getnameinfo (mongoc_socket_t *sock) /* IN */
-{
- /* getpeername parameter types vary, we check in CheckCompiler.m4 */
- struct sockaddr_storage addr;
- mongoc_socklen_t len = (mongoc_socklen_t) sizeof addr;
- char *ret;
- char host[BSON_HOST_NAME_MAX + 1];
-
- ENTRY;
-
- BSON_ASSERT (sock);
-
- if (getpeername (sock->sd, (struct sockaddr *) &addr, &len)) {
- RETURN (NULL);
- }
-
- if (getnameinfo (
- (struct sockaddr *) &addr, len, host, sizeof host, NULL, 0, 0)) {
- RETURN (NULL);
- }
-
- ret = bson_strdup (host);
- RETURN (ret);
-}
-
-
-bool
-mongoc_socket_check_closed (mongoc_socket_t *sock) /* IN */
-{
- bool closed = false;
- char buf[1];
- ssize_t r;
-
- if (_mongoc_socket_wait (sock, POLLIN, 0)) {
- sock->errno_ = 0;
-
- r = recv (sock->sd, buf, 1, MSG_PEEK);
-
- if (r < 0) {
- _mongoc_socket_capture_errno (sock);
- }
-
- if (r < 1) {
- closed = true;
- }
- }
-
- return closed;
-}
-
-/*
- *
- *--------------------------------------------------------------------------
- *
- * mongoc_socket_inet_ntop --
- *
- * Convert the ip from addrinfo into a c string.
- *
- * Returns:
- * The value is returned into 'buffer'. The memory has to be allocated
- * by the caller
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-void
-mongoc_socket_inet_ntop (struct addrinfo *rp, /* IN */
- char *buf, /* INOUT */
- size_t buflen) /* IN */
-{
- void *ptr;
- char tmp[256];
-
- switch (rp->ai_family) {
- case AF_INET:
- ptr = &((struct sockaddr_in *) rp->ai_addr)->sin_addr;
- inet_ntop (rp->ai_family, ptr, tmp, sizeof (tmp));
- bson_snprintf (buf, buflen, "ipv4 %s", tmp);
- break;
- case AF_INET6:
- ptr = &((struct sockaddr_in6 *) rp->ai_addr)->sin6_addr;
- inet_ntop (rp->ai_family, ptr, tmp, sizeof (tmp));
- bson_snprintf (buf, buflen, "ipv6 %s", tmp);
- break;
- default:
- bson_snprintf (buf, buflen, "unknown ip %d", rp->ai_family);
- break;
- }
-}
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-description-private.h b/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-description-private.h
deleted file mode 100644
index e5fb572e..00000000
--- a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-description-private.h
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * Copyright 2014 MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "mongoc-prelude.h"
-
-#ifndef MONGOC_TOPOLOGY_DESCRIPTION_PRIVATE_H
-#define MONGOC_TOPOLOGY_DESCRIPTION_PRIVATE_H
-
-#include "mongoc-set-private.h"
-#include "mongoc-server-description.h"
-#include "mongoc-array-private.h"
-#include "mongoc-topology-description.h"
-#include "mongoc-apm-private.h"
-
-
-typedef enum {
- MONGOC_TOPOLOGY_UNKNOWN,
- MONGOC_TOPOLOGY_SHARDED,
- MONGOC_TOPOLOGY_RS_NO_PRIMARY,
- MONGOC_TOPOLOGY_RS_WITH_PRIMARY,
- MONGOC_TOPOLOGY_SINGLE,
- MONGOC_TOPOLOGY_LOAD_BALANCED,
- MONGOC_TOPOLOGY_DESCRIPTION_TYPES
-} mongoc_topology_description_type_t;
-
-struct _mongoc_topology_description_t {
- bson_oid_t topology_id;
- bool opened;
- mongoc_topology_description_type_t type;
- int64_t heartbeat_msec;
- mongoc_set_t *_servers_;
- char *set_name;
- int64_t max_set_version;
- bson_oid_t max_election_id;
- bson_error_t compatibility_error;
- uint32_t max_server_id;
- bool stale;
- unsigned int rand_seed;
-
- /* the greatest seen cluster time, for a MongoDB 3.6+ sharded cluster.
- * see Driver Sessions Spec. */
- bson_t cluster_time;
-
- /* smallest seen logicalSessionTimeoutMinutes, or -1 if any server has no
- * logicalSessionTimeoutMinutes. see Server Discovery and Monitoring Spec */
- int64_t session_timeout_minutes;
-
- mongoc_apm_callbacks_t apm_callbacks;
- void *apm_context;
-};
-
-typedef enum { MONGOC_SS_READ, MONGOC_SS_WRITE } mongoc_ss_optype_t;
-
-void
-mongoc_topology_description_init (mongoc_topology_description_t *description,
- int64_t heartbeat_msec);
-
-
-/**
- * @brief Get a pointer to the set of server descriptions in the topology
- * description.
- */
-static BSON_INLINE mongoc_set_t *
-mc_tpld_servers (mongoc_topology_description_t *tpld)
-{
- BSON_ASSERT_PARAM (tpld);
- return tpld->_servers_;
-}
-
-static BSON_INLINE const mongoc_set_t *
-mc_tpld_servers_const (const mongoc_topology_description_t *tpld)
-{
- BSON_ASSERT_PARAM (tpld);
- return tpld->_servers_;
-}
-
-void
-_mongoc_topology_description_copy_to (const mongoc_topology_description_t *src,
- mongoc_topology_description_t *dst);
-
-void
-mongoc_topology_description_cleanup (
- mongoc_topology_description_t *description);
-
-void
-mongoc_topology_description_handle_hello (
- mongoc_topology_description_t *topology,
- uint32_t server_id,
- const bson_t *hello_response,
- int64_t rtt_msec,
- const bson_error_t *error /* IN */);
-
-mongoc_server_description_t const *
-mongoc_topology_description_select (
- const mongoc_topology_description_t *description,
- mongoc_ss_optype_t optype,
- const mongoc_read_prefs_t *read_pref,
- int64_t local_threshold_ms);
-
-mongoc_server_description_t *
-mongoc_topology_description_server_by_id (
- mongoc_topology_description_t *description,
- uint32_t id,
- bson_error_t *error);
-
-const mongoc_server_description_t *
-mongoc_topology_description_server_by_id_const (
- const mongoc_topology_description_t *description,
- uint32_t id,
- bson_error_t *error);
-
-int32_t
-mongoc_topology_description_lowest_max_wire_version (
- const mongoc_topology_description_t *td);
-
-bool
-mongoc_topology_description_all_sds_have_write_date (
- const mongoc_topology_description_t *td);
-
-bool
-_mongoc_topology_description_validate_max_staleness (
- const mongoc_topology_description_t *td,
- int64_t max_staleness_seconds,
- bson_error_t *error);
-
-void
-mongoc_topology_description_suitable_servers (
- mongoc_array_t *set, /* OUT */
- mongoc_ss_optype_t optype,
- const mongoc_topology_description_t *topology,
- const mongoc_read_prefs_t *read_pref,
- size_t local_threshold_ms);
-
-bool
-mongoc_topology_description_has_data_node (
- const mongoc_topology_description_t *td);
-
-void
-mongoc_topology_description_invalidate_server (
- mongoc_topology_description_t *topology,
- uint32_t id,
- const bson_error_t *error /* IN */);
-
-bool
-mongoc_topology_description_add_server (mongoc_topology_description_t *topology,
- const char *server,
- uint32_t *id /* OUT */);
-
-void
-mongoc_topology_description_update_cluster_time (
- mongoc_topology_description_t *td, const bson_t *reply);
-
-void
-mongoc_topology_description_reconcile (mongoc_topology_description_t *td,
- mongoc_host_list_t *host_list);
-
-/**
- * @brief Invalidate open connnections to a server.
- *
- * Pooled clients with open connections will discover the invalidation
- * the next time they fetch a stream to the server.
- *
- * @param td The topology description that will be updated.
- * @param server_id The ID of the server to invalidate.
- * @param service_id A service ID for load-balanced deployments. Use
- * kZeroServiceID if not applicable.
- *
- * @note Not applicable to single-threaded clients, which only maintain a
- * single connection per server and therefore have no connection pool.
- */
-void
-_mongoc_topology_description_clear_connection_pool (
- mongoc_topology_description_t *td,
- uint32_t server_id,
- const bson_oid_t *service_id);
-
-#endif /* MONGOC_TOPOLOGY_DESCRIPTION_PRIVATE_H */
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-description.c b/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-description.c
deleted file mode 100644
index c121fcdb..00000000
--- a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-description.c
+++ /dev/null
@@ -1,2350 +0,0 @@
-/*
- * Copyright 2014 MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "mongoc-array-private.h"
-#include "mongoc-error.h"
-#include "mongoc-server-description-private.h"
-#include "mongoc-topology-description-apm-private.h"
-#include "mongoc-trace-private.h"
-#include "mongoc-util-private.h"
-#include "mongoc-read-prefs-private.h"
-#include "mongoc-set-private.h"
-#include "mongoc-client-private.h"
-#include "mongoc-thread-private.h"
-#include "mongoc-host-list-private.h"
-#include "utlist.h"
-
-
-static bool
-_is_data_node (const mongoc_server_description_t *sd)
-{
- switch (sd->type) {
- case MONGOC_SERVER_MONGOS:
- case MONGOC_SERVER_STANDALONE:
- case MONGOC_SERVER_RS_SECONDARY:
- case MONGOC_SERVER_RS_PRIMARY:
- case MONGOC_SERVER_LOAD_BALANCER:
- return true;
- case MONGOC_SERVER_RS_OTHER:
- case MONGOC_SERVER_RS_ARBITER:
- case MONGOC_SERVER_UNKNOWN:
- case MONGOC_SERVER_POSSIBLE_PRIMARY:
- case MONGOC_SERVER_RS_GHOST:
- case MONGOC_SERVER_DESCRIPTION_TYPES:
- default:
- return false;
- }
-}
-
-
-static void
-_mongoc_topology_server_dtor (void *server_, void *ctx_)
-{
- mongoc_server_description_destroy ((mongoc_server_description_t *) server_);
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_topology_description_init --
- *
- * Initialize the given topology description
- *
- * Returns:
- * None.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-void
-mongoc_topology_description_init (mongoc_topology_description_t *description,
- int64_t heartbeat_msec)
-{
- ENTRY;
-
- BSON_ASSERT (description);
-
- memset (description, 0, sizeof (*description));
-
- bson_oid_init (&description->topology_id, NULL);
- description->opened = false;
- description->type = MONGOC_TOPOLOGY_UNKNOWN;
- description->heartbeat_msec = heartbeat_msec;
- description->_servers_ =
- mongoc_set_new (8, _mongoc_topology_server_dtor, NULL);
- description->set_name = NULL;
- description->max_set_version = MONGOC_NO_SET_VERSION;
- description->stale = true;
- description->rand_seed = (unsigned int) bson_get_monotonic_time ();
- bson_init (&description->cluster_time);
- description->session_timeout_minutes = MONGOC_NO_SESSIONS;
-
- EXIT;
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_topology_description_copy_to --
- *
- * Deep-copy @src to an uninitialized topology description @dst.
- * @dst must not already point to any allocated resources. Clean
- * up with mongoc_topology_description_cleanup.
- *
- * Returns:
- * None.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-void
-_mongoc_topology_description_copy_to (const mongoc_topology_description_t *src,
- mongoc_topology_description_t *dst)
-{
- size_t nitems;
- size_t i;
- const mongoc_server_description_t *sd;
- uint32_t id;
-
- ENTRY;
-
- BSON_ASSERT (src);
- BSON_ASSERT (dst);
-
- bson_oid_copy (&src->topology_id, &dst->topology_id);
- bson_oid_copy (&src->max_election_id, &dst->max_election_id);
- dst->opened = src->opened;
- dst->type = src->type;
- dst->heartbeat_msec = src->heartbeat_msec;
- dst->rand_seed = src->rand_seed;
-
- nitems = bson_next_power_of_two (mc_tpld_servers_const (src)->items_len);
- dst->_servers_ = mongoc_set_new (nitems, _mongoc_topology_server_dtor, NULL);
- for (i = 0; i < mc_tpld_servers_const (src)->items_len; i++) {
- sd = mongoc_set_get_item_and_id_const (
- mc_tpld_servers_const (src), (int) i, &id);
- mongoc_set_add (
- mc_tpld_servers (dst), id, mongoc_server_description_new_copy (sd));
- }
-
- dst->set_name = bson_strdup (src->set_name);
- dst->max_set_version = src->max_set_version;
- memcpy (&dst->compatibility_error,
- &src->compatibility_error,
- sizeof (bson_error_t));
- dst->max_server_id = src->max_server_id;
- dst->stale = src->stale;
- memcpy (&dst->apm_callbacks,
- &src->apm_callbacks,
- sizeof (mongoc_apm_callbacks_t));
-
- dst->apm_context = src->apm_context;
-
- bson_copy_to (&src->cluster_time, &dst->cluster_time);
-
- dst->session_timeout_minutes = src->session_timeout_minutes;
-
- EXIT;
-}
-
-/*
- *-------------------------------------------------------------------------
- *
- * mongoc_topology_description_new_copy --
- *
- * Allocates a new topology description and deep-copies @description to it
- * using _mongoc_topology_description_copy_to.
- *
- * Returns:
- * A copy of a topology description that you must destroy with
- * mongoc_topology_description_destroy, or NULL if @description is NULL.
- *
- * Side effects:
- * None.
- *
- *-------------------------------------------------------------------------
- */
-mongoc_topology_description_t *
-mongoc_topology_description_new_copy (
- const mongoc_topology_description_t *description)
-{
- mongoc_topology_description_t *copy;
-
- if (!description) {
- return NULL;
- }
-
- copy = (mongoc_topology_description_t *) bson_malloc0 (sizeof (*copy));
-
- _mongoc_topology_description_copy_to (description, copy);
-
- return copy;
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_topology_description_cleanup --
- *
- * Destroy allocated resources within @description but don't free it.
- *
- * Returns:
- * None.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-void
-mongoc_topology_description_cleanup (mongoc_topology_description_t *description)
-{
- ENTRY;
-
- BSON_ASSERT (description);
-
- if (mc_tpld_servers (description)) {
- mongoc_set_destroy (mc_tpld_servers (description));
- }
-
- if (description->set_name) {
- bson_free (description->set_name);
- }
-
- bson_destroy (&description->cluster_time);
-
- EXIT;
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_topology_description_destroy --
- *
- * Destroy allocated resources within @description and free
- * @description.
- *
- * Returns:
- * None.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-void
-mongoc_topology_description_destroy (mongoc_topology_description_t *description)
-{
- ENTRY;
-
- if (!description) {
- EXIT;
- }
-
- mongoc_topology_description_cleanup (description);
- bson_free (description);
-
- EXIT;
-}
-
-/* find the primary, then stop iterating */
-static bool
-_mongoc_topology_description_has_primary_cb (const void *item,
- void *ctx /* OUT */)
-{
- const mongoc_server_description_t *server = item;
- const mongoc_server_description_t **primary = ctx;
-
- /* TODO should this include MONGOS? */
- if (server->type == MONGOC_SERVER_RS_PRIMARY ||
- server->type == MONGOC_SERVER_STANDALONE) {
- *primary = (mongoc_server_description_t *) item;
- return false;
- }
- return true;
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_topology_description_has_primary --
- *
- * If topology has a primary, return it.
- *
- * Returns:
- * A pointer to the primary, or NULL.
- *
- * Side effects:
- * None
- *
- *--------------------------------------------------------------------------
- */
-static const mongoc_server_description_t *
-_mongoc_topology_description_has_primary (
- const mongoc_topology_description_t *description)
-{
- mongoc_server_description_t *primary = NULL;
-
- mongoc_set_for_each_const (mc_tpld_servers_const (description),
- _mongoc_topology_description_has_primary_cb,
- &primary);
-
- return primary;
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_topology_description_later_election --
- *
- * Check if we've seen a more recent election in the replica set
- * than this server has.
- *
- * Returns:
- * True if the topology description's max replica set version plus
- * election id is later than the server description's.
- *
- * Side effects:
- * None
- *
- *--------------------------------------------------------------------------
- */
-static bool
-_mongoc_topology_description_later_election (
- mongoc_topology_description_t *td, const mongoc_server_description_t *sd)
-{
- /* initially max_set_version is -1 and max_election_id is zeroed */
- return td->max_set_version > sd->set_version ||
- (td->max_set_version == sd->set_version &&
- bson_oid_compare (&td->max_election_id, &sd->election_id) > 0);
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_topology_description_set_max_set_version --
- *
- * Remember that we've seen a new replica set version. Unconditionally
- * sets td->set_version to sd->set_version.
- *
- *--------------------------------------------------------------------------
- */
-static void
-_mongoc_topology_description_set_max_set_version (
- mongoc_topology_description_t *td, const mongoc_server_description_t *sd)
-{
- td->max_set_version = sd->set_version;
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_topology_description_set_max_election_id --
- *
- * Remember that we've seen a new election id. Unconditionally sets
- * td->max_election_id to sd->election_id.
- *
- *--------------------------------------------------------------------------
- */
-static void
-_mongoc_topology_description_set_max_election_id (
- mongoc_topology_description_t *td, const mongoc_server_description_t *sd)
-{
- bson_oid_copy (&sd->election_id, &td->max_election_id);
-}
-
-static bool
-_mongoc_topology_description_server_is_candidate (
- mongoc_server_description_type_t desc_type,
- mongoc_read_mode_t read_mode,
- mongoc_topology_description_type_t topology_type)
-{
- switch ((int) topology_type) {
- case MONGOC_TOPOLOGY_SINGLE:
- switch ((int) desc_type) {
- case MONGOC_SERVER_STANDALONE:
- return true;
- default:
- return false;
- }
-
- case MONGOC_TOPOLOGY_RS_NO_PRIMARY:
- case MONGOC_TOPOLOGY_RS_WITH_PRIMARY:
- switch ((int) read_mode) {
- case MONGOC_READ_PRIMARY:
- switch ((int) desc_type) {
- case MONGOC_SERVER_RS_PRIMARY:
- return true;
- default:
- return false;
- }
- case MONGOC_READ_SECONDARY:
- switch ((int) desc_type) {
- case MONGOC_SERVER_RS_SECONDARY:
- return true;
- default:
- return false;
- }
- default:
- switch ((int) desc_type) {
- case MONGOC_SERVER_RS_PRIMARY:
- case MONGOC_SERVER_RS_SECONDARY:
- return true;
- default:
- return false;
- }
- }
-
- case MONGOC_TOPOLOGY_SHARDED:
- switch ((int) desc_type) {
- case MONGOC_SERVER_MONGOS:
- return true;
- default:
- return false;
- }
-
- /* Note, there is no call path that leads to the
- * MONGOC_TOPOLOGY_LOAD_BALANCED case. Server selection for load balanced
- * topologies bypasses this logic. This silences compiler warnings on
- * unhandled enum values. */
- case MONGOC_TOPOLOGY_LOAD_BALANCED:
- return desc_type == MONGOC_SERVER_LOAD_BALANCER;
-
- default:
- return false;
- }
-}
-
-typedef struct _mongoc_suitable_data_t {
- mongoc_read_mode_t read_mode;
- mongoc_topology_description_type_t topology_type;
- const mongoc_server_description_t *primary; /* OUT */
- const mongoc_server_description_t **candidates; /* OUT */
- size_t candidates_len; /* OUT */
- bool has_secondary; /* OUT */
-} mongoc_suitable_data_t;
-
-static bool
-_mongoc_replica_set_read_suitable_cb (const void *item, void *ctx)
-{
- const mongoc_server_description_t *server = item;
- mongoc_suitable_data_t *data = (mongoc_suitable_data_t *) ctx;
-
- /* primary's used in staleness calculation, even with mode SECONDARY */
- if (server->type == MONGOC_SERVER_RS_PRIMARY) {
- data->primary = server;
- }
-
- if (_mongoc_topology_description_server_is_candidate (
- server->type, data->read_mode, data->topology_type)) {
- if (server->type == MONGOC_SERVER_RS_PRIMARY) {
- if (data->read_mode == MONGOC_READ_PRIMARY ||
- data->read_mode == MONGOC_READ_PRIMARY_PREFERRED) {
- /* we want a primary and we have one, done! */
- return false;
- }
- }
-
- if (server->type == MONGOC_SERVER_RS_SECONDARY) {
- data->has_secondary = true;
- }
-
- /* add to our candidates */
- data->candidates[data->candidates_len++] = server;
- } else {
- TRACE ("Rejected [%s] [%s] for mode [%s]",
- mongoc_server_description_type (server),
- server->host.host_and_port,
- _mongoc_read_mode_as_str (data->read_mode));
- }
-
- return true;
-}
-
-
-/* if any mongos are candidates, add them to the candidates array */
-static void
-_mongoc_try_mode_secondary (mongoc_array_t *set, /* OUT */
- const mongoc_topology_description_t *topology,
- const mongoc_read_prefs_t *read_pref,
- size_t local_threshold_ms)
-{
- mongoc_read_prefs_t *secondary;
-
- secondary = mongoc_read_prefs_copy (read_pref);
- mongoc_read_prefs_set_mode (secondary, MONGOC_READ_SECONDARY);
-
- mongoc_topology_description_suitable_servers (
- set, MONGOC_SS_READ, topology, secondary, local_threshold_ms);
-
- mongoc_read_prefs_destroy (secondary);
-}
-
-
-/* if any mongos are candidates, add them to the candidates array */
-static bool
-_mongoc_find_suitable_mongos_cb (const void *item, void *ctx)
-{
- const mongoc_server_description_t *server = item;
- mongoc_suitable_data_t *data = (mongoc_suitable_data_t *) ctx;
-
- if (_mongoc_topology_description_server_is_candidate (
- server->type, data->read_mode, data->topology_type)) {
- data->candidates[data->candidates_len++] = server;
- }
- return true;
-}
-
-
-/*
- *-------------------------------------------------------------------------
- *
- * mongoc_topology_description_lowest_max_wire_version --
- *
- * The topology's max wire version.
- *
- * Returns:
- * The minimum of all known servers' max wire versions, or INT32_MAX
- * if there are no known servers.
- *
- * Side effects:
- * None.
- *
- *-------------------------------------------------------------------------
- */
-int32_t
-mongoc_topology_description_lowest_max_wire_version (
- const mongoc_topology_description_t *td)
-{
- int i;
- int32_t ret = INT32_MAX;
- const mongoc_set_t *servers = mc_tpld_servers_const (td);
-
- for (i = 0; (size_t) i < servers->items_len; i++) {
- const mongoc_server_description_t *sd =
- mongoc_set_get_item_const (servers, i);
- if (sd->type != MONGOC_SERVER_UNKNOWN &&
- sd->type != MONGOC_SERVER_POSSIBLE_PRIMARY &&
- sd->max_wire_version < ret) {
- ret = sd->max_wire_version;
- }
- }
-
- return ret;
-}
-
-
-/*
- *-------------------------------------------------------------------------
- *
- * mongoc_topology_description_all_sds_have_write_date --
- *
- * Whether the primary and all secondaries' server descriptions have
- * last_write_date_ms.
- *
- * Side effects:
- * None.
- *
- *-------------------------------------------------------------------------
- */
-bool
-mongoc_topology_description_all_sds_have_write_date (
- const mongoc_topology_description_t *td)
-{
- int i;
- for (i = 0; (size_t) i < mc_tpld_servers_const (td)->items_len; i++) {
- const mongoc_server_description_t *sd =
- mongoc_set_get_item_const (mc_tpld_servers_const (td), i);
-
- if (sd->last_write_date_ms <= 0 &&
- (sd->type == MONGOC_SERVER_RS_PRIMARY ||
- sd->type == MONGOC_SERVER_RS_SECONDARY)) {
- return false;
- }
- }
-
- return true;
-}
-
-/*
- *-------------------------------------------------------------------------
- *
- * _mongoc_topology_description_validate_max_staleness --
- *
- * If the provided "maxStalenessSeconds" component of the read
- * preference is not valid for this topology, fill out @error and
- * return false.
- *
- * Side effects:
- * None.
- *
- *-------------------------------------------------------------------------
- */
-bool
-_mongoc_topology_description_validate_max_staleness (
- const mongoc_topology_description_t *td,
- int64_t max_staleness_seconds,
- bson_error_t *error)
-{
- mongoc_topology_description_type_t td_type;
-
- /* Server Selection Spec: A driver MUST raise an error if the TopologyType
- * is ReplicaSetWithPrimary or ReplicaSetNoPrimary and either of these
- * conditions is false:
- *
- * maxStalenessSeconds * 1000 >= heartbeatFrequencyMS + idleWritePeriodMS
- * maxStalenessSeconds >= smallestMaxStalenessSeconds
- */
-
- td_type = td->type;
-
- if (td_type != MONGOC_TOPOLOGY_RS_WITH_PRIMARY &&
- td_type != MONGOC_TOPOLOGY_RS_NO_PRIMARY) {
- return true;
- }
-
- if (max_staleness_seconds * 1000 <
- td->heartbeat_msec + MONGOC_IDLE_WRITE_PERIOD_MS) {
- bson_set_error (error,
- MONGOC_ERROR_COMMAND,
- MONGOC_ERROR_COMMAND_INVALID_ARG,
- "maxStalenessSeconds is set to %" PRId64
- ", it must be at least heartbeatFrequencyMS (%" PRId64
- ") + server's idle write period (%d seconds)",
- max_staleness_seconds,
- td->heartbeat_msec,
- MONGOC_IDLE_WRITE_PERIOD_MS / 1000);
- return false;
- }
-
- if (max_staleness_seconds < MONGOC_SMALLEST_MAX_STALENESS_SECONDS) {
- bson_set_error (error,
- MONGOC_ERROR_COMMAND,
- MONGOC_ERROR_COMMAND_INVALID_ARG,
- "maxStalenessSeconds is set to %" PRId64
- ", it must be at least %d seconds",
- max_staleness_seconds,
- MONGOC_SMALLEST_MAX_STALENESS_SECONDS);
- return false;
- }
-
- return true;
-}
-
-
-/*
- *-------------------------------------------------------------------------
- *
- * mongoc_topology_description_suitable_servers --
- *
- * Fill out an array of servers matching the read preference and
- * localThresholdMS.
- *
- * Side effects:
- * None.
- *
- *-------------------------------------------------------------------------
- */
-
-void
-mongoc_topology_description_suitable_servers (
- mongoc_array_t *set, /* OUT */
- mongoc_ss_optype_t optype,
- const mongoc_topology_description_t *topology,
- const mongoc_read_prefs_t *read_pref,
- size_t local_threshold_ms)
-{
- mongoc_suitable_data_t data;
- const mongoc_server_description_t **candidates;
-
- const mongoc_set_t *td_servers = mc_tpld_servers_const (topology);
- int64_t nearest = -1;
- int i;
- mongoc_read_mode_t read_mode = mongoc_read_prefs_get_mode (read_pref);
-
- candidates = bson_malloc0 (sizeof (*candidates) * td_servers->items_len);
-
- data.read_mode = read_mode;
- data.topology_type = topology->type;
- data.primary = NULL;
- data.candidates = candidates;
- data.candidates_len = 0;
- data.has_secondary = false;
-
- /* Single server --
- * Either it is suitable or it isn't */
- if (topology->type == MONGOC_TOPOLOGY_SINGLE) {
- const mongoc_server_description_t *server =
- mongoc_set_get_item_const (td_servers, 0);
- if (_mongoc_topology_description_server_is_candidate (
- server->type, read_mode, topology->type)) {
- _mongoc_array_append_val (set, server);
- } else {
- TRACE (
- "Rejected [%s] [%s] for read mode [%s] with topology type Single",
- mongoc_server_description_type (server),
- server->host.host_and_port,
- _mongoc_read_mode_as_str (read_mode));
- }
- goto DONE;
- }
-
- /* Replica sets --
- * Find suitable servers based on read mode */
- if (topology->type == MONGOC_TOPOLOGY_RS_NO_PRIMARY ||
- topology->type == MONGOC_TOPOLOGY_RS_WITH_PRIMARY) {
- if (optype == MONGOC_SS_READ) {
- mongoc_set_for_each_const (
- td_servers, _mongoc_replica_set_read_suitable_cb, &data);
-
- if (read_mode == MONGOC_READ_PRIMARY) {
- if (data.primary) {
- _mongoc_array_append_val (set, data.primary);
- }
-
- goto DONE;
- }
-
- if (read_mode == MONGOC_READ_PRIMARY_PREFERRED && data.primary) {
- _mongoc_array_append_val (set, data.primary);
- goto DONE;
- }
-
- if (read_mode == MONGOC_READ_SECONDARY_PREFERRED) {
- /* try read_mode SECONDARY */
- _mongoc_try_mode_secondary (
- set, topology, read_pref, local_threshold_ms);
-
- /* otherwise fall back to primary */
- if (!set->len && data.primary) {
- _mongoc_array_append_val (set, data.primary);
- }
-
- goto DONE;
- }
-
- if (read_mode == MONGOC_READ_SECONDARY) {
- for (i = 0; i < data.candidates_len; i++) {
- if (candidates[i] &&
- candidates[i]->type != MONGOC_SERVER_RS_SECONDARY) {
- TRACE ("Rejected [%s] [%s] for mode [%s] with RS topology",
- mongoc_server_description_type (candidates[i]),
- candidates[i]->host.host_and_port,
- _mongoc_read_mode_as_str (read_mode));
- candidates[i] = NULL;
- }
- }
- }
-
- /* mode is SECONDARY or NEAREST, filter by staleness and tags */
- mongoc_server_description_filter_stale (data.candidates,
- data.candidates_len,
- data.primary,
- topology->heartbeat_msec,
- read_pref);
-
- mongoc_server_description_filter_tags (
- data.candidates, data.candidates_len, read_pref);
- } else if (topology->type == MONGOC_TOPOLOGY_RS_WITH_PRIMARY) {
- /* includes optype == MONGOC_SS_WRITE as the exclusion of the above if
- */
- mongoc_set_for_each_const (
- td_servers,
- _mongoc_topology_description_has_primary_cb,
- (mongoc_server_description_t *) &data.primary);
- if (data.primary) {
- _mongoc_array_append_val (set, data.primary);
- goto DONE;
- }
- }
- }
-
- /* Sharded clusters --
- * All candidates in the latency window are suitable */
- if (topology->type == MONGOC_TOPOLOGY_SHARDED) {
- mongoc_set_for_each_const (
- td_servers, _mongoc_find_suitable_mongos_cb, &data);
- }
-
- /* Load balanced clusters --
- * Always select the only server. */
- if (topology->type == MONGOC_TOPOLOGY_LOAD_BALANCED) {
- const mongoc_server_description_t *server;
- BSON_ASSERT (td_servers->items_len == 1);
- server = mongoc_set_get_item_const (td_servers, 0);
- _mongoc_array_append_val (set, server);
- goto DONE;
- }
-
- /* Ways to get here:
- * - secondary read
- * - secondary preferred read
- * - primary_preferred and no primary read
- * - sharded anything
- * Find the nearest, then select within the window */
-
- for (i = 0; i < data.candidates_len; i++) {
- if (candidates[i] &&
- (nearest == -1 || nearest > candidates[i]->round_trip_time_msec)) {
- nearest = candidates[i]->round_trip_time_msec;
- }
- }
-
- for (i = 0; i < data.candidates_len; i++) {
- if (candidates[i] && (candidates[i]->round_trip_time_msec <=
- nearest + local_threshold_ms)) {
- _mongoc_array_append_val (set, candidates[i]);
- }
- }
-
-DONE:
-
- bson_free ((mongoc_server_description_t *) candidates);
-
- return;
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_topology_description_has_data_node --
- *
- * Internal method: are any servers not Arbiter, Ghost, or Unknown?
- *
- *--------------------------------------------------------------------------
- */
-bool
-mongoc_topology_description_has_data_node (
- const mongoc_topology_description_t *td)
-{
- int i;
- const mongoc_set_t *servers = mc_tpld_servers_const (td);
-
- for (i = 0; i < (int) servers->items_len; i++) {
- const mongoc_server_description_t *sd =
- mongoc_set_get_item_const (servers, i);
- if (_is_data_node (sd)) {
- return true;
- }
- }
-
- return false;
-}
-
-/*
- *-------------------------------------------------------------------------
- *
- * mongoc_topology_description_select --
- *
- * Return a server description of a node that is appropriate for
- * the given read preference and operation type.
- *
- * NOTE: this method simply attempts to select a server from the
- * current topology, it does not retry or trigger topology checks.
- *
- * Returns:
- * Selected server description, or NULL upon failure.
- *
- * Side effects:
- * None.
- *
- *-------------------------------------------------------------------------
- */
-mongoc_server_description_t const *
-mongoc_topology_description_select (
- const mongoc_topology_description_t *topology,
- mongoc_ss_optype_t optype,
- const mongoc_read_prefs_t *read_pref,
- int64_t local_threshold_ms)
-{
- mongoc_array_t suitable_servers;
- mongoc_server_description_t const *sd = NULL;
- int rand_n;
-
- ENTRY;
-
- if (topology->type == MONGOC_TOPOLOGY_SINGLE) {
- sd = mongoc_set_get_item_const (mc_tpld_servers_const (topology), 0);
-
- if (sd->has_hello_response) {
- RETURN (sd);
- } else {
- TRACE ("Topology type single, [%s] is down", sd->host.host_and_port);
- RETURN (NULL);
- }
- }
-
- _mongoc_array_init (&suitable_servers,
- sizeof (mongoc_server_description_t *));
-
- mongoc_topology_description_suitable_servers (
- &suitable_servers, optype, topology, read_pref, local_threshold_ms);
- if (suitable_servers.len != 0) {
- rand_n = _mongoc_rand_simple ((unsigned *) &topology->rand_seed);
- sd = _mongoc_array_index (&suitable_servers,
- mongoc_server_description_t *,
- rand_n % suitable_servers.len);
- }
-
- _mongoc_array_destroy (&suitable_servers);
-
- if (sd) {
- TRACE ("Topology type [%s], selected [%s] [%s]",
- mongoc_topology_description_type (topology),
- mongoc_server_description_type (sd),
- sd->host.host_and_port);
- }
-
- RETURN (sd);
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_topology_description_server_by_id --
- *
- * Get the server description for @id, if that server is present
- * in @description. Otherwise, return NULL and fill out optional
- * @error.
- *
- * NOTE: In most cases, caller should create a duplicate of the
- * returned server description.
- *
- * Returns:
- * A mongoc_server_description_t *, or NULL.
- *
- * Side effects:
- * Fills out optional @error if server not found.
- *
- *--------------------------------------------------------------------------
- */
-
-mongoc_server_description_t *
-mongoc_topology_description_server_by_id (
- mongoc_topology_description_t *description, uint32_t id, bson_error_t *error)
-{
- return (mongoc_server_description_t *)
- mongoc_topology_description_server_by_id_const (description, id, error);
-}
-
-const mongoc_server_description_t *
-mongoc_topology_description_server_by_id_const (
- const mongoc_topology_description_t *td, uint32_t id, bson_error_t *error)
-{
- const mongoc_server_description_t *sd;
-
- BSON_ASSERT_PARAM (td);
-
- sd = mongoc_set_get_const (mc_tpld_servers_const (td), id);
- if (!sd) {
- bson_set_error (error,
- MONGOC_ERROR_STREAM,
- MONGOC_ERROR_STREAM_NOT_ESTABLISHED,
- "Could not find description for node %u",
- id);
- }
-
- return sd;
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_topology_description_remove_server --
- *
- * If present, remove this server from this topology description.
- *
- * Returns:
- * None.
- *
- * Side effects:
- * Removes the server description from topology and destroys it.
- *
- *--------------------------------------------------------------------------
- */
-static void
-_mongoc_topology_description_remove_server (
- mongoc_topology_description_t *description,
- const mongoc_server_description_t *server)
-{
- BSON_ASSERT (description);
- BSON_ASSERT (server);
-
- _mongoc_topology_description_monitor_server_closed (description, server);
- mongoc_set_rm (mc_tpld_servers (description), server->id);
-
- /* Check if removing server resulted in an empty set of servers */
- if (mc_tpld_servers_const (description)->items_len == 0) {
- MONGOC_WARNING ("Last server removed from topology");
- }
-}
-
-typedef struct _mongoc_address_and_id_t {
- const char *address; /* IN */
- bool found; /* OUT */
- uint32_t id; /* OUT */
-} mongoc_address_and_id_t;
-
-/* find the given server and stop iterating */
-static bool
-_mongoc_topology_description_has_server_cb (const void *item,
- void *ctx /* IN - OUT */)
-{
- const mongoc_server_description_t *server = item;
- mongoc_address_and_id_t *data = (mongoc_address_and_id_t *) ctx;
-
- if (strcasecmp (data->address, server->connection_address) == 0) {
- data->found = true;
- data->id = server->id;
- return false;
- }
- return true;
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_topology_description_has_set_version --
- *
- * Whether @topology's max replica set version has been set.
- *
- * Returns:
- * True if the max setVersion was ever set.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-static bool
-_mongoc_topology_description_has_set_version (mongoc_topology_description_t *td)
-{
- return td->max_set_version != MONGOC_NO_SET_VERSION;
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_topology_description_topology_has_server --
- *
- * Return true if @server is in @topology. If so, place its id in
- * @id if given.
- *
- * Returns:
- * True if server is in topology, false otherwise.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-static bool
-_mongoc_topology_description_has_server (
- mongoc_topology_description_t *description,
- const char *address,
- uint32_t *id /* OUT */)
-{
- mongoc_address_and_id_t data;
-
- BSON_ASSERT (description);
- BSON_ASSERT (address);
-
- data.address = address;
- data.found = false;
- mongoc_set_for_each_const (mc_tpld_servers_const (description),
- _mongoc_topology_description_has_server_cb,
- &data);
-
- if (data.found && id) {
- *id = data.id;
- }
-
- return data.found;
-}
-
-typedef struct _mongoc_address_and_type_t {
- const char *address;
- mongoc_server_description_type_t type;
-} mongoc_address_and_type_t;
-
-static bool
-_mongoc_label_unknown_member_cb (void *item, void *ctx)
-{
- mongoc_server_description_t *server = (mongoc_server_description_t *) item;
- mongoc_address_and_type_t *data = (mongoc_address_and_type_t *) ctx;
-
- if (strcasecmp (server->connection_address, data->address) == 0 &&
- server->type == MONGOC_SERVER_UNKNOWN) {
- mongoc_server_description_set_state (server, data->type);
- return false;
- }
- return true;
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_topology_description_label_unknown_member --
- *
- * Find the server description with the given @address and if its
- * type is UNKNOWN, set its type to @type.
- *
- * Returns:
- * None.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-static void
-_mongoc_topology_description_label_unknown_member (
- mongoc_topology_description_t *description,
- const char *address,
- mongoc_server_description_type_t type)
-{
- mongoc_address_and_type_t data;
-
- BSON_ASSERT (description);
- BSON_ASSERT (address);
-
- data.type = type;
- data.address = address;
-
- mongoc_set_for_each (
- mc_tpld_servers (description), _mongoc_label_unknown_member_cb, &data);
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_topology_description_set_state --
- *
- * Change the state of this cluster and unblock things waiting
- * on a change of topology type.
- *
- * Returns:
- * None.
- *
- * Side effects:
- * Unblocks anything waiting on this description to change states.
- *
- *--------------------------------------------------------------------------
- */
-static void
-_mongoc_topology_description_set_state (
- mongoc_topology_description_t *description,
- mongoc_topology_description_type_t type)
-{
- description->type = type;
-}
-
-
-static void
-_update_rs_type (mongoc_topology_description_t *topology)
-{
- if (_mongoc_topology_description_has_primary (topology)) {
- _mongoc_topology_description_set_state (topology,
- MONGOC_TOPOLOGY_RS_WITH_PRIMARY);
- } else {
- _mongoc_topology_description_set_state (topology,
- MONGOC_TOPOLOGY_RS_NO_PRIMARY);
- }
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_topology_description_check_if_has_primary --
- *
- * If there is a primary in topology, set topology
- * type to RS_WITH_PRIMARY, otherwise set it to
- * RS_NO_PRIMARY.
- *
- * Returns:
- * None.
- *
- * Side effects:
- * Changes the topology type.
- *
- *--------------------------------------------------------------------------
- */
-static void
-_mongoc_topology_description_check_if_has_primary (
- mongoc_topology_description_t *topology,
- const mongoc_server_description_t *server)
-{
- _update_rs_type (topology);
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_topology_description_invalidate_server --
- *
- * Invalidate a server if a network error occurred while using it in
- * another part of the client. Server description is set to type
- * UNKNOWN, the error is recorded, and other parameters are reset to
- * defaults. Pass in the reason for invalidation in @error.
- *
- * @todo Try to remove this function when CDRIVER-3654 is complete.
- * It is only called when an application thread needs to mark a server Unknown.
- * But an application error is also tied to other behavior, and should also
- * consider the connection generation. This logic is captured in
- * _mongoc_topology_handle_app_error. This should not be called directly
- */
-void
-mongoc_topology_description_invalidate_server (
- mongoc_topology_description_t *td,
- uint32_t id,
- const bson_error_t *error /* IN */)
-{
- BSON_ASSERT (error);
-
- if (td->type == MONGOC_TOPOLOGY_LOAD_BALANCED) {
- /* Load balancers must never be marked unknown. */
- return;
- }
-
- /* send NULL hello reply */
- mongoc_topology_description_handle_hello (
- td, id, NULL, MONGOC_RTT_UNSET, error);
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_topology_description_add_server --
- *
- * Add the specified server to the cluster topology if it is not
- * already a member. If @id, place its id in @id.
- *
- * Return:
- * True if the server was added or already existed in the topology,
- * false if an error occurred.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-bool
-mongoc_topology_description_add_server (mongoc_topology_description_t *topology,
- const char *server,
- uint32_t *id /* OUT */)
-{
- uint32_t server_id;
- mongoc_server_description_t *description;
-
- BSON_ASSERT (topology);
- BSON_ASSERT (server);
-
- if (!_mongoc_topology_description_has_server (
- topology, server, &server_id)) {
- /* TODO this might not be an accurate count in all cases */
- server_id = ++topology->max_server_id;
-
- description =
- (mongoc_server_description_t *) bson_malloc0 (sizeof *description);
- mongoc_server_description_init (description, server, server_id);
-
- mongoc_set_add (mc_tpld_servers (topology), server_id, description);
-
- /* if we're in topology_new then no callbacks are registered and this is
- * a no-op. later, if we discover a new RS member this sends an event. */
- _mongoc_topology_description_monitor_server_opening (topology,
- description);
- }
-
- if (id) {
- *id = server_id;
- }
-
- return true;
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_topology_description_update_cluster_time --
- *
- * Drivers Session Spec: Drivers MUST examine responses to server commands to
- * see if they contain a top level field named $clusterTime formatted as
- * follows:
- *
- * {
- * ...
- * $clusterTime : {
- * clusterTime : <BsonTimestamp>,
- * signature : {
- * hash : <BsonBinaryData>,
- * keyId : <BsonInt64>
- * }
- * },
- * ...
- * }
- *
- * Whenever a driver receives a clusterTime from a server it MUST compare it
- * to the current highest seen clusterTime for the cluster. If the new
- * clusterTime is higher than the highest seen clusterTime it MUST become
- * the new highest seen clusterTime. Two clusterTimes are compared using
- * only the BsonTimestamp value of the clusterTime embedded field (be sure to
- * include both the timestamp and the increment of the BsonTimestamp in the
- * comparison). The signature field does not participate in the comparison.
- *
- *--------------------------------------------------------------------------
- */
-
-void
-mongoc_topology_description_update_cluster_time (
- mongoc_topology_description_t *td, const bson_t *reply)
-{
- bson_iter_t iter;
- bson_iter_t child;
- const uint8_t *data;
- uint32_t size;
- bson_t cluster_time;
-
- if (!reply || !bson_iter_init_find (&iter, reply, "$clusterTime")) {
- return;
- }
-
- if (!BSON_ITER_HOLDS_DOCUMENT (&iter) ||
- !bson_iter_recurse (&iter, &child)) {
- MONGOC_ERROR ("Can't parse $clusterTime");
- return;
- }
-
- bson_iter_document (&iter, &size, &data);
- BSON_ASSERT (bson_init_static (&cluster_time, data, (size_t) size));
-
- if (bson_empty (&td->cluster_time) ||
- _mongoc_cluster_time_greater (&cluster_time, &td->cluster_time)) {
- bson_destroy (&td->cluster_time);
- bson_copy_to (&cluster_time, &td->cluster_time);
- }
-}
-
-
-static void
-_mongoc_topology_description_add_new_servers (
- mongoc_topology_description_t *topology,
- const mongoc_server_description_t *server)
-{
- bson_iter_t member_iter;
- const bson_t *rs_members[3];
- int i;
-
- rs_members[0] = &server->hosts;
- rs_members[1] = &server->arbiters;
- rs_members[2] = &server->passives;
-
- for (i = 0; i < 3; i++) {
- BSON_ASSERT (bson_iter_init (&member_iter, rs_members[i]));
-
- while (bson_iter_next (&member_iter)) {
- mongoc_topology_description_add_server (
- topology, bson_iter_utf8 (&member_iter, NULL), NULL);
- }
- }
-}
-
-typedef struct _mongoc_primary_and_topology_t {
- mongoc_topology_description_t *topology;
- const mongoc_server_description_t *primary;
-} mongoc_primary_and_topology_t;
-
-/* invalidate old primaries */
-static bool
-_mongoc_topology_description_invalidate_primaries_cb (void *item, void *ctx)
-{
- mongoc_server_description_t *server = (mongoc_server_description_t *) item;
- mongoc_primary_and_topology_t *data = (mongoc_primary_and_topology_t *) ctx;
-
- if (server->id != data->primary->id &&
- server->type == MONGOC_SERVER_RS_PRIMARY) {
- mongoc_server_description_set_state (server, MONGOC_SERVER_UNKNOWN);
- mongoc_server_description_set_set_version (server, MONGOC_NO_SET_VERSION);
- mongoc_server_description_set_election_id (server, NULL);
- mongoc_server_description_reset (server);
- }
- return true;
-}
-
-
-/* Remove and destroy all replica set members not in primary's hosts lists */
-static void
-_mongoc_topology_description_remove_unreported_servers (
- mongoc_topology_description_t *topology,
- const mongoc_server_description_t *primary)
-{
- mongoc_array_t to_remove;
- int i;
-
- _mongoc_array_init (&to_remove, sizeof (mongoc_server_description_t *));
-
- /* Accumulate servers to be removed - do this before calling
- * _mongoc_topology_description_remove_server, which could call
- * mongoc_server_description_cleanup on the primary itself if it
- * doesn't report its own connection_address in its hosts list.
- * See hosts_differ_from_seeds.json */
- for (i = 0; i < mc_tpld_servers_const (topology)->items_len; i++) {
- const mongoc_server_description_t *member =
- mongoc_set_get_item_const (mc_tpld_servers_const (topology), i);
- const char *address = member->connection_address;
- if (!mongoc_server_description_has_rs_member (primary, address)) {
- _mongoc_array_append_val (&to_remove, member);
- }
- }
-
- /* now it's safe to call _mongoc_topology_description_remove_server,
- * even on the primary */
- for (i = 0; i < to_remove.len; i++) {
- const mongoc_server_description_t *member =
- _mongoc_array_index (&to_remove, mongoc_server_description_t *, i);
-
- _mongoc_topology_description_remove_server (topology, member);
- }
-
- _mongoc_array_destroy (&to_remove);
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_topology_description_matches_me --
- *
- * Server Discovery And Monitoring Spec: "Removal from the topology of
- * seed list members where the "me" property does not match the address
- * used to connect prevents clients from being able to select a server,
- * only to fail to re-select that server once the primary has responded.
- *
- * Returns:
- * True if "me" matches "connection_address".
- *
- * Side Effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-static bool
-_mongoc_topology_description_matches_me (
- const mongoc_server_description_t *server)
-{
- BSON_ASSERT (server->connection_address);
-
- if (!server->me) {
- /* "me" is unknown: consider it a match */
- return true;
- }
-
- return strcasecmp (server->connection_address, server->me) == 0;
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_update_rs_from_primary --
- *
- * First, determine that this is really the primary:
- * -If this node isn't in the cluster, do nothing.
- * -If the cluster's set name is null, set it to node's set name.
- * Otherwise if the cluster's set name is different from node's,
- * we found a rogue primary, so remove it from the cluster and
- * check the cluster for a primary, then return.
- * -If any of the members of cluster reports an address different
- * from node's, node cannot be the primary.
- * Now that we know this is the primary:
- * -If any hosts, passives, or arbiters in node's description aren't
- * in the cluster, add them as UNKNOWN servers.
- * -If the cluster has any servers that aren't in node's description,
- * remove and destroy them.
- * Finally, check the cluster for the new primary.
- *
- * Returns:
- * None.
- *
- * Side effects:
- * Changes to the cluster, possible removal of cluster nodes.
- *
- *--------------------------------------------------------------------------
- */
-static void
-_mongoc_topology_description_update_rs_from_primary (
- mongoc_topology_description_t *topology,
- const mongoc_server_description_t *server)
-{
- mongoc_primary_and_topology_t data;
- bson_error_t error;
-
- BSON_ASSERT (topology);
- BSON_ASSERT (server);
-
- if (!_mongoc_topology_description_has_server (
- topology, server->connection_address, NULL))
- return;
-
- /* If server->set_name was null this function wouldn't be called from
- * mongoc_server_description_handle_hello(). static code analyzers however
- * don't know that so we check for it explicitly. */
- if (server->set_name) {
- /* 'Server' can only be the primary if it has the right rs name */
-
- if (!topology->set_name) {
- topology->set_name = bson_strdup (server->set_name);
- } else if (strcmp (topology->set_name, server->set_name) != 0) {
- _mongoc_topology_description_remove_server (topology, server);
- _update_rs_type (topology);
- return;
- }
- }
-
- if (mongoc_server_description_has_set_version (server) &&
- mongoc_server_description_has_election_id (server)) {
- /* Server Discovery And Monitoring Spec: "The client remembers the
- * greatest electionId reported by a primary, and distrusts primaries
- * with lesser electionIds. This prevents the client from oscillating
- * between the old and new primary during a split-brain period."
- */
- if (_mongoc_topology_description_later_election (topology, server)) {
- bson_set_error (&error,
- MONGOC_ERROR_STREAM,
- MONGOC_ERROR_STREAM_CONNECT,
- "member's setVersion or electionId is stale");
- mongoc_topology_description_invalidate_server (
- topology, server->id, &error);
- _update_rs_type (topology);
- return;
- }
-
- /* server's electionId >= topology's max electionId */
- _mongoc_topology_description_set_max_election_id (topology, server);
- }
-
- if (mongoc_server_description_has_set_version (server) &&
- (!_mongoc_topology_description_has_set_version (topology) ||
- server->set_version > topology->max_set_version)) {
- _mongoc_topology_description_set_max_set_version (topology, server);
- }
-
- /* 'Server' is the primary! Invalidate other primaries if found */
- data.primary = server;
- data.topology = topology;
- mongoc_set_for_each (mc_tpld_servers (topology),
- _mongoc_topology_description_invalidate_primaries_cb,
- &data);
-
- /* Add to topology description any new servers primary knows about */
- _mongoc_topology_description_add_new_servers (topology, server);
-
- /* Remove from topology description any servers primary doesn't know about */
- _mongoc_topology_description_remove_unreported_servers (topology, server);
-
- /* Finally, set topology type */
- _update_rs_type (topology);
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_topology_description_update_rs_without_primary --
- *
- * Update cluster's information when there is no primary.
- *
- * Returns:
- * None.
- *
- * Side Effects:
- * Alters cluster state, may remove node from cluster.
- *
- *--------------------------------------------------------------------------
- */
-static void
-_mongoc_topology_description_update_rs_without_primary (
- mongoc_topology_description_t *topology,
- const mongoc_server_description_t *server)
-{
- BSON_ASSERT (topology);
- BSON_ASSERT (server);
-
- if (!_mongoc_topology_description_has_server (
- topology, server->connection_address, NULL)) {
- return;
- }
-
- /* make sure we're talking about the same replica set */
- if (server->set_name) {
- if (!topology->set_name) {
- topology->set_name = bson_strdup (server->set_name);
- } else if (strcmp (topology->set_name, server->set_name) != 0) {
- _mongoc_topology_description_remove_server (topology, server);
- return;
- }
- }
-
- /* Add new servers that this replica set member knows about */
- _mongoc_topology_description_add_new_servers (topology, server);
-
- /* If this server thinks there is a primary, label it POSSIBLE_PRIMARY */
- if (server->current_primary) {
- _mongoc_topology_description_label_unknown_member (
- topology, server->current_primary, MONGOC_SERVER_POSSIBLE_PRIMARY);
- }
-
- if (!_mongoc_topology_description_matches_me (server)) {
- _mongoc_topology_description_remove_server (topology, server);
- return;
- }
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_topology_description_update_rs_with_primary_from_member --
- *
- * Update cluster's information when there is a primary, but the
- * update is coming from another replica set member.
- *
- * Returns:
- * None.
- *
- * Side Effects:
- * Alters cluster state.
- *
- *--------------------------------------------------------------------------
- */
-static void
-_mongoc_topology_description_update_rs_with_primary_from_member (
- mongoc_topology_description_t *topology,
- const mongoc_server_description_t *server)
-{
- BSON_ASSERT (topology);
- BSON_ASSERT (server);
-
- if (!_mongoc_topology_description_has_server (
- topology, server->connection_address, NULL)) {
- return;
- }
-
- /* set_name should never be null here */
- if (strcmp (topology->set_name, server->set_name) != 0) {
- _mongoc_topology_description_remove_server (topology, server);
- _update_rs_type (topology);
- return;
- }
-
- if (!_mongoc_topology_description_matches_me (server)) {
- _mongoc_topology_description_remove_server (topology, server);
- return;
- }
-
- /* If there is no primary, label server's current_primary as the
- * POSSIBLE_PRIMARY */
- if (!_mongoc_topology_description_has_primary (topology) &&
- server->current_primary) {
- _mongoc_topology_description_set_state (topology,
- MONGOC_TOPOLOGY_RS_NO_PRIMARY);
- _mongoc_topology_description_label_unknown_member (
- topology, server->current_primary, MONGOC_SERVER_POSSIBLE_PRIMARY);
- }
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_topology_description_set_topology_type_to_sharded --
- *
- * Sets topology's type to SHARDED.
- *
- * Returns:
- * None
- *
- * Side effects:
- * Alter's topology's type
- *
- *--------------------------------------------------------------------------
- */
-static void
-_mongoc_topology_description_set_topology_type_to_sharded (
- mongoc_topology_description_t *topology,
- const mongoc_server_description_t *server)
-{
- _mongoc_topology_description_set_state (topology, MONGOC_TOPOLOGY_SHARDED);
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_topology_description_transition_unknown_to_rs_no_primary --
- *
- * Encapsulates transition from cluster state UNKNOWN to
- * RS_NO_PRIMARY. Sets the type to RS_NO_PRIMARY,
- * then updates the replica set accordingly.
- *
- * Returns:
- * None.
- *
- * Side effects:
- * Changes topology state.
- *
- *--------------------------------------------------------------------------
- */
-static void
-_mongoc_topology_description_transition_unknown_to_rs_no_primary (
- mongoc_topology_description_t *topology,
- const mongoc_server_description_t *server)
-{
- _mongoc_topology_description_set_state (topology,
- MONGOC_TOPOLOGY_RS_NO_PRIMARY);
- _mongoc_topology_description_update_rs_without_primary (topology, server);
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_topology_description_remove_and_check_primary --
- *
- * Remove the server and check if the topology still has a primary.
- *
- * Returns:
- * None.
- *
- * Side effects:
- * Removes server from topology and destroys it.
- *
- *--------------------------------------------------------------------------
- */
-static void
-_mongoc_topology_description_remove_and_check_primary (
- mongoc_topology_description_t *topology,
- const mongoc_server_description_t *server)
-{
- _mongoc_topology_description_remove_server (topology, server);
- _update_rs_type (topology);
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_topology_description_update_unknown_with_standalone --
- *
- * If the cluster doesn't contain this server, do nothing.
- * Otherwise, if the topology only has one seed, change its
- * type to SINGLE. If the topology has multiple seeds, it does not
- * include us, so remove this server and destroy it.
- *
- * Returns:
- * None.
- *
- * Side effects:
- * Changes the topology type, might remove server from topology.
- *
- *--------------------------------------------------------------------------
- */
-static void
-_mongoc_topology_description_update_unknown_with_standalone (
- mongoc_topology_description_t *topology,
- const mongoc_server_description_t *server)
-{
- BSON_ASSERT (topology);
- BSON_ASSERT (server);
-
- if (!_mongoc_topology_description_has_server (
- topology, server->connection_address, NULL))
- return;
-
- if (mc_tpld_servers_const (topology)->items_len > 1) {
- /* This cluster contains other servers, it cannot be a standalone. */
- _mongoc_topology_description_remove_server (topology, server);
- } else {
- _mongoc_topology_description_set_state (topology, MONGOC_TOPOLOGY_SINGLE);
- }
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * This table implements the 'ToplogyType' table outlined in the Server
- * Discovery and Monitoring spec. Each row represents a server type,
- * and each column represents the topology type. Given a current topology
- * type T and a newly-observed server type S, use the function at
- * state_transions[S][T] to transition to a new state.
- *
- * Rows should be read like so:
- * { server type for this row
- * UNKNOWN,
- * SHARDED,
- * RS_NO_PRIMARY,
- * RS_WITH_PRIMARY
- * }
- *
- *--------------------------------------------------------------------------
- */
-
-typedef void (*transition_t) (mongoc_topology_description_t *topology,
- const mongoc_server_description_t *server);
-
-transition_t gSDAMTransitionTable
- [MONGOC_SERVER_DESCRIPTION_TYPES][MONGOC_TOPOLOGY_DESCRIPTION_TYPES] = {
- {
- /* UNKNOWN */
- NULL, /* MONGOC_TOPOLOGY_UNKNOWN */
- NULL, /* MONGOC_TOPOLOGY_SHARDED */
- NULL, /* MONGOC_TOPOLOGY_RS_NO_PRIMARY */
- _mongoc_topology_description_check_if_has_primary /* MONGOC_TOPOLOGY_RS_WITH_PRIMARY
- */
- },
- {/* STANDALONE */
- _mongoc_topology_description_update_unknown_with_standalone,
- _mongoc_topology_description_remove_server,
- _mongoc_topology_description_remove_server,
- _mongoc_topology_description_remove_and_check_primary},
- {/* MONGOS */
- _mongoc_topology_description_set_topology_type_to_sharded,
- NULL,
- _mongoc_topology_description_remove_server,
- _mongoc_topology_description_remove_and_check_primary},
- {/* POSSIBLE_PRIMARY */
- NULL,
- NULL,
- NULL,
- NULL},
- {/* PRIMARY */
- _mongoc_topology_description_update_rs_from_primary,
- _mongoc_topology_description_remove_server,
- _mongoc_topology_description_update_rs_from_primary,
- _mongoc_topology_description_update_rs_from_primary},
- {/* SECONDARY */
- _mongoc_topology_description_transition_unknown_to_rs_no_primary,
- _mongoc_topology_description_remove_server,
- _mongoc_topology_description_update_rs_without_primary,
- _mongoc_topology_description_update_rs_with_primary_from_member},
- {/* ARBITER */
- _mongoc_topology_description_transition_unknown_to_rs_no_primary,
- _mongoc_topology_description_remove_server,
- _mongoc_topology_description_update_rs_without_primary,
- _mongoc_topology_description_update_rs_with_primary_from_member},
- {/* RS_OTHER */
- _mongoc_topology_description_transition_unknown_to_rs_no_primary,
- _mongoc_topology_description_remove_server,
- _mongoc_topology_description_update_rs_without_primary,
- _mongoc_topology_description_update_rs_with_primary_from_member},
- {/* RS_GHOST */
- NULL,
- _mongoc_topology_description_remove_server,
- NULL,
- _mongoc_topology_description_check_if_has_primary}};
-
-#ifdef MONGOC_TRACE
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_topology_description_type --
- *
- * Get this topology's type, one of the types defined in the Server
- * Discovery And Monitoring Spec.
- *
- * Returns:
- * A string.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-static const char *
-_mongoc_topology_description_type (mongoc_topology_description_t *topology)
-{
- switch (topology->type) {
- case MONGOC_TOPOLOGY_UNKNOWN:
- return "Unknown";
- case MONGOC_TOPOLOGY_SHARDED:
- return "Sharded";
- case MONGOC_TOPOLOGY_RS_NO_PRIMARY:
- return "RSNoPrimary";
- case MONGOC_TOPOLOGY_RS_WITH_PRIMARY:
- return "RSWithPrimary";
- case MONGOC_TOPOLOGY_SINGLE:
- return "Single";
- case MONGOC_TOPOLOGY_LOAD_BALANCED:
- return "LoadBalanced";
- case MONGOC_TOPOLOGY_DESCRIPTION_TYPES:
- default:
- MONGOC_ERROR ("Invalid mongoc_topology_description_type_t type");
- return "Invalid";
- }
-}
-#endif
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_topology_description_update_session_timeout --
- *
- * Fill out td.session_timeout_minutes.
- *
- * Server Discovery and Monitoring Spec: "set logicalSessionTimeoutMinutes
- * to the smallest logicalSessionTimeoutMinutes value among all
- * ServerDescriptions of known ServerType. If any ServerDescription of
- * known ServerType has a null logicalSessionTimeoutMinutes, then
- * logicalSessionTimeoutMinutes MUST be set to null."
- *
- * --------------------------------------------------------------------------
- */
-
-static void
-_mongoc_topology_description_update_session_timeout (
- mongoc_topology_description_t *td)
-{
- mongoc_set_t *set;
- size_t i;
- mongoc_server_description_t *sd;
-
- set = mc_tpld_servers (td);
-
- td->session_timeout_minutes = MONGOC_NO_SESSIONS;
-
- for (i = 0; i < set->items_len; i++) {
- sd = (mongoc_server_description_t *) mongoc_set_get_item (set, (int) i);
- if (!_is_data_node (sd)) {
- continue;
- }
-
- if (sd->session_timeout_minutes == MONGOC_NO_SESSIONS) {
- td->session_timeout_minutes = MONGOC_NO_SESSIONS;
- return;
- } else if (td->session_timeout_minutes == MONGOC_NO_SESSIONS) {
- td->session_timeout_minutes = sd->session_timeout_minutes;
- } else if (td->session_timeout_minutes > sd->session_timeout_minutes) {
- td->session_timeout_minutes = sd->session_timeout_minutes;
- }
- }
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_topology_description_check_compatible --
- *
- * Fill out td.compatibility_error if any server's wire versions do
- * not overlap with ours. Otherwise clear td.compatibility_error.
- *
- * If any server is incompatible, the topology as a whole is considered
- * incompatible.
- *
- *--------------------------------------------------------------------------
- */
-
-static void
-_mongoc_topology_description_check_compatible (
- mongoc_topology_description_t *td)
-{
- size_t i;
- mongoc_set_t const *const servers = mc_tpld_servers_const (td);
-
- memset (&td->compatibility_error, 0, sizeof (bson_error_t));
-
- for (i = 0; i < servers->items_len; i++) {
- mongoc_server_description_t const *const sd =
- mongoc_set_get_item_const (servers, (int) i);
- if (sd->type == MONGOC_SERVER_UNKNOWN ||
- sd->type == MONGOC_SERVER_POSSIBLE_PRIMARY) {
- continue;
- }
-
- if (sd->min_wire_version > WIRE_VERSION_MAX) {
- bson_set_error (
- &td->compatibility_error,
- MONGOC_ERROR_PROTOCOL,
- MONGOC_ERROR_PROTOCOL_BAD_WIRE_VERSION,
- "Server at %s requires wire version %d,"
- " but this version of libmongoc only supports up to %d",
- sd->host.host_and_port,
- sd->min_wire_version,
- WIRE_VERSION_MAX);
- } else if (sd->max_wire_version < WIRE_VERSION_MIN) {
- bson_set_error (
- &td->compatibility_error,
- MONGOC_ERROR_PROTOCOL,
- MONGOC_ERROR_PROTOCOL_BAD_WIRE_VERSION,
- "Server at %s reports wire version %d, but this"
- " version of libmongoc requires at least 3 (MongoDB 3.0)",
- sd->host.host_and_port,
- sd->max_wire_version);
- }
- }
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_topology_description_handle_hello --
- *
- * Handle a hello. This is called by the background SDAM process,
- * and by client when performing a handshake or invalidating servers.
- * If there was an error calling hello, pass it in as @error.
- *
- *--------------------------------------------------------------------------
- */
-
-void
-mongoc_topology_description_handle_hello (
- mongoc_topology_description_t *topology,
- uint32_t server_id,
- const bson_t *hello_response,
- int64_t rtt_msec,
- const bson_error_t *error /* IN */)
-{
- mongoc_topology_description_t *prev_td = NULL;
- mongoc_server_description_t *prev_sd = NULL;
- mongoc_server_description_t *sd;
- bson_iter_t iter;
- /* sd_changed is set if the server description meaningfully changed AND
- * callbacks are registered. */
- bool sd_changed = false;
-
- BSON_ASSERT (topology);
- BSON_ASSERT (server_id != 0);
-
- sd = mongoc_topology_description_server_by_id (topology, server_id, NULL);
- if (!sd) {
- return; /* server already removed from topology */
- }
-
- if (topology->apm_callbacks.topology_changed) {
- prev_td = bson_malloc0 (sizeof (mongoc_topology_description_t));
- _mongoc_topology_description_copy_to (topology, prev_td);
- }
-
- if (hello_response &&
- bson_iter_init_find (&iter, hello_response, "topologyVersion") &&
- BSON_ITER_HOLDS_DOCUMENT (&iter)) {
- bson_t incoming_topology_version;
- const uint8_t *bytes;
- uint32_t len;
-
- bson_iter_document (&iter, &len, &bytes);
- bson_init_static (&incoming_topology_version, bytes, len);
-
- if (mongoc_server_description_topology_version_cmp (
- &sd->topology_version, &incoming_topology_version) == 1) {
- TRACE ("%s", "topology version is strictly less. Skipping.");
- if (prev_td) {
- mongoc_topology_description_cleanup (prev_td);
- bson_free (prev_td);
- }
- return;
- }
- }
-
- if (topology->apm_callbacks.topology_changed ||
- topology->apm_callbacks.server_changed) {
- /* Only copy the previous server description if a monitoring callback is
- * registered. */
- prev_sd = mongoc_server_description_new_copy (sd);
- }
-
- DUMP_BSON (hello_response);
- /* pass the current error in */
-
- mongoc_server_description_handle_hello (sd, hello_response, rtt_msec, error);
-
- /* if the user specified a set_name in the connection string
- * and they are in topology type single, check that the set name
- * matches. */
- if (topology->set_name && topology->type == MONGOC_TOPOLOGY_SINGLE) {
- bool wrong_set_name = false;
- bson_error_t set_name_err = {0};
-
- if (!sd->set_name) {
- wrong_set_name = true;
- bson_set_error (&set_name_err,
- MONGOC_ERROR_SERVER_SELECTION,
- MONGOC_ERROR_SERVER_SELECTION_FAILURE,
- "no reported set name, but expected '%s'",
- topology->set_name);
- } else if (0 != strcmp (sd->set_name, topology->set_name)) {
- wrong_set_name = true;
- bson_set_error (&set_name_err,
- MONGOC_ERROR_SERVER_SELECTION,
- MONGOC_ERROR_SERVER_SELECTION_FAILURE,
- "reported set name '%s' does not match '%s'",
- sd->set_name,
- topology->set_name);
- }
-
- if (wrong_set_name) {
- /* Replace with unknown. */
- TRACE ("%s", "wrong set name");
- mongoc_server_description_handle_hello (
- sd, NULL, MONGOC_RTT_UNSET, &set_name_err);
- }
- }
-
- mongoc_topology_description_update_cluster_time (topology, hello_response);
-
- if (prev_sd) {
- sd_changed = !_mongoc_server_description_equal (prev_sd, sd);
- }
- if (sd_changed) {
- _mongoc_topology_description_monitor_server_changed (
- topology, prev_sd, sd);
- }
-
- if (gSDAMTransitionTable[sd->type][topology->type]) {
- TRACE ("Topology description %s handling server description %s",
- _mongoc_topology_description_type (topology),
- mongoc_server_description_type (sd));
- gSDAMTransitionTable[sd->type][topology->type](topology, sd);
- } else {
- TRACE ("Topology description %s ignoring server description %s",
- _mongoc_topology_description_type (topology),
- mongoc_server_description_type (sd));
- }
-
- _mongoc_topology_description_update_session_timeout (topology);
-
- /* Don't bother checking wire version compatibility if we already errored */
- if (hello_response && (!error || !error->code)) {
- _mongoc_topology_description_check_compatible (topology);
- }
-
- /* If server description did not change, then neither did topology
- * description */
- if (sd_changed) {
- _mongoc_topology_description_monitor_changed (prev_td, topology);
- }
-
- if (prev_td) {
- mongoc_topology_description_cleanup (prev_td);
- bson_free (prev_td);
- }
-
- mongoc_server_description_destroy (prev_sd);
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_topology_description_has_readable_server --
- *
- * SDAM Monitoring Spec:
- * "Determines if the topology has a readable server available."
- *
- * NOTE: this method should only be called by user code in an SDAM
- * Monitoring callback.
- *
- *--------------------------------------------------------------------------
- */
-bool
-mongoc_topology_description_has_readable_server (
- const mongoc_topology_description_t *td, const mongoc_read_prefs_t *prefs)
-{
- bson_error_t error;
-
- if (!mongoc_topology_compatible (td, NULL, &error)) {
- return false;
- }
-
- /* local threshold argument doesn't matter */
- return mongoc_topology_description_select (td, MONGOC_SS_READ, prefs, 0) !=
- NULL;
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_topology_description_has_writable_server --
- *
- * SDAM Monitoring Spec:
- * "Determines if the topology has a writable server available."
- *
- * NOTE: this method should only be called by user code in an SDAM
- * Monitoring callback.
- *
- *--------------------------------------------------------------------------
- */
-bool
-mongoc_topology_description_has_writable_server (
- const mongoc_topology_description_t *td)
-{
- bson_error_t error;
-
- if (!mongoc_topology_compatible (td, NULL, &error)) {
- return false;
- }
-
- return mongoc_topology_description_select (td, MONGOC_SS_WRITE, NULL, 0) !=
- NULL;
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_topology_description_type --
- *
- * Get this topology's type, one of the types defined in the Server
- * Discovery And Monitoring Spec.
- *
- * NOTE: this method should only be called by user code in an SDAM
- * Monitoring callback.
- *
- * Returns:
- * A string.
- *
- *--------------------------------------------------------------------------
- */
-const char *
-mongoc_topology_description_type (const mongoc_topology_description_t *td)
-{
- switch (td->type) {
- case MONGOC_TOPOLOGY_UNKNOWN:
- return "Unknown";
- case MONGOC_TOPOLOGY_SHARDED:
- return "Sharded";
- case MONGOC_TOPOLOGY_RS_NO_PRIMARY:
- return "ReplicaSetNoPrimary";
- case MONGOC_TOPOLOGY_RS_WITH_PRIMARY:
- return "ReplicaSetWithPrimary";
- case MONGOC_TOPOLOGY_SINGLE:
- return "Single";
- case MONGOC_TOPOLOGY_LOAD_BALANCED:
- return "LoadBalanced";
- case MONGOC_TOPOLOGY_DESCRIPTION_TYPES:
- default:
- fprintf (stderr, "ERROR: Unknown topology type %d\n", td->type);
- BSON_ASSERT (0);
- }
-
- return NULL;
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_topology_description_get_servers --
- *
- * Fetch an array of server descriptions for all known servers in the
- * topology.
- *
- * Returns:
- * An array you must free with mongoc_server_descriptions_destroy_all.
- *
- *--------------------------------------------------------------------------
- */
-mongoc_server_description_t **
-mongoc_topology_description_get_servers (
- const mongoc_topology_description_t *td, size_t *n /* OUT */)
-{
- size_t i;
- const mongoc_set_t *const set =
- mc_tpld_servers_const (BSON_ASSERT_PTR_INLINE (td));
- /* enough room for all descriptions, even if some are unknown */
- mongoc_server_description_t **sds =
- bson_malloc0 (sizeof (mongoc_server_description_t *) * set->items_len);
-
- BSON_ASSERT_PARAM (n);
-
- *n = 0;
-
- for (i = 0; i < set->items_len; ++i) {
- const mongoc_server_description_t *sd =
- mongoc_set_get_item_const (set, (int) i);
-
- if (sd->type != MONGOC_SERVER_UNKNOWN) {
- sds[*n] = mongoc_server_description_new_copy (sd);
- ++(*n);
- }
- }
-
- return sds;
-}
-
-typedef struct {
- mongoc_host_list_t *host_list;
- mongoc_topology_description_t *td;
-} _remove_if_not_in_host_list_ctx_t;
-
-bool
-_remove_if_not_in_host_list_cb (void *sd_void, void *ctx_void)
-{
- _remove_if_not_in_host_list_ctx_t *ctx;
- mongoc_topology_description_t *td;
- mongoc_server_description_t *sd;
- mongoc_host_list_t *host_list;
-
- ctx = ctx_void;
- sd = sd_void;
- host_list = ctx->host_list;
- td = ctx->td;
-
- if (_mongoc_host_list_contains_one (host_list, &sd->host)) {
- return true;
- }
- _mongoc_topology_description_remove_server (td, sd);
- return true;
-}
-
-void
-mongoc_topology_description_reconcile (mongoc_topology_description_t *td,
- mongoc_host_list_t *host_list)
-{
- mongoc_host_list_t *host;
- _remove_if_not_in_host_list_ctx_t ctx;
-
- LL_FOREACH (host_list, host)
- {
- /* "add" is really an "upsert" */
- mongoc_topology_description_add_server (td, host->host_and_port, NULL);
- }
-
- ctx.host_list = host_list;
- ctx.td = td;
- mongoc_set_for_each (
- mc_tpld_servers (td), _remove_if_not_in_host_list_cb, &ctx);
-}
-
-
-void
-_mongoc_topology_description_clear_connection_pool (
- mongoc_topology_description_t *td,
- uint32_t server_id,
- const bson_oid_t *service_id)
-{
- mongoc_server_description_t *sd;
- bson_error_t error;
-
- BSON_ASSERT (service_id);
-
- sd = mongoc_topology_description_server_by_id (td, server_id, &error);
- if (!sd) {
- /* Server removed, ignore and ignore error. */
- return;
- }
-
- TRACE ("clearing pool for server: %s", sd->host.host_and_port);
-
- mc_tpl_sd_increment_generation (sd, service_id);
-}
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-private.h b/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-private.h
deleted file mode 100644
index d7168540..00000000
--- a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-private.h
+++ /dev/null
@@ -1,591 +0,0 @@
-/*
- * Copyright 2014 MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "mongoc-prelude.h"
-
-#ifndef MONGOC_TOPOLOGY_PRIVATE_H
-#define MONGOC_TOPOLOGY_PRIVATE_H
-
-#include "mongoc-config.h"
-#include "mongoc-topology-scanner-private.h"
-#include "mongoc-server-description-private.h"
-#include "mongoc-topology-description-private.h"
-#include "mongoc-thread-private.h"
-#include "mongoc-uri.h"
-#include "mongoc-client-session-private.h"
-#include "mongoc-crypt-private.h"
-#include "mongoc-ts-pool-private.h"
-#include "mongoc-shared-private.h"
-
-#define MONGOC_TOPOLOGY_MIN_HEARTBEAT_FREQUENCY_MS 500
-#define MONGOC_TOPOLOGY_SOCKET_CHECK_INTERVAL_MS 5000
-#define MONGOC_TOPOLOGY_COOLDOWN_MS 5000
-#define MONGOC_TOPOLOGY_LOCAL_THRESHOLD_MS 15
-#define MONGOC_TOPOLOGY_SERVER_SELECTION_TIMEOUT_MS 30000
-#define MONGOC_TOPOLOGY_HEARTBEAT_FREQUENCY_MS_MULTI_THREADED 10000
-#define MONGOC_TOPOLOGY_HEARTBEAT_FREQUENCY_MS_SINGLE_THREADED 60000
-#define MONGOC_TOPOLOGY_MIN_RESCAN_SRV_INTERVAL_MS 60000
-
-typedef enum {
- MONGOC_TOPOLOGY_SCANNER_OFF,
- MONGOC_TOPOLOGY_SCANNER_BG_RUNNING,
- MONGOC_TOPOLOGY_SCANNER_SHUTTING_DOWN
-} mongoc_topology_scanner_state_t;
-
-typedef enum mongoc_topology_cse_state_t {
- MONGOC_CSE_DISABLED,
- MONGOC_CSE_STARTING,
- MONGOC_CSE_ENABLED,
-} mongoc_topology_cse_state_t;
-
-struct _mongoc_background_monitor_t;
-struct _mongoc_client_pool_t;
-
-typedef enum { MONGOC_RR_SRV, MONGOC_RR_TXT } mongoc_rr_type_t;
-
-typedef struct _mongoc_rr_data_t {
- /* Number of records returned by DNS. */
- uint32_t count;
-
- /* Set to lowest TTL found when polling SRV records. */
- uint32_t min_ttl;
-
- /* Set to the resulting host list when polling SRV records */
- mongoc_host_list_t *hosts;
-
- /* Set to the TXT record when polling for TXT */
- char *txt_record_opts;
-} mongoc_rr_data_t;
-
-struct _mongoc_topology_t;
-
-MONGOC_DECL_SPECIAL_TS_POOL (
- mongoc_server_session_t,
- mongoc_server_session_pool,
- struct _mongoc_topology_t,
- /* ctor/dtor/prune are defined in the new_with_params call */
- NULL,
- NULL,
- NULL)
-
-typedef bool (*_mongoc_rr_resolver_fn) (const char *service,
- mongoc_rr_type_t rr_type,
- mongoc_rr_data_t *rr_data,
- size_t initial_buffer_size,
- bson_error_t *error);
-
-/**
- * @brief A reference-counted reference to a topology description.
- *
- * The referred-to topology description should be access via the `.ptr` member
- * of this object.
- */
-typedef union mc_shared_tpld {
- /* Private: The reference-counted shared pointer that manages the topology
- * description. */
- mongoc_shared_ptr _sptr_;
- /** The pointed-to topology description */
- mongoc_topology_description_t const *ptr;
-} mc_shared_tpld;
-
-/** A null-pointer initializer for an `mc_shared_tpld` */
-#define MC_SHARED_TPLD_NULL ((mc_shared_tpld){._sptr_ = MONGOC_SHARED_PTR_NULL})
-
-typedef struct _mongoc_topology_t {
- /**
- * @brief The topology description. Do not access directly. Instead, use
- * mc_tpld_take_ref()
- */
- mc_shared_tpld _shared_descr_;
-
- /* topology->uri is initialized as a copy of the client/pool's URI.
- * For a "mongodb+srv://" URI, topology->uri is then updated in
- * mongoc_topology_new() after initial seedlist discovery.
- */
- mongoc_uri_t *uri;
- mongoc_topology_scanner_t *scanner;
- bool server_selection_try_once;
-
- int64_t last_scan;
- int64_t local_threshold_msec;
- int64_t connect_timeout_msec;
- int64_t server_selection_timeout_msec;
- /* defaults to 500ms, configurable by tests */
- int64_t min_heartbeat_frequency_msec;
-
- /* Minimum of SRV record TTLs, but no lower than 60 seconds.
- * May be zero for non-SRV/non-MongoS topology. */
- int64_t srv_polling_rescan_interval_ms;
- int64_t srv_polling_last_scan_ms;
- /* For multi-threaded, srv polling occurs in a separate thread. */
- bson_thread_t srv_polling_thread;
- bson_mutex_t srv_polling_mtx;
- mongoc_cond_t srv_polling_cond;
-
- /**
- * @brief Signal for background monitoring threads to signal stop/shutdown.
- *
- * The values stored are mongoc_topology_scanner_state_t values
- */
- int scanner_state;
-
- /**
- * @brief This lock is held in order to serialize operations that modify the
- * topology description. It *should not* be held while performing read-only
- * operations on the topology.
- *
- * This mutex is also used by server selection to synchronize with threads
- * that may update the topology following a failed server selection. It is
- * used in conjunction with `cond_client`. This protects _shared_descr_, as
- * well as the server_monitors and rtt_monitors.
- */
- bson_mutex_t tpld_modification_mtx;
-
- /**
- * @brief Condition variable used to signal client threads that the topology
- * has been updated by another thread. This CV should be used with
- * tpld_modification_mtx, as it signals modifications to the topology.
- *
- * Note that mc_tpld_modify_begin/commit/drop will acquire/release
- * tpld_modification_mtx as well.
- */
- mongoc_cond_t cond_client;
-
- bool single_threaded;
- bool stale;
-
- mongoc_server_session_pool session_pool;
-
- /* Is client side encryption enabled? */
- mongoc_topology_cse_state_t cse_state;
- bool is_srv_polling;
-
-#ifdef MONGOC_ENABLE_CLIENT_SIDE_ENCRYPTION
- _mongoc_crypt_t *crypt;
- struct _mongoc_client_t *mongocryptd_client; /* single threaded */
- struct _mongoc_client_t *keyvault_client; /* single threaded */
- struct _mongoc_client_pool_t *mongocryptd_client_pool; /* multi threaded */
- struct _mongoc_client_pool_t *keyvault_client_pool; /* multi threaded */
- char *keyvault_db;
- char *keyvault_coll;
- bool bypass_auto_encryption;
- bool mongocryptd_bypass_spawn;
- char *mongocryptd_spawn_path;
- bson_t *mongocryptd_spawn_args;
-#endif
-
- /* For background monitoring. */
- mongoc_set_t *server_monitors;
- mongoc_set_t *rtt_monitors;
- bson_mutex_t apm_mutex;
-
- /* This is overridable for SRV polling tests to mock DNS records. */
- _mongoc_rr_resolver_fn rr_resolver;
-
- /* valid is false when mongoc_topology_new failed to construct a valid
- * topology. This could occur if the URI is invalid.
- * An invalid topology does not monitor servers. */
- bool valid;
-} mongoc_topology_t;
-
-mongoc_topology_t *
-mongoc_topology_new (const mongoc_uri_t *uri, bool single_threaded);
-
-void
-mongoc_topology_set_apm_callbacks (mongoc_topology_t *topology,
- mongoc_topology_description_t *td,
- mongoc_apm_callbacks_t *callbacks,
- void *context);
-
-void
-mongoc_topology_destroy (mongoc_topology_t *topology);
-
-void
-mongoc_topology_reconcile (const mongoc_topology_t *topology,
- mongoc_topology_description_t *td);
-
-bool
-mongoc_topology_compatible (const mongoc_topology_description_t *td,
- const mongoc_read_prefs_t *read_prefs,
- bson_error_t *error);
-
-/**
- * @brief Select a server description for an operation. May scan and update the
- * topology.
- *
- * A server description might be returned that matches the given `optype` and
- * `read_prefs`. If the topology is out-of-date or due for a scan, then this
- * function will perform a scan and update the topology accordingly. If no
- * matching server is found, returns a NULL pointer.
- *
- * @param topology The topology to inspect and/or update.
- * @param optype The operation that is intended to be performed.
- * @param read_prefs The read preferences for the command.
- * @param error An output parameter for any error information.
- * @return mongoc_server_description_t* A copy of the topology's server
- * description that matches the request, or NULL if there is no such server.
- *
- * @note The returned object is a COPY, and should be released with
- * `mongoc_server_description_destroy()`
- *
- * @note This function may update the topology description.
- */
-mongoc_server_description_t *
-mongoc_topology_select (mongoc_topology_t *topology,
- mongoc_ss_optype_t optype,
- const mongoc_read_prefs_t *read_prefs,
- bson_error_t *error);
-
-/**
- * @brief Obtain the integral ID of a server description matching the requested
- * ops.
- *
- * Refer to @see mongoc_topology_select() for more information
- *
- * @param topology The topology to inspect and/or update.
- * @param optype The operation that is intended to be performed.
- * @param read_prefs The read preferences for the command.
- * @param error An output parameter for any error information.
- * @return uint32_t A non-zero integer ID of the server description. In case of
- * error, sets `error` and returns zero.
- *
- * @note This function may update the topology description.
- */
-uint32_t
-mongoc_topology_select_server_id (mongoc_topology_t *topology,
- mongoc_ss_optype_t optype,
- const mongoc_read_prefs_t *read_prefs,
- bson_error_t *error);
-
-/**
- * @brief Return a new mongoc_host_list_t for the given server matching the
- * given ID.
- *
- * @param topology The topology description to inspect
- * @param id The ID of a server in the topology
- * @param error Output error information
- * @return mongoc_host_list_t* A new host list, or NULL on error
- *
- * @note The returned list should be freed with
- * `_mongoc_host_list_destroy_all()`
- */
-mongoc_host_list_t *
-_mongoc_topology_host_by_id (const mongoc_topology_description_t *topology,
- uint32_t id,
- bson_error_t *error);
-
-/**
- * @brief Update the topology from the response to a handshake on a new
- * application connection.
- *
- * @note Only applicable to a client pool (single-threaded clients reuse
- * monitoring connections).
- *
- * @param topology The topology that will be updated.
- * @param sd The server description that contains the hello response.
- * @return true If the server is valid in the topology.
- * @return false If the server was already removed from the topology.
- */
-bool
-_mongoc_topology_update_from_handshake (mongoc_topology_t *topology,
- const mongoc_server_description_t *sd);
-
-void
-_mongoc_topology_update_last_used (mongoc_topology_t *topology,
- uint32_t server_id);
-
-int64_t
-mongoc_topology_server_timestamp (mongoc_topology_t *topology, uint32_t id);
-
-/**
- * @brief Get the current type of the topology
- */
-mongoc_topology_description_type_t
-_mongoc_topology_get_type (const mongoc_topology_t *topology);
-
-bool
-_mongoc_topology_set_appname (mongoc_topology_t *topology, const char *appname);
-
-void
-_mongoc_topology_update_cluster_time (mongoc_topology_t *topology,
- const bson_t *reply);
-
-mongoc_server_session_t *
-_mongoc_topology_pop_server_session (mongoc_topology_t *topology,
- bson_error_t *error);
-
-void
-_mongoc_topology_push_server_session (mongoc_topology_t *topology,
- mongoc_server_session_t *server_session);
-
-bool
-_mongoc_topology_end_sessions_cmd (mongoc_topology_t *topology, bson_t *cmd);
-
-void
-_mongoc_topology_do_blocking_scan (mongoc_topology_t *topology,
- bson_error_t *error);
-
-/**
- * @brief Duplicate the handshake command of the topology scanner.
- *
- * @param topology The topology to inspect.
- * @param copy_into The destination of the copy. Should be uninitialized storage
- * for a bson_t.
- *
- * @note This API will lazily construct the handshake command for the scanner.
- *
- * @note This is called at the start of the scan in
- * _mongoc_topology_run_background, when a node is added in
- * _mongoc_topology_reconcile_add_nodes, or when running a hello directly on a
- * node in _mongoc_stream_run_hello.
- */
-void
-_mongoc_topology_dup_handshake_cmd (const mongoc_topology_t *topology,
- bson_t *copy_into);
-void
-_mongoc_topology_request_scan (mongoc_topology_t *topology);
-
-void
-_mongoc_topology_bypass_cooldown (mongoc_topology_t *topology);
-
-typedef enum {
- MONGOC_SDAM_APP_ERROR_COMMAND,
- MONGOC_SDAM_APP_ERROR_NETWORK,
- MONGOC_SDAM_APP_ERROR_TIMEOUT
-} _mongoc_sdam_app_error_type_t;
-
-/**
- * @brief Handle an error from an app connection
- *
- * Processes network errors, timeouts, and command replies.
- *
- * @param topology The topology that will be updated
- * @param server_id The ID of the server on which the error occurred.
- * @param handshake_complete Whether the handshake was complete for this server
- * @param type The type of error to process
- * @param reply If checking for a command error, the server reply. Otherwise
- * NULL
- * @param why An error that will be attached to the server description
- * @param max_wire_version
- * @param generation The generation of the server description the caller was
- * using.
- * @param service_id A service ID for a load-balanced deployment. If not
- * applicable, pass kZeroServiceID.
- * @return true If the topology was updated and the pool was cleared.
- * @return false If no modifications were made and the error was ignored.
- *
- * @note May update the topology description.
- */
-bool
-_mongoc_topology_handle_app_error (mongoc_topology_t *topology,
- uint32_t server_id,
- bool handshake_complete,
- _mongoc_sdam_app_error_type_t type,
- const bson_t *reply,
- const bson_error_t *why,
- uint32_t max_wire_version,
- uint32_t generation,
- const bson_oid_t *service_id);
-
-void
-mongoc_topology_rescan_srv (mongoc_topology_t *topology);
-
-bool
-mongoc_topology_should_rescan_srv (mongoc_topology_t *topology);
-
-/* _mongoc_topology_set_rr_resolver is called by tests to mock DNS responses for
- * SRV polling.
- * This is necessarily called after initial seedlist discovery completes in
- * mongoc_topology_new.
- * Callers should call this before monitoring starts.
- */
-void
-_mongoc_topology_set_rr_resolver (mongoc_topology_t *topology,
- _mongoc_rr_resolver_fn rr_resolver);
-
-/* _mongoc_topology_set_srv_polling_rescan_interval_ms is called by tests to
- * shorten the rescan interval.
- * Callers should call this before monitoring starts.
- */
-void
-_mongoc_topology_set_srv_polling_rescan_interval_ms (
- mongoc_topology_t *topology, int64_t val);
-
-/**
- * @brief Return the latest connection generation for the server_id and/or
- * service_id.
- *
- * Use this generation for newly established connections.
- *
- * @param td The topology that contains the server
- * @param server_id The ID of the server to inspect
- * @param service_id The service ID of the connection if applicable, or
- * kZeroServiceID.
- * @returns uint32_t A generation counter for the given server, or zero if the
- * server does not exist in the topology.
- */
-uint32_t
-_mongoc_topology_get_connection_pool_generation (
- const mongoc_topology_description_t *td,
- uint32_t server_id,
- const bson_oid_t *service_id);
-
-/**
- * @brief Obtain a reference to the current topology description for the given
- * topology.
- *
- * Returns a ref-counted reference to the topology description. The returned
- * reference must later be released with mc_tpld_drop_ref(). The contents of the
- * topology description are immutable.
- */
-static BSON_INLINE mc_shared_tpld
-mc_tpld_take_ref (const mongoc_topology_t *tpl)
-{
- return (mc_shared_tpld){
- ._sptr_ = mongoc_atomic_shared_ptr_load (&tpl->_shared_descr_._sptr_)};
-}
-
-/**
- * @brief Release a reference to a topology description obtained via
- * mc_tpld_take_ref().
- *
- * The pointed-to shared reference will be reset to NULL.
- */
-static BSON_INLINE void
-mc_tpld_drop_ref (mc_shared_tpld *p)
-{
- mongoc_shared_ptr_reset_null (&p->_sptr_);
-}
-
-/**
- * @brief Refresh a reference to a topology description for the given topology.
- *
- * @param td Pointer-to-shared-pointer of the topology description
- * @param tpl The topology to query.
- *
- * The pointed-to shared pointer will be modified to refer to the topology
- * description of the topology.
- *
- * Equivalent to a call to `mc_tpld_drop_ref()` followed by a call to
- * `mc_tpld_take_ref()`.
- */
-static BSON_INLINE void
-mc_tpld_renew_ref (mc_shared_tpld *td, mongoc_topology_t *tpl)
-{
- mc_tpld_drop_ref (td);
- *td = mc_tpld_take_ref (tpl);
-}
-
-/**
- * @brief A pending topology description modification.
- *
- * Create an instance using `mc_tpld_modify_begin()`.
- */
-typedef struct mc_tpld_modification {
- /** The new topology. Modifications should be applied to this topology
- * description. Those modifications will be published by
- * `mc_tpld_modify_commit()`. */
- mongoc_topology_description_t *new_td;
- /** The topology that owns the topology description */
- mongoc_topology_t *topology;
-} mc_tpld_modification;
-
-/**
- * @brief Begin a new modification transaction of the topology description owned
- * by `tpl`
- *
- * @return mc_tpld_modification A pending modification.
- *
- * @note MUST be followed by a call to `mc_tpld_modify_commit` OR
- * `mc_tpld_modify_drop`
- *
- * @note THIS FUNCTION MAY BLOCK: This call takes a lock, which will only be
- * released by mc_tpld_modify_commit() or mc_tpld_modify_drop(). Do not call
- * this API while the current thread is already performing a modification!
- */
-mc_tpld_modification
-mc_tpld_modify_begin (mongoc_topology_t *tpl);
-
-/**
- * @brief Commit a topology description modification to the owning topology.
- *
- * All later calls to mc_tpld_take_ref() will see the new topology.
- */
-void mc_tpld_modify_commit (mc_tpld_modification);
-
-/**
- * @brief Drop a pending modification to a topology description. No changes will
- * be made to the topology.
- */
-void mc_tpld_modify_drop (mc_tpld_modification);
-
-/**
- * @brief Obtain a pointer-to-mutable mongoc_topology_description_t for the
- * given topology.
- *
- * This call is "unsafe" as the returned pointer may be invalidated by
- * concurrent modifications done using mc_tpld_modify_begin() and
- * mc_tpld_modify_commit().
- *
- * To obtain a safe pointer to the topology description, use mc_tpld_take_ref().
- */
-static BSON_INLINE mongoc_topology_description_t *
-mc_tpld_unsafe_get_mutable (mongoc_topology_t *tpl)
-{
- return tpl->_shared_descr_._sptr_.ptr;
-}
-
-/**
- * @brief Obtain a pointer-to-const mongoc_topology_description_t for the
- * given topology.
- *
- * This call is "unsafe" as the returned pointer may be invalidated by
- * concurrent modifications done using mc_tpld_modify_begin() and
- * mc_tpld_modify_commit().
- *
- * To obtain a safe pointer to the topology description, use mc_tpld_take_ref().
- *
- * @return const mongoc_topology_description_t* Pointer to the topology
- * description for the given topology.
- */
-static BSON_INLINE const mongoc_topology_description_t *
-mc_tpld_unsafe_get_const (const mongoc_topology_t *tpl)
-{
- return tpl->_shared_descr_._sptr_.ptr;
-}
-
-/**
- * @brief Directly invalidate a server in the topology by its ID.
- *
- * This is intended for testing purposes, as it provides thread-safe
- * direct topology modification.
- *
- * @param td The topology to modify.
- * @param server_id The ID of a server in the topology.
- */
-static BSON_INLINE void
-_mongoc_topology_invalidate_server (mongoc_topology_t *td, uint32_t server_id)
-{
- bson_error_t error;
- mc_tpld_modification tdmod = mc_tpld_modify_begin (td);
- bson_set_error (
- &error, MONGOC_ERROR_STREAM, MONGOC_ERROR_STREAM_CONNECT, "invalidated");
- mongoc_topology_description_invalidate_server (
- tdmod.new_td, server_id, &error);
- mc_tpld_modify_commit (tdmod);
-}
-
-#endif
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-scanner-private.h b/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-scanner-private.h
deleted file mode 100644
index 60a3c187..00000000
--- a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-scanner-private.h
+++ /dev/null
@@ -1,282 +0,0 @@
-/*
- * Copyright 2014 MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "mongoc-prelude.h"
-
-#ifndef MONGOC_TOPOLOGY_SCANNER_PRIVATE_H
-#define MONGOC_TOPOLOGY_SCANNER_PRIVATE_H
-
-/* TODO: rename to TOPOLOGY scanner */
-
-#include <bson/bson.h>
-#include "mongoc-async-private.h"
-#include "mongoc-async-cmd-private.h"
-#include "mongoc-handshake-private.h"
-#include "mongoc-host-list.h"
-#include "mongoc-apm-private.h"
-#include "mongoc-scram-private.h"
-#include "mongoc-ssl.h"
-#include "mongoc-crypto-private.h"
-#include "mongoc-server-description-private.h"
-#include "common-thread-private.h"
-
-BSON_BEGIN_DECLS
-
-typedef void (*mongoc_topology_scanner_setup_err_cb_t) (
- uint32_t id, void *data, const bson_error_t *error /* IN */);
-
-typedef void (*mongoc_topology_scanner_cb_t) (
- uint32_t id,
- const bson_t *bson,
- int64_t rtt,
- void *data,
- const bson_error_t *error /* IN */);
-
-struct mongoc_topology_scanner;
-struct mongoc_topology_scanner_node;
-
-typedef struct mongoc_topology_scanner_node {
- uint32_t id;
- /* after scanning, this is set to the successful stream if one exists. */
- mongoc_stream_t *stream;
-
- int64_t last_used;
- int64_t last_failed;
- bool has_auth;
- bool hello_ok;
- mongoc_host_list_t host;
- struct mongoc_topology_scanner *ts;
-
- struct mongoc_topology_scanner_node *next;
- struct mongoc_topology_scanner_node *prev;
-
- bool retired;
- bson_error_t last_error;
-
- /* the hostname for a node may resolve to multiple DNS results.
- * dns_results has the full list of DNS results, ordered by host preference.
- * successful_dns_result is the most recent successful DNS result.
- */
- struct addrinfo *dns_results;
- struct addrinfo *successful_dns_result;
- int64_t last_dns_cache;
-
- /* used by single-threaded clients to store negotiated sasl mechanisms on a
- * node. */
- mongoc_handshake_sasl_supported_mechs_t sasl_supported_mechs;
- bool negotiated_sasl_supported_mechs;
- bson_t speculative_auth_response;
- mongoc_scram_t scram;
-
- /* handshake_sd is a server description constructed from the response of the
- * initial handshake. It is bound to the lifetime of stream. */
- mongoc_server_description_t *handshake_sd;
-} mongoc_topology_scanner_node_t;
-
-typedef enum handshake_state_t {
- /**
- * The handshake command has no value. The handshake_cmd pointer will be
- * NULL.
- */
- HANDSHAKE_CMD_UNINITIALIZED,
- /**
- * The handshake command could not be constructed because it would be too
- * large. The handshake_cmd pointer will be NULL.
- */
- HANDSHAKE_CMD_TOO_BIG,
- /**
- * The handshake command is valid and ready to be copied-from.
- */
- HANDSHAKE_CMD_OKAY,
-} handshake_state_t;
-
-typedef struct mongoc_topology_scanner {
- mongoc_async_t *async;
- int64_t connect_timeout_msec;
- mongoc_topology_scanner_node_t *nodes;
- bson_t hello_cmd;
- bson_t legacy_hello_cmd;
- bson_mutex_t handshake_cmd_mtx;
- bson_t *handshake_cmd;
- handshake_state_t handshake_state;
- bson_t cluster_time;
- const char *appname;
-
- mongoc_topology_scanner_setup_err_cb_t setup_err_cb;
- mongoc_topology_scanner_cb_t cb;
- void *cb_data;
- const mongoc_uri_t *uri;
- mongoc_async_cmd_setup_t setup;
- mongoc_stream_initiator_t initiator;
- void *initiator_context;
- bson_error_t error;
-
-#ifdef MONGOC_ENABLE_SSL
- mongoc_ssl_opt_t *ssl_opts;
-#endif
-
- mongoc_apm_callbacks_t apm_callbacks;
- void *apm_context;
- int64_t dns_cache_timeout_ms;
- /* only used by single-threaded clients to negotiate auth mechanisms. */
- bool negotiate_sasl_supported_mechs;
- bool bypass_cooldown;
- bool speculative_authentication;
-
- mongoc_server_api_t *api;
- bool loadbalanced;
-} mongoc_topology_scanner_t;
-
-mongoc_topology_scanner_t *
-mongoc_topology_scanner_new (
- const mongoc_uri_t *uri,
- mongoc_topology_scanner_setup_err_cb_t setup_err_cb,
- mongoc_topology_scanner_cb_t cb,
- void *data,
- int64_t connect_timeout_msec);
-
-void
-mongoc_topology_scanner_destroy (mongoc_topology_scanner_t *ts);
-
-bool
-mongoc_topology_scanner_valid (mongoc_topology_scanner_t *ts);
-
-void
-mongoc_topology_scanner_add (mongoc_topology_scanner_t *ts,
- const mongoc_host_list_t *host,
- uint32_t id,
- bool hello_ok);
-
-void
-mongoc_topology_scanner_scan (mongoc_topology_scanner_t *ts, uint32_t id);
-
-void
-mongoc_topology_scanner_disconnect (mongoc_topology_scanner_t *scanner);
-
-void
-mongoc_topology_scanner_node_retire (mongoc_topology_scanner_node_t *node);
-
-void
-mongoc_topology_scanner_node_disconnect (mongoc_topology_scanner_node_t *node,
- bool failed);
-
-void
-mongoc_topology_scanner_node_destroy (mongoc_topology_scanner_node_t *node,
- bool failed);
-
-bool
-mongoc_topology_scanner_in_cooldown (mongoc_topology_scanner_t *ts,
- int64_t when);
-
-void
-mongoc_topology_scanner_start (mongoc_topology_scanner_t *ts,
- bool obey_cooldown);
-
-void
-mongoc_topology_scanner_work (mongoc_topology_scanner_t *ts);
-
-void
-_mongoc_topology_scanner_finish (mongoc_topology_scanner_t *ts);
-
-void
-mongoc_topology_scanner_get_error (mongoc_topology_scanner_t *ts,
- bson_error_t *error);
-
-void
-mongoc_topology_scanner_reset (mongoc_topology_scanner_t *ts);
-
-void
-mongoc_topology_scanner_node_setup (mongoc_topology_scanner_node_t *node,
- bson_error_t *error);
-
-mongoc_topology_scanner_node_t *
-mongoc_topology_scanner_get_node (mongoc_topology_scanner_t *ts, uint32_t id);
-
-void
-_mongoc_topology_scanner_add_speculative_authentication (
- bson_t *cmd,
- const mongoc_uri_t *uri,
- const mongoc_ssl_opt_t *ssl_opts,
- mongoc_scram_cache_t *scram_cache,
- mongoc_scram_t *scram /* OUT */);
-
-void
-_mongoc_topology_scanner_parse_speculative_authentication (
- const bson_t *hello, bson_t *speculative_authenticate);
-
-const char *
-_mongoc_topology_scanner_get_speculative_auth_mechanism (
- const mongoc_uri_t *uri);
-
-const bson_t *
-_mongoc_topology_scanner_get_monitoring_cmd (mongoc_topology_scanner_t *ts,
- bool hello_ok);
-
-/**
- * @brief Get the scanner's associated handshake command BSON document.
- *
- * @param ts The scanner to inspect
- * @param copy_into A pointer to an initialized bson_t. The handshake command
- * will be copied into the pointee.
- */
-void
-_mongoc_topology_scanner_dup_handshake_cmd (mongoc_topology_scanner_t *ts,
- bson_t *copy_into);
-
-bool
-mongoc_topology_scanner_has_node_for_host (mongoc_topology_scanner_t *ts,
- mongoc_host_list_t *host);
-
-void
-mongoc_topology_scanner_set_stream_initiator (mongoc_topology_scanner_t *ts,
- mongoc_stream_initiator_t si,
- void *ctx);
-bool
-_mongoc_topology_scanner_set_appname (mongoc_topology_scanner_t *ts,
- const char *name);
-void
-_mongoc_topology_scanner_set_cluster_time (mongoc_topology_scanner_t *ts,
- const bson_t *cluster_time);
-
-void
-_mongoc_topology_scanner_set_dns_cache_timeout (mongoc_topology_scanner_t *ts,
- int64_t timeout_ms);
-
-#ifdef MONGOC_ENABLE_SSL
-void
-mongoc_topology_scanner_set_ssl_opts (mongoc_topology_scanner_t *ts,
- mongoc_ssl_opt_t *opts);
-#endif
-
-bool
-mongoc_topology_scanner_node_in_cooldown (mongoc_topology_scanner_node_t *node,
- int64_t when);
-
-void
-_mongoc_topology_scanner_set_server_api (mongoc_topology_scanner_t *ts,
- const mongoc_server_api_t *api);
-
-void
-_mongoc_topology_scanner_set_loadbalanced (mongoc_topology_scanner_t *ts,
- bool val);
-
-/* for testing. */
-mongoc_stream_t *
-_mongoc_topology_scanner_tcp_initiate (mongoc_async_cmd_t *acmd);
-
-BSON_END_DECLS
-
-#endif /* MONGOC_TOPOLOGY_SCANNER_PRIVATE_H */
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-scanner.c b/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-scanner.c
deleted file mode 100644
index 1320177c..00000000
--- a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-scanner.c
+++ /dev/null
@@ -1,1466 +0,0 @@
-/*
- * Copyright 2014 MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <bson/bson.h>
-
-#include "mongoc-config.h"
-#include "mongoc-error.h"
-#include "mongoc-trace-private.h"
-#include "mongoc-topology-scanner-private.h"
-#include "mongoc-stream-private.h"
-#include "mongoc-stream-socket.h"
-
-#include "mongoc-handshake.h"
-#include "mongoc-handshake-private.h"
-
-#ifdef MONGOC_ENABLE_SSL
-#include "mongoc-stream-tls.h"
-#endif
-
-#include "mongoc-counters-private.h"
-#include "utlist.h"
-#include "mongoc-topology-private.h"
-#include "mongoc-host-list-private.h"
-#include "mongoc-uri-private.h"
-#include "mongoc-cluster-private.h"
-#include "mongoc-client-private.h"
-#include "mongoc-util-private.h"
-
-#undef MONGOC_LOG_DOMAIN
-#define MONGOC_LOG_DOMAIN "topology_scanner"
-
-#define DNS_CACHE_TIMEOUT_MS 10 * 60 * 1000
-#define HAPPY_EYEBALLS_DELAY_MS 250
-
-/* forward declarations */
-static void
-_async_connected (mongoc_async_cmd_t *acmd);
-
-static void
-_async_success (mongoc_async_cmd_t *acmd,
- const bson_t *hello_response,
- int64_t duration_usec);
-
-static void
-_async_error_or_timeout (mongoc_async_cmd_t *acmd,
- int64_t duration_usec,
- const char *default_err_msg);
-
-static void
-_async_handler (mongoc_async_cmd_t *acmd,
- mongoc_async_cmd_result_t async_status,
- const bson_t *hello_response,
- int64_t duration_usec);
-
-static void
-_mongoc_topology_scanner_monitor_heartbeat_started (
- const mongoc_topology_scanner_t *ts, const mongoc_host_list_t *host);
-
-static void
-_mongoc_topology_scanner_monitor_heartbeat_succeeded (
- const mongoc_topology_scanner_t *ts,
- const mongoc_host_list_t *host,
- const bson_t *reply,
- int64_t duration_usec);
-
-static void
-_mongoc_topology_scanner_monitor_heartbeat_failed (
- const mongoc_topology_scanner_t *ts,
- const mongoc_host_list_t *host,
- const bson_error_t *error,
- int64_t duration_usec);
-
-
-/* reset "retired" nodes that failed or were removed in the previous scan */
-static void
-_delete_retired_nodes (mongoc_topology_scanner_t *ts);
-
-/* cancel any pending async commands for a specific node excluding acmd.
- * If acmd is NULL, cancel all async commands on the node. */
-static void
-_cancel_commands_excluding (mongoc_topology_scanner_node_t *node,
- mongoc_async_cmd_t *acmd);
-
-/* return the number of pending async commands for a node. */
-static int
-_count_acmds (mongoc_topology_scanner_node_t *node);
-
-/* if acmd fails, schedule the sibling commands sooner. */
-static void
-_jumpstart_other_acmds (mongoc_topology_scanner_node_t *node,
- mongoc_async_cmd_t *acmd);
-
-static void
-_add_hello (mongoc_topology_scanner_t *ts)
-{
- mongoc_server_api_t *api = ts->api;
-
- BSON_APPEND_INT32 (&ts->hello_cmd, "hello", 1);
- BSON_APPEND_BOOL (&ts->hello_cmd, "helloOk", true);
-
- BSON_APPEND_INT32 (&ts->legacy_hello_cmd, HANDSHAKE_CMD_LEGACY_HELLO, 1);
- BSON_APPEND_BOOL (&ts->legacy_hello_cmd, "helloOk", true);
-
- if (api) {
- _mongoc_cmd_append_server_api (&ts->hello_cmd, api);
- }
-}
-
-static void
-_init_hello (mongoc_topology_scanner_t *ts)
-{
- bson_init (&ts->hello_cmd);
- bson_init (&ts->legacy_hello_cmd);
- bson_init (&ts->cluster_time);
- ts->handshake_cmd = NULL;
-
- _add_hello (ts);
-}
-
-static void
-_reset_hello (mongoc_topology_scanner_t *ts)
-{
- bson_t *prev_cmd;
- bson_reinit (&ts->hello_cmd);
- bson_reinit (&ts->legacy_hello_cmd);
-
- bson_mutex_lock (&ts->handshake_cmd_mtx);
- prev_cmd = ts->handshake_cmd;
- ts->handshake_cmd = NULL;
- ts->handshake_state = HANDSHAKE_CMD_UNINITIALIZED;
- bson_mutex_unlock (&ts->handshake_cmd_mtx);
- bson_destroy (prev_cmd);
-
- _add_hello (ts);
-}
-
-const char *
-_mongoc_topology_scanner_get_speculative_auth_mechanism (
- const mongoc_uri_t *uri)
-{
- const char *mechanism = mongoc_uri_get_auth_mechanism (uri);
- bool requires_auth = mechanism || mongoc_uri_get_username (uri);
-
- if (!requires_auth) {
- return NULL;
- }
-
- if (!mechanism) {
- return "SCRAM-SHA-256";
- }
-
- return mechanism;
-}
-
-void
-_mongoc_topology_scanner_add_speculative_authentication (
- bson_t *cmd,
- const mongoc_uri_t *uri,
- const mongoc_ssl_opt_t *ssl_opts,
- mongoc_scram_cache_t *scram_cache,
- mongoc_scram_t *scram /* OUT */)
-{
- bson_t auth_cmd;
- bson_error_t error;
- bool has_auth = false;
- const char *mechanism =
- _mongoc_topology_scanner_get_speculative_auth_mechanism (uri);
-
- if (!mechanism) {
- return;
- }
-
- if (strcasecmp (mechanism, "MONGODB-X509") == 0) {
- /* Ignore errors while building authentication document: we proceed with
- * the handshake as usual and let the subsequent authenticate command
- * fail. */
- if (_mongoc_cluster_get_auth_cmd_x509 (
- uri, ssl_opts, &auth_cmd, &error)) {
- has_auth = true;
- BSON_APPEND_UTF8 (&auth_cmd, "db", "$external");
- }
- }
-
-#ifdef MONGOC_ENABLE_CRYPTO
- if (strcasecmp (mechanism, "SCRAM-SHA-1") == 0 ||
- strcasecmp (mechanism, "SCRAM-SHA-256") == 0) {
- mongoc_crypto_hash_algorithm_t algo =
- strcasecmp (mechanism, "SCRAM-SHA-1") == 0
- ? MONGOC_CRYPTO_ALGORITHM_SHA_1
- : MONGOC_CRYPTO_ALGORITHM_SHA_256;
-
- _mongoc_uri_init_scram (uri, scram, algo);
-
- if (scram_cache) {
- _mongoc_scram_set_cache (scram, scram_cache);
- }
-
- if (_mongoc_cluster_get_auth_cmd_scram (algo, scram, &auth_cmd, &error)) {
- const char *auth_source;
-
- if (!(auth_source = mongoc_uri_get_auth_source (uri)) ||
- (*auth_source == '\0')) {
- auth_source = "admin";
- }
-
- has_auth = true;
- BSON_APPEND_UTF8 (&auth_cmd, "db", auth_source);
- }
- }
-#endif
-
- if (has_auth) {
- BSON_APPEND_DOCUMENT (cmd, "speculativeAuthenticate", &auth_cmd);
- bson_destroy (&auth_cmd);
- }
-}
-
-void
-_mongoc_topology_scanner_parse_speculative_authentication (
- const bson_t *hello, bson_t *speculative_authenticate)
-{
- bson_iter_t iter;
- uint32_t data_len;
- const uint8_t *data;
- bson_t auth_response;
-
- BSON_ASSERT (hello);
- BSON_ASSERT (speculative_authenticate);
-
- if (!bson_iter_init_find (&iter, hello, "speculativeAuthenticate")) {
- return;
- }
-
- bson_iter_document (&iter, &data_len, &data);
- BSON_ASSERT (bson_init_static (&auth_response, data, data_len));
-
- bson_destroy (speculative_authenticate);
- bson_copy_to (&auth_response, speculative_authenticate);
-}
-
-static bson_t *
-_build_handshake_cmd (const bson_t *basis_cmd,
- const char *appname,
- const mongoc_uri_t *uri,
- bool is_loadbalanced)
-{
- bson_t *doc = bson_copy (basis_cmd);
- bson_t subdoc;
- bson_iter_t iter;
- const char *key;
- int keylen;
- const bson_t *compressors;
- int count = 0;
- char buf[16];
- bool subdoc_okay;
-
- BSON_APPEND_DOCUMENT_BEGIN (doc, HANDSHAKE_FIELD, &subdoc);
- subdoc_okay =
- _mongoc_handshake_build_doc_with_application (&subdoc, appname);
- bson_append_document_end (doc, &subdoc);
-
- if (!subdoc_okay) {
- bson_destroy (doc);
- return NULL;
- }
-
- BSON_APPEND_ARRAY_BEGIN (doc, "compression", &subdoc);
- if (uri) {
- compressors = mongoc_uri_get_compressors (uri);
-
- if (bson_iter_init (&iter, compressors)) {
- while (bson_iter_next (&iter)) {
- keylen = bson_uint32_to_string (count++, &key, buf, sizeof buf);
- bson_append_utf8 (
- &subdoc, key, (int) keylen, bson_iter_key (&iter), -1);
- }
- }
- }
- bson_append_array_end (doc, &subdoc);
-
- if (is_loadbalanced) {
- BSON_APPEND_BOOL (doc, "loadBalanced", true);
- }
-
- /* Return whether the handshake doc fit the size limit */
- return doc;
-}
-
-const bson_t *
-_mongoc_topology_scanner_get_monitoring_cmd (mongoc_topology_scanner_t *ts,
- bool hello_ok)
-{
- return hello_ok || ts->api ? &ts->hello_cmd : &ts->legacy_hello_cmd;
-}
-
-void
-_mongoc_topology_scanner_dup_handshake_cmd (mongoc_topology_scanner_t *ts,
- bson_t *copy_into)
-{
- bson_t *new_cmd;
- const char *appname;
- BSON_ASSERT_PARAM (ts);
- BSON_ASSERT_PARAM (copy_into);
-
- /* appname will only be changed from NULL, so a non-null pointer will never
- * be invalidated after this fetch. */
- appname =
- bson_atomic_ptr_fetch ((void *) &ts->appname, bson_memory_order_relaxed);
-
- bson_mutex_lock (&ts->handshake_cmd_mtx);
- /* If this is the first time using the node or if it's the first time
- * using it after a failure, build handshake doc */
- if (ts->handshake_state != HANDSHAKE_CMD_UNINITIALIZED) {
- /* We're good to just return the handshake now */
- goto after_init;
- }
-
- /* There is not yet a handshake command associated with this scanner.
- * Initialize one and set it now. */
- /* Note: Don't hold the mutex while we build our command */
- /* Construct a new handshake command to be sent */
- BSON_ASSERT (ts->handshake_cmd == NULL);
- bson_mutex_unlock (&ts->handshake_cmd_mtx);
- new_cmd =
- _build_handshake_cmd (ts->api ? &ts->hello_cmd : &ts->legacy_hello_cmd,
- appname,
- ts->uri,
- ts->loadbalanced);
- bson_mutex_lock (&ts->handshake_cmd_mtx);
- if (ts->handshake_state != HANDSHAKE_CMD_UNINITIALIZED) {
- /* Someone else updated the handshake_cmd while we were building ours.
- * Defer to their copy and just destroy the one we created. */
- bson_destroy (new_cmd);
- goto after_init;
- }
- BSON_ASSERT (ts->handshake_cmd == NULL);
- /* We're still the one updating the command */
- ts->handshake_cmd = new_cmd;
- /* The "_build" may have failed. */
- /* Even if new_cmd is NULL, this is still what we want */
- ts->handshake_state =
- new_cmd == NULL ? HANDSHAKE_CMD_TOO_BIG : HANDSHAKE_CMD_OKAY;
- if (ts->handshake_state == HANDSHAKE_CMD_TOO_BIG) {
- MONGOC_WARNING ("Handshake doc too big, not including in hello");
- }
-
-after_init:
- /* If the doc turned out to be too big */
- if (ts->handshake_state == HANDSHAKE_CMD_TOO_BIG) {
- bson_t *ret = ts->api ? &ts->hello_cmd : &ts->legacy_hello_cmd;
- bson_copy_to (ret, copy_into);
- } else {
- BSON_ASSERT (ts->handshake_cmd != NULL);
- bson_copy_to (ts->handshake_cmd, copy_into);
- }
- bson_mutex_unlock (&ts->handshake_cmd_mtx);
-}
-
-static void
-_begin_hello_cmd (mongoc_topology_scanner_node_t *node,
- mongoc_stream_t *stream,
- bool is_setup_done,
- struct addrinfo *dns_result,
- int64_t initiate_delay_ms)
-{
- mongoc_topology_scanner_t *ts = node->ts;
- bson_t cmd;
-
- if (node->last_used != -1 && node->last_failed == -1) {
- /* The node's been used before and not failed recently */
- bson_copy_to (
- _mongoc_topology_scanner_get_monitoring_cmd (ts, node->hello_ok),
- &cmd);
- } else {
- _mongoc_topology_scanner_dup_handshake_cmd (ts, &cmd);
- }
-
- if (node->ts->negotiate_sasl_supported_mechs &&
- !node->negotiated_sasl_supported_mechs) {
- _mongoc_handshake_append_sasl_supported_mechs (ts->uri, &cmd);
- }
-
- if (node->ts->speculative_authentication && !node->has_auth &&
- bson_empty (&node->speculative_auth_response) && node->scram.step == 0) {
- mongoc_ssl_opt_t *ssl_opts = NULL;
-
-#ifdef MONGOC_ENABLE_SSL
- ssl_opts = ts->ssl_opts;
-#endif
-
- _mongoc_topology_scanner_add_speculative_authentication (
- &cmd, ts->uri, ssl_opts, NULL, &node->scram);
- }
-
- if (!bson_empty (&ts->cluster_time)) {
- bson_append_document (&cmd, "$clusterTime", 12, &ts->cluster_time);
- }
-
- /* if the node should connect with a TCP socket, stream will be null, and
- * dns_result will be set. The async loop is responsible for calling the
- * _tcp_initiator to construct TCP sockets. */
- mongoc_async_cmd_new (ts->async,
- stream,
- is_setup_done,
- dns_result,
- _mongoc_topology_scanner_tcp_initiate,
- initiate_delay_ms,
- ts->setup,
- node->host.host,
- "admin",
- &cmd,
- &_async_handler,
- node,
- ts->connect_timeout_msec);
-
- bson_destroy (&cmd);
-}
-
-
-mongoc_topology_scanner_t *
-mongoc_topology_scanner_new (
- const mongoc_uri_t *uri,
- mongoc_topology_scanner_setup_err_cb_t setup_err_cb,
- mongoc_topology_scanner_cb_t cb,
- void *data,
- int64_t connect_timeout_msec)
-{
- mongoc_topology_scanner_t *ts =
- (mongoc_topology_scanner_t *) bson_malloc0 (sizeof (*ts));
-
- ts->async = mongoc_async_new ();
-
- ts->setup_err_cb = setup_err_cb;
- ts->cb = cb;
- ts->cb_data = data;
- ts->uri = uri;
- ts->appname = NULL;
- ts->api = NULL;
- ts->handshake_state = HANDSHAKE_CMD_UNINITIALIZED;
- ts->connect_timeout_msec = connect_timeout_msec;
- /* may be overridden for testing. */
- ts->dns_cache_timeout_ms = DNS_CACHE_TIMEOUT_MS;
- bson_mutex_init (&ts->handshake_cmd_mtx);
-
- _init_hello (ts);
-
- return ts;
-}
-
-#ifdef MONGOC_ENABLE_SSL
-void
-mongoc_topology_scanner_set_ssl_opts (mongoc_topology_scanner_t *ts,
- mongoc_ssl_opt_t *opts)
-{
- ts->ssl_opts = opts;
- ts->setup = mongoc_async_cmd_tls_setup;
-}
-#endif
-
-void
-mongoc_topology_scanner_set_stream_initiator (mongoc_topology_scanner_t *ts,
- mongoc_stream_initiator_t si,
- void *ctx)
-{
- ts->initiator = si;
- ts->initiator_context = ctx;
- ts->setup = NULL;
-}
-
-void
-mongoc_topology_scanner_destroy (mongoc_topology_scanner_t *ts)
-{
- mongoc_topology_scanner_node_t *ele, *tmp;
-
- DL_FOREACH_SAFE (ts->nodes, ele, tmp)
- {
- mongoc_topology_scanner_node_destroy (ele, false);
- }
-
- mongoc_async_destroy (ts->async);
- bson_destroy (&ts->hello_cmd);
- bson_destroy (&ts->legacy_hello_cmd);
- bson_destroy (ts->handshake_cmd);
- bson_destroy (&ts->cluster_time);
- mongoc_server_api_destroy (ts->api);
- bson_mutex_destroy (&ts->handshake_cmd_mtx);
-
- /* This field can be set by a mongoc_client */
- bson_free ((char *) ts->appname);
-
- bson_free (ts);
-}
-
-/* whether the scanner was successfully initialized - false if a mongodb+srv
- * URI failed to resolve to any hosts */
-bool
-mongoc_topology_scanner_valid (mongoc_topology_scanner_t *ts)
-{
- return ts->nodes != NULL;
-}
-
-void
-mongoc_topology_scanner_add (mongoc_topology_scanner_t *ts,
- const mongoc_host_list_t *host,
- uint32_t id,
- bool hello_ok)
-{
- mongoc_topology_scanner_node_t *node;
-
- node = (mongoc_topology_scanner_node_t *) bson_malloc0 (sizeof (*node));
-
- memcpy (&node->host, host, sizeof (*host));
-
- node->id = id;
- node->ts = ts;
- node->last_failed = -1;
- node->last_used = -1;
- node->hello_ok = hello_ok;
- bson_init (&node->speculative_auth_response);
-
- DL_APPEND (ts->nodes, node);
-}
-
-void
-mongoc_topology_scanner_scan (mongoc_topology_scanner_t *ts, uint32_t id)
-{
- mongoc_topology_scanner_node_t *node;
-
- node = mongoc_topology_scanner_get_node (ts, id);
-
- /* begin non-blocking connection, don't wait for success */
- if (node) {
- mongoc_topology_scanner_node_setup (node, &node->last_error);
- }
-
- /* if setup fails the node stays in the scanner. destroyed after the scan. */
-}
-
-void
-mongoc_topology_scanner_disconnect (mongoc_topology_scanner_t *scanner)
-{
- mongoc_topology_scanner_node_t *node;
-
- BSON_ASSERT (scanner);
- node = scanner->nodes;
-
- while (node) {
- mongoc_topology_scanner_node_disconnect (node, false);
- node = node->next;
- }
-}
-
-void
-mongoc_topology_scanner_node_retire (mongoc_topology_scanner_node_t *node)
-{
- /* cancel any pending commands. */
- _cancel_commands_excluding (node, NULL);
-
- node->retired = true;
-}
-
-void
-mongoc_topology_scanner_node_disconnect (mongoc_topology_scanner_node_t *node,
- bool failed)
-{
- /* the node may or may not have succeeded in finding a working stream. */
- if (node->stream) {
- if (failed) {
- mongoc_stream_failed (node->stream);
- } else {
- mongoc_stream_destroy (node->stream);
- }
-
- node->stream = NULL;
- memset (
- &node->sasl_supported_mechs, 0, sizeof (node->sasl_supported_mechs));
- node->negotiated_sasl_supported_mechs = false;
- bson_reinit (&node->speculative_auth_response);
- }
- mongoc_server_description_destroy (node->handshake_sd);
- node->handshake_sd = NULL;
-}
-
-void
-mongoc_topology_scanner_node_destroy (mongoc_topology_scanner_node_t *node,
- bool failed)
-{
- DL_DELETE (node->ts->nodes, node);
- mongoc_topology_scanner_node_disconnect (node, failed);
- if (node->dns_results) {
- freeaddrinfo (node->dns_results);
- }
-
- bson_destroy (&node->speculative_auth_response);
-
-#ifdef MONGOC_ENABLE_CRYPTO
- _mongoc_scram_destroy (&node->scram);
-#endif
-
- bson_free (node);
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_topology_scanner_get_node --
- *
- * Return the scanner node with the given id.
- *
- *--------------------------------------------------------------------------
- */
-mongoc_topology_scanner_node_t *
-mongoc_topology_scanner_get_node (mongoc_topology_scanner_t *ts, uint32_t id)
-{
- mongoc_topology_scanner_node_t *ele, *tmp;
-
- DL_FOREACH_SAFE (ts->nodes, ele, tmp)
- {
- if (ele->id == id) {
- return ele;
- }
-
- if (ele->id > id) {
- break;
- }
- }
-
- return NULL;
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_topology_scanner_has_node_for_host --
- *
- * Whether the scanner has a node for the given host and port.
- *
- *--------------------------------------------------------------------------
- */
-bool
-mongoc_topology_scanner_has_node_for_host (mongoc_topology_scanner_t *ts,
- mongoc_host_list_t *host)
-{
- mongoc_topology_scanner_node_t *ele, *tmp;
-
- DL_FOREACH_SAFE (ts->nodes, ele, tmp)
- {
- if (_mongoc_host_list_compare_one (&ele->host, host)) {
- return true;
- }
- }
-
- return false;
-}
-
-static void
-_async_connected (mongoc_async_cmd_t *acmd)
-{
- mongoc_topology_scanner_node_t *node =
- (mongoc_topology_scanner_node_t *) acmd->data;
- /* this cmd connected successfully, cancel other cmds on this node. */
- _cancel_commands_excluding (node, acmd);
- node->successful_dns_result = acmd->dns_result;
-}
-
-static void
-_async_success (mongoc_async_cmd_t *acmd,
- const bson_t *hello_response,
- int64_t duration_usec)
-{
- void *data = acmd->data;
- mongoc_topology_scanner_node_t *node =
- (mongoc_topology_scanner_node_t *) data;
- mongoc_stream_t *stream = acmd->stream;
- mongoc_topology_scanner_t *ts = node->ts;
-
- if (node->retired) {
- if (stream) {
- mongoc_stream_failed (stream);
- }
- return;
- }
-
- node->last_used = bson_get_monotonic_time ();
- node->last_failed = -1;
-
- _mongoc_topology_scanner_monitor_heartbeat_succeeded (
- ts, &node->host, hello_response, duration_usec);
-
- /* set our successful stream. */
- BSON_ASSERT (!node->stream);
- node->stream = stream;
-
- if (!node->handshake_sd) {
- mongoc_server_description_t sd;
-
- /* Store a server description associated with the handshake. */
- mongoc_server_description_init (&sd, node->host.host_and_port, node->id);
- mongoc_server_description_handle_hello (
- &sd, hello_response, duration_usec / 1000, &acmd->error);
- node->handshake_sd = mongoc_server_description_new_copy (&sd);
- mongoc_server_description_cleanup (&sd);
- }
-
- if (ts->negotiate_sasl_supported_mechs &&
- !node->negotiated_sasl_supported_mechs) {
- _mongoc_handshake_parse_sasl_supported_mechs (
- hello_response, &node->sasl_supported_mechs);
- }
-
- if (ts->speculative_authentication) {
- _mongoc_topology_scanner_parse_speculative_authentication (
- hello_response, &node->speculative_auth_response);
- }
-
- /* mongoc_topology_scanner_cb_t takes rtt_msec, not usec */
- ts->cb (node->id,
- hello_response,
- duration_usec / 1000,
- ts->cb_data,
- &acmd->error);
-}
-
-static void
-_async_error_or_timeout (mongoc_async_cmd_t *acmd,
- int64_t duration_usec,
- const char *default_err_msg)
-{
- void *data = acmd->data;
- mongoc_topology_scanner_node_t *node =
- (mongoc_topology_scanner_node_t *) data;
- mongoc_stream_t *stream = acmd->stream;
- mongoc_topology_scanner_t *ts = node->ts;
- bson_error_t *error = &acmd->error;
- int64_t now = bson_get_monotonic_time ();
- const char *message;
-
- /* the stream may have failed on initiation. */
- if (stream) {
- mongoc_stream_failed (stream);
- }
-
- if (node->retired) {
- return;
- }
-
- node->last_used = now;
-
- if (!node->stream && _count_acmds (node) == 1) {
- /* there are no remaining streams, connecting has failed. */
- node->last_failed = now;
- if (error->code) {
- message = error->message;
- } else {
- message = default_err_msg;
- }
-
- /* invalidate any cached DNS results. */
- if (node->dns_results) {
- freeaddrinfo (node->dns_results);
- node->dns_results = NULL;
- node->successful_dns_result = NULL;
- }
-
- bson_set_error (&node->last_error,
- MONGOC_ERROR_CLIENT,
- MONGOC_ERROR_STREAM_CONNECT,
- "%s calling hello on \'%s\'",
- message,
- node->host.host_and_port);
-
- _mongoc_topology_scanner_monitor_heartbeat_failed (
- ts, &node->host, &node->last_error, duration_usec);
-
- /* call the topology scanner callback. cannot connect to this node.
- * callback takes rtt_msec, not usec. */
- ts->cb (node->id, NULL, duration_usec / 1000, ts->cb_data, error);
-
- mongoc_server_description_destroy (node->handshake_sd);
- node->handshake_sd = NULL;
- } else {
- /* there are still more commands left for this node or it succeeded
- * with another stream. skip the topology scanner callback. */
- _jumpstart_other_acmds (node, acmd);
- }
-}
-
-/*
- *-----------------------------------------------------------------------
- *
- * This is the callback passed to async_cmd when we're running
- * hellos from within the topology monitor.
- *
- *-----------------------------------------------------------------------
- */
-
-static void
-_async_handler (mongoc_async_cmd_t *acmd,
- mongoc_async_cmd_result_t async_status,
- const bson_t *hello_response,
- int64_t duration_usec)
-{
- BSON_ASSERT (acmd->data);
-
- switch (async_status) {
- case MONGOC_ASYNC_CMD_CONNECTED:
- _async_connected (acmd);
- return;
- case MONGOC_ASYNC_CMD_SUCCESS:
- _async_success (acmd, hello_response, duration_usec);
- return;
- case MONGOC_ASYNC_CMD_TIMEOUT:
- _async_error_or_timeout (acmd, duration_usec, "connection timeout");
- return;
- case MONGOC_ASYNC_CMD_ERROR:
- _async_error_or_timeout (acmd, duration_usec, "connection error");
- return;
- case MONGOC_ASYNC_CMD_IN_PROGRESS:
- default:
- fprintf (stderr, "unexpected async status: %d\n", async_status);
- BSON_ASSERT (false);
- return;
- }
-}
-
-mongoc_stream_t *
-_mongoc_topology_scanner_node_setup_stream_for_tls (
- mongoc_topology_scanner_node_t *node, mongoc_stream_t *stream)
-{
-#ifdef MONGOC_ENABLE_SSL
- mongoc_stream_t *tls_stream;
-#endif
- if (!stream) {
- return NULL;
- }
-#ifdef MONGOC_ENABLE_SSL
- if (node->ts->ssl_opts) {
- tls_stream = mongoc_stream_tls_new_with_hostname (
- stream, node->host.host, node->ts->ssl_opts, 1);
- if (!tls_stream) {
- mongoc_stream_destroy (stream);
- return NULL;
- } else {
- return tls_stream;
- }
- }
-#endif
- return stream;
-}
-
-/* attempt to create a new socket stream using this dns result. */
-mongoc_stream_t *
-_mongoc_topology_scanner_tcp_initiate (mongoc_async_cmd_t *acmd)
-{
- mongoc_topology_scanner_node_t *node =
- (mongoc_topology_scanner_node_t *) acmd->data;
- struct addrinfo *res = acmd->dns_result;
- mongoc_socket_t *sock = NULL;
-
- BSON_ASSERT (acmd->dns_result);
- /* create a new non-blocking socket. */
- if (!(sock = mongoc_socket_new (
- res->ai_family, res->ai_socktype, res->ai_protocol))) {
- return NULL;
- }
-
- (void) mongoc_socket_connect (
- sock, res->ai_addr, (mongoc_socklen_t) res->ai_addrlen, 0);
-
- return _mongoc_topology_scanner_node_setup_stream_for_tls (
- node, mongoc_stream_socket_new (sock));
-}
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_topology_scanner_node_setup_tcp --
- *
- * Create an async command for each DNS record found for this node.
- *
- * Returns:
- * A bool. On failure error is set.
- *
- *--------------------------------------------------------------------------
- */
-
-bool
-mongoc_topology_scanner_node_setup_tcp (mongoc_topology_scanner_node_t *node,
- bson_error_t *error)
-{
- struct addrinfo hints;
- struct addrinfo *iter;
- char portstr[8];
- mongoc_host_list_t *host;
- int s;
- int64_t delay = 0;
- int64_t now = bson_get_monotonic_time ();
-
- ENTRY;
-
- host = &node->host;
-
- /* if cached dns results are expired, flush. */
- if (node->dns_results &&
- (now - node->last_dns_cache) > node->ts->dns_cache_timeout_ms * 1000) {
- freeaddrinfo (node->dns_results);
- node->dns_results = NULL;
- node->successful_dns_result = NULL;
- }
-
- if (!node->dns_results) {
- bson_snprintf (portstr, sizeof portstr, "%hu", host->port);
-
- memset (&hints, 0, sizeof hints);
- hints.ai_family = host->family;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_flags = 0;
- hints.ai_protocol = 0;
-
- s = getaddrinfo (host->host, portstr, &hints, &node->dns_results);
-
- if (s != 0) {
- mongoc_counter_dns_failure_inc ();
- bson_set_error (error,
- MONGOC_ERROR_STREAM,
- MONGOC_ERROR_STREAM_NAME_RESOLUTION,
- "Failed to resolve '%s'",
- host->host);
- RETURN (false);
- }
-
- mongoc_counter_dns_success_inc ();
- node->last_dns_cache = now;
- }
-
- if (node->successful_dns_result) {
- _begin_hello_cmd (node, NULL, false, node->successful_dns_result, 0);
- } else {
- LL_FOREACH2 (node->dns_results, iter, ai_next)
- {
- _begin_hello_cmd (node, NULL, false, iter, delay);
- /* each subsequent DNS result will have an additional 250ms delay. */
- delay += HAPPY_EYEBALLS_DELAY_MS;
- }
- }
-
- RETURN (true);
-}
-
-bool
-mongoc_topology_scanner_node_connect_unix (mongoc_topology_scanner_node_t *node,
- bson_error_t *error)
-{
-#ifdef _WIN32
- ENTRY;
- bson_set_error (error,
- MONGOC_ERROR_STREAM,
- MONGOC_ERROR_STREAM_CONNECT,
- "UNIX domain sockets not supported on win32.");
- RETURN (false);
-#else
- struct sockaddr_un saddr;
- mongoc_socket_t *sock;
- mongoc_stream_t *stream;
- mongoc_host_list_t *host;
-
- ENTRY;
-
- host = &node->host;
-
- memset (&saddr, 0, sizeof saddr);
- saddr.sun_family = AF_UNIX;
- bson_snprintf (saddr.sun_path, sizeof saddr.sun_path - 1, "%s", host->host);
-
- sock = mongoc_socket_new (AF_UNIX, SOCK_STREAM, 0);
-
- if (sock == NULL) {
- bson_set_error (error,
- MONGOC_ERROR_STREAM,
- MONGOC_ERROR_STREAM_SOCKET,
- "Failed to create socket.");
- RETURN (false);
- }
-
- if (-1 == mongoc_socket_connect (
- sock, (struct sockaddr *) &saddr, sizeof saddr, -1)) {
- char buf[128];
- char *errstr;
-
- errstr = bson_strerror_r (mongoc_socket_errno (sock), buf, sizeof (buf));
-
- bson_set_error (error,
- MONGOC_ERROR_STREAM,
- MONGOC_ERROR_STREAM_CONNECT,
- "Failed to connect to UNIX domain socket: %s",
- errstr);
- mongoc_socket_destroy (sock);
- RETURN (false);
- }
-
- stream = _mongoc_topology_scanner_node_setup_stream_for_tls (
- node, mongoc_stream_socket_new (sock));
- if (stream) {
- _begin_hello_cmd (node,
- stream,
- false /* is_setup_done */,
- NULL /* dns result */,
- 0 /* delay */);
- RETURN (true);
- }
- bson_set_error (error,
- MONGOC_ERROR_STREAM,
- MONGOC_ERROR_STREAM_CONNECT,
- "Failed to create TLS stream");
- RETURN (false);
-#endif
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_topology_scanner_node_setup --
- *
- * Create a stream and begin a non-blocking connect.
- *
- * Returns:
- * true on success, or false and error is set.
- *
- *--------------------------------------------------------------------------
- */
-
-void
-mongoc_topology_scanner_node_setup (mongoc_topology_scanner_node_t *node,
- bson_error_t *error)
-{
- bool success = false;
- mongoc_stream_t *stream;
- int64_t start;
-
- _mongoc_topology_scanner_monitor_heartbeat_started (node->ts, &node->host);
- start = bson_get_monotonic_time ();
-
- /* if there is already a working stream, push it back to be re-scanned. */
- if (node->stream) {
- _begin_hello_cmd (node, node->stream, true /* is_setup_done */, NULL, 0);
- node->stream = NULL;
- return;
- }
-
- BSON_ASSERT (!node->retired);
-
- if (node->ts->initiator) {
- stream = node->ts->initiator (
- node->ts->uri, &node->host, node->ts->initiator_context, error);
- if (stream) {
- success = true;
- _begin_hello_cmd (node, stream, false, NULL, 0);
- }
- } else {
- if (node->host.family == AF_UNIX) {
- success = mongoc_topology_scanner_node_connect_unix (node, error);
- } else {
- success = mongoc_topology_scanner_node_setup_tcp (node, error);
- }
- }
-
- if (!success) {
- _mongoc_topology_scanner_monitor_heartbeat_failed (
- node->ts,
- &node->host,
- error,
- (bson_get_monotonic_time () - start) / 1000);
-
- node->ts->setup_err_cb (node->id, node->ts->cb_data, error);
- return;
- }
-
- node->has_auth = false;
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_topology_scanner_node_in_cooldown --
- *
- * Return true if @node has experienced a network error attempting
- * to call "hello" less than 5 seconds before @when, a timestamp in
- * microseconds.
- *
- * Server Discovery and Monitoring Spec: "After a single-threaded client
- * gets a network error trying to check a server, the client skips
- * re-checking the server until cooldownMS has passed. This avoids
- * spending connectTimeoutMS on each unavailable server during each scan.
- * This value MUST be 5000 ms, and it MUST NOT be configurable."
- *
- *--------------------------------------------------------------------------
- */
-bool
-mongoc_topology_scanner_node_in_cooldown (mongoc_topology_scanner_node_t *node,
- int64_t when)
-{
- if (node->last_failed == -1 || node->ts->bypass_cooldown) {
- return false; /* node is new, or connected */
- }
-
- return node->last_failed + 1000 * MONGOC_TOPOLOGY_COOLDOWN_MS >= when;
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_topology_scanner_in_cooldown --
- *
- * Return true if all nodes will be in cooldown at time @when, a
- * timestamp in microseconds.
- *
- *--------------------------------------------------------------------------
- */
-
-bool
-mongoc_topology_scanner_in_cooldown (mongoc_topology_scanner_t *ts,
- int64_t when)
-{
- mongoc_topology_scanner_node_t *node;
-
- if (ts->bypass_cooldown) {
- return false;
- }
- DL_FOREACH (ts->nodes, node)
- {
- if (!mongoc_topology_scanner_node_in_cooldown (node, when)) {
- return false;
- }
- }
-
- return true;
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_topology_scanner_start --
- *
- * Initializes the scanner and begins a full topology check. This
- * should be called once before calling mongoc_topology_scanner_work()
- * to complete the scan.
- *
- * If "obey_cooldown" is true, this is a single-threaded blocking scan
- * that must obey the Server Discovery And Monitoring Spec's cooldownMS:
- *
- * "After a single-threaded client gets a network error trying to check
- * a server, the client skips re-checking the server until cooldownMS has
- * passed.
- *
- * "This avoids spending connectTimeoutMS on each unavailable server
- * during each scan.
- *
- * "This value MUST be 5000 ms, and it MUST NOT be configurable."
- *
- *--------------------------------------------------------------------------
- */
-
-void
-mongoc_topology_scanner_start (mongoc_topology_scanner_t *ts,
- bool obey_cooldown)
-{
- mongoc_topology_scanner_node_t *node, *tmp;
- bool skip;
- int64_t now;
-
- BSON_ASSERT (ts);
-
- _delete_retired_nodes (ts);
-
- now = bson_get_monotonic_time ();
-
- DL_FOREACH_SAFE (ts->nodes, node, tmp)
- {
- skip =
- obey_cooldown && mongoc_topology_scanner_node_in_cooldown (node, now);
-
- if (!skip) {
- mongoc_topology_scanner_node_setup (node, &node->last_error);
- }
- }
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_topology_scanner_finish_scan --
- *
- * Summarizes all scanner node errors into one error message,
- * deletes retired nodes.
- *
- *--------------------------------------------------------------------------
- */
-
-void
-_mongoc_topology_scanner_finish (mongoc_topology_scanner_t *ts)
-{
- mongoc_topology_scanner_node_t *node, *tmp;
- bson_error_t *error = &ts->error;
- bson_string_t *msg;
-
- memset (&ts->error, 0, sizeof (bson_error_t));
-
- msg = bson_string_new (NULL);
-
- DL_FOREACH_SAFE (ts->nodes, node, tmp)
- {
- if (node->last_error.code) {
- if (msg->len) {
- bson_string_append_c (msg, ' ');
- }
-
- bson_string_append_printf (msg, "[%s]", node->last_error.message);
-
- /* last error domain and code win */
- error->domain = node->last_error.domain;
- error->code = node->last_error.code;
- }
- }
-
- bson_strncpy ((char *) &error->message, msg->str, sizeof (error->message));
- bson_string_free (msg, true);
-
- _delete_retired_nodes (ts);
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_topology_scanner_work --
- *
- * Crank the knob on the topology scanner state machine. This should
- * be called only after mongoc_topology_scanner_start() has been used
- * to begin the scan.
- *
- *--------------------------------------------------------------------------
- */
-
-void
-mongoc_topology_scanner_work (mongoc_topology_scanner_t *ts)
-{
- mongoc_async_run (ts->async);
- BSON_ASSERT (ts->async->ncmds == 0);
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_topology_scanner_get_error --
- *
- * Copy the scanner's current error; which may no-error (code 0).
- *
- *--------------------------------------------------------------------------
- */
-
-void
-mongoc_topology_scanner_get_error (mongoc_topology_scanner_t *ts,
- bson_error_t *error)
-{
- BSON_ASSERT (ts);
- BSON_ASSERT (error);
-
- memcpy (error, &ts->error, sizeof (bson_error_t));
-}
-
-/*
- * Set a field in the topology scanner.
- */
-bool
-_mongoc_topology_scanner_set_appname (mongoc_topology_scanner_t *ts,
- const char *appname)
-{
- char *s;
- const char *prev;
- if (!_mongoc_handshake_appname_is_valid (appname)) {
- MONGOC_ERROR ("Cannot set appname: %s is invalid", appname);
- return false;
- }
-
- s = bson_strdup (appname);
- prev = bson_atomic_ptr_compare_exchange_strong (
- (void *) &ts->appname, NULL, s, bson_memory_order_relaxed);
- if (prev == NULL) {
- return true;
- }
-
- MONGOC_ERROR ("Cannot set appname more than once");
- bson_free (s);
- return false;
-}
-
-/*
- * Set the scanner's clusterTime unconditionally: don't compare with prior
- * @cluster_time is like {clusterTime: <timestamp>}
- */
-void
-_mongoc_topology_scanner_set_cluster_time (mongoc_topology_scanner_t *ts,
- const bson_t *cluster_time)
-{
- bson_destroy (&ts->cluster_time);
- bson_copy_to (cluster_time, &ts->cluster_time);
-}
-
-/* SDAM Monitoring Spec: send HeartbeatStartedEvent */
-static void
-_mongoc_topology_scanner_monitor_heartbeat_started (
- const mongoc_topology_scanner_t *ts, const mongoc_host_list_t *host)
-{
- if (ts->apm_callbacks.server_heartbeat_started) {
- mongoc_apm_server_heartbeat_started_t event;
- event.host = host;
- event.context = ts->apm_context;
- event.awaited = false;
- ts->apm_callbacks.server_heartbeat_started (&event);
- }
-}
-
-/* SDAM Monitoring Spec: send HeartbeatSucceededEvent */
-static void
-_mongoc_topology_scanner_monitor_heartbeat_succeeded (
- const mongoc_topology_scanner_t *ts,
- const mongoc_host_list_t *host,
- const bson_t *reply,
- int64_t duration_usec)
-{
- if (ts->apm_callbacks.server_heartbeat_succeeded) {
- mongoc_apm_server_heartbeat_succeeded_t event;
- bson_t hello_redacted;
-
- bson_init (&hello_redacted);
- bson_copy_to_excluding_noinit (
- reply, &hello_redacted, "speculativeAuthenticate", NULL);
-
- event.host = host;
- event.context = ts->apm_context;
- event.reply = reply;
- event.duration_usec = duration_usec;
- event.awaited = false;
- ts->apm_callbacks.server_heartbeat_succeeded (&event);
-
- bson_destroy (&hello_redacted);
- }
-}
-
-/* SDAM Monitoring Spec: send HeartbeatFailedEvent */
-static void
-_mongoc_topology_scanner_monitor_heartbeat_failed (
- const mongoc_topology_scanner_t *ts,
- const mongoc_host_list_t *host,
- const bson_error_t *error,
- int64_t duration_usec)
-{
- if (ts->apm_callbacks.server_heartbeat_failed) {
- mongoc_apm_server_heartbeat_failed_t event;
- event.host = host;
- event.context = ts->apm_context;
- event.error = error;
- event.duration_usec = duration_usec;
- event.awaited = false;
- ts->apm_callbacks.server_heartbeat_failed (&event);
- }
-}
-
-/* this is for testing the dns cache timeout. */
-void
-_mongoc_topology_scanner_set_dns_cache_timeout (mongoc_topology_scanner_t *ts,
- int64_t timeout_ms)
-{
- ts->dns_cache_timeout_ms = timeout_ms;
-}
-
-/* reset "retired" nodes that failed or were removed in the previous scan */
-static void
-_delete_retired_nodes (mongoc_topology_scanner_t *ts)
-{
- mongoc_topology_scanner_node_t *node, *tmp;
-
- DL_FOREACH_SAFE (ts->nodes, node, tmp)
- {
- if (node->retired) {
- mongoc_topology_scanner_node_destroy (node, true);
- }
- }
-}
-
-static void
-_cancel_commands_excluding (mongoc_topology_scanner_node_t *node,
- mongoc_async_cmd_t *acmd)
-{
- mongoc_async_cmd_t *iter;
- DL_FOREACH (node->ts->async->cmds, iter)
- {
- if ((mongoc_topology_scanner_node_t *) iter->data == node &&
- iter != acmd) {
- iter->state = MONGOC_ASYNC_CMD_CANCELED_STATE;
- }
- }
-}
-
-static int
-_count_acmds (mongoc_topology_scanner_node_t *node)
-{
- mongoc_async_cmd_t *iter;
- int count = 0;
- DL_FOREACH (node->ts->async->cmds, iter)
- {
- if ((mongoc_topology_scanner_node_t *) iter->data == node) {
- ++count;
- }
- }
- return count;
-}
-
-static void
-_jumpstart_other_acmds (mongoc_topology_scanner_node_t *node,
- mongoc_async_cmd_t *acmd)
-{
- mongoc_async_cmd_t *iter;
- DL_FOREACH (node->ts->async->cmds, iter)
- {
- if ((mongoc_topology_scanner_node_t *) iter->data == node &&
- iter != acmd && acmd->initiate_delay_ms < iter->initiate_delay_ms) {
- iter->initiate_delay_ms =
- BSON_MAX (iter->initiate_delay_ms - HAPPY_EYEBALLS_DELAY_MS, 0);
- }
- }
-}
-
-void
-_mongoc_topology_scanner_set_server_api (mongoc_topology_scanner_t *ts,
- const mongoc_server_api_t *api)
-{
- BSON_ASSERT (ts);
- BSON_ASSERT (api);
-
- mongoc_server_api_destroy (ts->api);
- ts->api = mongoc_server_api_copy (api);
- _reset_hello (ts);
-}
-
-/* This must be called before the handshake command is constructed. */
-void
-_mongoc_topology_scanner_set_loadbalanced (mongoc_topology_scanner_t *ts,
- bool val)
-{
- BSON_ASSERT (ts->handshake_cmd == NULL);
- ts->loadbalanced = true;
-}
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology.c b/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology.c
deleted file mode 100644
index 0b6e2b73..00000000
--- a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology.c
+++ /dev/null
@@ -1,1987 +0,0 @@
-/*
- * Copyright 2014 MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "mongoc-config.h"
-
-#include "mongoc-handshake.h"
-#include "mongoc-handshake-private.h"
-
-#include "mongoc-error.h"
-#include "mongoc-host-list-private.h"
-#include "mongoc-log.h"
-#include "mongoc-topology-private.h"
-#include "mongoc-topology-description-apm-private.h"
-#include "mongoc-client-private.h"
-#include "mongoc-cmd-private.h"
-#include "mongoc-uri-private.h"
-#include "mongoc-util-private.h"
-#include "mongoc-trace-private.h"
-#include "mongoc-error-private.h"
-#include "mongoc-topology-background-monitoring-private.h"
-#include "mongoc-read-prefs-private.h"
-
-#include "utlist.h"
-
-static void
-_topology_collect_errors (const mongoc_topology_description_t *topology,
- bson_error_t *error_out);
-
-static bool
-_mongoc_topology_reconcile_add_nodes (mongoc_server_description_t *sd,
- mongoc_topology_scanner_t *scanner)
-{
- mongoc_topology_scanner_node_t *node;
-
- /* Search by ID and update hello_ok */
- node = mongoc_topology_scanner_get_node (scanner, sd->id);
- if (node) {
- node->hello_ok = sd->hello_ok;
- } else if (!mongoc_topology_scanner_has_node_for_host (scanner, &sd->host)) {
- /* A node for this host was retired in this scan. */
- mongoc_topology_scanner_add (scanner, &sd->host, sd->id, sd->hello_ok);
- mongoc_topology_scanner_scan (scanner, sd->id);
- }
-
- return true;
-}
-
-/* Called from:
- * - the topology scanner callback (when a hello was just received)
- * - at the start of a single-threaded scan (mongoc_topology_scan_once)
- * Not called for multi threaded monitoring.
- */
-void
-mongoc_topology_reconcile (const mongoc_topology_t *topology,
- mongoc_topology_description_t *td)
-{
- mongoc_set_t *servers;
- mongoc_server_description_t *sd;
- int i;
- mongoc_topology_scanner_node_t *ele, *tmp;
-
- servers = mc_tpld_servers (td);
- /* Add newly discovered nodes */
- for (i = 0; i < (int) servers->items_len; i++) {
- sd = mongoc_set_get_item (servers, i);
- _mongoc_topology_reconcile_add_nodes (sd, topology->scanner);
- }
-
- /* Remove removed nodes */
- DL_FOREACH_SAFE (topology->scanner->nodes, ele, tmp)
- {
- if (!mongoc_topology_description_server_by_id (td, ele->id, NULL)) {
- mongoc_topology_scanner_node_retire (ele);
- }
- }
-}
-
-
-/* call this while already holding the lock */
-static bool
-_mongoc_topology_update_no_lock (uint32_t id,
- const bson_t *hello_response,
- int64_t rtt_msec,
- mongoc_topology_description_t *td,
- const bson_error_t *error /* IN */)
-{
- mongoc_topology_description_handle_hello (
- td, id, hello_response, rtt_msec, error);
-
- /* return false if server removed from topology */
- return mongoc_topology_description_server_by_id (td, id, NULL) != NULL;
-}
-
-
-/*
- *-------------------------------------------------------------------------
- *
- * _mongoc_topology_scanner_setup_err_cb --
- *
- * Callback method to handle errors during topology scanner node
- * setup, typically DNS or SSL errors.
- *
- *-------------------------------------------------------------------------
- */
-
-void
-_mongoc_topology_scanner_setup_err_cb (uint32_t id,
- void *data,
- const bson_error_t *error /* IN */)
-{
- mongoc_topology_t *topology = BSON_ASSERT_PTR_INLINE (data);
-
- if (_mongoc_topology_get_type (topology) == MONGOC_TOPOLOGY_LOAD_BALANCED) {
- /* In load balanced mode, scanning is only for connection establishment.
- * It must not modify the topology description. */
- } else {
- /* We need to update the topology description */
- mc_tpld_modification mod = mc_tpld_modify_begin (topology);
- mongoc_topology_description_handle_hello (
- mod.new_td, id, NULL /* hello reply */, -1 /* rtt_msec */, error);
- mc_tpld_modify_commit (mod);
- }
-}
-
-
-/*
- *-------------------------------------------------------------------------
- *
- * _mongoc_topology_scanner_cb --
- *
- * Callback method to handle hello responses received by async
- * command objects.
- *
- * Only called for single-threaded monitoring.
- *
- *-------------------------------------------------------------------------
- */
-
-void
-_mongoc_topology_scanner_cb (uint32_t id,
- const bson_t *hello_response,
- int64_t rtt_msec,
- void *data,
- const bson_error_t *error /* IN */)
-{
- mongoc_topology_t *const topology = BSON_ASSERT_PTR_INLINE (data);
- mongoc_server_description_t *sd;
- mc_tpld_modification tdmod;
-
- if (_mongoc_topology_get_type (topology) == MONGOC_TOPOLOGY_LOAD_BALANCED) {
- /* In load balanced mode, scanning is only for connection establishment.
- * It must not modify the topology description. */
- return;
- }
-
- tdmod = mc_tpld_modify_begin (topology);
-
- sd = mongoc_topology_description_server_by_id (tdmod.new_td, id, NULL);
-
- if (!hello_response) {
- /* Server monitoring: When a server check fails due to a network error
- * (including a network timeout), the client MUST clear its connection
- * pool for the server */
- _mongoc_topology_description_clear_connection_pool (
- tdmod.new_td, id, &kZeroServiceId);
- }
-
- /* Server Discovery and Monitoring Spec: "Once a server is connected, the
- * client MUST change its type to Unknown only after it has retried the
- * server once." */
- if (!hello_response && sd && sd->type != MONGOC_SERVER_UNKNOWN) {
- _mongoc_topology_update_no_lock (
- id, hello_response, rtt_msec, tdmod.new_td, error);
-
- /* add another hello call to the current scan - the scan continues
- * until all commands are done */
- mongoc_topology_scanner_scan (topology->scanner, sd->id);
- } else {
- _mongoc_topology_update_no_lock (
- id, hello_response, rtt_msec, tdmod.new_td, error);
-
- /* The processing of the hello results above may have added, changed, or
- * removed server descriptions. We need to reconcile that with our
- * monitoring agents
- */
- mongoc_topology_reconcile (topology, tdmod.new_td);
-
- mongoc_cond_broadcast (&topology->cond_client);
- }
-
-
- mc_tpld_modify_commit (tdmod);
-}
-
-static void
-_server_session_init (mongoc_server_session_t *session,
- mongoc_topology_t *unused,
- bson_error_t *error)
-{
- _mongoc_server_session_init (session, error);
-}
-
-static void
-_server_session_destroy (mongoc_server_session_t *session,
- mongoc_topology_t *unused)
-{
- _mongoc_server_session_destroy (session);
-}
-
-static int
-_server_session_should_prune (mongoc_server_session_t *session,
- mongoc_topology_t *topo)
-{
- bool is_loadbalanced;
- int timeout;
- mc_shared_tpld td;
-
- BSON_ASSERT_PARAM (session);
- BSON_ASSERT_PARAM (topo);
-
- /** If "dirty" (i.e. contains a network error), it should be dropped */
- if (session->dirty) {
- return true;
- }
-
- /** If the session has never been used, it should be dropped */
- if (session->last_used_usec == SESSION_NEVER_USED) {
- return true;
- }
-
- /* Check for a timeout */
- td = mc_tpld_take_ref (topo);
- timeout = td.ptr->session_timeout_minutes;
- is_loadbalanced = td.ptr->type == MONGOC_TOPOLOGY_LOAD_BALANCED;
- mc_tpld_drop_ref (&td);
-
- /** Load balanced topology sessions never expire */
- if (is_loadbalanced) {
- return false;
- }
-
- /* Prune the session if it has hit a timeout */
- return _mongoc_server_session_timed_out (session, timeout);
-}
-
-static void
-_tpld_destroy_and_free (void *tpl_descr)
-{
- mongoc_topology_description_t *td = tpl_descr;
- mongoc_topology_description_destroy (td);
-}
-
-/*
- *-------------------------------------------------------------------------
- *
- * mongoc_topology_new --
- *
- * Creates and returns a new topology object.
- *
- * Returns:
- * A new topology object.
- *
- * Side effects:
- * None.
- *
- *-------------------------------------------------------------------------
- */
-mongoc_topology_t *
-mongoc_topology_new (const mongoc_uri_t *uri, bool single_threaded)
-{
- int64_t heartbeat_default;
- int64_t heartbeat;
- mongoc_topology_t *topology;
- mongoc_topology_description_type_t init_type;
- const char *service;
- char *prefixed_service;
- uint32_t id;
- const mongoc_host_list_t *hl;
- mongoc_rr_data_t rr_data;
- bool has_directconnection;
- bool directconnection;
-
- BSON_ASSERT (uri);
-
-#ifndef MONGOC_ENABLE_CRYPTO
- if (mongoc_uri_get_option_as_bool (
- uri, MONGOC_URI_RETRYWRITES, MONGOC_DEFAULT_RETRYWRITES)) {
- /* retryWrites requires sessions, which require crypto - just warn */
- MONGOC_WARNING (
- "retryWrites not supported without an SSL crypto library");
- }
-#endif
-
- topology = (mongoc_topology_t *) bson_malloc0 (sizeof *topology);
- topology->session_pool =
- mongoc_server_session_pool_new_with_params (_server_session_init,
- _server_session_destroy,
- _server_session_should_prune,
- topology);
-
- topology->valid = false;
- heartbeat_default =
- single_threaded ? MONGOC_TOPOLOGY_HEARTBEAT_FREQUENCY_MS_SINGLE_THREADED
- : MONGOC_TOPOLOGY_HEARTBEAT_FREQUENCY_MS_MULTI_THREADED;
-
- heartbeat = mongoc_uri_get_option_as_int32 (
- uri, MONGOC_URI_HEARTBEATFREQUENCYMS, heartbeat_default);
-
- topology->_shared_descr_._sptr_ = mongoc_shared_ptr_create (
- bson_malloc0 (sizeof (mongoc_topology_description_t)),
- _tpld_destroy_and_free);
- mongoc_topology_description_init (mc_tpld_unsafe_get_mutable (topology),
- heartbeat);
-
- mc_tpld_unsafe_get_mutable (topology)->set_name =
- bson_strdup (mongoc_uri_get_replica_set (uri));
-
- topology->uri = mongoc_uri_copy (uri);
- topology->cse_state = MONGOC_CSE_DISABLED;
- topology->single_threaded = single_threaded;
- if (single_threaded) {
- /* Server Selection Spec:
- *
- * "Single-threaded drivers MUST provide a "serverSelectionTryOnce"
- * mode, in which the driver scans the topology exactly once after
- * server selection fails, then either selects a server or raises an
- * error.
- *
- * "The serverSelectionTryOnce option MUST be true by default."
- */
- topology->server_selection_try_once = mongoc_uri_get_option_as_bool (
- uri, MONGOC_URI_SERVERSELECTIONTRYONCE, true);
- } else {
- topology->server_selection_try_once = false;
- }
-
- topology->server_selection_timeout_msec = mongoc_uri_get_option_as_int32 (
- topology->uri,
- MONGOC_URI_SERVERSELECTIONTIMEOUTMS,
- MONGOC_TOPOLOGY_SERVER_SELECTION_TIMEOUT_MS);
-
- /* tests can override this */
- topology->min_heartbeat_frequency_msec =
- MONGOC_TOPOLOGY_MIN_HEARTBEAT_FREQUENCY_MS;
-
- topology->local_threshold_msec =
- mongoc_uri_get_local_threshold_option (topology->uri);
-
- /* Total time allowed to check a server is connectTimeoutMS.
- * Server Discovery And Monitoring Spec:
- *
- * "The socket used to check a server MUST use the same connectTimeoutMS as
- * regular sockets. Multi-threaded clients SHOULD set monitoring sockets'
- * socketTimeoutMS to the connectTimeoutMS."
- */
- topology->connect_timeout_msec =
- mongoc_uri_get_option_as_int32 (topology->uri,
- MONGOC_URI_CONNECTTIMEOUTMS,
- MONGOC_DEFAULT_CONNECTTIMEOUTMS);
-
- topology->scanner_state = MONGOC_TOPOLOGY_SCANNER_OFF;
- topology->scanner =
- mongoc_topology_scanner_new (topology->uri,
- _mongoc_topology_scanner_setup_err_cb,
- _mongoc_topology_scanner_cb,
- topology,
- topology->connect_timeout_msec);
-
- bson_mutex_init (&topology->tpld_modification_mtx);
- mongoc_cond_init (&topology->cond_client);
-
- if (single_threaded) {
- /* single threaded drivers attempt speculative authentication during a
- * topology scan */
- topology->scanner->speculative_authentication = true;
-
- /* single threaded clients negotiate sasl supported mechanisms during
- * a topology scan. */
- if (_mongoc_uri_requires_auth_negotiation (uri)) {
- topology->scanner->negotiate_sasl_supported_mechs = true;
- }
- }
-
- service = mongoc_uri_get_service (uri);
- if (service) {
- memset (&rr_data, 0, sizeof (mongoc_rr_data_t));
- /* Set the default resource record resolver */
- topology->rr_resolver = _mongoc_client_get_rr;
-
- /* Initialize the last scan time and interval. Even if the initial DNS
- * lookup fails, SRV polling will still start when background monitoring
- * starts. */
- topology->srv_polling_last_scan_ms = bson_get_monotonic_time () / 1000;
- topology->srv_polling_rescan_interval_ms =
- MONGOC_TOPOLOGY_MIN_RESCAN_SRV_INTERVAL_MS;
-
- /* a mongodb+srv URI. try SRV lookup, if no error then also try TXT */
- prefixed_service = bson_strdup_printf ("_mongodb._tcp.%s", service);
- if (!topology->rr_resolver (prefixed_service,
- MONGOC_RR_SRV,
- &rr_data,
- MONGOC_RR_DEFAULT_BUFFER_SIZE,
- &topology->scanner->error)) {
- GOTO (srv_fail);
- }
-
- /* Failure to find TXT records will not return an error (since it is only
- * for options). But _mongoc_client_get_rr may return an error if
- * there is more than one TXT record returned. */
- if (!topology->rr_resolver (service,
- MONGOC_RR_TXT,
- &rr_data,
- MONGOC_RR_DEFAULT_BUFFER_SIZE,
- &topology->scanner->error)) {
- GOTO (srv_fail);
- }
-
- /* Use rr_data to update the topology's URI. */
- if (rr_data.txt_record_opts &&
- !mongoc_uri_parse_options (topology->uri,
- rr_data.txt_record_opts,
- true /* from_dns */,
- &topology->scanner->error)) {
- GOTO (srv_fail);
- }
-
- if (!mongoc_uri_init_with_srv_host_list (
- topology->uri, rr_data.hosts, &topology->scanner->error)) {
- GOTO (srv_fail);
- }
-
- topology->srv_polling_last_scan_ms = bson_get_monotonic_time () / 1000;
- /* TODO (CDRIVER-4047) use BSON_MIN */
- topology->srv_polling_rescan_interval_ms = BSON_MAX (
- rr_data.min_ttl * 1000, MONGOC_TOPOLOGY_MIN_RESCAN_SRV_INTERVAL_MS);
-
- topology->valid = true;
- srv_fail:
- bson_free (rr_data.txt_record_opts);
- bson_free (prefixed_service);
- _mongoc_host_list_destroy_all (rr_data.hosts);
- } else {
- topology->valid = true;
- }
-
- if (!mongoc_uri_finalize_loadbalanced (topology->uri,
- &topology->scanner->error)) {
- topology->valid = false;
- }
-
- /*
- * Set topology type from URI:
- * + if directConnection=true
- * - whether or not we have a replicaSet name, initialize to SINGLE
- * (directConnect with SRV or multiple hosts triggers a URI parse error)
- * + if directConnection=false
- * - if we've got a replicaSet name, initialize to RS_NO_PRIMARY
- * - otherwise, initialize to UNKNOWN
- * + if directConnection was not specified in the URI (old behavior)
- * - if we've got a replicaSet name, initialize to RS_NO_PRIMARY
- * - otherwise, if the seed list has a single host, initialize to SINGLE
- * - everything else gets initialized to UNKNOWN
- */
- has_directconnection =
- mongoc_uri_has_option (uri, MONGOC_URI_DIRECTCONNECTION);
- directconnection =
- has_directconnection &&
- mongoc_uri_get_option_as_bool (uri, MONGOC_URI_DIRECTCONNECTION, false);
- hl = mongoc_uri_get_hosts (topology->uri);
- /* If loadBalanced is enabled, directConnection is disabled. This was
- * validated in mongoc_uri_finalize_loadbalanced. */
- if (mongoc_uri_get_option_as_bool (
- topology->uri, MONGOC_URI_LOADBALANCED, false)) {
- init_type = MONGOC_TOPOLOGY_LOAD_BALANCED;
- if (topology->single_threaded) {
- /* Cooldown only applies to server monitoring for single-threaded
- * clients. In load balanced mode, the topology scanner is used to
- * create connections. The cooldown period does not apply. A network
- * error to a load balanced connection does not imply subsequent
- * connection attempts will be to the same server and that a delay
- * should occur. */
- _mongoc_topology_bypass_cooldown (topology);
- }
- _mongoc_topology_scanner_set_loadbalanced (topology->scanner, true);
- } else if (service && !has_directconnection) {
- init_type = MONGOC_TOPOLOGY_UNKNOWN;
- } else if (has_directconnection) {
- if (directconnection) {
- init_type = MONGOC_TOPOLOGY_SINGLE;
- } else {
- if (mongoc_uri_get_replica_set (topology->uri)) {
- init_type = MONGOC_TOPOLOGY_RS_NO_PRIMARY;
- } else {
- init_type = MONGOC_TOPOLOGY_UNKNOWN;
- }
- }
- } else if (mongoc_uri_get_replica_set (topology->uri)) {
- init_type = MONGOC_TOPOLOGY_RS_NO_PRIMARY;
- } else {
- if (hl && hl->next) {
- init_type = MONGOC_TOPOLOGY_UNKNOWN;
- } else {
- init_type = MONGOC_TOPOLOGY_SINGLE;
- }
- }
-
- mc_tpld_unsafe_get_mutable (topology)->type = init_type;
-
- if (!topology->single_threaded) {
- topology->server_monitors = mongoc_set_new (1, NULL, NULL);
- topology->rtt_monitors = mongoc_set_new (1, NULL, NULL);
- bson_mutex_init (&topology->apm_mutex);
- bson_mutex_init (&topology->srv_polling_mtx);
- mongoc_cond_init (&topology->srv_polling_cond);
- }
-
- if (!topology->valid) {
- TRACE ("%s", "topology invalid");
- /* add no nodes */
- return topology;
- }
-
- while (hl) {
- mongoc_topology_description_add_server (
- mc_tpld_unsafe_get_mutable (topology), hl->host_and_port, &id);
- mongoc_topology_scanner_add (topology->scanner, hl, id, false);
-
- hl = hl->next;
- }
-
- return topology;
-}
-/*
- *-------------------------------------------------------------------------
- *
- * mongoc_topology_set_apm_callbacks --
- *
- * Set Application Performance Monitoring callbacks.
- *
- *-------------------------------------------------------------------------
- */
-void
-mongoc_topology_set_apm_callbacks (mongoc_topology_t *topology,
- mongoc_topology_description_t *td,
- mongoc_apm_callbacks_t *callbacks,
- void *context)
-{
- if (callbacks) {
- memcpy (&td->apm_callbacks, callbacks, sizeof (mongoc_apm_callbacks_t));
- memcpy (&topology->scanner->apm_callbacks,
- callbacks,
- sizeof (mongoc_apm_callbacks_t));
- } else {
- memset (&td->apm_callbacks, 0, sizeof (mongoc_apm_callbacks_t));
- memset (
- &topology->scanner->apm_callbacks, 0, sizeof (mongoc_apm_callbacks_t));
- }
-
- td->apm_context = context;
- topology->scanner->apm_context = context;
-}
-
-/*
- *-------------------------------------------------------------------------
- *
- * mongoc_topology_destroy --
- *
- * Free the memory associated with this topology object.
- *
- * Returns:
- * None.
- *
- * Side effects:
- * @topology will be cleaned up.
- *
- *-------------------------------------------------------------------------
- */
-void
-mongoc_topology_destroy (mongoc_topology_t *topology)
-{
- if (!topology) {
- return;
- }
-
-#ifdef MONGOC_ENABLE_CLIENT_SIDE_ENCRYPTION
- bson_free (topology->keyvault_db);
- bson_free (topology->keyvault_coll);
- mongoc_client_destroy (topology->mongocryptd_client);
- mongoc_client_pool_destroy (topology->mongocryptd_client_pool);
- _mongoc_crypt_destroy (topology->crypt);
- bson_destroy (topology->mongocryptd_spawn_args);
- bson_free (topology->mongocryptd_spawn_path);
-#endif
-
- if (!topology->single_threaded) {
- _mongoc_topology_background_monitoring_stop (topology);
- BSON_ASSERT (topology->scanner_state == MONGOC_TOPOLOGY_SCANNER_OFF);
- mongoc_set_destroy (topology->server_monitors);
- mongoc_set_destroy (topology->rtt_monitors);
- bson_mutex_destroy (&topology->apm_mutex);
- bson_mutex_destroy (&topology->srv_polling_mtx);
- mongoc_cond_destroy (&topology->srv_polling_cond);
- }
-
- if (topology->valid) {
- /* Do not emit a topology_closed event. A topology opening event was not
- * emitted. */
- _mongoc_topology_description_monitor_closed (
- mc_tpld_unsafe_get_const (topology));
- }
-
- mongoc_uri_destroy (topology->uri);
- mongoc_shared_ptr_reset_null (&topology->_shared_descr_._sptr_);
- mongoc_topology_scanner_destroy (topology->scanner);
- mongoc_server_session_pool_free (topology->session_pool);
-
- mongoc_cond_destroy (&topology->cond_client);
- bson_mutex_destroy (&topology->tpld_modification_mtx);
-
- bson_free (topology);
-}
-
-/* Returns false if none of the hosts were valid. */
-bool
-mongoc_topology_apply_scanned_srv_hosts (mongoc_uri_t *uri,
- mongoc_topology_description_t *td,
- mongoc_host_list_t *hosts,
- bson_error_t *error)
-{
- mongoc_host_list_t *host;
- mongoc_host_list_t *valid_hosts = NULL;
- bool had_valid_hosts = false;
-
- /* Validate that the hosts have a matching domain.
- * If validation fails, log it.
- * If no valid hosts remain, do not update the topology description.
- */
- LL_FOREACH (hosts, host)
- {
- if (mongoc_uri_validate_srv_result (uri, host->host, error)) {
- _mongoc_host_list_upsert (&valid_hosts, host);
- } else {
- MONGOC_ERROR ("Invalid host returned by SRV: %s", host->host_and_port);
- /* Continue on, there may still be valid hosts returned. */
- }
- }
-
- if (valid_hosts) {
- /* Reconcile with the topology description. Newly found servers will start
- * getting monitored and are eligible to be used by clients. */
- mongoc_topology_description_reconcile (td, valid_hosts);
- had_valid_hosts = true;
- } else {
- bson_set_error (error,
- MONGOC_ERROR_STREAM,
- MONGOC_ERROR_STREAM_NAME_RESOLUTION,
- "SRV response did not contain any valid hosts");
- }
-
- _mongoc_host_list_destroy_all (valid_hosts);
- return had_valid_hosts;
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_topology_should_rescan_srv --
- *
- * Checks whether it is valid to rescan SRV records on the topology.
- * Namely, that the topology type is Sharded or Unknown, and that
- * the topology URI was configured with SRV.
- *
- * If this returns false, caller can stop scanning SRV records
- * and does not need to try again in the future.
- *
- * --------------------------------------------------------------------------
- */
-bool
-mongoc_topology_should_rescan_srv (mongoc_topology_t *topology)
-{
- const char *service = mongoc_uri_get_service (topology->uri);
- mongoc_topology_description_type_t type;
-
- if (!service) {
- /* Only rescan if we have a mongodb+srv:// URI. */
- return false;
- }
-
- type = _mongoc_topology_get_type (topology);
-
- /* Only perform rescan for sharded topology. */
- return type == MONGOC_TOPOLOGY_SHARDED || type == MONGOC_TOPOLOGY_UNKNOWN;
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_topology_rescan_srv --
- *
- * Queries SRV records for new hosts in a mongos cluster.
- * Caller must call mongoc_topology_should_rescan_srv before calling
- * to ensure preconditions are met.
- *
- * NOTE: This method may update the topology description.
- *
- * --------------------------------------------------------------------------
- */
-void
-mongoc_topology_rescan_srv (mongoc_topology_t *topology)
-{
- mongoc_rr_data_t rr_data = {0};
- const char *service;
- char *prefixed_service = NULL;
- int64_t scan_time_ms;
- bool ret;
- mc_shared_tpld td;
- mc_tpld_modification tdmod;
-
- BSON_ASSERT (mongoc_topology_should_rescan_srv (topology));
-
- service = mongoc_uri_get_service (topology->uri);
- scan_time_ms = topology->srv_polling_last_scan_ms +
- topology->srv_polling_rescan_interval_ms;
- if (bson_get_monotonic_time () / 1000 < scan_time_ms) {
- /* Query SRV no more frequently than srv_polling_rescan_interval_ms. */
- return;
- }
-
- TRACE ("%s", "Polling for SRV records");
-
- /* Go forth and query... */
- prefixed_service = bson_strdup_printf ("_mongodb._tcp.%s", service);
-
- ret = topology->rr_resolver (prefixed_service,
- MONGOC_RR_SRV,
- &rr_data,
- MONGOC_RR_DEFAULT_BUFFER_SIZE,
- &topology->scanner->error);
-
- td = mc_tpld_take_ref (topology);
- topology->srv_polling_last_scan_ms = bson_get_monotonic_time () / 1000;
- if (!ret) {
- /* Failed querying, soldier on and try again next time. */
- topology->srv_polling_rescan_interval_ms = td.ptr->heartbeat_msec;
- MONGOC_ERROR ("SRV polling error: %s", topology->scanner->error.message);
- GOTO (done);
- }
-
- /* TODO (CDRIVER-4047) use BSON_MIN */
- topology->srv_polling_rescan_interval_ms = BSON_MAX (
- rr_data.min_ttl * 1000, MONGOC_TOPOLOGY_MIN_RESCAN_SRV_INTERVAL_MS);
-
- tdmod = mc_tpld_modify_begin (topology);
- if (!mongoc_topology_apply_scanned_srv_hosts (topology->uri,
- tdmod.new_td,
- rr_data.hosts,
- &topology->scanner->error)) {
- MONGOC_ERROR ("%s", topology->scanner->error.message);
- /* Special case when DNS returns zero records successfully or no valid
- * hosts exist.
- * Leave the toplogy alone and perform another scan at the next interval
- * rather than removing all records and having nothing to connect to.
- * For no verified hosts drivers "MUST temporarily set
- * srv_polling_rescan_interval_ms
- * to heartbeatFrequencyMS until at least one verified SRV record is
- * obtained."
- */
- topology->srv_polling_rescan_interval_ms = td.ptr->heartbeat_msec;
- }
- mc_tpld_modify_commit (tdmod);
-
-done:
- mc_tpld_drop_ref (&td);
- bson_free (prefixed_service);
- _mongoc_host_list_destroy_all (rr_data.hosts);
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_topology_scan_once --
- *
- * Runs a single complete scan.
- *
- * NOTE: This method updates the topology description.
- *
- * Only runs for single threaded monitoring. (obey_cooldown is always
- * true).
- *
- *--------------------------------------------------------------------------
- */
-static void
-mongoc_topology_scan_once (mongoc_topology_t *topology, bool obey_cooldown)
-{
- mc_tpld_modification tdmod;
- if (mongoc_topology_should_rescan_srv (topology)) {
- /* Prior to scanning hosts, update the list of SRV hosts, if applicable.
- */
- mongoc_topology_rescan_srv (topology);
- }
-
- /* since the last scan, members may be added or removed from the topology
- * description based on hello responses in connection handshakes, see
- * _mongoc_topology_update_from_handshake. retire scanner nodes for removed
- * members and create scanner nodes for new ones. */
- tdmod = mc_tpld_modify_begin (topology);
- mongoc_topology_reconcile (topology, tdmod.new_td);
- mc_tpld_modify_commit (tdmod);
-
- mongoc_topology_scanner_start (topology->scanner, obey_cooldown);
- mongoc_topology_scanner_work (topology->scanner);
-
- _mongoc_topology_scanner_finish (topology->scanner);
-
- topology->last_scan = bson_get_monotonic_time ();
- topology->stale = false;
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_topology_do_blocking_scan --
- *
- * Monitoring entry for single-threaded use case. Assumes the caller
- * has checked that it's the right time to scan.
- *
- *--------------------------------------------------------------------------
- */
-void
-_mongoc_topology_do_blocking_scan (mongoc_topology_t *topology,
- bson_error_t *error)
-{
- _mongoc_handshake_freeze ();
-
- mongoc_topology_scan_once (topology, true /* obey cooldown */);
- mongoc_topology_scanner_get_error (topology->scanner, error);
-}
-
-
-bool
-mongoc_topology_compatible (const mongoc_topology_description_t *td,
- const mongoc_read_prefs_t *read_prefs,
- bson_error_t *error)
-{
- int64_t max_staleness_seconds;
- int32_t max_wire_version;
-
- if (td->compatibility_error.code) {
- if (error) {
- memcpy (error, &td->compatibility_error, sizeof (bson_error_t));
- }
- return false;
- }
-
- if (!read_prefs) {
- /* NULL means read preference Primary */
- return true;
- }
-
- max_staleness_seconds =
- mongoc_read_prefs_get_max_staleness_seconds (read_prefs);
-
- if (max_staleness_seconds != MONGOC_NO_MAX_STALENESS) {
- max_wire_version =
- mongoc_topology_description_lowest_max_wire_version (td);
-
- if (max_wire_version < WIRE_VERSION_MAX_STALENESS) {
- bson_set_error (error,
- MONGOC_ERROR_COMMAND,
- MONGOC_ERROR_PROTOCOL_BAD_WIRE_VERSION,
- "Not all servers support maxStalenessSeconds");
- return false;
- }
-
- /* shouldn't happen if we've properly enforced wire version */
- if (!mongoc_topology_description_all_sds_have_write_date (td)) {
- bson_set_error (error,
- MONGOC_ERROR_COMMAND,
- MONGOC_ERROR_PROTOCOL_BAD_WIRE_VERSION,
- "Not all servers have lastWriteDate");
- return false;
- }
-
- if (!_mongoc_topology_description_validate_max_staleness (
- td, max_staleness_seconds, error)) {
- return false;
- }
- }
-
- return true;
-}
-
-
-static void
-_mongoc_server_selection_error (const char *msg,
- const bson_error_t *scanner_error,
- bson_error_t *error)
-{
- if (scanner_error && scanner_error->code) {
- bson_set_error (error,
- MONGOC_ERROR_SERVER_SELECTION,
- MONGOC_ERROR_SERVER_SELECTION_FAILURE,
- "%s: %s",
- msg,
- scanner_error->message);
- } else {
- bson_set_error (error,
- MONGOC_ERROR_SERVER_SELECTION,
- MONGOC_ERROR_SERVER_SELECTION_FAILURE,
- "%s",
- msg);
- }
-}
-
-/*
- *-------------------------------------------------------------------------
- *
- * mongoc_topology_select --
- *
- * Selects a server description for an operation based on @optype
- * and @read_prefs.
- *
- * NOTE: this method returns a copy of the original server
- * description. Callers must own and clean up this copy.
- *
- * Parameters:
- * @topology: The topology.
- * @optype: Whether we are selecting for a read or write operation.
- * @read_prefs: Required, the read preferences for the command.
- * @error: Required, out pointer for error info.
- *
- * Returns:
- * A mongoc_server_description_t, or NULL on failure, in which case
- * @error will be set.
- *
- * Side effects:
- * @error may be set. This function may update the topology description.
- *
- *-------------------------------------------------------------------------
- */
-mongoc_server_description_t *
-mongoc_topology_select (mongoc_topology_t *topology,
- mongoc_ss_optype_t optype,
- const mongoc_read_prefs_t *read_prefs,
- bson_error_t *error)
-{
- uint32_t server_id =
- mongoc_topology_select_server_id (topology, optype, read_prefs, error);
-
- if (server_id) {
- /* new copy of the server description */
- mongoc_server_description_t *ret;
- mc_shared_tpld td = mc_tpld_take_ref (topology);
- mongoc_server_description_t const *sd =
- mongoc_topology_description_server_by_id_const (
- td.ptr, server_id, error);
- ret = mongoc_server_description_new_copy (sd);
- mc_tpld_drop_ref (&td);
- return ret;
- } else {
- return NULL;
- }
-}
-
-/* Bypasses normal server selection behavior for a load balanced topology.
- * Returns the id of the one load balancer server. Returns 0 on failure.
- * Successful post-condition: On a single threaded client, a connection will
- * have been established. */
-static uint32_t
-_mongoc_topology_select_server_id_loadbalanced (mongoc_topology_t *topology,
- bson_error_t *error)
-{
- mongoc_server_description_t const *selected_server;
- int32_t selected_server_id;
- mongoc_topology_scanner_node_t *node;
- bson_error_t scanner_error = {0};
- mc_shared_tpld td = mc_tpld_take_ref (topology);
-
- BSON_ASSERT (td.ptr->type == MONGOC_TOPOLOGY_LOAD_BALANCED);
-
- /* Emit the opening SDAM events if they have not emitted already. */
- if (!td.ptr->opened) {
- mc_tpld_modification tdmod = mc_tpld_modify_begin (topology);
- _mongoc_topology_description_monitor_opening (tdmod.new_td);
- mc_tpld_modify_commit (tdmod);
- mc_tpld_renew_ref (&td, topology);
- }
- selected_server = mongoc_topology_description_select (
- td.ptr, MONGOC_SS_WRITE, NULL /* read prefs */, 0 /* local threshold */);
-
- if (!selected_server) {
- _mongoc_server_selection_error (
- "No suitable server found in load balanced deployment", NULL, error);
- selected_server_id = 0;
- goto done;
- }
-
- selected_server_id = selected_server->id;
-
- if (!topology->single_threaded) {
- goto done;
- }
-
- /* If this is a single threaded topology, we must ensure that a connection is
- * available to this server. Wrapping drivers make the assumption that
- * successful server selection implies a connection is available. */
- node =
- mongoc_topology_scanner_get_node (topology->scanner, selected_server_id);
- if (!node) {
- _mongoc_server_selection_error (
- "Topology scanner in invalid state; cannot find load balancer",
- NULL,
- error);
- selected_server_id = 0;
- goto done;
- }
-
- if (!node->stream) {
- TRACE ("%s",
- "Server selection performing scan since no connection has "
- "been established");
- _mongoc_topology_do_blocking_scan (topology, &scanner_error);
- }
-
- if (!node->stream) {
- /* Use the same error domain / code that is returned in mongoc-cluster.c
- * when fetching a stream fails. */
- if (scanner_error.code) {
- bson_set_error (error,
- MONGOC_ERROR_STREAM,
- MONGOC_ERROR_STREAM_NOT_ESTABLISHED,
- "Could not establish stream for node %s: %s",
- node->host.host_and_port,
- scanner_error.message);
- } else {
- bson_set_error (error,
- MONGOC_ERROR_STREAM,
- MONGOC_ERROR_STREAM_NOT_ESTABLISHED,
- "Could not establish stream for node %s",
- node->host.host_and_port);
- }
- selected_server_id = 0;
- goto done;
- }
-
-done:
- mc_tpld_drop_ref (&td);
- return selected_server_id;
-}
-
-/*
- *-------------------------------------------------------------------------
- *
- * mongoc_topology_select_server_id --
- *
- * Alternative to mongoc_topology_select when you only need the id.
- *
- * Returns:
- * A server id, or 0 on failure, in which case @error will be set.
- *
- *-------------------------------------------------------------------------
- */
-uint32_t
-mongoc_topology_select_server_id (mongoc_topology_t *topology,
- mongoc_ss_optype_t optype,
- const mongoc_read_prefs_t *read_prefs,
- bson_error_t *error)
-{
- static const char *timeout_msg =
- "No suitable servers found: `serverSelectionTimeoutMS` expired";
-
- mongoc_topology_scanner_t *ts;
- int r;
- int64_t local_threshold_ms;
- const mongoc_server_description_t *selected_server = NULL;
- bool try_once;
- int64_t sleep_usec;
- bool tried_once;
- bson_error_t scanner_error = {0};
- int64_t heartbeat_msec;
- uint32_t server_id;
- mc_shared_tpld td = mc_tpld_take_ref (topology);
-
- /* These names come from the Server Selection Spec pseudocode */
- int64_t loop_start; /* when we entered this function */
- int64_t loop_end; /* when we last completed a loop (single-threaded) */
- int64_t scan_ready; /* the soonest we can do a blocking scan */
- int64_t next_update; /* the latest we must do a blocking scan */
- int64_t expire_at; /* when server selection timeout expires */
-
- BSON_ASSERT (topology);
- ts = topology->scanner;
-
- if (!mongoc_topology_scanner_valid (ts)) {
- if (error) {
- mongoc_topology_scanner_get_error (ts, error);
- error->domain = MONGOC_ERROR_SERVER_SELECTION;
- error->code = MONGOC_ERROR_SERVER_SELECTION_FAILURE;
- }
- server_id = 0;
- goto done;
- }
-
- if (td.ptr->type == MONGOC_TOPOLOGY_LOAD_BALANCED) {
- server_id =
- _mongoc_topology_select_server_id_loadbalanced (topology, error);
- goto done;
- }
-
- heartbeat_msec = td.ptr->heartbeat_msec;
- local_threshold_ms = topology->local_threshold_msec;
- try_once = topology->server_selection_try_once;
- loop_start = loop_end = bson_get_monotonic_time ();
- expire_at =
- loop_start + ((int64_t) topology->server_selection_timeout_msec * 1000);
-
- if (topology->single_threaded) {
- if (!td.ptr->opened) {
- mc_tpld_modification tdmod = mc_tpld_modify_begin (topology);
- _mongoc_topology_description_monitor_opening (tdmod.new_td);
- mc_tpld_modify_commit (tdmod);
- mc_tpld_renew_ref (&td, topology);
- }
-
- tried_once = false;
- next_update = topology->last_scan + heartbeat_msec * 1000;
- if (next_update < loop_start) {
- /* we must scan now */
- topology->stale = true;
- }
-
- /* until we find a server or time out */
- for (;;) {
- if (topology->stale) {
- /* how soon are we allowed to scan? */
- scan_ready = topology->last_scan +
- topology->min_heartbeat_frequency_msec * 1000;
-
- if (scan_ready > expire_at && !try_once) {
- /* selection timeout will expire before min heartbeat passes */
- _mongoc_server_selection_error (
- "No suitable servers found: "
- "`serverselectiontimeoutms` timed out",
- &scanner_error,
- error);
-
- server_id = 0;
- goto done;
- }
-
- sleep_usec = scan_ready - loop_end;
- if (sleep_usec > 0) {
- if (try_once &&
- mongoc_topology_scanner_in_cooldown (ts, scan_ready)) {
- _mongoc_server_selection_error (
- "No servers yet eligible for rescan",
- &scanner_error,
- error);
-
- server_id = 0;
- goto done;
- }
-
- _mongoc_usleep (sleep_usec);
- }
-
- /* takes up to connectTimeoutMS. sets "last_scan", clears "stale" */
- _mongoc_topology_do_blocking_scan (topology, &scanner_error);
- loop_end = topology->last_scan;
- tried_once = true;
- }
-
- /* Topology may have just been updated by a scan. */
- mc_tpld_renew_ref (&td, topology);
-
- if (!mongoc_topology_compatible (td.ptr, read_prefs, error)) {
- server_id = 0;
- goto done;
- }
-
- selected_server = mongoc_topology_description_select (
- td.ptr, optype, read_prefs, local_threshold_ms);
-
- if (selected_server) {
- server_id = selected_server->id;
- goto done;
- }
-
- topology->stale = true;
-
- if (try_once) {
- if (tried_once) {
- _mongoc_server_selection_error (
- "No suitable servers found (`serverSelectionTryOnce` set)",
- &scanner_error,
- error);
-
- server_id = 0;
- goto done;
- }
- } else {
- loop_end = bson_get_monotonic_time ();
-
- if (loop_end > expire_at) {
- /* no time left in server_selection_timeout_msec */
- _mongoc_server_selection_error (
- timeout_msg, &scanner_error, error);
-
- server_id = 0;
- goto done;
- }
- }
- }
- }
-
- /* With background thread */
- /* we break out when we've found a server or timed out */
- for (;;) {
- /* Topology may have been updated on a previous loop iteration */
- mc_tpld_renew_ref (&td, topology);
-
- if (!mongoc_topology_compatible (td.ptr, read_prefs, error)) {
- server_id = 0;
- goto done;
- }
-
- selected_server = mongoc_topology_description_select (
- td.ptr, optype, read_prefs, local_threshold_ms);
-
- if (selected_server) {
- server_id = selected_server->id;
- goto done;
- }
-
- /* tlpd_modification_mtx is used to synchronize updates to the topology.
- * Take that lock to do a wait on the topology to become up-to-date and
- * synchronize with a condition variable that will be signalled upon
- * topology changes. */
- bson_mutex_lock (&topology->tpld_modification_mtx);
- /* Now that we have the lock, check again, since a scan may have
- * occurred while we were waiting on the lock. */
- mc_tpld_renew_ref (&td, topology);
- selected_server = mongoc_topology_description_select (
- td.ptr, optype, read_prefs, local_threshold_ms);
- if (selected_server) {
- server_id = selected_server->id;
- bson_mutex_unlock (&topology->tpld_modification_mtx);
- goto done;
- }
-
- /* Still nothing. Request that the scanner do a scan now. */
- TRACE (
- "server selection requesting an immediate scan, want %s",
- _mongoc_read_mode_as_str (mongoc_read_prefs_get_mode (read_prefs)));
- _mongoc_topology_request_scan (topology);
-
- TRACE ("server selection about to wait for %" PRId64 "ms",
- (expire_at - loop_start) / 1000);
- r = mongoc_cond_timedwait (&topology->cond_client,
- &topology->tpld_modification_mtx,
- (expire_at - loop_start) / 1000);
- TRACE ("%s", "server selection awake");
- /* Refresh our topology handle */
- mc_tpld_renew_ref (&td, topology);
- _topology_collect_errors (td.ptr, &scanner_error);
-
- bson_mutex_unlock (&topology->tpld_modification_mtx);
-
-#ifdef _WIN32
- if (r == WSAETIMEDOUT) {
-#else
- if (r == ETIMEDOUT) {
-#endif
- /* handle timeouts */
- _mongoc_server_selection_error (timeout_msg, &scanner_error, error);
-
- server_id = 0;
- goto done;
- } else if (r) {
- bson_set_error (error,
- MONGOC_ERROR_SERVER_SELECTION,
- MONGOC_ERROR_SERVER_SELECTION_FAILURE,
- "Unknown error '%d' received while waiting on "
- "thread condition",
- r);
- server_id = 0;
- goto done;
- }
-
- loop_start = bson_get_monotonic_time ();
-
- if (loop_start > expire_at) {
- _mongoc_server_selection_error (timeout_msg, &scanner_error, error);
-
- server_id = 0;
- goto done;
- }
- }
-
-done:
- mc_tpld_drop_ref (&td);
- return server_id;
-}
-
-
-mongoc_host_list_t *
-_mongoc_topology_host_by_id (const mongoc_topology_description_t *td,
- uint32_t id,
- bson_error_t *error)
-{
- mongoc_server_description_t const *sd;
- mongoc_host_list_t *host = NULL;
-
- /* not a copy - direct pointer into topology description data */
- sd = mongoc_topology_description_server_by_id_const (td, id, error);
-
- if (sd) {
- host = bson_malloc0 (sizeof (mongoc_host_list_t));
- memcpy (host, &sd->host, sizeof (mongoc_host_list_t));
- }
-
- return host;
-}
-
-
-void
-_mongoc_topology_request_scan (mongoc_topology_t *topology)
-{
- _mongoc_topology_background_monitoring_request_scan (topology);
-}
-
-bool
-_mongoc_topology_update_from_handshake (mongoc_topology_t *topology,
- const mongoc_server_description_t *sd)
-{
- bool has_server;
- mc_tpld_modification tdmod;
-
- BSON_ASSERT (topology);
- BSON_ASSERT (sd);
- BSON_ASSERT (!topology->single_threaded);
-
- if (_mongoc_topology_get_type (topology) == MONGOC_TOPOLOGY_LOAD_BALANCED) {
- /* In load balanced mode, scanning is only for connection establishment.
- * It must not modify the topology description. */
- return true;
- }
-
- tdmod = mc_tpld_modify_begin (topology);
-
- /* return false if server was removed from topology */
- has_server = _mongoc_topology_update_no_lock (sd->id,
- &sd->last_hello_response,
- sd->round_trip_time_msec,
- tdmod.new_td,
- NULL);
-
- /* if pooled, wake threads waiting in mongoc_topology_server_by_id */
- mongoc_cond_broadcast (&topology->cond_client);
- /* Update background monitoring. */
- _mongoc_topology_background_monitoring_reconcile (topology, tdmod.new_td);
- mc_tpld_modify_commit (tdmod);
-
- return has_server;
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_topology_update_last_used --
- *
- * Internal function. In single-threaded mode only, track when the socket
- * to a particular server was last used. This is required for
- * mongoc_cluster_check_interval to know when a socket has been idle.
- *
- *--------------------------------------------------------------------------
- */
-
-void
-_mongoc_topology_update_last_used (mongoc_topology_t *topology,
- uint32_t server_id)
-{
- mongoc_topology_scanner_node_t *node;
-
- if (!topology->single_threaded) {
- return;
- }
-
- node = mongoc_topology_scanner_get_node (topology->scanner, server_id);
- if (node) {
- node->last_used = bson_get_monotonic_time ();
- }
-}
-
-
-mongoc_topology_description_type_t
-_mongoc_topology_get_type (const mongoc_topology_t *topology)
-{
- mc_shared_tpld td = mc_tpld_take_ref (topology);
- mongoc_topology_description_type_t td_type = td.ptr->type;
- mc_tpld_drop_ref (&td);
- return td_type;
-}
-
-bool
-_mongoc_topology_set_appname (mongoc_topology_t *topology, const char *appname)
-{
- bool ret = false;
-
- if (topology->scanner_state == MONGOC_TOPOLOGY_SCANNER_OFF) {
- ret = _mongoc_topology_scanner_set_appname (topology->scanner, appname);
- } else {
- MONGOC_ERROR ("Cannot set appname after handshake initiated");
- }
- return ret;
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_topology_update_cluster_time --
- *
- * Internal function. If the server reply has a later $clusterTime than
- * any seen before, update the topology's clusterTime. See the Driver
- * Sessions Spec.
- *
- *--------------------------------------------------------------------------
- */
-
-void
-_mongoc_topology_update_cluster_time (mongoc_topology_t *topology,
- const bson_t *reply)
-{
- bson_iter_t iter;
- bson_iter_t child;
- const uint8_t *data;
- uint32_t size;
- bson_t cluster_time;
- mc_shared_tpld td;
-
- if (!reply || !bson_iter_init_find (&iter, reply, "$clusterTime")) {
- return;
- }
-
- if (!BSON_ITER_HOLDS_DOCUMENT (&iter) ||
- !bson_iter_recurse (&iter, &child)) {
- MONGOC_ERROR ("Can't parse $clusterTime");
- return;
- }
-
- bson_iter_document (&iter, &size, &data);
- BSON_ASSERT (bson_init_static (&cluster_time, data, (size_t) size));
-
- td = mc_tpld_take_ref (topology);
-
- /* This func is called frequently and repeatedly, but the cluster time itself
- * is infrequently updated. mc_tpld_modify_begin() is very expensive, so we
- * only want to actually call it if we anticipate performing an update to the
- * cluster time.
- *
- * Check that the cluster time has actually changed from what we have on
- * record before opening a topology modification to update it. */
- if (bson_empty (&td.ptr->cluster_time) ||
- _mongoc_cluster_time_greater (&cluster_time, &td.ptr->cluster_time)) {
- mc_tpld_modification tdmod = mc_tpld_modify_begin (topology);
- /* Check again if we need to update the cluster time, since it may have
- * been updated behind our back. */
- if (bson_empty (&tdmod.new_td->cluster_time) ||
- _mongoc_cluster_time_greater (&cluster_time,
- &tdmod.new_td->cluster_time)) {
- bson_destroy (&tdmod.new_td->cluster_time);
- bson_copy_to (&cluster_time, &tdmod.new_td->cluster_time);
- _mongoc_topology_scanner_set_cluster_time (
- topology->scanner, &tdmod.new_td->cluster_time);
- mc_tpld_modify_commit (tdmod);
- } else {
- mc_tpld_modify_drop (tdmod);
- }
- }
- mc_tpld_drop_ref (&td);
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_topology_pop_server_session --
- *
- * Internal function. Get a server session from the pool or create
- * one. On error, return NULL and fill out @error.
- *
- *--------------------------------------------------------------------------
- */
-
-mongoc_server_session_t *
-_mongoc_topology_pop_server_session (mongoc_topology_t *topology,
- bson_error_t *error)
-{
- int64_t timeout;
- mongoc_server_session_t *ss = NULL;
- bool loadbalanced;
- mc_shared_tpld td = mc_tpld_take_ref (topology);
-
- ENTRY;
-
- timeout = td.ptr->session_timeout_minutes;
- loadbalanced = td.ptr->type == MONGOC_TOPOLOGY_LOAD_BALANCED;
-
- /* When the topology type is LoadBalanced, sessions are always supported. */
- if (!loadbalanced && timeout == MONGOC_NO_SESSIONS) {
- /* if needed, connect and check for session timeout again */
- if (!mongoc_topology_description_has_data_node (td.ptr)) {
- if (!mongoc_topology_select_server_id (
- topology, MONGOC_SS_READ, NULL, error)) {
- ss = NULL;
- goto done;
- }
-
- /* Topology may have been updated by a scan */
- mc_tpld_renew_ref (&td, topology);
-
- timeout = td.ptr->session_timeout_minutes;
- }
-
- if (timeout == MONGOC_NO_SESSIONS) {
- bson_set_error (error,
- MONGOC_ERROR_CLIENT,
- MONGOC_ERROR_CLIENT_SESSION_FAILURE,
- "Server does not support sessions");
- ss = NULL;
- goto done;
- }
- }
-
- ss = mongoc_server_session_pool_get (topology->session_pool, error);
-
-done:
- mc_tpld_drop_ref (&td);
- RETURN (ss);
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_topology_push_server_session --
- *
- * Internal function. Return a server session to the pool.
- *
- *--------------------------------------------------------------------------
- */
-
-void
-_mongoc_topology_push_server_session (mongoc_topology_t *topology,
- mongoc_server_session_t *server_session)
-{
- ENTRY;
-
- /**
- * ! note:
- * At time of writing, this diverges from the spec:
- * https://github.com/mongodb/specifications/blob/df6be82f865e9b72444488fd62ae1eb5fca18569/source/sessions/driver-sessions.rst#algorithm-to-return-a-serversession-instance-to-the-server-session-pool
- *
- * The spec notes that before returning a session, we should first inspect
- * the back of the pool for expired items and delete them. In this case, we
- * simply return the item to the top of the pool and leave the remainder
- * unchanged.
- *
- * The next pop operation that encounters an expired session will clear the
- * entire session pool, thus preventing unbounded growth of the pool.
- */
- mongoc_server_session_pool_return (server_session);
-
- EXIT;
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_topology_end_sessions_cmd --
- *
- * Internal function. End up to 10,000 server sessions. @cmd is an
- * uninitialized document. Sessions are destroyed as their ids are
- * appended to @cmd.
- *
- * Driver Sessions Spec: "If the number of sessions is very large the
- * endSessions command SHOULD be run multiple times to end 10,000
- * sessions at a time (in order to avoid creating excessively large
- * commands)."
- *
- * Returns:
- * true if any session ids were appended to @cmd.
- *
- *--------------------------------------------------------------------------
- */
-
-bool
-_mongoc_topology_end_sessions_cmd (mongoc_topology_t *topology, bson_t *cmd)
-{
- bson_t ar;
- /* Only end up to 10'000 sessions */
- const int ENDED_SESSION_PRUNING_LIMIT = 10000;
- int i = 0;
- mongoc_server_session_t *ss =
- mongoc_server_session_pool_get_existing (topology->session_pool);
-
- bson_init (cmd);
- BSON_APPEND_ARRAY_BEGIN (cmd, "endSessions", &ar);
-
- for (; i < ENDED_SESSION_PRUNING_LIMIT && ss != NULL;
- ++i,
- ss = mongoc_server_session_pool_get_existing (topology->session_pool)) {
- char buf[16];
- const char *key;
- bson_uint32_to_string (i, &key, buf, sizeof buf);
- BSON_APPEND_DOCUMENT (&ar, key, &ss->lsid);
- mongoc_server_session_pool_drop (ss);
- }
-
- if (ss) {
- /* We deleted at least 10'000 sessions, so we will need to return the
- * final session that we didn't drop */
- mongoc_server_session_pool_return (ss);
- }
-
- bson_append_array_end (cmd, &ar);
-
- return i > 0;
-}
-
-void
-_mongoc_topology_dup_handshake_cmd (const mongoc_topology_t *topology,
- bson_t *copy_into)
-{
- _mongoc_topology_scanner_dup_handshake_cmd (topology->scanner, copy_into);
-}
-
-void
-_mongoc_topology_bypass_cooldown (mongoc_topology_t *topology)
-{
- BSON_ASSERT (topology->single_threaded);
- topology->scanner->bypass_cooldown = true;
-}
-
-static void
-_find_topology_version (const bson_t *reply, bson_t *topology_version)
-{
- bson_iter_t iter;
- const uint8_t *bytes;
- uint32_t len;
-
- if (!bson_iter_init_find (&iter, reply, "topologyVersion") ||
- !BSON_ITER_HOLDS_DOCUMENT (&iter)) {
- bson_init (topology_version);
- return;
- }
- bson_iter_document (&iter, &len, &bytes);
- bson_init_static (topology_version, bytes, len);
-}
-
-
-static bool
-_handle_sdam_app_error_command (mongoc_topology_t *topology,
- const mongoc_topology_description_t *td,
- uint32_t server_id,
- uint32_t generation,
- const bson_oid_t *service_id,
- const mongoc_server_description_t *sd,
- uint32_t max_wire_version,
- const bson_t *reply)
-{
- bson_error_t cmd_error;
- bson_t incoming_topology_version;
- bool pool_cleared = false;
- bool should_clear_pool = false;
- mc_tpld_modification tdmod;
- mongoc_server_description_t *mut_sd;
-
- if (_mongoc_cmd_check_ok_no_wce (
- reply, MONGOC_ERROR_API_VERSION_2, &cmd_error)) {
- /* No error. */
- return false;
- }
-
- if (!_mongoc_error_is_state_change (&cmd_error)) {
- /* Not a "not primary" or "node is recovering" error. */
- return false;
- }
-
- /* Check if the error is "stale", i.e. the topologyVersion refers to an
- * older
- * version of the server than we have stored in the topology description.
- */
- _find_topology_version (reply, &incoming_topology_version);
- if (mongoc_server_description_topology_version_cmp (
- &sd->topology_version, &incoming_topology_version) >= 0) {
- /* The server description is greater or equal, ignore the error. */
- bson_destroy (&incoming_topology_version);
- return false;
- }
-
- should_clear_pool = (max_wire_version <= WIRE_VERSION_4_0 ||
- _mongoc_error_is_shutdown (&cmd_error));
-
- tdmod = mc_tpld_modify_begin (topology);
-
- /* Get the server handle again, which might have been removed. */
- mut_sd =
- mongoc_topology_description_server_by_id (tdmod.new_td, server_id, NULL);
-
- if (!mut_sd) {
- /* Server was already removed/invalidated */
- mc_tpld_modify_drop (tdmod);
- bson_destroy (&incoming_topology_version);
- return false;
- }
-
- /* Check the topology version a second time, now that we have an exclusive
- * lock on the latest topology description. */
- if (mongoc_server_description_topology_version_cmp (
- &mut_sd->topology_version, &incoming_topology_version) >= 0) {
- /* The server description is greater or equal, ignore the error. */
- mc_tpld_modify_drop (tdmod);
- bson_destroy (&incoming_topology_version);
- return false;
- }
-
- if (generation < mc_tpl_sd_get_generation (mut_sd, service_id)) {
- /* Our view of the server description is stale. Ignore it. */
- mc_tpld_modify_drop (tdmod);
- bson_destroy (&incoming_topology_version);
- return false;
- }
-
- /* Overwrite the topology version. */
- mongoc_server_description_set_topology_version (mut_sd,
- &incoming_topology_version);
-
- /* SDAM: When handling a "not primary" or "node is recovering" error, the
- * client MUST clear the server's connection pool if and only if the error
- * is "node is shutting down" or the error originated from server version
- * < 4.2.
- */
- if (should_clear_pool) {
- _mongoc_topology_description_clear_connection_pool (
- tdmod.new_td, server_id, service_id);
- pool_cleared = true;
- }
-
- /*
- * SDAM: When the client sees a "not primary" or "node is recovering"
- * error and the error's topologyVersion is strictly greater than the
- * current ServerDescription's topologyVersion it MUST replace the
- * server's description with a ServerDescription of type Unknown.
- */
- mongoc_topology_description_invalidate_server (
- tdmod.new_td, server_id, &cmd_error);
-
- if (topology->single_threaded) {
- /* SDAM: For single-threaded clients, in the case of a "not primary" or
- * "node is shutting down" error, the client MUST mark the topology as
- * "stale"
- */
- if (_mongoc_error_is_not_primary (&cmd_error)) {
- topology->stale = true;
- }
- } else {
- /* SDAM Spec: "Multi-threaded and asynchronous clients MUST request an
- * immediate check of the server."
- * Instead of requesting a check of the one server, request a scan
- * to all servers (to find the new primary).
- */
- _mongoc_topology_request_scan (topology);
- }
-
- mc_tpld_modify_commit (tdmod);
- bson_destroy (&incoming_topology_version);
-
- return pool_cleared;
-}
-
-
-bool
-_mongoc_topology_handle_app_error (mongoc_topology_t *topology,
- uint32_t server_id,
- bool handshake_complete,
- _mongoc_sdam_app_error_type_t type,
- const bson_t *reply,
- const bson_error_t *why,
- uint32_t max_wire_version,
- uint32_t generation,
- const bson_oid_t *service_id)
-{
- bson_error_t server_selection_error;
- const mongoc_server_description_t *sd;
- bool cleared_pool = false;
- mc_shared_tpld td = mc_tpld_take_ref (topology);
-
- /* Start by checking every condition in which we should ignore the error */
- sd = mongoc_topology_description_server_by_id_const (
- td.ptr, server_id, &server_selection_error);
-
- if (!sd) {
- /* The server was already removed from the topology. Ignore error. */
- goto ignore_error;
- }
-
- /* When establishing a new connection in load balanced mode, drivers MUST NOT
- * perform SDAM error handling for any errors that occur before the MongoDB
- * Handshake. */
- if (td.ptr->type == MONGOC_TOPOLOGY_LOAD_BALANCED && !handshake_complete) {
- goto ignore_error;
- }
-
- if (generation < mc_tpl_sd_get_generation (sd, service_id)) {
- /* This is a stale connection. Ignore. */
- goto ignore_error;
- }
-
- if (type == MONGOC_SDAM_APP_ERROR_TIMEOUT && handshake_complete) {
- /* Timeout errors after handshake are ok, do nothing. */
- goto ignore_error;
- }
-
- /* Do something with the error */
- if (type == MONGOC_SDAM_APP_ERROR_COMMAND) {
- cleared_pool = _handle_sdam_app_error_command (topology,
- td.ptr,
- server_id,
- generation,
- service_id,
- sd,
- max_wire_version,
- reply);
- } else {
- /* Invalidate the server that saw the error. */
- mc_tpld_modification tdmod = mc_tpld_modify_begin (topology);
- sd = mongoc_topology_description_server_by_id_const (
- tdmod.new_td, server_id, NULL);
- /* Check if the server has already been invalidated */
- if (!sd || generation < mc_tpl_sd_get_generation (sd, service_id)) {
- mc_tpld_modify_drop (tdmod);
- goto ignore_error;
- }
- /* Mark server as unknown. */
- mongoc_topology_description_invalidate_server (
- tdmod.new_td, server_id, why);
- /* Clear the connection pool */
- _mongoc_topology_description_clear_connection_pool (
- tdmod.new_td, server_id, service_id);
- cleared_pool = true;
- if (!topology->single_threaded) {
- _mongoc_topology_background_monitoring_cancel_check (topology,
- server_id);
- }
- mc_tpld_modify_commit (tdmod);
- }
-
-ignore_error: /* <- Jump taken if we should ignore the error */
-
- mc_tpld_drop_ref (&td);
- return cleared_pool;
-}
-
-/* Called from application threads
- * Caller must hold topology lock.
- * For single-threaded monitoring, the topology scanner may include errors for
- * servers that were removed from the topology.
- */
-static void
-_topology_collect_errors (const mongoc_topology_description_t *td,
- bson_error_t *error_out)
-{
- const mongoc_server_description_t *server_description;
- bson_string_t *error_message;
- int i;
-
- memset (error_out, 0, sizeof (bson_error_t));
- error_message = bson_string_new ("");
-
- for (i = 0; i < mc_tpld_servers_const (td)->items_len; i++) {
- const bson_error_t *error;
-
- server_description = mc_tpld_servers_const (td)->items[i].item;
- error = &server_description->error;
- if (error->code) {
- if (error_message->len > 0) {
- bson_string_append_c (error_message, ' ');
- }
- bson_string_append_printf (
- error_message, "[%s]", server_description->error.message);
- /* The last error's code and domain wins. */
- error_out->code = error->code;
- error_out->domain = error->domain;
- }
- }
-
- bson_strncpy ((char *) &error_out->message,
- error_message->str,
- sizeof (error_out->message));
- bson_string_free (error_message, true);
-}
-
-void
-_mongoc_topology_set_rr_resolver (mongoc_topology_t *topology,
- _mongoc_rr_resolver_fn rr_resolver)
-{
- topology->rr_resolver = rr_resolver;
-}
-
-void
-_mongoc_topology_set_srv_polling_rescan_interval_ms (
- mongoc_topology_t *topology, int64_t val)
-{
- topology->srv_polling_rescan_interval_ms = val;
-}
-
-uint32_t
-_mongoc_topology_get_connection_pool_generation (
- const mongoc_topology_description_t *td,
- uint32_t server_id,
- const bson_oid_t *service_id)
-{
- const mongoc_server_description_t *sd;
- bson_error_t error;
-
- BSON_ASSERT (service_id);
-
- sd = mongoc_topology_description_server_by_id_const (td, server_id, &error);
- if (!sd) {
- /* Server removed, ignore and ignore error. */
- return 0;
- }
-
- return mc_tpl_sd_get_generation (sd, service_id);
-}
-
-mc_tpld_modification
-mc_tpld_modify_begin (mongoc_topology_t *tpl)
-{
- mc_shared_tpld prev_td;
- mongoc_topology_description_t *new_td;
- bson_mutex_lock (&tpl->tpld_modification_mtx);
- prev_td = mc_tpld_take_ref (tpl);
- new_td = mongoc_topology_description_new_copy (prev_td.ptr),
- mc_tpld_drop_ref (&prev_td);
- return (mc_tpld_modification){
- .new_td = new_td,
- .topology = tpl,
- };
-}
-
-void
-mc_tpld_modify_commit (mc_tpld_modification mod)
-{
- mongoc_shared_ptr old_sptr =
- mongoc_shared_ptr_copy (mod.topology->_shared_descr_._sptr_);
- mongoc_shared_ptr new_sptr =
- mongoc_shared_ptr_create (mod.new_td, _tpld_destroy_and_free);
- mongoc_atomic_shared_ptr_store (&mod.topology->_shared_descr_._sptr_,
- new_sptr);
- bson_mutex_unlock (&mod.topology->tpld_modification_mtx);
- mongoc_shared_ptr_reset_null (&new_sptr);
- mongoc_shared_ptr_reset_null (&old_sptr);
-}
-
-void
-mc_tpld_modify_drop (mc_tpld_modification mod)
-{
- bson_mutex_unlock (&mod.topology->tpld_modification_mtx);
- mongoc_topology_description_destroy (mod.new_td);
-}
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-trace-private.h b/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-trace-private.h
deleted file mode 100644
index 6774b934..00000000
--- a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-trace-private.h
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright 2013 MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "mongoc-prelude.h"
-
-
-#ifndef MONGOC_TRACE_PRIVATE_H
-#define MONGOC_TRACE_PRIVATE_H
-
-
-#include <bson/bson.h>
-#include <ctype.h>
-
-#include "mongoc-log.h"
-#include "mongoc-log-private.h"
-
-
-BSON_BEGIN_DECLS
-
-
-#ifdef MONGOC_TRACE
-#define TRACE(msg, ...) \
- do { \
- mongoc_log (MONGOC_LOG_LEVEL_TRACE, \
- MONGOC_LOG_DOMAIN, \
- "TRACE: %s():%d " msg, \
- BSON_FUNC, \
- __LINE__, \
- __VA_ARGS__); \
- } while (0)
-#define ENTRY \
- do { \
- mongoc_log (MONGOC_LOG_LEVEL_TRACE, \
- MONGOC_LOG_DOMAIN, \
- "ENTRY: %s():%d", \
- BSON_FUNC, \
- __LINE__); \
- } while (0)
-#define EXIT \
- do { \
- mongoc_log (MONGOC_LOG_LEVEL_TRACE, \
- MONGOC_LOG_DOMAIN, \
- " EXIT: %s():%d", \
- BSON_FUNC, \
- __LINE__); \
- return; \
- } while (0)
-#define RETURN(ret) \
- do { \
- mongoc_log (MONGOC_LOG_LEVEL_TRACE, \
- MONGOC_LOG_DOMAIN, \
- " EXIT: %s():%d", \
- BSON_FUNC, \
- __LINE__); \
- return ret; \
- } while (0)
-#define GOTO(label) \
- do { \
- mongoc_log (MONGOC_LOG_LEVEL_TRACE, \
- MONGOC_LOG_DOMAIN, \
- " GOTO: %s():%d %s", \
- BSON_FUNC, \
- __LINE__, \
- #label); \
- goto label; \
- } while (0)
-#define DUMP_BYTES(_n, _b, _l) \
- do { \
- mongoc_log (MONGOC_LOG_LEVEL_TRACE, \
- MONGOC_LOG_DOMAIN, \
- "TRACE: %s():%d %s = %p [%d]", \
- BSON_FUNC, \
- __LINE__, \
- #_n, \
- _b, \
- (int) _l); \
- mongoc_log_trace_bytes (MONGOC_LOG_DOMAIN, _b, _l); \
- } while (0)
-#define DUMP_BSON(_bson) \
- do { \
- char *_bson_str; \
- if (_bson) { \
- _bson_str = bson_as_canonical_extended_json (_bson, NULL); \
- } else { \
- _bson_str = bson_strdup ("<NULL>"); \
- } \
- mongoc_log (MONGOC_LOG_LEVEL_TRACE, \
- MONGOC_LOG_DOMAIN, \
- "TRACE: %s():%d %s = %s", \
- BSON_FUNC, \
- __LINE__, \
- #_bson, \
- _bson_str); \
- bson_free (_bson_str); \
- } while (0)
-#define DUMP_IOVEC(_n, _iov, _iovcnt) \
- do { \
- mongoc_log (MONGOC_LOG_LEVEL_TRACE, \
- MONGOC_LOG_DOMAIN, \
- "TRACE: %s():%d %s = %p [%d]", \
- BSON_FUNC, \
- __LINE__, \
- #_n, \
- (void *) _iov, \
- (int) _iovcnt); \
- mongoc_log_trace_iovec (MONGOC_LOG_DOMAIN, _iov, _iovcnt); \
- } while (0)
-#else
-#define TRACE(msg, ...) (void) 0
-#define ENTRY
-#define EXIT return
-#define RETURN(ret) return ret
-#define GOTO(label) goto label
-#define DUMP_BYTES(_n, _b, _l)
-#define DUMP_IOVEC(_n, _iov, _iovcnt)
-#define DUMP_BSON(_bson)
-#endif
-
-
-BSON_END_DECLS
-
-
-#endif /* MONGOC_TRACE_PRIVATE_H */
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-uri-private.h b/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-uri-private.h
deleted file mode 100644
index c75c206f..00000000
--- a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-uri-private.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright 2015 MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "mongoc-prelude.h"
-
-#ifndef MONGOC_URI_PRIVATE_H
-#define MONGOC_URI_PRIVATE_H
-
-#include "mongoc-uri.h"
-#include "mongoc-scram-private.h"
-#include "mongoc-crypto-private.h"
-
-
-BSON_BEGIN_DECLS
-
-
-bool
-mongoc_uri_upsert_host_and_port (mongoc_uri_t *uri,
- const char *host_and_port,
- bson_error_t *error);
-bool
-mongoc_uri_upsert_host (mongoc_uri_t *uri,
- const char *host,
- uint16_t port,
- bson_error_t *error);
-void
-mongoc_uri_remove_host (mongoc_uri_t *uri, const char *host, uint16_t port);
-
-bool
-mongoc_uri_parse_host (mongoc_uri_t *uri, const char *str);
-bool
-mongoc_uri_parse_options (mongoc_uri_t *uri,
- const char *str,
- bool from_dns,
- bson_error_t *error);
-int32_t
-mongoc_uri_get_local_threshold_option (const mongoc_uri_t *uri);
-
-bool
-_mongoc_uri_requires_auth_negotiation (const mongoc_uri_t *uri);
-
-const char *
-mongoc_uri_canonicalize_option (const char *key);
-
-mongoc_uri_t *
-_mongoc_uri_copy_and_replace_host_list (const mongoc_uri_t *original,
- const char *host);
-
-bool
-mongoc_uri_init_with_srv_host_list (mongoc_uri_t *uri,
- mongoc_host_list_t *hosts,
- bson_error_t *error);
-
-bool
-mongoc_uri_validate_srv_result (const mongoc_uri_t *uri,
- const char *host,
- bson_error_t *error);
-
-#ifdef MONGOC_ENABLE_CRYPTO
-void
-_mongoc_uri_init_scram (const mongoc_uri_t *uri,
- mongoc_scram_t *scram,
- mongoc_crypto_hash_algorithm_t algo);
-#endif
-
-/* mongoc_uri_finalize_loadbalanced validates constraints for the loadBalanced
- * URI option.
- * For example, it is invalid to have loadBalanced=true with multiple hosts in
- * the URI.
- * This is expected to be called whenever URI options may change (e.g. parsing a
- * new URI or applying TXT records).
- * Returns false and sets @error on failure.
- * Returns true and does not modify @error on success.
- */
-bool
-mongoc_uri_finalize_loadbalanced (const mongoc_uri_t *uri, bson_error_t *error);
-
-BSON_END_DECLS
-
-
-#endif /* MONGOC_URI_PRIVATE_H */
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-uri.c b/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-uri.c
deleted file mode 100644
index e1d35ed6..00000000
--- a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-uri.c
+++ /dev/null
@@ -1,3149 +0,0 @@
-/*
- * Copyright 2013 MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <math.h>
-
-/* strcasecmp on windows */
-#include "mongoc-util-private.h"
-
-#include "mongoc-config.h"
-#include "mongoc-host-list.h"
-#include "mongoc-host-list-private.h"
-#include "mongoc-log.h"
-#include "mongoc-handshake-private.h"
-#include "mongoc-socket.h"
-#include "mongoc-topology-private.h"
-#include "mongoc-uri-private.h"
-#include "mongoc-read-concern-private.h"
-#include "mongoc-write-concern-private.h"
-#include "mongoc-compression-private.h"
-#include "utlist.h"
-
-struct _mongoc_uri_t {
- char *str;
- bool is_srv;
- char srv[BSON_HOST_NAME_MAX + 1];
- mongoc_host_list_t *hosts;
- char *username;
- char *password;
- char *database;
- bson_t raw; /* Unparsed options, see mongoc_uri_parse_options */
- bson_t options; /* Type-coerced and canonicalized options */
- bson_t credentials;
- bson_t compressors;
- mongoc_read_prefs_t *read_prefs;
- mongoc_read_concern_t *read_concern;
- mongoc_write_concern_t *write_concern;
-};
-
-#define MONGOC_URI_ERROR(error, format, ...) \
- bson_set_error (error, \
- MONGOC_ERROR_COMMAND, \
- MONGOC_ERROR_COMMAND_INVALID_ARG, \
- format, \
- __VA_ARGS__);
-
-
-static const char *escape_instructions = "Percent-encode username and password"
- " according to RFC 3986";
-
-static bool
-_mongoc_uri_set_option_as_int32 (mongoc_uri_t *uri,
- const char *option,
- int32_t value);
-
-static bool
-_mongoc_uri_set_option_as_int32_with_error (mongoc_uri_t *uri,
- const char *option,
- int32_t value,
- bson_error_t *error);
-
-static bool
-_mongoc_uri_set_option_as_int64_with_error (mongoc_uri_t *uri,
- const char *option,
- int64_t value,
- bson_error_t *error);
-
-static bool
-ends_with (const char *str, const char *suffix);
-
-static void
-mongoc_uri_do_unescape (char **str)
-{
- char *tmp;
-
- if ((tmp = *str)) {
- *str = mongoc_uri_unescape (tmp);
- bson_free (tmp);
- }
-}
-
-
-#define VALIDATE_SRV_ERR() \
- do { \
- bson_set_error (error, \
- MONGOC_ERROR_STREAM, \
- MONGOC_ERROR_STREAM_NAME_RESOLUTION, \
- "Invalid host \"%s\" returned for service \"%s\": " \
- "host must be subdomain of service name", \
- host, \
- service); \
- return false; \
- } while (0)
-
-
-static int
-count_dots (const char *s)
-{
- int n = 0;
- const char *dot = s;
-
- while ((dot = strchr (dot + 1, '.'))) {
- n++;
- }
-
- return n;
-}
-
-static char *
-lowercase_str_new (const char *key)
-{
- char *ret = bson_strdup (key);
- mongoc_lowercase (key, ret);
- return ret;
-}
-
-/* at least one character, and does not start with dot */
-static bool
-valid_hostname (const char *s)
-{
- size_t len = strlen (s);
-
- return len > 1 && s[0] != '.';
-}
-
-
-bool
-mongoc_uri_validate_srv_result (const mongoc_uri_t *uri,
- const char *host,
- bson_error_t *error)
-{
- const char *service;
- const char *service_root;
-
- service = mongoc_uri_get_service (uri);
- BSON_ASSERT (service);
-
- if (!valid_hostname (host)) {
- VALIDATE_SRV_ERR ();
- }
-
- service_root = strchr (service, '.');
- BSON_ASSERT (service_root);
-
- /* host must be descendent of service root: if service is
- * "a.foo.co" host can be like "a.foo.co", "b.foo.co", "a.b.foo.co", etc.
- */
- if (strlen (host) < strlen (service_root)) {
- VALIDATE_SRV_ERR ();
- }
-
- if (!ends_with (host, service_root)) {
- VALIDATE_SRV_ERR ();
- }
-
- return true;
-}
-
-/* copy and upsert @host into @uri's host list. */
-static bool
-_upsert_into_host_list (mongoc_uri_t *uri,
- mongoc_host_list_t *host,
- bson_error_t *error)
-{
- if (uri->is_srv &&
- !mongoc_uri_validate_srv_result (uri, host->host, error)) {
- return false;
- }
-
- _mongoc_host_list_upsert (&uri->hosts, host);
-
- return true;
-}
-
-bool
-mongoc_uri_upsert_host_and_port (mongoc_uri_t *uri,
- const char *host_and_port,
- bson_error_t *error)
-{
- mongoc_host_list_t temp;
-
- memset (&temp, 0, sizeof (mongoc_host_list_t));
- if (!_mongoc_host_list_from_string_with_err (&temp, host_and_port, error)) {
- return false;
- }
-
- return _upsert_into_host_list (uri, &temp, error);
-}
-
-bool
-mongoc_uri_upsert_host (mongoc_uri_t *uri,
- const char *host,
- uint16_t port,
- bson_error_t *error)
-{
- mongoc_host_list_t temp;
-
- memset (&temp, 0, sizeof (mongoc_host_list_t));
- if (!_mongoc_host_list_from_hostport_with_err (&temp, host, port, error)) {
- return false;
- }
-
- return _upsert_into_host_list (uri, &temp, error);
-}
-
-void
-mongoc_uri_remove_host (mongoc_uri_t *uri, const char *host, uint16_t port)
-{
- _mongoc_host_list_remove_host (&(uri->hosts), host, port);
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * scan_to_unichar --
- *
- * Scans 'str' until either a character matching 'match' is found,
- * until one of the characters in 'terminators' is encountered, or
- * until we reach the end of 'str'.
- *
- * NOTE: 'terminators' may not include multibyte UTF-8 characters.
- *
- * Returns:
- * If 'match' is found, returns a copy of the section of 'str' before
- * that character. Otherwise, returns NULL.
- *
- * Side Effects:
- * If 'match' is found, sets 'end' to begin at the matching character
- * in 'str'.
- *
- *--------------------------------------------------------------------------
- */
-
-static char *
-scan_to_unichar (const char *str,
- bson_unichar_t match,
- const char *terminators,
- const char **end)
-{
- bson_unichar_t c;
- const char *iter;
-
- for (iter = str; iter && *iter && (c = bson_utf8_get_char (iter));
- iter = bson_utf8_next_char (iter)) {
- if (c == match) {
- *end = iter;
- return bson_strndup (str, iter - str);
- } else if (c == '\\') {
- iter = bson_utf8_next_char (iter);
- if (!bson_utf8_get_char (iter)) {
- break;
- }
- } else {
- const char *term_iter;
- for (term_iter = terminators; *term_iter; term_iter++) {
- if (c == *term_iter) {
- return NULL;
- }
- }
- }
- }
-
- return NULL;
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * ends_with --
- *
- * Return true if str ends with suffix.
- *
- *--------------------------------------------------------------------------
- */
-static bool
-ends_with (const char *str, const char *suffix)
-{
- size_t str_len = strlen (str);
- size_t suffix_len = strlen (suffix);
- const char *s1, *s2;
-
- if (str_len < suffix_len) {
- return false;
- }
-
- /* start at the ends of both strings */
- s1 = str + str_len;
- s2 = suffix + suffix_len;
-
- /* until either pointer reaches start of its string, compare the pointers */
- for (; s1 >= str && s2 >= suffix; s1--, s2--) {
- if (*s1 != *s2) {
- return false;
- }
- }
-
- return true;
-}
-
-
-static bool
-mongoc_uri_parse_scheme (mongoc_uri_t *uri, const char *str, const char **end)
-{
- if (!strncmp (str, "mongodb+srv://", 14)) {
- uri->is_srv = true;
- *end = str + 14;
- return true;
- }
-
- if (!strncmp (str, "mongodb://", 10)) {
- uri->is_srv = false;
- *end = str + 10;
- return true;
- }
-
- return false;
-}
-
-
-static bool
-mongoc_uri_has_unescaped_chars (const char *str, const char *chars)
-{
- const char *c;
- const char *tmp;
- char *s;
-
- for (c = chars; *c; c++) {
- s = scan_to_unichar (str, (bson_unichar_t) *c, "", &tmp);
- if (s) {
- bson_free (s);
- return true;
- }
- }
-
- return false;
-}
-
-
-/* "str" is non-NULL, the part of URI between "mongodb://" and first "@" */
-static bool
-mongoc_uri_parse_userpass (mongoc_uri_t *uri,
- const char *str,
- bson_error_t *error)
-{
- const char *prohibited = "@:/";
- const char *end_user;
-
- BSON_ASSERT (str);
- BSON_ASSERT (uri);
-
- if ((uri->username = scan_to_unichar (str, ':', "", &end_user))) {
- uri->password = bson_strdup (end_user + 1);
- } else {
- uri->username = bson_strdup (str);
- uri->password = NULL;
- }
-
- if (mongoc_uri_has_unescaped_chars (uri->username, prohibited)) {
- MONGOC_URI_ERROR (error,
- "Username \"%s\" must not have unescaped chars. %s",
- uri->username,
- escape_instructions);
- return false;
- }
-
- mongoc_uri_do_unescape (&uri->username);
- if (!uri->username) {
- MONGOC_URI_ERROR (
- error, "Incorrect URI escapes in username. %s", escape_instructions);
- return false;
- }
-
- /* Providing password at all is optional */
- if (uri->password) {
- if (mongoc_uri_has_unescaped_chars (uri->password, prohibited)) {
- MONGOC_URI_ERROR (error,
- "Password \"%s\" must not have unescaped chars. %s",
- uri->password,
- escape_instructions);
- return false;
- }
-
- mongoc_uri_do_unescape (&uri->password);
- if (!uri->password) {
- MONGOC_URI_ERROR (error, "%s", "Incorrect URI escapes in password");
- return false;
- }
- }
-
- return true;
-}
-
-bool
-mongoc_uri_parse_host (mongoc_uri_t *uri, const char *host_and_port_in)
-{
- char *host_and_port = bson_strdup (host_and_port_in);
- bson_error_t err = {0};
- bool r;
-
- /* unescape host. It doesn't hurt including port. */
- if (mongoc_uri_has_unescaped_chars (host_and_port, "/")) {
- MONGOC_WARNING ("Unix Domain Sockets must be escaped (e.g. / = %%2F)");
- bson_free (host_and_port);
- return false;
- }
-
- mongoc_uri_do_unescape (&host_and_port);
- if (!host_and_port) {
- /* invalid */
- bson_free (host_and_port);
- return false;
- }
-
- r = mongoc_uri_upsert_host_and_port (uri, host_and_port, &err);
-
- if (!r) {
- MONGOC_ERROR ("%s", err.message);
- bson_free (host_and_port);
- return false;
- }
-
- bson_free (host_and_port);
- return true;
-}
-
-
-bool
-mongoc_uri_parse_srv (mongoc_uri_t *uri, const char *str)
-{
- char *service;
-
- if (*str == '\0') {
- return false;
- }
-
- service = bson_strdup (str);
- mongoc_uri_do_unescape (&service);
- if (!service) {
- /* invalid */
- return false;
- }
-
- if (!valid_hostname (service) || count_dots (service) < 2) {
- bson_free (service);
- return false;
- }
-
- bson_strncpy (uri->srv, service, sizeof uri->srv);
- bson_free (service);
-
- if (strchr (uri->srv, ',') || strchr (uri->srv, ':')) {
- /* prohibit port number or multiple service names */
- return false;
- }
-
- return true;
-}
-
-
-/* "hosts" is non-NULL, the part between "mongodb://" or "@" and last "/" */
-static bool
-mongoc_uri_parse_hosts (mongoc_uri_t *uri, const char *hosts)
-{
- const char *next;
- const char *end_hostport;
- char *s;
- BSON_ASSERT (hosts);
- /*
- * Parsing the series of hosts is a lot more complicated than you might
- * imagine. This is due to some characters being both separators as well as
- * valid characters within the "hostname". In particularly, we can have file
- * paths to specify paths to UNIX domain sockets. We impose the restriction
- * that they must be suffixed with ".sock" to simplify the parsing.
- *
- * You can separate hosts and file system paths to UNIX domain sockets with
- * ",".
- */
- s = scan_to_unichar (hosts, '?', "", &end_hostport);
- if (s) {
- MONGOC_WARNING (
- "%s", "A '/' is required between the host list and any options.");
- goto error;
- }
- next = hosts;
- do {
- /* makes a copy of the section of the string */
- s = scan_to_unichar (next, ',', "", &end_hostport);
- if (s) {
- next = (char *) end_hostport + 1;
- } else {
- s = bson_strdup (next);
- next = NULL;
- }
- if (!mongoc_uri_parse_host (uri, s)) {
- goto error;
- }
- bson_free (s);
- } while (next);
- return true;
-error:
- bson_free (s);
- return false;
-}
-
-/* -----------------------------------------------------------------------------
- *
- * mongoc_uri_parse_database --
- *
- * Parse the database after @str. @str is expected to point after the
- * host list to the character immediately after the / in the uri string.
- * If no database is specified in the uri, e.g. the uri has a form like:
- * mongodb://localhost/?option=X then uri->database remains NULL after
- * parsing.
- *
- * Return:
- * True if the parsed database is valid. An empty database is considered
- * valid.
- * -----------------------------------------------------------------------------
- */
-static bool
-mongoc_uri_parse_database (mongoc_uri_t *uri, const char *str, const char **end)
-{
- const char *end_database;
- const char *c;
- char *invalid_c;
- const char *tmp;
-
- if ((uri->database = scan_to_unichar (str, '?', "", &end_database))) {
- if (strcmp (uri->database, "") == 0) {
- /* no database is found, don't store the empty string. */
- bson_free (uri->database);
- uri->database = NULL;
- /* but it is valid to have an empty database. */
- return true;
- }
- *end = end_database;
- } else if (*str) {
- uri->database = bson_strdup (str);
- *end = str + strlen (str);
- }
-
- mongoc_uri_do_unescape (&uri->database);
- if (!uri->database) {
- /* invalid */
- return false;
- }
-
- /* invalid characters in database name */
- for (c = "/\\. \"$"; *c; c++) {
- invalid_c =
- scan_to_unichar (uri->database, (bson_unichar_t) *c, "", &tmp);
- if (invalid_c) {
- bson_free (invalid_c);
- return false;
- }
- }
-
- return true;
-}
-
-
-static bool
-mongoc_uri_parse_auth_mechanism_properties (mongoc_uri_t *uri, const char *str)
-{
- char *field;
- char *value;
- const char *end_scan;
- bson_t properties;
-
- bson_init (&properties);
-
- /* build up the properties document */
- while ((field = scan_to_unichar (str, ':', "&", &end_scan))) {
- str = end_scan + 1;
- if (!(value = scan_to_unichar (str, ',', ":&", &end_scan))) {
- value = bson_strdup (str);
- str = "";
- } else {
- str = end_scan + 1;
- }
- bson_append_utf8 (&properties, field, -1, value, -1);
- bson_free (field);
- bson_free (value);
- }
-
- /* append our auth properties to our credentials */
- if (!mongoc_uri_set_mechanism_properties (uri, &properties)) {
- bson_destroy (&properties);
- return false;
- }
- bson_destroy (&properties);
- return true;
-}
-
-static bool
-mongoc_uri_parse_tags (mongoc_uri_t *uri, /* IN */
- const char *str) /* IN */
-{
- const char *end_keyval;
- const char *end_key;
- bson_t b;
- char *keyval;
- char *key;
-
- bson_init (&b);
-
-again:
- if ((keyval = scan_to_unichar (str, ',', "", &end_keyval))) {
- if (!(key = scan_to_unichar (keyval, ':', "", &end_key))) {
- bson_free (keyval);
- goto fail;
- }
-
- bson_append_utf8 (&b, key, -1, end_key + 1, -1);
- bson_free (key);
- bson_free (keyval);
- str = end_keyval + 1;
- goto again;
- } else if ((key = scan_to_unichar (str, ':', "", &end_key))) {
- bson_append_utf8 (&b, key, -1, end_key + 1, -1);
- bson_free (key);
- } else if (strlen (str)) {
- /* we're not finished but we couldn't parse the string */
- goto fail;
- }
-
- mongoc_read_prefs_add_tag (uri->read_prefs, &b);
- bson_destroy (&b);
-
- return true;
-
-fail:
- MONGOC_WARNING ("Unsupported value for \"" MONGOC_URI_READPREFERENCETAGS
- "\": \"%s\"",
- str);
- bson_destroy (&b);
- return false;
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_uri_bson_append_or_replace_key --
- *
- *
- * Appends 'option' to the end of 'options' if not already set.
- *
- * Since we cannot grow utf8 strings inline, we have to allocate a
- * temporary bson variable and splice in the new value if the key
- * is already set.
- *
- * NOTE: This function keeps the order of the BSON keys.
- *
- * NOTE: 'option' is case*in*sensitive.
- *
- *
- *--------------------------------------------------------------------------
- */
-
-static void
-mongoc_uri_bson_append_or_replace_key (bson_t *options,
- const char *option,
- const char *value)
-{
- bson_iter_t iter;
- bool found = false;
-
- if (bson_iter_init (&iter, options)) {
- bson_t tmp = BSON_INITIALIZER;
-
- while (bson_iter_next (&iter)) {
- const bson_value_t *bvalue;
-
- if (!strcasecmp (bson_iter_key (&iter), option)) {
- bson_append_utf8 (&tmp, option, -1, value, -1);
- found = true;
- continue;
- }
-
- bvalue = bson_iter_value (&iter);
- BSON_APPEND_VALUE (&tmp, bson_iter_key (&iter), bvalue);
- }
-
- if (!found) {
- bson_append_utf8 (&tmp, option, -1, value, -1);
- }
-
- bson_destroy (options);
- bson_copy_to (&tmp, options);
- bson_destroy (&tmp);
- }
-}
-
-
-bool
-mongoc_uri_has_option (const mongoc_uri_t *uri, const char *key)
-{
- bson_iter_t iter;
-
- return bson_iter_init_find_case (&iter, &uri->options, key);
-}
-
-bool
-mongoc_uri_option_is_int32 (const char *key)
-{
- return mongoc_uri_option_is_int64 (key) ||
- !strcasecmp (key, MONGOC_URI_CONNECTTIMEOUTMS) ||
- !strcasecmp (key, MONGOC_URI_HEARTBEATFREQUENCYMS) ||
- !strcasecmp (key, MONGOC_URI_SERVERSELECTIONTIMEOUTMS) ||
- !strcasecmp (key, MONGOC_URI_SOCKETCHECKINTERVALMS) ||
- !strcasecmp (key, MONGOC_URI_SOCKETTIMEOUTMS) ||
- !strcasecmp (key, MONGOC_URI_LOCALTHRESHOLDMS) ||
- !strcasecmp (key, MONGOC_URI_MAXPOOLSIZE) ||
- !strcasecmp (key, MONGOC_URI_MAXSTALENESSSECONDS) ||
- !strcasecmp (key, MONGOC_URI_MINPOOLSIZE) ||
- !strcasecmp (key, MONGOC_URI_MAXIDLETIMEMS) ||
- !strcasecmp (key, MONGOC_URI_WAITQUEUEMULTIPLE) ||
- !strcasecmp (key, MONGOC_URI_WAITQUEUETIMEOUTMS) ||
- !strcasecmp (key, MONGOC_URI_ZLIBCOMPRESSIONLEVEL);
-}
-
-bool
-mongoc_uri_option_is_int64 (const char *key)
-{
- return !strcasecmp (key, MONGOC_URI_WTIMEOUTMS);
-}
-
-bool
-mongoc_uri_option_is_bool (const char *key)
-{
- return !strcasecmp (key, MONGOC_URI_CANONICALIZEHOSTNAME) ||
- !strcasecmp (key, MONGOC_URI_DIRECTCONNECTION) ||
- !strcasecmp (key, MONGOC_URI_JOURNAL) ||
- !strcasecmp (key, MONGOC_URI_RETRYREADS) ||
- !strcasecmp (key, MONGOC_URI_RETRYWRITES) ||
- !strcasecmp (key, MONGOC_URI_SAFE) ||
- !strcasecmp (key, MONGOC_URI_SERVERSELECTIONTRYONCE) ||
- !strcasecmp (key, MONGOC_URI_TLS) ||
- !strcasecmp (key, MONGOC_URI_TLSINSECURE) ||
- !strcasecmp (key, MONGOC_URI_TLSALLOWINVALIDCERTIFICATES) ||
- !strcasecmp (key, MONGOC_URI_TLSALLOWINVALIDHOSTNAMES) ||
- !strcasecmp (key, MONGOC_URI_TLSDISABLECERTIFICATEREVOCATIONCHECK) ||
- !strcasecmp (key, MONGOC_URI_TLSDISABLEOCSPENDPOINTCHECK) ||
- !strcasecmp (key, MONGOC_URI_LOADBALANCED) ||
- /* deprecated options */
- !strcasecmp (key, MONGOC_URI_SSL) ||
- !strcasecmp (key, MONGOC_URI_SSLALLOWINVALIDCERTIFICATES) ||
- !strcasecmp (key, MONGOC_URI_SSLALLOWINVALIDHOSTNAMES);
-}
-
-bool
-mongoc_uri_option_is_utf8 (const char *key)
-{
- return !strcasecmp (key, MONGOC_URI_APPNAME) ||
- !strcasecmp (key, MONGOC_URI_REPLICASET) ||
- !strcasecmp (key, MONGOC_URI_READPREFERENCE) ||
- !strcasecmp (key, MONGOC_URI_TLSCERTIFICATEKEYFILE) ||
- !strcasecmp (key, MONGOC_URI_TLSCERTIFICATEKEYFILEPASSWORD) ||
- !strcasecmp (key, MONGOC_URI_TLSCAFILE) ||
- /* deprecated options */
- !strcasecmp (key, MONGOC_URI_SSLCLIENTCERTIFICATEKEYFILE) ||
- !strcasecmp (key, MONGOC_URI_SSLCLIENTCERTIFICATEKEYPASSWORD) ||
- !strcasecmp (key, MONGOC_URI_SSLCERTIFICATEAUTHORITYFILE);
-}
-
-const char *
-mongoc_uri_canonicalize_option (const char *key)
-{
- if (!strcasecmp (key, MONGOC_URI_SSL)) {
- return MONGOC_URI_TLS;
- } else if (!strcasecmp (key, MONGOC_URI_SSLCLIENTCERTIFICATEKEYFILE)) {
- return MONGOC_URI_TLSCERTIFICATEKEYFILE;
- } else if (!strcasecmp (key, MONGOC_URI_SSLCLIENTCERTIFICATEKEYPASSWORD)) {
- return MONGOC_URI_TLSCERTIFICATEKEYFILEPASSWORD;
- } else if (!strcasecmp (key, MONGOC_URI_SSLCERTIFICATEAUTHORITYFILE)) {
- return MONGOC_URI_TLSCAFILE;
- } else if (!strcasecmp (key, MONGOC_URI_SSLALLOWINVALIDCERTIFICATES)) {
- return MONGOC_URI_TLSALLOWINVALIDCERTIFICATES;
- } else if (!strcasecmp (key, MONGOC_URI_SSLALLOWINVALIDHOSTNAMES)) {
- return MONGOC_URI_TLSALLOWINVALIDHOSTNAMES;
- } else {
- return key;
- }
-}
-
-static bool
-_mongoc_uri_parse_int64 (const char *key, const char *value, int64_t *result)
-{
- char *endptr;
- int64_t i;
-
- errno = 0;
- i = bson_ascii_strtoll (value, &endptr, 10);
- if (errno || endptr < value + strlen (value)) {
- MONGOC_WARNING ("Invalid %s: cannot parse integer\n", key);
- return false;
- }
-
- *result = i;
- return true;
-}
-
-
-static bool
-mongoc_uri_parse_int32 (const char *key, const char *value, int32_t *result)
-{
- int64_t i;
-
- if (!_mongoc_uri_parse_int64 (key, value, &i)) {
- /* _mongoc_uri_parse_int64 emits a warning if it could not parse the
- * given value, so we don't have to add one here.
- */
- return false;
- }
-
- if (i > INT32_MAX || i < INT32_MIN) {
- MONGOC_WARNING ("Invalid %s: cannot fit in int32\n", key);
- return false;
- }
-
- *result = (int32_t) i;
- return true;
-}
-
-
-static bool
-dns_option_allowed (const char *lkey)
-{
- /* Initial DNS Seedlist Discovery Spec: "A Client MUST only support the
- * authSource, replicaSet, and loadBalanced options through a TXT record, and
- * MUST raise an error if any other option is encountered."
- */
- return !strcmp (lkey, MONGOC_URI_AUTHSOURCE) ||
- !strcmp (lkey, MONGOC_URI_REPLICASET) ||
- !strcmp (lkey, MONGOC_URI_LOADBALANCED);
-}
-
-
-/* Decompose a key=val pair and place them into a document.
- * Includes case-folding for key portion.
- */
-static bool
-mongoc_uri_split_option (mongoc_uri_t *uri,
- bson_t *options,
- const char *str,
- bool from_dns,
- bson_error_t *error)
-{
- bson_iter_t iter;
- const char *end_key;
- char *key = NULL;
- char *lkey = NULL;
- char *value = NULL;
- const char *opt;
- char *opt_end;
- size_t opt_len;
- bool ret = false;
-
- if (!(key = scan_to_unichar (str, '=', "", &end_key))) {
- MONGOC_URI_ERROR (error, "URI option \"%s\" contains no \"=\" sign", str);
- goto CLEANUP;
- }
-
- value = bson_strdup (end_key + 1);
- mongoc_uri_do_unescape (&value);
- if (!value) {
- /* do_unescape detected invalid UTF-8 and freed value */
- MONGOC_URI_ERROR (
- error, "Value for URI option \"%s\" contains invalid UTF-8", key);
- goto CLEANUP;
- }
-
- lkey = bson_strdup (key);
- mongoc_lowercase (key, lkey);
-
- /* Initial DNS Seedlist Discovery Spec: "A Client MUST only support the
- * authSource, replicaSet, and loadBalanced options through a TXT record, and
- * MUST raise an error if any other option is encountered."*/
- if (from_dns && !dns_option_allowed (lkey)) {
- MONGOC_URI_ERROR (
- error, "URI option \"%s\" prohibited in TXT record", key);
- goto CLEANUP;
- }
-
- /* Special case: READPREFERENCETAGS is a composing option.
- * Multiple instances should append, not overwrite.
- * Encode them directly to the options field,
- * bypassing canonicalization and duplicate checks.
- */
- if (!strcmp (lkey, MONGOC_URI_READPREFERENCETAGS)) {
- if (!mongoc_uri_parse_tags (uri, value)) {
- MONGOC_URI_ERROR (
- error, "Unsupported value for \"%s\": \"%s\"", key, value);
- goto CLEANUP;
- }
- } else if (bson_iter_init_find (&iter, &uri->raw, lkey) ||
- bson_iter_init_find (&iter, options, lkey)) {
- /* Special case, MONGOC_URI_W == "any non-int" is not overridden
- * by later values.
- */
- if (!strcmp (lkey, MONGOC_URI_W) &&
- (opt = bson_iter_utf8_unsafe (&iter, &opt_len))) {
- strtol (opt, &opt_end, 10);
- if (*opt_end != '\0') {
- ret = true;
- goto CLEANUP;
- }
- }
-
- /* Initial DNS Seedlist Discovery Spec: "Client MUST use options
- * specified in the Connection String to override options provided
- * through TXT records." So, do NOT override existing options with TXT
- * options. */
- if (from_dns) {
- MONGOC_WARNING (
- "Cannot override URI option \"%s\" from TXT record \"%s\"",
- key,
- str);
- ret = true;
- goto CLEANUP;
- }
- MONGOC_WARNING ("Overwriting previously provided value for '%s'", key);
- }
-
- if (!(strcmp (lkey, MONGOC_URI_REPLICASET)) && *value == '\0') {
- MONGOC_URI_ERROR (
- error, "Value for URI option \"%s\" cannot be empty string", lkey);
- goto CLEANUP;
- }
-
- mongoc_uri_bson_append_or_replace_key (options, lkey, value);
- ret = true;
-
-CLEANUP:
- bson_free (key);
- bson_free (lkey);
- bson_free (value);
-
- return ret;
-}
-
-
-/* Check for canonical/deprecated conflicts
- * between the option list a, and b.
- * If both names exist either way with differing values, error.
- */
-static bool
-mongoc_uri_options_validate_names (const bson_t *a,
- const bson_t *b,
- bson_error_t *error)
-{
- bson_iter_t key_iter, canon_iter;
- const char *key = NULL;
- const char *canon = NULL;
- const char *value = NULL;
- const char *cval = NULL;
- size_t value_len = 0;
- size_t cval_len = 0;
-
- /* Scan `a` looking for deprecated names
- * where the canonical name was also used in `a`,
- * or was used in `b`. */
- bson_iter_init (&key_iter, a);
- while (bson_iter_next (&key_iter)) {
- key = bson_iter_key (&key_iter);
- value = bson_iter_utf8_unsafe (&key_iter, &value_len);
- canon = mongoc_uri_canonicalize_option (key);
-
- if (key == canon) {
- /* Canonical form, no point checking `b`. */
- continue;
- }
-
- /* Check for a conflict in `a`. */
- if (bson_iter_init_find (&canon_iter, a, canon)) {
- cval = bson_iter_utf8_unsafe (&canon_iter, &cval_len);
- if ((value_len != cval_len) || strcmp (value, cval)) {
- goto HANDLE_CONFLICT;
- }
- }
-
- /* Check for a conflict in `b`. */
- if (bson_iter_init_find (&canon_iter, b, canon)) {
- cval = bson_iter_utf8_unsafe (&canon_iter, &cval_len);
- if ((value_len != cval_len) || strcmp (value, cval)) {
- goto HANDLE_CONFLICT;
- }
- }
- }
-
- return true;
-
-HANDLE_CONFLICT:
- MONGOC_URI_ERROR (error,
- "Deprecated option '%s=%s' conflicts with "
- "canonical name '%s=%s'",
- key,
- value,
- canon,
- cval);
-
- return false;
-}
-
-
-#define HANDLE_DUPE() \
- if (from_dns) { \
- MONGOC_WARNING ("Cannot override URI option \"%s\" from TXT record", \
- key); \
- continue; \
- } else { \
- MONGOC_WARNING ("Overwriting previously provided value for '%s'", key); \
- }
-
-static bool
-mongoc_uri_apply_options (mongoc_uri_t *uri,
- const bson_t *options,
- bool from_dns,
- bson_error_t *error)
-{
- bson_iter_t iter;
- int32_t v_int;
- int64_t v_int64;
- const char *key = NULL;
- const char *canon = NULL;
- const char *value = NULL;
- size_t value_len;
- bool bval;
-
- bson_iter_init (&iter, options);
- while (bson_iter_next (&iter)) {
- key = bson_iter_key (&iter);
- canon = mongoc_uri_canonicalize_option (key);
- value = bson_iter_utf8_unsafe (&iter, &value_len);
-
- /* Keep a record of how the option was originally presented. */
- mongoc_uri_bson_append_or_replace_key (&uri->raw, key, value);
-
- /* This check precedes mongoc_uri_option_is_int32 as all 64-bit values are
- * also recognised as 32-bit ints.
- */
- if (mongoc_uri_option_is_int64 (key)) {
- if (0 < strlen (value)) {
- if (!_mongoc_uri_parse_int64 (key, value, &v_int64)) {
- goto UNSUPPORTED_VALUE;
- }
-
- if (!_mongoc_uri_set_option_as_int64_with_error (
- uri, canon, v_int64, error)) {
- return false;
- }
- } else {
- MONGOC_WARNING ("Empty value provided for \"%s\"", key);
- }
- } else if (mongoc_uri_option_is_int32 (key)) {
- if (0 < strlen (value)) {
- if (!mongoc_uri_parse_int32 (key, value, &v_int)) {
- goto UNSUPPORTED_VALUE;
- }
-
- if (!_mongoc_uri_set_option_as_int32_with_error (
- uri, canon, v_int, error)) {
- return false;
- }
- } else {
- MONGOC_WARNING ("Empty value provided for \"%s\"", key);
- }
- } else if (!strcmp (key, MONGOC_URI_W)) {
- if (*value == '-' || isdigit (*value)) {
- v_int = (int) strtol (value, NULL, 10);
- _mongoc_uri_set_option_as_int32 (uri, MONGOC_URI_W, v_int);
- } else if (0 == strcasecmp (value, "majority")) {
- mongoc_uri_bson_append_or_replace_key (
- &uri->options, MONGOC_URI_W, "majority");
- } else if (*value) {
- mongoc_uri_bson_append_or_replace_key (
- &uri->options, MONGOC_URI_W, value);
- }
-
- } else if (mongoc_uri_option_is_bool (key)) {
- if (0 < strlen (value)) {
- if (0 == strcasecmp (value, "true")) {
- bval = true;
- } else if (0 == strcasecmp (value, "false")) {
- bval = false;
- } else if ((0 == strcmp (value, "1")) ||
- (0 == strcasecmp (value, "yes")) ||
- (0 == strcasecmp (value, "y")) ||
- (0 == strcasecmp (value, "t"))) {
- MONGOC_WARNING ("Deprecated boolean value for \"%s\": \"%s\", "
- "please update to \"%s=true\"",
- key,
- value,
- key);
- bval = true;
- } else if ((0 == strcasecmp (value, "0")) ||
- (0 == strcasecmp (value, "-1")) ||
- (0 == strcmp (value, "no")) ||
- (0 == strcmp (value, "n")) ||
- (0 == strcmp (value, "f"))) {
- MONGOC_WARNING ("Deprecated boolean value for \"%s\": \"%s\", "
- "please update to \"%s=false\"",
- key,
- value,
- key);
- bval = false;
- } else {
- goto UNSUPPORTED_VALUE;
- }
-
- if (!mongoc_uri_set_option_as_bool (uri, canon, bval)) {
- bson_set_error (error,
- MONGOC_ERROR_COMMAND,
- MONGOC_ERROR_COMMAND_INVALID_ARG,
- "Failed to set %s to %d",
- canon, bval);
- return false;
- }
- } else {
- MONGOC_WARNING ("Empty value provided for \"%s\"", key);
- }
-
- } else if (!strcmp (key, MONGOC_URI_READPREFERENCETAGS)) {
- /* Skip this option here.
- * It was marshalled during mongoc_uri_split_option()
- * as a special case composing option.
- */
-
- } else if (!strcmp (key, MONGOC_URI_AUTHMECHANISM) ||
- !strcmp (key, MONGOC_URI_AUTHSOURCE)) {
- if (bson_has_field (&uri->credentials, key)) {
- HANDLE_DUPE ();
- }
- mongoc_uri_bson_append_or_replace_key (
- &uri->credentials, canon, value);
-
- } else if (!strcmp (key, MONGOC_URI_READCONCERNLEVEL)) {
- if (!mongoc_read_concern_is_default (uri->read_concern)) {
- HANDLE_DUPE ();
- }
- mongoc_read_concern_set_level (uri->read_concern, value);
-
- } else if (!strcmp (key, MONGOC_URI_GSSAPISERVICENAME)) {
- char *tmp = bson_strdup_printf ("SERVICE_NAME:%s", value);
- if (bson_has_field (&uri->credentials,
- MONGOC_URI_AUTHMECHANISMPROPERTIES)) {
- MONGOC_WARNING ("authMechanismProperties SERVICE_NAME already set, "
- "ignoring '%s'",
- key);
- } else if (!mongoc_uri_parse_auth_mechanism_properties (uri, tmp)) {
- bson_free (tmp);
- goto UNSUPPORTED_VALUE;
- }
- bson_free (tmp);
-
- } else if (!strcmp (key, MONGOC_URI_AUTHMECHANISMPROPERTIES)) {
- if (bson_has_field (&uri->credentials, key)) {
- HANDLE_DUPE ();
- }
- if (!mongoc_uri_parse_auth_mechanism_properties (uri, value)) {
- goto UNSUPPORTED_VALUE;
- }
-
- } else if (!strcmp (key, MONGOC_URI_APPNAME)) {
- /* Part of uri->options */
- if (!mongoc_uri_set_appname (uri, value)) {
- goto UNSUPPORTED_VALUE;
- }
-
- } else if (!strcmp (key, MONGOC_URI_COMPRESSORS)) {
- if (!bson_empty (mongoc_uri_get_compressors (uri))) {
- HANDLE_DUPE ();
- }
- if (!mongoc_uri_set_compressors (uri, value)) {
- goto UNSUPPORTED_VALUE;
- }
-
- } else if (mongoc_uri_option_is_utf8 (key)) {
- mongoc_uri_bson_append_or_replace_key (&uri->options, canon, value);
-
- } else {
- /*
- * Keys that aren't supported by a driver MUST be ignored.
- *
- * A WARN level logging message MUST be issued
- * https://github.com/mongodb/specifications/blob/master/source/connection-string/connection-string-spec.rst#keys
- */
- MONGOC_WARNING ("Unsupported URI option \"%s\"", key);
- }
- }
-
- return true;
-
-UNSUPPORTED_VALUE:
- MONGOC_URI_ERROR (error, "Unsupported value for \"%s\": \"%s\"", key, value);
-
- return false;
-}
-
-
-/* Processes a query string formatted set of driver options
- * (i.e. tls=true&connectTimeoutMS=250 ) into a BSON dict of values.
- * uri->raw is initially populated with the raw split of key/value pairs,
- * then the keys are canonicalized and the values coerced
- * to their appropriate type and stored in uri->options.
- */
-bool
-mongoc_uri_parse_options (mongoc_uri_t *uri,
- const char *str,
- bool from_dns,
- bson_error_t *error)
-{
- bson_t options;
- const char *end_option;
- char *option;
-
- bson_init (&options);
- while ((option = scan_to_unichar (str, '&', "", &end_option))) {
- if (!mongoc_uri_split_option (uri, &options, option, from_dns, error)) {
- bson_free (option);
- bson_destroy (&options);
- return false;
- }
- bson_free (option);
- str = end_option + 1;
- }
-
- if (*str && !mongoc_uri_split_option (uri, &options, str, from_dns, error)) {
- bson_destroy (&options);
- return false;
- }
-
- /* Walk both sides of this map to handle each ordering:
- * deprecated first canonical later, and vice-versa.
- * Then finalize parse by writing final values to uri->options.
- */
- if (!mongoc_uri_options_validate_names (&uri->options, &options, error) ||
- !mongoc_uri_options_validate_names (&options, &uri->options, error) ||
- !mongoc_uri_apply_options (uri, &options, from_dns, error)) {
- bson_destroy (&options);
- return false;
- }
-
- bson_destroy (&options);
- return true;
-}
-
-
-static bool
-mongoc_uri_finalize_tls (mongoc_uri_t *uri, bson_error_t *error)
-{
- /* Initial DNS Seedlist Discovery Spec: "If mongodb+srv is used, a driver
- * MUST implicitly also enable TLS." */
- if (uri->is_srv && !bson_has_field (&uri->options, MONGOC_URI_TLS)) {
- mongoc_uri_set_option_as_bool (uri, MONGOC_URI_TLS, true);
- }
-
- /* tlsInsecure implies tlsAllowInvalidCertificates, tlsAllowInvalidHostnames,
- * tlsDisableOCSPEndpointCheck, and tlsDisableCertificateRevocationCheck, so
- * consider it an error to have both. The user might have the wrong idea. */
- if (bson_has_field (&uri->options, MONGOC_URI_TLSINSECURE) &&
- (bson_has_field (&uri->options,
- MONGOC_URI_TLSALLOWINVALIDCERTIFICATES) ||
- bson_has_field (&uri->options, MONGOC_URI_TLSALLOWINVALIDHOSTNAMES) ||
- bson_has_field (&uri->options,
- MONGOC_URI_TLSDISABLEOCSPENDPOINTCHECK) ||
- bson_has_field (&uri->options,
- MONGOC_URI_TLSDISABLECERTIFICATEREVOCATIONCHECK))) {
- MONGOC_URI_ERROR (error,
- "%s may not be specified with %s, %s, %s, or %s",
- MONGOC_URI_TLSINSECURE,
- MONGOC_URI_TLSALLOWINVALIDCERTIFICATES,
- MONGOC_URI_TLSALLOWINVALIDHOSTNAMES,
- MONGOC_URI_TLSDISABLEOCSPENDPOINTCHECK,
- MONGOC_URI_TLSDISABLECERTIFICATEREVOCATIONCHECK);
- return false;
- }
-
- /* tlsAllowInvalidCertificates implies tlsDisableOCSPEndpointCheck and
- * tlsDisableCertificateRevocationCheck, so consider it an error to have
- * both. The user might have the wrong idea. */
- if (bson_has_field (&uri->options, MONGOC_URI_TLSALLOWINVALIDCERTIFICATES) &&
- (bson_has_field (&uri->options,
- MONGOC_URI_TLSDISABLECERTIFICATEREVOCATIONCHECK) ||
- bson_has_field (&uri->options,
- MONGOC_URI_TLSDISABLEOCSPENDPOINTCHECK))) {
- MONGOC_URI_ERROR (error,
- "%s may not be specified with %s or %s",
- MONGOC_URI_TLSALLOWINVALIDCERTIFICATES,
- MONGOC_URI_TLSDISABLEOCSPENDPOINTCHECK,
- MONGOC_URI_TLSDISABLECERTIFICATEREVOCATIONCHECK);
- return false;
- }
-
- /* tlsDisableCertificateRevocationCheck implies tlsDisableOCSPEndpointCheck,
- * so consider it an error to have both. The user might have the wrong idea.
- */
- if (bson_has_field (&uri->options,
- MONGOC_URI_TLSDISABLECERTIFICATEREVOCATIONCHECK) &&
- bson_has_field (&uri->options, MONGOC_URI_TLSDISABLEOCSPENDPOINTCHECK)) {
- MONGOC_URI_ERROR (error,
- "%s may not be specified with %s",
- MONGOC_URI_TLSDISABLECERTIFICATEREVOCATIONCHECK,
- MONGOC_URI_TLSDISABLEOCSPENDPOINTCHECK);
- return false;
- }
-
- return true;
-}
-
-
-static bool
-mongoc_uri_finalize_auth (mongoc_uri_t *uri,
- bson_error_t *error,
- bool require_auth)
-{
- bson_iter_t iter;
- const char *source = NULL;
-
- if (bson_iter_init_find_case (
- &iter, &uri->credentials, MONGOC_URI_AUTHSOURCE)) {
- source = bson_iter_utf8 (&iter, NULL);
- }
-
- if (mongoc_uri_get_auth_mechanism (uri)) {
- /* authSource with GSSAPI or X509 should always be external */
- if (!strcasecmp (mongoc_uri_get_auth_mechanism (uri), "GSSAPI") ||
- !strcasecmp (mongoc_uri_get_auth_mechanism (uri), "MONGODB-X509")) {
- if (source) {
- if (strcasecmp (source, "$external")) {
- MONGOC_URI_ERROR (
- error,
- "%s",
- "GSSAPI and X509 require \"$external\" authSource");
- return false;
- }
- } else {
- bson_append_utf8 (
- &uri->credentials, MONGOC_URI_AUTHSOURCE, -1, "$external", -1);
- }
- }
- /* MONGODB-X509 and MONGODB-AWS are the only mechanisms that don't require
- * username */
- if (!(strcasecmp (mongoc_uri_get_auth_mechanism (uri), "MONGODB-X509") ==
- 0 ||
- strcasecmp (mongoc_uri_get_auth_mechanism (uri), "MONGODB-AWS") ==
- 0)) {
- if (!mongoc_uri_get_username (uri) ||
- strcmp (mongoc_uri_get_username (uri), "") == 0) {
- MONGOC_URI_ERROR (error,
- "'%s' authentication mechanism requires username",
- mongoc_uri_get_auth_mechanism (uri));
- return false;
- }
- }
- /* MONGODB-X509 errors if a password is supplied. */
- if (strcasecmp (mongoc_uri_get_auth_mechanism (uri), "MONGODB-X509") ==
- 0) {
- if (mongoc_uri_get_password (uri)) {
- MONGOC_URI_ERROR (
- error,
- "'%s' authentication mechanism does not accept a password",
- mongoc_uri_get_auth_mechanism (uri));
- return false;
- }
- }
- /* GSSAPI uses 'mongodb' as the default service name */
- if (strcasecmp (mongoc_uri_get_auth_mechanism (uri), "GSSAPI") == 0 &&
- !(bson_iter_init_find (
- &iter, &uri->credentials, MONGOC_URI_AUTHMECHANISMPROPERTIES) &&
- BSON_ITER_HOLDS_DOCUMENT (&iter) &&
- bson_iter_recurse (&iter, &iter) &&
- bson_iter_find_case (&iter, "SERVICE_NAME"))) {
- bson_t tmp;
- bson_t *props = NULL;
-
- props = mongoc_uri_get_mechanism_properties (uri, &tmp)
- ? bson_copy (&tmp)
- : bson_new ();
-
- BSON_APPEND_UTF8 (props, "SERVICE_NAME", "mongodb");
- mongoc_uri_set_mechanism_properties (uri, props);
-
- bson_destroy (props);
- }
-
- } else if (require_auth) /* Default auth mechanism is used */ {
- if (!mongoc_uri_get_username (uri) ||
- strcmp (mongoc_uri_get_username (uri), "") == 0) {
- MONGOC_URI_ERROR (
- error, "%s", "Default authentication mechanism requires username");
- return false;
- }
- }
- return true;
-}
-
-static bool
-mongoc_uri_finalize_directconnection (mongoc_uri_t *uri, bson_error_t *error)
-{
- bool directconnection = false;
-
- directconnection =
- mongoc_uri_get_option_as_bool (uri, MONGOC_URI_DIRECTCONNECTION, false);
- if (!directconnection) {
- return true;
- }
-
- /* URI options spec: "The driver MUST report an error if the
- * directConnection=true URI option is specified with an SRV URI, because
- * the URI may resolve to multiple hosts. The driver MUST allow specifying
- * directConnection=false URI option with an SRV URI." */
- if (uri->is_srv) {
- MONGOC_URI_ERROR (
- error, "%s", "SRV URI not allowed with directConnection option");
- return false;
- }
-
- /* URI options spec: "The driver MUST report an error if the
- * directConnection=true URI option is specified with multiple seeds." */
- if (uri->hosts && uri->hosts->next) {
- MONGOC_URI_ERROR (
- error,
- "%s",
- "Multiple seeds not allowed with directConnection option");
- return false;
- }
-
- return true;
-}
-
-static bool
-mongoc_uri_parse_before_slash (mongoc_uri_t *uri,
- const char *before_slash,
- bson_error_t *error)
-{
- char *userpass;
- const char *hosts;
-
- userpass = scan_to_unichar (before_slash, '@', "", &hosts);
- if (userpass) {
- if (!mongoc_uri_parse_userpass (uri, userpass, error)) {
- goto error;
- }
-
- hosts++; /* advance past "@" */
- if (*hosts == '@') {
- /* special case: "mongodb://alice@@localhost" */
- MONGOC_URI_ERROR (
- error, "Invalid username or password. %s", escape_instructions);
- goto error;
- }
- } else {
- hosts = before_slash;
- }
-
- if (uri->is_srv) {
- if (!mongoc_uri_parse_srv (uri, hosts)) {
- MONGOC_URI_ERROR (error, "%s", "Invalid service name in URI");
- goto error;
- }
- } else {
- if (!mongoc_uri_parse_hosts (uri, hosts)) {
- MONGOC_URI_ERROR (error, "%s", "Invalid host string in URI");
- goto error;
- }
- }
-
- bson_free (userpass);
- return true;
-
-error:
- bson_free (userpass);
- return false;
-}
-
-
-static bool
-mongoc_uri_parse (mongoc_uri_t *uri, const char *str, bson_error_t *error)
-{
- char *before_slash = NULL;
- const char *tmp;
- bool require_auth = false;
-
- if (!bson_utf8_validate (str, strlen (str), false /* allow_null */)) {
- MONGOC_URI_ERROR (error, "%s", "Invalid UTF-8 in URI");
- goto error;
- }
-
- if (!mongoc_uri_parse_scheme (uri, str, &str)) {
- MONGOC_URI_ERROR (
- error,
- "%s",
- "Invalid URI Schema, expecting 'mongodb://' or 'mongodb+srv://'");
- goto error;
- }
-
- before_slash = scan_to_unichar (str, '/', "", &tmp);
- if (!before_slash) {
- before_slash = bson_strdup (str);
- str += strlen (before_slash);
- } else {
- str = tmp;
- }
-
- if (!mongoc_uri_parse_before_slash (uri, before_slash, error)) {
- goto error;
- }
-
- if (*str) {
- if (*str == '/') {
- str++;
- if (*str) {
- if (!mongoc_uri_parse_database (uri, str, &str)) {
- MONGOC_URI_ERROR (error, "%s", "Invalid database name in URI");
- goto error;
- }
- }
-
- if (*str == '?') {
- str++;
- if (*str) {
- if (!mongoc_uri_parse_options (
- uri, str, false /* from DNS */, error)) {
- goto error;
- }
- }
- }
- } else {
- MONGOC_URI_ERROR (error, "%s", "Expected end of hostname delimiter");
- goto error;
- }
- }
-
- /* TODO (CDRIVER-3723) Consider moving all "finalize" calls into one function
- * that is additionally called after initial SRV and TXT records are applied
- * in mongoc_topology_new. */
- if (!mongoc_uri_finalize_tls (uri, error)) {
- goto error;
- }
-
- require_auth = uri->username != NULL;
- if (!mongoc_uri_finalize_auth (uri, error, require_auth)) {
- goto error;
- }
-
- if (!mongoc_uri_finalize_directconnection (uri, error)) {
- goto error;
- }
-
- if (!mongoc_uri_finalize_loadbalanced (uri, error)) {
- goto error;
- }
-
- bson_free (before_slash);
- return true;
-
-error:
- bson_free (before_slash);
- return false;
-}
-
-
-const mongoc_host_list_t *
-mongoc_uri_get_hosts (const mongoc_uri_t *uri)
-{
- BSON_ASSERT (uri);
- return uri->hosts;
-}
-
-
-const char *
-mongoc_uri_get_replica_set (const mongoc_uri_t *uri)
-{
- bson_iter_t iter;
-
- BSON_ASSERT (uri);
-
- if (bson_iter_init_find_case (&iter, &uri->options, MONGOC_URI_REPLICASET) &&
- BSON_ITER_HOLDS_UTF8 (&iter)) {
- return bson_iter_utf8 (&iter, NULL);
- }
-
- return NULL;
-}
-
-
-const bson_t *
-mongoc_uri_get_credentials (const mongoc_uri_t *uri)
-{
- BSON_ASSERT (uri);
- return &uri->credentials;
-}
-
-
-const char *
-mongoc_uri_get_auth_mechanism (const mongoc_uri_t *uri)
-{
- bson_iter_t iter;
-
- BSON_ASSERT (uri);
-
- if (bson_iter_init_find_case (
- &iter, &uri->credentials, MONGOC_URI_AUTHMECHANISM) &&
- BSON_ITER_HOLDS_UTF8 (&iter)) {
- return bson_iter_utf8 (&iter, NULL);
- }
-
- return NULL;
-}
-
-
-bool
-mongoc_uri_set_auth_mechanism (mongoc_uri_t *uri, const char *value)
-{
- size_t len;
-
- BSON_ASSERT (value);
-
- len = strlen (value);
-
- if (!bson_utf8_validate (value, len, false)) {
- return false;
- }
-
- mongoc_uri_bson_append_or_replace_key (
- &uri->credentials, MONGOC_URI_AUTHMECHANISM, value);
-
- return true;
-}
-
-
-bool
-mongoc_uri_get_mechanism_properties (const mongoc_uri_t *uri,
- bson_t *properties /* OUT */)
-{
- bson_iter_t iter;
-
- BSON_ASSERT (uri);
- BSON_ASSERT (properties);
-
- if (bson_iter_init_find_case (
- &iter, &uri->credentials, MONGOC_URI_AUTHMECHANISMPROPERTIES) &&
- BSON_ITER_HOLDS_DOCUMENT (&iter)) {
- uint32_t len = 0;
- const uint8_t *data = NULL;
-
- bson_iter_document (&iter, &len, &data);
- BSON_ASSERT (bson_init_static (properties, data, len));
-
- return true;
- }
-
- return false;
-}
-
-
-bool
-mongoc_uri_set_mechanism_properties (mongoc_uri_t *uri,
- const bson_t *properties)
-{
- bson_iter_t iter;
- bson_t tmp = BSON_INITIALIZER;
- bool r;
-
- BSON_ASSERT (uri);
- BSON_ASSERT (properties);
-
- if (bson_iter_init_find (
- &iter, &uri->credentials, MONGOC_URI_AUTHMECHANISMPROPERTIES)) {
- /* copy all elements to tmp besides authMechanismProperties */
- bson_copy_to_excluding_noinit (&uri->credentials,
- &tmp,
- MONGOC_URI_AUTHMECHANISMPROPERTIES,
- (char *) NULL);
-
- r = BSON_APPEND_DOCUMENT (
- &tmp, MONGOC_URI_AUTHMECHANISMPROPERTIES, properties);
- if (!r) {
- bson_destroy (&tmp);
- return false;
- }
-
- bson_destroy (&uri->credentials);
- bson_copy_to (&tmp, &uri->credentials);
- bson_destroy (&tmp);
-
- return true;
- } else {
- bson_destroy (&tmp);
- return BSON_APPEND_DOCUMENT (
- &uri->credentials, MONGOC_URI_AUTHMECHANISMPROPERTIES, properties);
- }
-}
-
-
-static bool
-_mongoc_uri_assign_read_prefs_mode (mongoc_uri_t *uri, bson_error_t *error)
-{
- const char *str;
- bson_iter_t iter;
-
- BSON_ASSERT (uri);
-
- if (bson_iter_init_find_case (
- &iter, &uri->options, MONGOC_URI_READPREFERENCE) &&
- BSON_ITER_HOLDS_UTF8 (&iter)) {
- str = bson_iter_utf8 (&iter, NULL);
-
- if (0 == strcasecmp ("primary", str)) {
- mongoc_read_prefs_set_mode (uri->read_prefs, MONGOC_READ_PRIMARY);
- } else if (0 == strcasecmp ("primarypreferred", str)) {
- mongoc_read_prefs_set_mode (uri->read_prefs,
- MONGOC_READ_PRIMARY_PREFERRED);
- } else if (0 == strcasecmp ("secondary", str)) {
- mongoc_read_prefs_set_mode (uri->read_prefs, MONGOC_READ_SECONDARY);
- } else if (0 == strcasecmp ("secondarypreferred", str)) {
- mongoc_read_prefs_set_mode (uri->read_prefs,
- MONGOC_READ_SECONDARY_PREFERRED);
- } else if (0 == strcasecmp ("nearest", str)) {
- mongoc_read_prefs_set_mode (uri->read_prefs, MONGOC_READ_NEAREST);
- } else {
- MONGOC_URI_ERROR (
- error, "Unsupported readPreference value [readPreference=%s]", str);
- return false;
- }
- }
- return true;
-}
-
-
-static bool
-_mongoc_uri_build_write_concern (mongoc_uri_t *uri, bson_error_t *error)
-{
- mongoc_write_concern_t *write_concern;
- const char *str;
- bson_iter_t iter;
- int64_t wtimeoutms;
- int value;
-
- BSON_ASSERT (uri);
-
- write_concern = mongoc_write_concern_new ();
- uri->write_concern = write_concern;
-
- if (bson_iter_init_find_case (&iter, &uri->options, MONGOC_URI_SAFE) &&
- BSON_ITER_HOLDS_BOOL (&iter)) {
- mongoc_write_concern_set_w (
- write_concern,
- bson_iter_bool (&iter) ? 1 : MONGOC_WRITE_CONCERN_W_UNACKNOWLEDGED);
- }
-
- wtimeoutms = mongoc_uri_get_option_as_int64 (uri, MONGOC_URI_WTIMEOUTMS, 0);
- if (wtimeoutms < 0) {
- MONGOC_URI_ERROR (
- error, "Unsupported wtimeoutMS value [w=%" PRId64 "]", wtimeoutms);
- return false;
- } else if (wtimeoutms > 0) {
- mongoc_write_concern_set_wtimeout_int64 (write_concern, wtimeoutms);
- }
-
- if (bson_iter_init_find_case (&iter, &uri->options, MONGOC_URI_JOURNAL) &&
- BSON_ITER_HOLDS_BOOL (&iter)) {
- mongoc_write_concern_set_journal (write_concern, bson_iter_bool (&iter));
- }
-
- if (bson_iter_init_find_case (&iter, &uri->options, MONGOC_URI_W)) {
- if (BSON_ITER_HOLDS_INT32 (&iter)) {
- value = bson_iter_int32 (&iter);
-
- switch (value) {
- case MONGOC_WRITE_CONCERN_W_ERRORS_IGNORED:
- case MONGOC_WRITE_CONCERN_W_UNACKNOWLEDGED:
- if (mongoc_write_concern_get_journal (write_concern)) {
- MONGOC_URI_ERROR (
- error, "Journal conflicts with w value [w=%d]", value);
- return false;
- }
- mongoc_write_concern_set_w (write_concern, value);
- break;
- default:
- if (value > 0) {
- mongoc_write_concern_set_w (write_concern, value);
- break;
- }
- MONGOC_URI_ERROR (error, "Unsupported w value [w=%d]", value);
- return false;
- }
- } else if (BSON_ITER_HOLDS_UTF8 (&iter)) {
- str = bson_iter_utf8 (&iter, NULL);
-
- if (0 == strcasecmp ("majority", str)) {
- mongoc_write_concern_set_w (write_concern,
- MONGOC_WRITE_CONCERN_W_MAJORITY);
- } else {
- mongoc_write_concern_set_wtag (write_concern, str);
- }
- } else {
- BSON_ASSERT (false);
- return false;
- }
- }
-
- return true;
-}
-
-/* can't use mongoc_uri_get_option_as_int32, it treats 0 specially */
-static int32_t
-_mongoc_uri_get_max_staleness_option (const mongoc_uri_t *uri)
-{
- const bson_t *options;
- bson_iter_t iter;
- int32_t retval = MONGOC_NO_MAX_STALENESS;
-
- if ((options = mongoc_uri_get_options (uri)) &&
- bson_iter_init_find_case (
- &iter, options, MONGOC_URI_MAXSTALENESSSECONDS) &&
- BSON_ITER_HOLDS_INT32 (&iter)) {
- retval = bson_iter_int32 (&iter);
- if (retval == 0) {
- MONGOC_WARNING (
- "Unsupported value for \"" MONGOC_URI_MAXSTALENESSSECONDS
- "\": \"%d\"",
- retval);
- retval = -1;
- } else if (retval < 0 && retval != -1) {
- MONGOC_WARNING (
- "Unsupported value for \"" MONGOC_URI_MAXSTALENESSSECONDS
- "\": \"%d\"",
- retval);
- retval = MONGOC_NO_MAX_STALENESS;
- }
- }
-
- return retval;
-}
-
-mongoc_uri_t *
-mongoc_uri_new_with_error (const char *uri_string, bson_error_t *error)
-{
- mongoc_uri_t *uri;
- int32_t max_staleness_seconds;
-
- uri = (mongoc_uri_t *) bson_malloc0 (sizeof *uri);
- bson_init (&uri->raw);
- bson_init (&uri->options);
- bson_init (&uri->credentials);
- bson_init (&uri->compressors);
-
- /* Initialize read_prefs, since parsing may add to it */
- uri->read_prefs = mongoc_read_prefs_new (MONGOC_READ_PRIMARY);
-
- /* Initialize empty read_concern */
- uri->read_concern = mongoc_read_concern_new ();
-
- if (!uri_string) {
- uri_string = "mongodb://127.0.0.1/";
- }
-
- if (!mongoc_uri_parse (uri, uri_string, error)) {
- mongoc_uri_destroy (uri);
- return NULL;
- }
-
- uri->str = bson_strdup (uri_string);
-
- if (!_mongoc_uri_assign_read_prefs_mode (uri, error)) {
- mongoc_uri_destroy (uri);
- return NULL;
- }
- max_staleness_seconds = _mongoc_uri_get_max_staleness_option (uri);
- mongoc_read_prefs_set_max_staleness_seconds (uri->read_prefs,
- max_staleness_seconds);
-
- if (!mongoc_read_prefs_is_valid (uri->read_prefs)) {
- mongoc_uri_destroy (uri);
- MONGOC_URI_ERROR (error, "%s", "Invalid readPreferences");
- return NULL;
- }
-
- if (!_mongoc_uri_build_write_concern (uri, error)) {
- mongoc_uri_destroy (uri);
- return NULL;
- }
-
- if (!mongoc_write_concern_is_valid (uri->write_concern)) {
- mongoc_uri_destroy (uri);
- MONGOC_URI_ERROR (error, "%s", "Invalid writeConcern");
- return NULL;
- }
-
- return uri;
-}
-
-mongoc_uri_t *
-mongoc_uri_new (const char *uri_string)
-{
- bson_error_t error = {0};
- mongoc_uri_t *uri;
-
- uri = mongoc_uri_new_with_error (uri_string, &error);
- if (error.domain) {
- MONGOC_WARNING ("Error parsing URI: '%s'", error.message);
- }
-
- return uri;
-}
-
-
-mongoc_uri_t *
-mongoc_uri_new_for_host_port (const char *hostname, uint16_t port)
-{
- mongoc_uri_t *uri;
- char *str;
-
- BSON_ASSERT (hostname);
- BSON_ASSERT (port);
-
- str = bson_strdup_printf ("mongodb://%s:%hu/", hostname, port);
- uri = mongoc_uri_new (str);
- bson_free (str);
-
- return uri;
-}
-
-
-const char *
-mongoc_uri_get_username (const mongoc_uri_t *uri)
-{
- BSON_ASSERT (uri);
-
- return uri->username;
-}
-
-bool
-mongoc_uri_set_username (mongoc_uri_t *uri, const char *username)
-{
- size_t len;
-
- BSON_ASSERT (username);
-
- len = strlen (username);
-
- if (!bson_utf8_validate (username, len, false)) {
- return false;
- }
-
- if (uri->username) {
- bson_free (uri->username);
- }
-
- uri->username = bson_strdup (username);
- return true;
-}
-
-
-const char *
-mongoc_uri_get_password (const mongoc_uri_t *uri)
-{
- BSON_ASSERT (uri);
-
- return uri->password;
-}
-
-bool
-mongoc_uri_set_password (mongoc_uri_t *uri, const char *password)
-{
- size_t len;
-
- BSON_ASSERT (password);
-
- len = strlen (password);
-
- if (!bson_utf8_validate (password, len, false)) {
- return false;
- }
-
- if (uri->password) {
- bson_free (uri->password);
- }
-
- uri->password = bson_strdup (password);
- return true;
-}
-
-
-const char *
-mongoc_uri_get_database (const mongoc_uri_t *uri)
-{
- BSON_ASSERT (uri);
- return uri->database;
-}
-
-bool
-mongoc_uri_set_database (mongoc_uri_t *uri, const char *database)
-{
- size_t len;
-
- BSON_ASSERT (database);
-
- len = strlen (database);
-
- if (!bson_utf8_validate (database, len, false)) {
- return false;
- }
-
- if (uri->database) {
- bson_free (uri->database);
- }
-
- uri->database = bson_strdup (database);
- return true;
-}
-
-
-const char *
-mongoc_uri_get_auth_source (const mongoc_uri_t *uri)
-{
- bson_iter_t iter;
- const char *mechanism;
-
- BSON_ASSERT (uri);
-
- if (bson_iter_init_find_case (
- &iter, &uri->credentials, MONGOC_URI_AUTHSOURCE)) {
- return bson_iter_utf8 (&iter, NULL);
- }
-
- /* Auth spec:
- * "For GSSAPI and MONGODB-X509 authMechanisms the authSource defaults to
- * $external. For PLAIN the authSource defaults to the database name if
- * supplied on the connection string or $external. For MONGODB-CR,
- * SCRAM-SHA-1 and SCRAM-SHA-256 authMechanisms, the authSource defaults to
- * the database name if supplied on the connection string or admin."
- */
- mechanism = mongoc_uri_get_auth_mechanism (uri);
- if (mechanism) {
- if (!strcasecmp (mechanism, "GSSAPI") ||
- !strcasecmp (mechanism, "MONGODB-X509")) {
- return "$external";
- }
- if (!strcasecmp (mechanism, "PLAIN")) {
- return uri->database ? uri->database : "$external";
- }
- }
-
- return uri->database ? uri->database : "admin";
-}
-
-
-bool
-mongoc_uri_set_auth_source (mongoc_uri_t *uri, const char *value)
-{
- size_t len;
-
- BSON_ASSERT (value);
-
- len = strlen (value);
-
- if (!bson_utf8_validate (value, len, false)) {
- return false;
- }
-
- mongoc_uri_bson_append_or_replace_key (
- &uri->credentials, MONGOC_URI_AUTHSOURCE, value);
-
- return true;
-}
-
-
-const char *
-mongoc_uri_get_appname (const mongoc_uri_t *uri)
-{
- BSON_ASSERT (uri);
-
- return mongoc_uri_get_option_as_utf8 (uri, MONGOC_URI_APPNAME, NULL);
-}
-
-
-bool
-mongoc_uri_set_appname (mongoc_uri_t *uri, const char *value)
-{
- BSON_ASSERT (value);
-
- if (!bson_utf8_validate (value, strlen (value), false)) {
- return false;
- }
-
- if (!_mongoc_handshake_appname_is_valid (value)) {
- return false;
- }
-
- mongoc_uri_bson_append_or_replace_key (
- &uri->options, MONGOC_URI_APPNAME, value);
-
- return true;
-}
-
-bool
-mongoc_uri_set_compressors (mongoc_uri_t *uri, const char *value)
-{
- const char *end_compressor;
- char *entry;
-
- bson_destroy (&uri->compressors);
- bson_init (&uri->compressors);
-
- if (value && !bson_utf8_validate (value, strlen (value), false)) {
- return false;
- }
- while ((entry = scan_to_unichar (value, ',', "", &end_compressor))) {
- if (mongoc_compressor_supported (entry)) {
- mongoc_uri_bson_append_or_replace_key (
- &uri->compressors, entry, "yes");
- } else {
- MONGOC_WARNING ("Unsupported compressor: '%s'", entry);
- }
- value = end_compressor + 1;
- bson_free (entry);
- }
- if (value) {
- if (mongoc_compressor_supported (value)) {
- mongoc_uri_bson_append_or_replace_key (
- &uri->compressors, value, "yes");
- } else {
- MONGOC_WARNING ("Unsupported compressor: '%s'", value);
- }
- }
-
- return true;
-}
-
-const bson_t *
-mongoc_uri_get_compressors (const mongoc_uri_t *uri)
-{
- BSON_ASSERT (uri);
- return &uri->compressors;
-}
-
-
-/* can't use mongoc_uri_get_option_as_int32, it treats 0 specially */
-int32_t
-mongoc_uri_get_local_threshold_option (const mongoc_uri_t *uri)
-{
- const bson_t *options;
- bson_iter_t iter;
- int32_t retval = MONGOC_TOPOLOGY_LOCAL_THRESHOLD_MS;
-
- if ((options = mongoc_uri_get_options (uri)) &&
- bson_iter_init_find_case (&iter, options, "localthresholdms") &&
- BSON_ITER_HOLDS_INT32 (&iter)) {
- retval = bson_iter_int32 (&iter);
-
- if (retval < 0) {
- MONGOC_WARNING ("Invalid localThresholdMS: %d", retval);
- retval = MONGOC_TOPOLOGY_LOCAL_THRESHOLD_MS;
- }
- }
-
- return retval;
-}
-
-
-const char *
-mongoc_uri_get_service (const mongoc_uri_t *uri)
-{
- if (uri->is_srv) {
- return uri->srv;
- }
-
- return NULL;
-}
-
-
-const bson_t *
-mongoc_uri_get_options (const mongoc_uri_t *uri)
-{
- BSON_ASSERT (uri);
- return &uri->options;
-}
-
-
-void
-mongoc_uri_destroy (mongoc_uri_t *uri)
-{
- if (uri) {
- _mongoc_host_list_destroy_all (uri->hosts);
- bson_free (uri->str);
- bson_free (uri->database);
- bson_free (uri->username);
- bson_destroy (&uri->raw);
- bson_destroy (&uri->options);
- bson_destroy (&uri->credentials);
- bson_destroy (&uri->compressors);
- mongoc_read_prefs_destroy (uri->read_prefs);
- mongoc_read_concern_destroy (uri->read_concern);
- mongoc_write_concern_destroy (uri->write_concern);
-
- if (uri->password) {
- bson_zero_free (uri->password, strlen (uri->password));
- }
-
- bson_free (uri);
- }
-}
-
-
-mongoc_uri_t *
-mongoc_uri_copy (const mongoc_uri_t *uri)
-{
- mongoc_uri_t *copy;
- mongoc_host_list_t *iter;
- bson_error_t error;
-
- BSON_ASSERT (uri);
-
- copy = (mongoc_uri_t *) bson_malloc0 (sizeof (*copy));
-
- copy->str = bson_strdup (uri->str);
- copy->is_srv = uri->is_srv;
- bson_strncpy (copy->srv, uri->srv, sizeof uri->srv);
- copy->username = bson_strdup (uri->username);
- copy->password = bson_strdup (uri->password);
- copy->database = bson_strdup (uri->database);
-
- copy->read_prefs = mongoc_read_prefs_copy (uri->read_prefs);
- copy->read_concern = mongoc_read_concern_copy (uri->read_concern);
- copy->write_concern = mongoc_write_concern_copy (uri->write_concern);
-
- LL_FOREACH (uri->hosts, iter)
- {
- if (!mongoc_uri_upsert_host (copy, iter->host, iter->port, &error)) {
- MONGOC_ERROR ("%s", error.message);
- mongoc_uri_destroy (copy);
- return NULL;
- }
- }
-
- bson_copy_to (&uri->raw, &copy->raw);
- bson_copy_to (&uri->options, &copy->options);
- bson_copy_to (&uri->credentials, &copy->credentials);
- bson_copy_to (&uri->compressors, &copy->compressors);
-
- return copy;
-}
-
-
-const char *
-mongoc_uri_get_string (const mongoc_uri_t *uri)
-{
- BSON_ASSERT (uri);
- return uri->str;
-}
-
-
-const bson_t *
-mongoc_uri_get_read_prefs (const mongoc_uri_t *uri)
-{
- BSON_ASSERT (uri);
- return mongoc_read_prefs_get_tags (uri->read_prefs);
-}
-
-char *
-mongoc_uri_unescape (const char *escaped_string)
-{
- bson_unichar_t c;
- bson_string_t *str;
- unsigned int hex = 0;
- const char *ptr;
- const char *end;
- size_t len;
- bool unescape_occurred = false;
-
- BSON_ASSERT (escaped_string);
-
- len = strlen (escaped_string);
-
- /*
- * Double check that this is a UTF-8 valid string. Bail out if necessary.
- */
- if (!bson_utf8_validate (escaped_string, len, false)) {
- MONGOC_WARNING ("%s(): escaped_string contains invalid UTF-8", BSON_FUNC);
- return NULL;
- }
-
- ptr = escaped_string;
- end = ptr + len;
- str = bson_string_new (NULL);
-
- for (; *ptr; ptr = bson_utf8_next_char (ptr)) {
- c = bson_utf8_get_char (ptr);
- switch (c) {
- case '%':
- if (((end - ptr) < 2) || !isxdigit (ptr[1]) || !isxdigit (ptr[2]) ||
-#ifdef _MSC_VER
- (1 != sscanf_s (&ptr[1], "%02x", &hex))
-#else
- (1 != sscanf (&ptr[1], "%02x", &hex))
-#endif
- ||
- 0 == hex) {
- bson_string_free (str, true);
- MONGOC_WARNING ("Invalid %% escape sequence");
- return NULL;
- }
- bson_string_append_c (str, hex);
- ptr += 2;
- unescape_occurred = true;
- break;
- default:
- bson_string_append_unichar (str, c);
- break;
- }
- }
-
- /* Check that after unescaping, it is still valid UTF-8 */
- if (unescape_occurred && !bson_utf8_validate (str->str, str->len, false)) {
- MONGOC_WARNING (
- "Invalid %% escape sequence: unescaped string contains invalid UTF-8");
- bson_string_free (str, true);
- return NULL;
- }
-
- return bson_string_free (str, false);
-}
-
-
-const mongoc_read_prefs_t *
-mongoc_uri_get_read_prefs_t (const mongoc_uri_t *uri) /* IN */
-{
- BSON_ASSERT (uri);
-
- return uri->read_prefs;
-}
-
-
-void
-mongoc_uri_set_read_prefs_t (mongoc_uri_t *uri,
- const mongoc_read_prefs_t *prefs)
-{
- BSON_ASSERT (uri);
- BSON_ASSERT (prefs);
-
- mongoc_read_prefs_destroy (uri->read_prefs);
- uri->read_prefs = mongoc_read_prefs_copy (prefs);
-}
-
-
-const mongoc_read_concern_t *
-mongoc_uri_get_read_concern (const mongoc_uri_t *uri) /* IN */
-{
- BSON_ASSERT (uri);
-
- return uri->read_concern;
-}
-
-
-void
-mongoc_uri_set_read_concern (mongoc_uri_t *uri, const mongoc_read_concern_t *rc)
-{
- BSON_ASSERT (uri);
- BSON_ASSERT (rc);
-
- mongoc_read_concern_destroy (uri->read_concern);
- uri->read_concern = mongoc_read_concern_copy (rc);
-}
-
-
-const mongoc_write_concern_t *
-mongoc_uri_get_write_concern (const mongoc_uri_t *uri) /* IN */
-{
- BSON_ASSERT (uri);
-
- return uri->write_concern;
-}
-
-
-void
-mongoc_uri_set_write_concern (mongoc_uri_t *uri,
- const mongoc_write_concern_t *wc)
-{
- BSON_ASSERT (uri);
- BSON_ASSERT (wc);
-
- mongoc_write_concern_destroy (uri->write_concern);
- uri->write_concern = mongoc_write_concern_copy (wc);
-}
-
-
-bool
-mongoc_uri_get_tls (const mongoc_uri_t *uri) /* IN */
-{
- bson_iter_t iter;
-
- BSON_ASSERT (uri);
-
- if (bson_iter_init_find_case (&iter, &uri->options, MONGOC_URI_TLS) &&
- BSON_ITER_HOLDS_BOOL (&iter)) {
- return bson_iter_bool (&iter);
- }
-
- if (bson_iter_init_find_case (
- &iter, &uri->options, MONGOC_URI_TLSCERTIFICATEKEYFILE) ||
- bson_iter_init_find_case (&iter, &uri->options, MONGOC_URI_TLSCAFILE) ||
- bson_iter_init_find_case (
- &iter, &uri->options, MONGOC_URI_TLSALLOWINVALIDCERTIFICATES) ||
- bson_iter_init_find_case (
- &iter, &uri->options, MONGOC_URI_TLSALLOWINVALIDHOSTNAMES) ||
- bson_iter_init_find_case (
- &iter, &uri->options, MONGOC_URI_TLSINSECURE) ||
- bson_iter_init_find_case (
- &iter, &uri->options, MONGOC_URI_TLSCERTIFICATEKEYFILEPASSWORD) ||
- bson_iter_init_find_case (
- &iter, &uri->options, MONGOC_URI_TLSDISABLEOCSPENDPOINTCHECK) ||
- bson_iter_init_find_case (
- &iter,
- &uri->options,
- MONGOC_URI_TLSDISABLECERTIFICATEREVOCATIONCHECK)) {
- return true;
- }
-
- return false;
-}
-
-bool
-mongoc_uri_get_ssl (const mongoc_uri_t *uri) /* IN */
-{
- return mongoc_uri_get_tls (uri);
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_uri_get_option_as_int32 --
- *
- * Checks if the URI 'option' is set and of correct type (int32).
- * The special value '0' is considered as "unset".
- * This is so users can provide
- * sprintf("mongodb://localhost/?option=%d", myvalue) style connection
- * strings, and still apply default values.
- *
- * If not set, or set to invalid type, 'fallback' is returned.
- *
- * NOTE: 'option' is case*in*sensitive.
- *
- * Returns:
- * The value of 'option' if available as int32 (and not 0), or
- * 'fallback'.
- *
- *--------------------------------------------------------------------------
- */
-
-int32_t
-mongoc_uri_get_option_as_int32 (const mongoc_uri_t *uri,
- const char *option_orig,
- int32_t fallback)
-{
- const char *option;
- const bson_t *options;
- bson_iter_t iter;
- int64_t retval = 0;
-
- option = mongoc_uri_canonicalize_option (option_orig);
-
- /* BC layer to allow retrieving 32-bit values stored in 64-bit options */
- if (mongoc_uri_option_is_int64 (option_orig)) {
- retval = mongoc_uri_get_option_as_int64 (uri, option_orig, 0);
-
- if (retval > INT32_MAX || retval < INT32_MIN) {
- MONGOC_WARNING ("Cannot read 64-bit value for \"%s\": %" PRId64,
- option_orig,
- retval);
-
- retval = 0;
- }
- } else if ((options = mongoc_uri_get_options (uri)) &&
- bson_iter_init_find_case (&iter, options, option) &&
- BSON_ITER_HOLDS_INT32 (&iter)) {
- retval = bson_iter_int32 (&iter);
- }
-
- if (!retval) {
- retval = fallback;
- }
-
- return (int32_t) retval;
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_uri_set_option_as_int32 --
- *
- * Sets a URI option 'after the fact'. Allows users to set individual
- * URI options without passing them as a connection string.
- *
- * Only allows a set of known options to be set.
- * @see mongoc_uri_option_is_int32 ().
- *
- * Does in-place-update of the option BSON if 'option' is already set.
- * Appends the option to the end otherwise.
- *
- * NOTE: If 'option' is already set, and is of invalid type, this
- * function will return false.
- *
- * NOTE: 'option' is case*in*sensitive.
- *
- * Returns:
- * true on successfully setting the option, false on failure.
- *
- *--------------------------------------------------------------------------
- */
-
-bool
-mongoc_uri_set_option_as_int32 (mongoc_uri_t *uri,
- const char *option_orig,
- int32_t value)
-{
- const char *option;
- bson_error_t error;
- bool r;
-
- if (mongoc_uri_option_is_int64 (option_orig)) {
- return mongoc_uri_set_option_as_int64 (uri, option_orig, value);
- }
-
- option = mongoc_uri_canonicalize_option (option_orig);
-
- if (!mongoc_uri_option_is_int32 (option)) {
- MONGOC_WARNING (
- "Unsupported value for \"%s\": %d, \"%s\" is not an int32 option",
- option_orig,
- value,
- option);
- return false;
- }
-
- r = _mongoc_uri_set_option_as_int32_with_error (uri, option, value, &error);
- if (!r) {
- MONGOC_WARNING ("%s", error.message);
- }
-
- return r;
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_uri_set_option_as_int32_with_error --
- *
- * Same as mongoc_uri_set_option_as_int32, with error reporting.
- *
- * Precondition:
- * mongoc_uri_option_is_int32(option) must be true.
- *
- * Returns:
- * true on successfully setting the option, false on failure.
- *
- *--------------------------------------------------------------------------
- */
-
-static bool
-_mongoc_uri_set_option_as_int32_with_error (mongoc_uri_t *uri,
- const char *option_orig,
- int32_t value,
- bson_error_t *error)
-{
- const char *option;
- const bson_t *options;
- bson_iter_t iter;
- char *option_lowercase = NULL;
-
- option = mongoc_uri_canonicalize_option (option_orig);
- /* Server Discovery and Monitoring Spec: "the driver MUST NOT permit users
- * to configure it less than minHeartbeatFrequencyMS (500ms)." */
- if (!bson_strcasecmp (option, MONGOC_URI_HEARTBEATFREQUENCYMS) &&
- value < MONGOC_TOPOLOGY_MIN_HEARTBEAT_FREQUENCY_MS) {
- MONGOC_URI_ERROR (error,
- "Invalid \"%s\" of %d: must be at least %d",
- option_orig,
- value,
- MONGOC_TOPOLOGY_MIN_HEARTBEAT_FREQUENCY_MS);
- return false;
- }
-
- /* zlib levels are from -1 (default) through 9 (best compression) */
- if (!bson_strcasecmp (option, MONGOC_URI_ZLIBCOMPRESSIONLEVEL) &&
- (value < -1 || value > 9)) {
- MONGOC_URI_ERROR (error,
- "Invalid \"%s\" of %d: must be between -1 and 9",
- option_orig,
- value);
- return false;
- }
-
- if ((options = mongoc_uri_get_options (uri)) &&
- bson_iter_init_find_case (&iter, options, option)) {
- if (BSON_ITER_HOLDS_INT32 (&iter)) {
- bson_iter_overwrite_int32 (&iter, value);
- return true;
- } else {
- MONGOC_URI_ERROR (error,
- "Cannot set URI option \"%s\" to %d, it already has "
- "a non-32-bit integer value",
- option,
- value);
- return false;
- }
- }
- option_lowercase = lowercase_str_new (option);
- if (!bson_append_int32 (&uri->options, option_lowercase, -1, value)) {
- bson_free (option_lowercase);
- MONGOC_URI_ERROR (
- error, "Failed to set URI option \"%s\" to %d", option_orig, value);
-
- return false;
- }
-
- bson_free (option_lowercase);
- return true;
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_uri_set_option_as_int32 --
- *
- * Same as mongoc_uri_set_option_as_int32, except the option is not
- * validated against valid int32 options
- *
- * Returns:
- * true on successfully setting the option, false on failure.
- *
- *--------------------------------------------------------------------------
- */
-
-static bool
-_mongoc_uri_set_option_as_int32 (mongoc_uri_t *uri,
- const char *option_orig,
- int32_t value)
-{
- const char *option;
- const bson_t *options;
- bson_iter_t iter;
- char *option_lowercase = NULL;
-
- option = mongoc_uri_canonicalize_option (option_orig);
- if ((options = mongoc_uri_get_options (uri)) &&
- bson_iter_init_find_case (&iter, options, option)) {
- if (BSON_ITER_HOLDS_INT32 (&iter)) {
- bson_iter_overwrite_int32 (&iter, value);
- return true;
- } else {
- return false;
- }
- }
-
- option_lowercase = lowercase_str_new (option);
- bson_append_int32 (&uri->options, option_lowercase, -1, value);
- bson_free (option_lowercase);
- return true;
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_uri_get_option_as_int64 --
- *
- * Checks if the URI 'option' is set and of correct type (int32 or
- * int64).
- * The special value '0' is considered as "unset".
- * This is so users can provide
- * sprintf("mongodb://localhost/?option=%" PRId64, myvalue) style
- * connection strings, and still apply default values.
- *
- * If not set, or set to invalid type, 'fallback' is returned.
- *
- * NOTE: 'option' is case*in*sensitive.
- *
- * Returns:
- * The value of 'option' if available as int64 or int32 (and not 0), or
- * 'fallback'.
- *
- *--------------------------------------------------------------------------
- */
-
-int64_t
-mongoc_uri_get_option_as_int64 (const mongoc_uri_t *uri,
- const char *option_orig,
- int64_t fallback)
-{
- const char *option;
- const bson_t *options;
- bson_iter_t iter;
- int64_t retval = fallback;
-
- option = mongoc_uri_canonicalize_option (option_orig);
- if ((options = mongoc_uri_get_options (uri)) &&
- bson_iter_init_find_case (&iter, options, option)) {
- if (BSON_ITER_HOLDS_INT (&iter)) {
- if (!(retval = bson_iter_as_int64 (&iter))) {
- retval = fallback;
- }
- }
- }
-
- return retval;
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_uri_set_option_as_int64 --
- *
- * Sets a URI option 'after the fact'. Allows users to set individual
- * URI options without passing them as a connection string.
- *
- * Only allows a set of known options to be set.
- * @see mongoc_uri_option_is_int64 ().
- *
- * Does in-place-update of the option BSON if 'option' is already set.
- * Appends the option to the end otherwise.
- *
- * NOTE: If 'option' is already set, and is of invalid type, this
- * function will return false.
- *
- * NOTE: 'option' is case*in*sensitive.
- *
- * Returns:
- * true on successfully setting the option, false on failure.
- *
- *--------------------------------------------------------------------------
- */
-
-bool
-mongoc_uri_set_option_as_int64 (mongoc_uri_t *uri,
- const char *option_orig,
- int64_t value)
-{
- const char *option;
- bson_error_t error;
- bool r;
-
- option = mongoc_uri_canonicalize_option (option_orig);
- if (!mongoc_uri_option_is_int64 (option)) {
- if (mongoc_uri_option_is_int32 (option_orig)) {
- if (value >= INT32_MIN && value <= INT32_MAX) {
- MONGOC_WARNING (
- "Setting value for 32-bit option \"%s\" through 64-bit method",
- option_orig);
-
- return mongoc_uri_set_option_as_int32 (
- uri, option_orig, (int32_t) value);
- }
-
- MONGOC_WARNING ("Unsupported value for \"%s\": %" PRId64
- ", \"%s\" is not an int64 option",
- option_orig,
- value,
- option);
- return false;
- }
- }
-
- r = _mongoc_uri_set_option_as_int64_with_error (uri, option, value, &error);
- if (!r) {
- MONGOC_WARNING ("%s", error.message);
- }
-
- return r;
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_uri_set_option_as_int64_with_error --
- *
- * Same as mongoc_uri_set_option_as_int64, with error reporting.
- *
- * Precondition:
- * mongoc_uri_option_is_int64(option) must be true.
- *
- * Returns:
- * true on successfully setting the option, false on failure.
- *
- *--------------------------------------------------------------------------
- */
-
-static bool
-_mongoc_uri_set_option_as_int64_with_error (mongoc_uri_t *uri,
- const char *option_orig,
- int64_t value,
- bson_error_t *error)
-{
- const char *option;
- const bson_t *options;
- bson_iter_t iter;
- char *option_lowercase = NULL;
-
- option = mongoc_uri_canonicalize_option (option_orig);
-
- if ((options = mongoc_uri_get_options (uri)) &&
- bson_iter_init_find_case (&iter, options, option)) {
- if (BSON_ITER_HOLDS_INT64 (&iter)) {
- bson_iter_overwrite_int64 (&iter, value);
- return true;
- } else {
- MONGOC_URI_ERROR (error,
- "Cannot set URI option \"%s\" to %" PRId64
- ", it already has "
- "a non-64-bit integer value",
- option,
- value);
- return false;
- }
- }
-
- option_lowercase = lowercase_str_new (option);
- if (!bson_append_int64 (&uri->options, option_lowercase, -1, value)) {
- bson_free (option_lowercase);
- MONGOC_URI_ERROR (error,
- "Failed to set URI option \"%s\" to %" PRId64,
- option_orig,
- value);
-
- return false;
- }
- bson_free (option_lowercase);
- return true;
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_uri_get_option_as_bool --
- *
- * Checks if the URI 'option' is set and of correct type (bool).
- *
- * If not set, or set to invalid type, 'fallback' is returned.
- *
- * NOTE: 'option' is case*in*sensitive.
- *
- * Returns:
- * The value of 'option' if available as bool, or 'fallback'.
- *
- *--------------------------------------------------------------------------
- */
-
-bool
-mongoc_uri_get_option_as_bool (const mongoc_uri_t *uri,
- const char *option_orig,
- bool fallback)
-{
- const char *option;
- const bson_t *options;
- bson_iter_t iter;
-
- option = mongoc_uri_canonicalize_option (option_orig);
- if ((options = mongoc_uri_get_options (uri)) &&
- bson_iter_init_find_case (&iter, options, option) &&
- BSON_ITER_HOLDS_BOOL (&iter)) {
- return bson_iter_bool (&iter);
- }
-
- return fallback;
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_uri_set_option_as_bool --
- *
- * Sets a URI option 'after the fact'. Allows users to set individual
- * URI options without passing them as a connection string.
- *
- * Only allows a set of known options to be set.
- * @see mongoc_uri_option_is_bool ().
- *
- * Does in-place-update of the option BSON if 'option' is already set.
- * Appends the option to the end otherwise.
- *
- * NOTE: If 'option' is already set, and is of invalid type, this
- * function will return false.
- *
- * NOTE: 'option' is case*in*sensitive.
- *
- * Returns:
- * true on successfully setting the option, false on failure.
- *
- *--------------------------------------------------------------------------
- */
-
-bool
-mongoc_uri_set_option_as_bool (mongoc_uri_t *uri,
- const char *option_orig,
- bool value)
-{
- const char *option;
- char *option_lowercase;
- const bson_t *options;
- bson_iter_t iter;
-
- option = mongoc_uri_canonicalize_option (option_orig);
- BSON_ASSERT (option);
-
- if (!mongoc_uri_option_is_bool (option)) {
- return false;
- }
-
- if ((options = mongoc_uri_get_options (uri)) &&
- bson_iter_init_find_case (&iter, options, option)) {
- if (BSON_ITER_HOLDS_BOOL (&iter)) {
- bson_iter_overwrite_bool (&iter, value);
- return true;
- } else {
- return false;
- }
- }
- option_lowercase = lowercase_str_new (option);
- bson_append_bool (&uri->options, option_lowercase, -1, value);
- bson_free (option_lowercase);
- return true;
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_uri_get_option_as_utf8 --
- *
- * Checks if the URI 'option' is set and of correct type (utf8).
- *
- * If not set, or set to invalid type, 'fallback' is returned.
- *
- * NOTE: 'option' is case*in*sensitive.
- *
- * Returns:
- * The value of 'option' if available as utf8, or 'fallback'.
- *
- *--------------------------------------------------------------------------
- */
-
-const char *
-mongoc_uri_get_option_as_utf8 (const mongoc_uri_t *uri,
- const char *option_orig,
- const char *fallback)
-{
- const char *option;
- const bson_t *options;
- bson_iter_t iter;
-
- option = mongoc_uri_canonicalize_option (option_orig);
- if ((options = mongoc_uri_get_options (uri)) &&
- bson_iter_init_find_case (&iter, options, option) &&
- BSON_ITER_HOLDS_UTF8 (&iter)) {
- return bson_iter_utf8 (&iter, NULL);
- }
-
- return fallback;
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * mongoc_uri_set_option_as_utf8 --
- *
- * Sets a URI option 'after the fact'. Allows users to set individual
- * URI options without passing them as a connection string.
- *
- * Only allows a set of known options to be set.
- * @see mongoc_uri_option_is_utf8 ().
- *
- * If the option is not already set, this function will append it to
- *the end of the options bson. NOTE: If the option is already set the entire
- *options bson will be overwritten, containing the new option=value
- *(at the same position).
- *
- * NOTE: If 'option' is already set, and is of invalid type, this
- * function will return false.
- *
- * NOTE: 'option' must be valid utf8.
- *
- * NOTE: 'option' is case*in*sensitive.
- *
- * Returns:
- * true on successfully setting the option, false on failure.
- *
- *--------------------------------------------------------------------------
- */
-
-bool
-mongoc_uri_set_option_as_utf8 (mongoc_uri_t *uri,
- const char *option_orig,
- const char *value)
-{
- const char *option;
- size_t len;
- char *option_lowercase = NULL;
-
- option = mongoc_uri_canonicalize_option (option_orig);
- BSON_ASSERT (option);
-
- len = strlen (value);
-
- if (!bson_utf8_validate (value, len, false)) {
- return false;
- }
-
- if (!mongoc_uri_option_is_utf8 (option)) {
- return false;
- }
- if (!bson_strcasecmp (option, MONGOC_URI_APPNAME)) {
- return mongoc_uri_set_appname (uri, value);
- } else {
- option_lowercase = lowercase_str_new (option);
- mongoc_uri_bson_append_or_replace_key (
- &uri->options, option_lowercase, value);
- bson_free (option_lowercase);
- }
-
- return true;
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_uri_requires_auth_negotiation --
- *
- * Returns true if auth mechanism is necessary for this uri. According
- * to the auth spec: "If an application provides a username but does
- * not provide an authentication mechanism, drivers MUST negotiate a
- * mechanism".
- *
- * Returns:
- * true if the driver should negotiate the auth mechanism for the uri
- *
- *--------------------------------------------------------------------------
- */
-bool
-_mongoc_uri_requires_auth_negotiation (const mongoc_uri_t *uri)
-{
- return mongoc_uri_get_username (uri) && !mongoc_uri_get_auth_mechanism (uri);
-}
-
-
-/* A bit of a hack. Needed for multi mongos tests to create a URI with the same
- * auth, SSL, and compressors settings but with only one specific host. */
-mongoc_uri_t *
-_mongoc_uri_copy_and_replace_host_list (const mongoc_uri_t *original,
- const char *host)
-{
- mongoc_uri_t *uri = mongoc_uri_copy (original);
- _mongoc_host_list_destroy_all (uri->hosts);
- uri->hosts = bson_malloc0 (sizeof (mongoc_host_list_t));
- _mongoc_host_list_from_string (uri->hosts, host);
- return uri;
-}
-
-bool
-mongoc_uri_init_with_srv_host_list (mongoc_uri_t *uri,
- mongoc_host_list_t *host_list,
- bson_error_t *error)
-{
- mongoc_host_list_t *host;
-
- BSON_ASSERT (uri->is_srv);
- BSON_ASSERT (!uri->hosts);
-
- LL_FOREACH (host_list, host)
- {
- if (!mongoc_uri_upsert_host_and_port (uri, host->host_and_port, error)) {
- return false;
- }
- }
-
- return true;
-}
-
-#ifdef MONGOC_ENABLE_CRYPTO
-void
-_mongoc_uri_init_scram (const mongoc_uri_t *uri,
- mongoc_scram_t *scram,
- mongoc_crypto_hash_algorithm_t algo)
-{
- BSON_ASSERT (uri);
- BSON_ASSERT (scram);
-
- _mongoc_scram_init (scram, algo);
-
- _mongoc_scram_set_pass (scram, mongoc_uri_get_password (uri));
- _mongoc_scram_set_user (scram, mongoc_uri_get_username (uri));
-}
-#endif
-
-bool
-mongoc_uri_finalize_loadbalanced (const mongoc_uri_t *uri, bson_error_t *error)
-{
- if (!mongoc_uri_get_option_as_bool (uri, MONGOC_URI_LOADBALANCED, false)) {
- return true;
- }
-
- if (!uri->hosts || (uri->hosts && uri->hosts->next)) {
- MONGOC_URI_ERROR (error,
- "URI with \"%s\" enabled must contain exactly one host",
- MONGOC_URI_LOADBALANCED);
- return false;
- }
-
- if (mongoc_uri_has_option (uri, MONGOC_URI_REPLICASET)) {
- MONGOC_URI_ERROR (
- error,
- "URI with \"%s\" enabled must not contain option \"%s\"",
- MONGOC_URI_LOADBALANCED,
- MONGOC_URI_REPLICASET);
- return false;
- }
-
- if (mongoc_uri_has_option (uri, MONGOC_URI_DIRECTCONNECTION) &&
- mongoc_uri_get_option_as_bool (
- uri, MONGOC_URI_DIRECTCONNECTION, false)) {
- MONGOC_URI_ERROR (
- error,
- "URI with \"%s\" enabled must not contain option \"%s\" enabled",
- MONGOC_URI_LOADBALANCED,
- MONGOC_URI_DIRECTCONNECTION);
- return false;
- }
-
- return true;
-}
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-uri.h b/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-uri.h
deleted file mode 100644
index 96d8711e..00000000
--- a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-uri.h
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * Copyright 2013 MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "mongoc-prelude.h"
-
-#ifndef MONGOC_URI_H
-#define MONGOC_URI_H
-
-#include <bson/bson.h>
-
-#include "mongoc-macros.h"
-#include "mongoc-host-list.h"
-#include "mongoc-read-prefs.h"
-#include "mongoc-read-concern.h"
-#include "mongoc-write-concern.h"
-#include "mongoc-config.h"
-
-
-#ifndef MONGOC_DEFAULT_PORT
-#define MONGOC_DEFAULT_PORT 27017
-#endif
-
-#define MONGOC_URI_APPNAME "appname"
-#define MONGOC_URI_AUTHMECHANISM "authmechanism"
-#define MONGOC_URI_AUTHMECHANISMPROPERTIES "authmechanismproperties"
-#define MONGOC_URI_AUTHSOURCE "authsource"
-#define MONGOC_URI_CANONICALIZEHOSTNAME "canonicalizehostname"
-#define MONGOC_URI_CONNECTTIMEOUTMS "connecttimeoutms"
-#define MONGOC_URI_COMPRESSORS "compressors"
-#define MONGOC_URI_DIRECTCONNECTION "directconnection"
-#define MONGOC_URI_GSSAPISERVICENAME "gssapiservicename"
-#define MONGOC_URI_HEARTBEATFREQUENCYMS "heartbeatfrequencyms"
-#define MONGOC_URI_JOURNAL "journal"
-#define MONGOC_URI_LOADBALANCED "loadbalanced"
-#define MONGOC_URI_LOCALTHRESHOLDMS "localthresholdms"
-#define MONGOC_URI_MAXIDLETIMEMS "maxidletimems"
-#define MONGOC_URI_MAXPOOLSIZE "maxpoolsize"
-#define MONGOC_URI_MAXSTALENESSSECONDS "maxstalenessseconds"
-#define MONGOC_URI_MINPOOLSIZE "minpoolsize"
-#define MONGOC_URI_READCONCERNLEVEL "readconcernlevel"
-#define MONGOC_URI_READPREFERENCE "readpreference"
-#define MONGOC_URI_READPREFERENCETAGS "readpreferencetags"
-#define MONGOC_URI_REPLICASET "replicaset"
-#define MONGOC_URI_RETRYREADS "retryreads"
-#define MONGOC_URI_RETRYWRITES "retrywrites"
-#define MONGOC_URI_SAFE "safe"
-#define MONGOC_URI_SERVERSELECTIONTIMEOUTMS "serverselectiontimeoutms"
-#define MONGOC_URI_SERVERSELECTIONTRYONCE "serverselectiontryonce"
-#define MONGOC_URI_SLAVEOK "slaveok"
-#define MONGOC_URI_SOCKETCHECKINTERVALMS "socketcheckintervalms"
-#define MONGOC_URI_SOCKETTIMEOUTMS "sockettimeoutms"
-#define MONGOC_URI_TLS "tls"
-#define MONGOC_URI_TLSCERTIFICATEKEYFILE "tlscertificatekeyfile"
-#define MONGOC_URI_TLSCERTIFICATEKEYFILEPASSWORD "tlscertificatekeyfilepassword"
-#define MONGOC_URI_TLSCAFILE "tlscafile"
-#define MONGOC_URI_TLSALLOWINVALIDCERTIFICATES "tlsallowinvalidcertificates"
-#define MONGOC_URI_TLSALLOWINVALIDHOSTNAMES "tlsallowinvalidhostnames"
-#define MONGOC_URI_TLSINSECURE "tlsinsecure"
-#define MONGOC_URI_TLSDISABLECERTIFICATEREVOCATIONCHECK \
- "tlsdisablecertificaterevocationcheck"
-#define MONGOC_URI_TLSDISABLEOCSPENDPOINTCHECK "tlsdisableocspendpointcheck"
-#define MONGOC_URI_W "w"
-#define MONGOC_URI_WAITQUEUEMULTIPLE "waitqueuemultiple"
-#define MONGOC_URI_WAITQUEUETIMEOUTMS "waitqueuetimeoutms"
-#define MONGOC_URI_WTIMEOUTMS "wtimeoutms"
-#define MONGOC_URI_ZLIBCOMPRESSIONLEVEL "zlibcompressionlevel"
-
-/* Deprecated in MongoDB 4.2, use "tls" variants instead. */
-#define MONGOC_URI_SSL "ssl"
-#define MONGOC_URI_SSLCLIENTCERTIFICATEKEYFILE "sslclientcertificatekeyfile"
-#define MONGOC_URI_SSLCLIENTCERTIFICATEKEYPASSWORD \
- "sslclientcertificatekeypassword"
-#define MONGOC_URI_SSLCERTIFICATEAUTHORITYFILE "sslcertificateauthorityfile"
-#define MONGOC_URI_SSLALLOWINVALIDCERTIFICATES "sslallowinvalidcertificates"
-#define MONGOC_URI_SSLALLOWINVALIDHOSTNAMES "sslallowinvalidhostnames"
-
-BSON_BEGIN_DECLS
-
-
-typedef struct _mongoc_uri_t mongoc_uri_t;
-
-
-MONGOC_EXPORT (mongoc_uri_t *)
-mongoc_uri_copy (const mongoc_uri_t *uri) BSON_GNUC_WARN_UNUSED_RESULT;
-MONGOC_EXPORT (void)
-mongoc_uri_destroy (mongoc_uri_t *uri);
-MONGOC_EXPORT (mongoc_uri_t *)
-mongoc_uri_new (const char *uri_string) BSON_GNUC_WARN_UNUSED_RESULT;
-MONGOC_EXPORT (mongoc_uri_t *)
-mongoc_uri_new_with_error (const char *uri_string,
- bson_error_t *error) BSON_GNUC_WARN_UNUSED_RESULT;
-MONGOC_EXPORT (mongoc_uri_t *)
-mongoc_uri_new_for_host_port (const char *hostname,
- uint16_t port) BSON_GNUC_WARN_UNUSED_RESULT;
-MONGOC_EXPORT (const mongoc_host_list_t *)
-mongoc_uri_get_hosts (const mongoc_uri_t *uri);
-MONGOC_EXPORT (const char *)
-mongoc_uri_get_service (const mongoc_uri_t *uri);
-MONGOC_EXPORT (const char *)
-mongoc_uri_get_database (const mongoc_uri_t *uri);
-MONGOC_EXPORT (bool)
-mongoc_uri_set_database (mongoc_uri_t *uri, const char *database);
-MONGOC_EXPORT (const bson_t *)
-mongoc_uri_get_compressors (const mongoc_uri_t *uri);
-MONGOC_EXPORT (const bson_t *)
-mongoc_uri_get_options (const mongoc_uri_t *uri);
-MONGOC_EXPORT (const char *)
-mongoc_uri_get_password (const mongoc_uri_t *uri);
-MONGOC_EXPORT (bool)
-mongoc_uri_set_password (mongoc_uri_t *uri, const char *password);
-MONGOC_EXPORT (bool)
-mongoc_uri_has_option (const mongoc_uri_t *uri, const char *key);
-MONGOC_EXPORT (bool)
-mongoc_uri_option_is_int32 (const char *key);
-MONGOC_EXPORT (bool)
-mongoc_uri_option_is_int64 (const char *key);
-MONGOC_EXPORT (bool)
-mongoc_uri_option_is_bool (const char *key);
-MONGOC_EXPORT (bool)
-mongoc_uri_option_is_utf8 (const char *key);
-MONGOC_EXPORT (int32_t)
-mongoc_uri_get_option_as_int32 (const mongoc_uri_t *uri,
- const char *option,
- int32_t fallback);
-MONGOC_EXPORT (int64_t)
-mongoc_uri_get_option_as_int64 (const mongoc_uri_t *uri,
- const char *option,
- int64_t fallback);
-MONGOC_EXPORT (bool)
-mongoc_uri_get_option_as_bool (const mongoc_uri_t *uri,
- const char *option,
- bool fallback);
-MONGOC_EXPORT (const char *)
-mongoc_uri_get_option_as_utf8 (const mongoc_uri_t *uri,
- const char *option,
- const char *fallback);
-MONGOC_EXPORT (bool)
-mongoc_uri_set_option_as_int32 (mongoc_uri_t *uri,
- const char *option,
- int32_t value);
-MONGOC_EXPORT (bool)
-mongoc_uri_set_option_as_int64 (mongoc_uri_t *uri,
- const char *option,
- int64_t value);
-MONGOC_EXPORT (bool)
-mongoc_uri_set_option_as_bool (mongoc_uri_t *uri,
- const char *option,
- bool value);
-MONGOC_EXPORT (bool)
-mongoc_uri_set_option_as_utf8 (mongoc_uri_t *uri,
- const char *option,
- const char *value);
-MONGOC_EXPORT (const bson_t *)
-mongoc_uri_get_read_prefs (const mongoc_uri_t *uri)
- BSON_GNUC_DEPRECATED_FOR (mongoc_uri_get_read_prefs_t);
-MONGOC_EXPORT (const char *)
-mongoc_uri_get_replica_set (const mongoc_uri_t *uri);
-MONGOC_EXPORT (const char *)
-mongoc_uri_get_string (const mongoc_uri_t *uri);
-MONGOC_EXPORT (const char *)
-mongoc_uri_get_username (const mongoc_uri_t *uri);
-MONGOC_EXPORT (bool)
-mongoc_uri_set_username (mongoc_uri_t *uri, const char *username);
-MONGOC_EXPORT (const bson_t *)
-mongoc_uri_get_credentials (const mongoc_uri_t *uri);
-MONGOC_EXPORT (const char *)
-mongoc_uri_get_auth_source (const mongoc_uri_t *uri);
-MONGOC_EXPORT (bool)
-mongoc_uri_set_auth_source (mongoc_uri_t *uri, const char *value);
-MONGOC_EXPORT (const char *)
-mongoc_uri_get_appname (const mongoc_uri_t *uri);
-MONGOC_EXPORT (bool)
-mongoc_uri_set_appname (mongoc_uri_t *uri, const char *value);
-MONGOC_EXPORT (bool)
-mongoc_uri_set_compressors (mongoc_uri_t *uri, const char *value);
-MONGOC_EXPORT (const char *)
-mongoc_uri_get_auth_mechanism (const mongoc_uri_t *uri);
-MONGOC_EXPORT (bool)
-mongoc_uri_set_auth_mechanism (mongoc_uri_t *uri, const char *value);
-MONGOC_EXPORT (bool)
-mongoc_uri_get_mechanism_properties (const mongoc_uri_t *uri,
- bson_t *properties);
-MONGOC_EXPORT (bool)
-mongoc_uri_set_mechanism_properties (mongoc_uri_t *uri,
- const bson_t *properties);
-MONGOC_EXPORT (bool)
-mongoc_uri_get_ssl (const mongoc_uri_t *uri)
- BSON_GNUC_DEPRECATED_FOR (mongoc_uri_get_tls);
-MONGOC_EXPORT (bool)
-mongoc_uri_get_tls (const mongoc_uri_t *uri);
-MONGOC_EXPORT (char *)
-mongoc_uri_unescape (const char *escaped_string) BSON_GNUC_WARN_UNUSED_RESULT;
-MONGOC_EXPORT (const mongoc_read_prefs_t *)
-mongoc_uri_get_read_prefs_t (const mongoc_uri_t *uri);
-MONGOC_EXPORT (void)
-mongoc_uri_set_read_prefs_t (mongoc_uri_t *uri,
- const mongoc_read_prefs_t *prefs);
-MONGOC_EXPORT (const mongoc_write_concern_t *)
-mongoc_uri_get_write_concern (const mongoc_uri_t *uri);
-MONGOC_EXPORT (void)
-mongoc_uri_set_write_concern (mongoc_uri_t *uri,
- const mongoc_write_concern_t *wc);
-MONGOC_EXPORT (const mongoc_read_concern_t *)
-mongoc_uri_get_read_concern (const mongoc_uri_t *uri);
-MONGOC_EXPORT (void)
-mongoc_uri_set_read_concern (mongoc_uri_t *uri,
- const mongoc_read_concern_t *rc);
-
-BSON_END_DECLS
-
-
-#endif /* MONGOC_URI_H */
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-util-private.h b/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-util-private.h
deleted file mode 100644
index 1a1bc522..00000000
--- a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-util-private.h
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright 2013 MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "mongoc-prelude.h"
-
-#ifndef MONGOC_UTIL_PRIVATE_H
-#define MONGOC_UTIL_PRIVATE_H
-
-#include <bson/bson.h>
-#include "mongoc.h"
-
-#ifdef BSON_HAVE_STRINGS_H
-#include <strings.h>
-#endif
-
-/* string comparison functions for Windows */
-#ifdef _WIN32
-#define strcasecmp _stricmp
-#define strncasecmp _strnicmp
-#endif
-
-#if BSON_GNUC_CHECK_VERSION(4, 6)
-#define BEGIN_IGNORE_DEPRECATIONS \
- _Pragma ("GCC diagnostic push") \
- _Pragma ("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
-#define END_IGNORE_DEPRECATIONS _Pragma ("GCC diagnostic pop")
-#elif defined(__clang__)
-#define BEGIN_IGNORE_DEPRECATIONS \
- _Pragma ("clang diagnostic push") \
- _Pragma ("clang diagnostic ignored \"-Wdeprecated-declarations\"")
-#define END_IGNORE_DEPRECATIONS _Pragma ("clang diagnostic pop")
-#else
-#define BEGIN_IGNORE_DEPRECATIONS
-#define END_IGNORE_DEPRECATIONS
-#endif
-
-#ifndef _WIN32
-#define MONGOC_PRINTF_FORMAT(a, b) __attribute__ ((format (__printf__, a, b)))
-#else
-#define MONGOC_PRINTF_FORMAT(a, b) /* no-op */
-#endif
-
-#define COALESCE(x, y) ((x == 0) ? (y) : (x))
-
-
-/* Helper macros for stringifying things */
-#define MONGOC_STR(s) #s
-#define MONGOC_EVALUATE_STR(s) MONGOC_STR (s)
-
-BSON_BEGIN_DECLS
-
-extern const bson_validate_flags_t _mongoc_default_insert_vflags;
-extern const bson_validate_flags_t _mongoc_default_replace_vflags;
-extern const bson_validate_flags_t _mongoc_default_update_vflags;
-
-int
-_mongoc_rand_simple (unsigned int *seed);
-
-char *
-_mongoc_hex_md5 (const char *input);
-
-void
-_mongoc_usleep (int64_t usec);
-
-/* Get the current time as a number of milliseconds since the Unix Epoch. */
-int64_t
-_mongoc_get_real_time_ms (void);
-
-const char *
-_mongoc_get_command_name (const bson_t *command);
-
-const char *
-_mongoc_get_documents_field_name (const char *command_name);
-
-bool
-_mongoc_lookup_bool (const bson_t *bson, const char *key, bool default_value);
-
-/* Returns a database name that the caller must free. */
-char *
-_mongoc_get_db_name (const char *ns);
-
-void
-_mongoc_bson_init_if_set (bson_t *bson);
-
-const char *
-_mongoc_bson_type_to_str (bson_type_t t);
-
-bool
-_mongoc_get_server_id_from_opts (const bson_t *opts,
- mongoc_error_domain_t domain,
- mongoc_error_code_t code,
- uint32_t *server_id,
- bson_error_t *error);
-
-bool
-_mongoc_validate_new_document (const bson_t *insert,
- bson_validate_flags_t vflags,
- bson_error_t *error);
-
-bool
-_mongoc_validate_replace (const bson_t *insert,
- bson_validate_flags_t vflags,
- bson_error_t *error);
-
-bool
-_mongoc_validate_update (const bson_t *update,
- bson_validate_flags_t vflags,
- bson_error_t *error);
-
-void
-mongoc_lowercase (const char *src, char *buf /* OUT */);
-
-bool
-mongoc_parse_port (uint16_t *port, const char *str);
-
-void
-_mongoc_bson_array_add_label (bson_t *bson, const char *label);
-
-void
-_mongoc_bson_array_copy_labels_to (const bson_t *reply, bson_t *dst);
-
-void
-_mongoc_bson_init_with_transient_txn_error (const mongoc_client_session_t *cs,
- bson_t *reply);
-
-bool
-_mongoc_document_is_pipeline (const bson_t *document);
-
-/*
- *--------------------------------------------------------------------------
- *
- * _mongoc_getenv --
- *
- * Get the value of an environment variable.
- *
- * Returns:
- * A string you must bson_free, or NULL if the variable is not set.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-char *
-_mongoc_getenv (const char *name);
-
-BSON_END_DECLS
-
-#endif /* MONGOC_UTIL_PRIVATE_H */
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-util.c b/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-util.c
deleted file mode 100644
index 8d08c59e..00000000
--- a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-util.c
+++ /dev/null
@@ -1,628 +0,0 @@
-/*
- * Copyright 2013 MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifdef _WIN32
-#define _CRT_RAND_S
-#endif
-
-#include <string.h>
-
-#include "common-md5-private.h"
-#include "mongoc-util-private.h"
-#include "mongoc-client.h"
-#include "mongoc-client-session-private.h"
-#include "mongoc-trace-private.h"
-
-const bson_validate_flags_t _mongoc_default_insert_vflags =
- BSON_VALIDATE_UTF8 | BSON_VALIDATE_UTF8_ALLOW_NULL |
- BSON_VALIDATE_EMPTY_KEYS;
-
-const bson_validate_flags_t _mongoc_default_replace_vflags =
- BSON_VALIDATE_UTF8 | BSON_VALIDATE_UTF8_ALLOW_NULL |
- BSON_VALIDATE_EMPTY_KEYS;
-
-const bson_validate_flags_t _mongoc_default_update_vflags =
- BSON_VALIDATE_UTF8 | BSON_VALIDATE_UTF8_ALLOW_NULL |
- BSON_VALIDATE_EMPTY_KEYS;
-
-int
-_mongoc_rand_simple (unsigned int *seed)
-{
-#ifdef _WIN32
- /* ignore the seed */
- unsigned int ret = 0;
- errno_t err;
-
- err = rand_s (&ret);
- if (0 != err) {
- MONGOC_ERROR ("rand_s failed: %s", strerror (err));
- }
-
- return (int) ret;
-#else
- return rand_r (seed);
-#endif
-}
-
-
-char *
-_mongoc_hex_md5 (const char *input)
-{
- uint8_t digest[16];
- bson_md5_t md5;
- char digest_str[33];
- int i;
-
- COMMON_PREFIX (_bson_md5_init (&md5));
- COMMON_PREFIX (_bson_md5_append (
- &md5, (const uint8_t *) input, (uint32_t) strlen (input)));
- COMMON_PREFIX (_bson_md5_finish (&md5, digest));
-
- for (i = 0; i < sizeof digest; i++) {
- bson_snprintf (&digest_str[i * 2], 3, "%02x", digest[i]);
- }
- digest_str[sizeof digest_str - 1] = '\0';
-
- return bson_strdup (digest_str);
-}
-
-
-void
-_mongoc_usleep (int64_t usec)
-{
-#ifdef _WIN32
- LARGE_INTEGER ft;
- HANDLE timer;
-
- BSON_ASSERT (usec >= 0);
-
- ft.QuadPart = -(10 * usec);
- timer = CreateWaitableTimer (NULL, true, NULL);
- SetWaitableTimer (timer, &ft, 0, NULL, NULL, 0);
- WaitForSingleObject (timer, INFINITE);
- CloseHandle (timer);
-#else
- BSON_ASSERT (usec >= 0);
- usleep ((useconds_t) usec);
-#endif
-}
-
-int64_t
-_mongoc_get_real_time_ms (void)
-{
- struct timeval tv;
- const bool rc = bson_gettimeofday (&tv);
- if (rc != 0) {
- return -1;
- }
- return tv.tv_sec * (int64_t) 1000 + tv.tv_usec / (int64_t) 1000;
-}
-
-
-const char *
-_mongoc_get_command_name (const bson_t *command)
-{
- bson_iter_t iter;
- const char *name;
- bson_iter_t child;
- const char *wrapper_name = NULL;
-
- BSON_ASSERT (command);
-
- if (!bson_iter_init (&iter, command) || !bson_iter_next (&iter)) {
- return NULL;
- }
-
- name = bson_iter_key (&iter);
-
- /* wrapped in "$query" or "query"?
- *
- * {$query: {count: "collection"}, $readPreference: {...}}
- */
- if (name[0] == '$') {
- wrapper_name = "$query";
- } else if (!strcmp (name, "query")) {
- wrapper_name = "query";
- }
-
- if (wrapper_name && bson_iter_init_find (&iter, command, wrapper_name) &&
- BSON_ITER_HOLDS_DOCUMENT (&iter) && bson_iter_recurse (&iter, &child) &&
- bson_iter_next (&child)) {
- name = bson_iter_key (&child);
- }
-
- return name;
-}
-
-
-const char *
-_mongoc_get_documents_field_name (const char *command_name)
-{
- if (!strcmp (command_name, "insert")) {
- return "documents";
- }
-
- if (!strcmp (command_name, "update")) {
- return "updates";
- }
-
- if (!strcmp (command_name, "delete")) {
- return "deletes";
- }
-
- return NULL;
-}
-
-bool
-_mongoc_lookup_bool (const bson_t *bson, const char *key, bool default_value)
-{
- bson_iter_t iter;
- bson_iter_t child;
-
- if (!bson) {
- return default_value;
- }
-
- BSON_ASSERT (bson_iter_init (&iter, bson));
- if (!bson_iter_find_descendant (&iter, key, &child)) {
- return default_value;
- }
-
- return bson_iter_as_bool (&child);
-}
-
-char *
-_mongoc_get_db_name (const char *ns)
-{
- size_t dblen;
- const char *dot;
-
- BSON_ASSERT (ns);
-
- dot = strstr (ns, ".");
-
- if (dot) {
- dblen = dot - ns;
- return bson_strndup (ns, dblen);
- } else {
- return bson_strdup (ns);
- }
-}
-
-void
-_mongoc_bson_init_if_set (bson_t *bson)
-{
- if (bson) {
- bson_init (bson);
- }
-}
-
-const char *
-_mongoc_bson_type_to_str (bson_type_t t)
-{
- switch (t) {
- case BSON_TYPE_EOD:
- return "EOD";
- case BSON_TYPE_DOUBLE:
- return "DOUBLE";
- case BSON_TYPE_UTF8:
- return "UTF8";
- case BSON_TYPE_DOCUMENT:
- return "DOCUMENT";
- case BSON_TYPE_ARRAY:
- return "ARRAY";
- case BSON_TYPE_BINARY:
- return "BINARY";
- case BSON_TYPE_UNDEFINED:
- return "UNDEFINED";
- case BSON_TYPE_OID:
- return "OID";
- case BSON_TYPE_BOOL:
- return "BOOL";
- case BSON_TYPE_DATE_TIME:
- return "DATE_TIME";
- case BSON_TYPE_NULL:
- return "NULL";
- case BSON_TYPE_REGEX:
- return "REGEX";
- case BSON_TYPE_DBPOINTER:
- return "DBPOINTER";
- case BSON_TYPE_CODE:
- return "CODE";
- case BSON_TYPE_SYMBOL:
- return "SYMBOL";
- case BSON_TYPE_CODEWSCOPE:
- return "CODEWSCOPE";
- case BSON_TYPE_INT32:
- return "INT32";
- case BSON_TYPE_TIMESTAMP:
- return "TIMESTAMP";
- case BSON_TYPE_INT64:
- return "INT64";
- case BSON_TYPE_MAXKEY:
- return "MAXKEY";
- case BSON_TYPE_MINKEY:
- return "MINKEY";
- case BSON_TYPE_DECIMAL128:
- return "DECIMAL128";
- default:
- return "Unknown";
- }
-}
-
-
-/* Get "serverId" from opts. Sets *server_id to the serverId from "opts" or 0
- * if absent. On error, fills out *error with domain and code and return false.
- */
-bool
-_mongoc_get_server_id_from_opts (const bson_t *opts,
- mongoc_error_domain_t domain,
- mongoc_error_code_t code,
- uint32_t *server_id,
- bson_error_t *error)
-{
- bson_iter_t iter;
-
- ENTRY;
-
- BSON_ASSERT (server_id);
-
- *server_id = 0;
-
- if (!opts || !bson_iter_init_find (&iter, opts, "serverId")) {
- RETURN (true);
- }
-
- if (!BSON_ITER_HOLDS_INT (&iter)) {
- bson_set_error (
- error, domain, code, "The serverId option must be an integer");
- RETURN (false);
- }
-
- if (bson_iter_as_int64 (&iter) <= 0) {
- bson_set_error (error, domain, code, "The serverId option must be >= 1");
- RETURN (false);
- }
-
- *server_id = (uint32_t) bson_iter_as_int64 (&iter);
-
- RETURN (true);
-}
-
-
-bool
-_mongoc_validate_new_document (const bson_t *doc,
- bson_validate_flags_t vflags,
- bson_error_t *error)
-{
- bson_error_t validate_err;
-
- if (vflags == BSON_VALIDATE_NONE) {
- return true;
- }
-
- if (!bson_validate_with_error (doc, vflags, &validate_err)) {
- bson_set_error (error,
- MONGOC_ERROR_COMMAND,
- MONGOC_ERROR_COMMAND_INVALID_ARG,
- "invalid document for insert: %s",
- validate_err.message);
- return false;
- }
-
- return true;
-}
-
-
-bool
-_mongoc_validate_replace (const bson_t *doc,
- bson_validate_flags_t vflags,
- bson_error_t *error)
-{
- bson_error_t validate_err;
- bson_iter_t iter;
- const char *key;
-
- if (vflags == BSON_VALIDATE_NONE) {
- return true;
- }
-
- if (!bson_validate_with_error (doc, vflags, &validate_err)) {
- bson_set_error (error,
- MONGOC_ERROR_COMMAND,
- MONGOC_ERROR_COMMAND_INVALID_ARG,
- "invalid argument for replace: %s",
- validate_err.message);
- return false;
- }
-
- if (!bson_iter_init (&iter, doc)) {
- bson_set_error (error,
- MONGOC_ERROR_BSON,
- MONGOC_ERROR_BSON_INVALID,
- "replace document is corrupt");
- return false;
- }
-
- while (bson_iter_next (&iter)) {
- key = bson_iter_key (&iter);
- if (key[0] == '$') {
- bson_set_error (error,
- MONGOC_ERROR_COMMAND,
- MONGOC_ERROR_COMMAND_INVALID_ARG,
- "Invalid key '%s': replace prohibits $ operators",
- key);
-
- return false;
- }
- }
-
- return true;
-}
-
-
-bool
-_mongoc_validate_update (const bson_t *update,
- bson_validate_flags_t vflags,
- bson_error_t *error)
-{
- bson_error_t validate_err;
- bson_iter_t iter;
- const char *key;
-
- if (vflags == BSON_VALIDATE_NONE) {
- return true;
- }
-
- if (!bson_validate_with_error (update, vflags, &validate_err)) {
- bson_set_error (error,
- MONGOC_ERROR_COMMAND,
- MONGOC_ERROR_COMMAND_INVALID_ARG,
- "invalid argument for update: %s",
- validate_err.message);
- return false;
- }
-
- if (_mongoc_document_is_pipeline (update)) {
- return true;
- }
-
- if (!bson_iter_init (&iter, update)) {
- bson_set_error (error,
- MONGOC_ERROR_BSON,
- MONGOC_ERROR_BSON_INVALID,
- "update document is corrupt");
- return false;
- }
-
- while (bson_iter_next (&iter)) {
- key = bson_iter_key (&iter);
- if (key[0] != '$') {
- bson_set_error (error,
- MONGOC_ERROR_COMMAND,
- MONGOC_ERROR_COMMAND_INVALID_ARG,
- "Invalid key '%s': update only works with $ operators"
- " and pipelines",
- key);
-
- return false;
- }
- }
-
- return true;
-}
-
-void
-mongoc_lowercase (const char *src, char *buf /* OUT */)
-{
- for (; *src; ++src, ++buf) {
- /* UTF8 non-ascii characters have a 1 at the leftmost bit. If this is the
- * case, just copy */
- if ((*src & (0x1 << 7)) == 0) {
- *buf = (char) tolower (*src);
- } else {
- *buf = *src;
- }
- }
-}
-
-bool
-mongoc_parse_port (uint16_t *port, const char *str)
-{
- unsigned long ul_port;
-
- ul_port = strtoul (str, NULL, 10);
-
- if (ul_port == 0 || ul_port > UINT16_MAX) {
- /* Parse error or port number out of range. mongod prohibits port 0. */
- return false;
- }
-
- *port = (uint16_t) ul_port;
- return true;
-}
-
-
-/*--------------------------------------------------------------------------
- *
- * _mongoc_bson_array_add_label --
- *
- * Append an error label like "TransientTransactionError" to a BSON
- * array iff the array does not already contain it.
- *
- * Side effects:
- * Aborts if the array is invalid or contains non-string elements.
- *
- *--------------------------------------------------------------------------
- */
-
-void
-_mongoc_bson_array_add_label (bson_t *bson, const char *label)
-{
- bson_iter_t iter;
- char buf[16];
- uint32_t i = 0;
- const char *key;
-
- BSON_ASSERT (bson_iter_init (&iter, bson));
- while (bson_iter_next (&iter)) {
- if (!strcmp (bson_iter_utf8 (&iter, NULL), label)) {
- /* already included once */
- return;
- }
-
- i++;
- }
-
- bson_uint32_to_string (i, &key, buf, sizeof buf);
- BSON_APPEND_UTF8 (bson, key, label);
-}
-
-
-/*--------------------------------------------------------------------------
- *
- * _mongoc_bson_array_copy_labels_to --
- *
- * Copy error labels like "TransientTransactionError" from a server
- * reply to a BSON array iff the array does not already contain it.
- *
- * Side effects:
- * Aborts if @dst is invalid or contains non-string elements.
- *
- *--------------------------------------------------------------------------
- */
-
-void
-_mongoc_bson_array_copy_labels_to (const bson_t *reply, bson_t *dst)
-{
- bson_iter_t iter;
- bson_iter_t label;
-
- if (bson_iter_init_find (&iter, reply, "errorLabels")) {
- BSON_ASSERT (bson_iter_recurse (&iter, &label));
- while (bson_iter_next (&label)) {
- if (BSON_ITER_HOLDS_UTF8 (&label)) {
- _mongoc_bson_array_add_label (dst, bson_iter_utf8 (&label, NULL));
- }
- }
- }
-}
-
-
-/*--------------------------------------------------------------------------
- *
- * _mongoc_bson_init_with_transient_txn_error --
- *
- * If @reply is not NULL, initialize it. If @cs is not NULL and in a
- * transaction, add errorLabels: ["TransientTransactionError"] to @cs.
- *
- * Transactions Spec: TransientTransactionError includes "server
- * selection error encountered running any command besides
- * commitTransaction in a transaction. ...in the case of network errors
- * or server selection errors where the client receives no server reply,
- * the client adds the label."
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------------------
- */
-
-void
-_mongoc_bson_init_with_transient_txn_error (const mongoc_client_session_t *cs,
- bson_t *reply)
-{
- bson_t labels;
-
- if (!reply) {
- return;
- }
-
- bson_init (reply);
-
- if (_mongoc_client_session_in_txn (cs)) {
- BSON_APPEND_ARRAY_BEGIN (reply, "errorLabels", &labels);
- BSON_APPEND_UTF8 (&labels, "0", TRANSIENT_TXN_ERR);
- bson_append_array_end (reply, &labels);
- }
-}
-
-bool
-_mongoc_document_is_pipeline (const bson_t *document)
-{
- bson_iter_t iter;
- bson_iter_t child;
- const char *key;
- int i = 0;
- char *i_str;
-
- if (!bson_iter_init (&iter, document)) {
- return false;
- }
-
- while (bson_iter_next (&iter)) {
- key = bson_iter_key (&iter);
- i_str = bson_strdup_printf ("%d", i++);
-
- if (strcmp (key, i_str)) {
- bson_free (i_str);
- return false;
- }
-
- bson_free (i_str);
-
- if (BSON_ITER_HOLDS_DOCUMENT (&iter)) {
- if (!bson_iter_recurse (&iter, &child)) {
- return false;
- }
- if (!bson_iter_next (&child)) {
- return false;
- }
- key = bson_iter_key (&child);
- if (key[0] != '$') {
- return false;
- }
- } else {
- return false;
- }
- }
-
- /* should return false when the document is empty */
- return i != 0;
-}
-
-char *
-_mongoc_getenv (const char *name)
-{
-#ifdef _MSC_VER
- char buf[2048];
- size_t buflen;
-
- if ((0 == getenv_s (&buflen, buf, sizeof buf, name)) && buflen) {
- return bson_strdup (buf);
- } else {
- return NULL;
- }
-#else
-
- if (getenv (name) && strlen (getenv (name))) {
- return bson_strdup (getenv (name));
- } else {
- return NULL;
- }
-
-#endif
-}
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-version.h b/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-version.h
deleted file mode 100644
index eca3d245..00000000
--- a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-version.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright 2013 MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-#if !defined (MONGOC_INSIDE) && !defined (MONGOC_COMPILATION)
-#error "Only <mongoc/mongoc.h> can be included directly."
-#endif
-
-
-#ifndef MONGOC_VERSION_H
-#define MONGOC_VERSION_H
-
-
-/**
- * MONGOC_MAJOR_VERSION:
- *
- * MONGOC major version component (e.g. 1 if %MONGOC_VERSION is 1.2.3)
- */
-#define MONGOC_MAJOR_VERSION (1)
-
-
-/**
- * MONGOC_MINOR_VERSION:
- *
- * MONGOC minor version component (e.g. 2 if %MONGOC_VERSION is 1.2.3)
- */
-#define MONGOC_MINOR_VERSION (20)
-
-
-/**
- * MONGOC_MICRO_VERSION:
- *
- * MONGOC micro version component (e.g. 3 if %MONGOC_VERSION is 1.2.3)
- */
-#define MONGOC_MICRO_VERSION (0)
-
-
-/**
- * MONGOC_PRERELEASE_VERSION:
- *
- * MONGOC prerelease version component (e.g. pre if %MONGOC_VERSION is 1.2.3-pre)
- */
-#define MONGOC_PRERELEASE_VERSION ()
-
-
-/**
- * MONGOC_VERSION:
- *
- * MONGOC version.
- */
-#define MONGOC_VERSION (1.20.0)
-
-
-/**
- * MONGOC_VERSION_S:
- *
- * MONGOC version, encoded as a string, useful for printing and
- * concatenation.
- */
-#define MONGOC_VERSION_S "1.20.0"
-
-
-/**
- * MONGOC_VERSION_HEX:
- *
- * MONGOC version, encoded as an hexadecimal number, useful for
- * integer comparisons.
- */
-#define MONGOC_VERSION_HEX (MONGOC_MAJOR_VERSION << 24 | \
- MONGOC_MINOR_VERSION << 16 | \
- MONGOC_MICRO_VERSION << 8)
-
-
-/**
- * MONGOC_CHECK_VERSION:
- * @major: required major version
- * @minor: required minor version
- * @micro: required micro version
- *
- * Compile-time version checking. Evaluates to %TRUE if the version
- * of MONGOC is greater than the required one.
- */
-#define MONGOC_CHECK_VERSION(major,minor,micro) \
- (MONGOC_MAJOR_VERSION > (major) || \
- (MONGOC_MAJOR_VERSION == (major) && MONGOC_MINOR_VERSION > (minor)) || \
- (MONGOC_MAJOR_VERSION == (major) && MONGOC_MINOR_VERSION == (minor) && \
- MONGOC_MICRO_VERSION >= (micro)))
-
-#endif /* MONGOC_VERSION_H */
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/crypto/cng.c b/mongodb-1.12.0/src/libmongocrypt/src/crypto/cng.c
deleted file mode 100644
index 34a97e66..00000000
--- a/mongodb-1.12.0/src/libmongocrypt/src/crypto/cng.c
+++ /dev/null
@@ -1,318 +0,0 @@
-/*
- * Copyright 2019-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "../mongocrypt-crypto-private.h"
-#include "../mongocrypt-private.h"
-
-#ifdef MONGOCRYPT_ENABLE_CRYPTO_CNG
-
-#include <bcrypt.h>
-
-static BCRYPT_ALG_HANDLE _algo_sha512_hmac = 0;
-static BCRYPT_ALG_HANDLE _algo_aes256 = 0;
-static DWORD _aes256_key_blob_length;
-
-static BCRYPT_ALG_HANDLE _random;
-
-#define STATUS_SUCCESS 0
-
-bool _native_crypto_initialized = false;
-
-void
-_native_crypto_init ()
-{
- DWORD cbOutput;
- NTSTATUS nt_status;
-
- /* Note, there is no mechanism for libmongocrypt to close these providers,
- * If we ever add such a mechanism, call BCryptCloseAlgorithmProvider.
- */
- nt_status = BCryptOpenAlgorithmProvider (&_algo_sha512_hmac,
- BCRYPT_SHA512_ALGORITHM,
- MS_PRIMITIVE_PROVIDER,
- BCRYPT_ALG_HANDLE_HMAC_FLAG);
- if (nt_status != STATUS_SUCCESS) {
- return;
- }
-
- nt_status = BCryptOpenAlgorithmProvider (
- &_algo_aes256, BCRYPT_AES_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0);
- if (nt_status != STATUS_SUCCESS) {
- return;
- }
-
- nt_status = BCryptSetProperty (
- _algo_aes256,
- BCRYPT_CHAINING_MODE,
- (PUCHAR) (BCRYPT_CHAIN_MODE_CBC),
- (ULONG) (sizeof (wchar_t) * wcslen (BCRYPT_CHAIN_MODE_CBC)),
- 0);
- if (nt_status != STATUS_SUCCESS) {
- return;
- }
-
- cbOutput = sizeof (_aes256_key_blob_length);
- nt_status = BCryptGetProperty (_algo_aes256,
- BCRYPT_OBJECT_LENGTH,
- (PUCHAR) (&_aes256_key_blob_length),
- cbOutput,
- &cbOutput,
- 0);
- if (nt_status != STATUS_SUCCESS) {
- return;
- }
-
- nt_status = BCryptOpenAlgorithmProvider (
- &_random, BCRYPT_RNG_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0);
- if (nt_status != STATUS_SUCCESS) {
- return;
- }
-
- _native_crypto_initialized = true;
-}
-
-typedef struct {
- unsigned char *key_object;
- uint32_t key_object_length;
-
- BCRYPT_KEY_HANDLE key_handle;
-
- unsigned char *iv;
- uint32_t iv_len;
-} cng_encrypt_state;
-
-static void
-_crypto_state_destroy (cng_encrypt_state *state);
-
-static cng_encrypt_state *
-_crypto_state_init (const _mongocrypt_buffer_t *key,
- const _mongocrypt_buffer_t *iv,
- mongocrypt_status_t *status)
-{
- cng_encrypt_state *state;
- uint32_t keyBlobLength;
- unsigned char *keyBlob;
- BCRYPT_KEY_DATA_BLOB_HEADER blobHeader;
- NTSTATUS nt_status;
-
- keyBlob = NULL;
-
- state = bson_malloc0 (sizeof (*state));
- BSON_ASSERT (state);
-
- state->key_handle = INVALID_HANDLE_VALUE;
-
- /* Initialize key storage buffer */
- state->key_object = bson_malloc0 (_aes256_key_blob_length);
- BSON_ASSERT (state->key_object);
-
- state->key_object_length = _aes256_key_blob_length;
-
- /* Allocate temporary buffer for key import */
- keyBlobLength = sizeof (BCRYPT_KEY_DATA_BLOB_HEADER) + key->len;
- keyBlob = bson_malloc0 (keyBlobLength);
- BSON_ASSERT (keyBlob);
-
-
- blobHeader.dwMagic = BCRYPT_KEY_DATA_BLOB_MAGIC;
- blobHeader.dwVersion = BCRYPT_KEY_DATA_BLOB_VERSION1;
- blobHeader.cbKeyData = key->len;
-
- memcpy (keyBlob, &blobHeader, sizeof (BCRYPT_KEY_DATA_BLOB_HEADER));
-
- memcpy (keyBlob + sizeof (BCRYPT_KEY_DATA_BLOB_HEADER), key->data, key->len);
-
- nt_status = BCryptImportKey (_algo_aes256,
- NULL,
- BCRYPT_KEY_DATA_BLOB,
- &(state->key_handle),
- state->key_object,
- state->key_object_length,
- keyBlob,
- keyBlobLength,
- 0);
- if (nt_status != STATUS_SUCCESS) {
- CLIENT_ERR ("Import Key Failed: 0x%x", (int) nt_status);
- goto fail;
- }
-
- bson_free (keyBlob);
-
- state->iv = bson_malloc0 (iv->len);
- BSON_ASSERT (state->iv);
-
- state->iv_len = iv->len;
- memcpy (state->iv, iv->data, iv->len);
-
- return state;
-fail:
- _crypto_state_destroy (state);
- bson_free (keyBlob);
-
- return NULL;
-}
-
-
-static void
-_crypto_state_destroy (cng_encrypt_state *state)
-{
- if (state) {
- /* Free the key handle before the key_object that contains it */
- if (state->key_handle != INVALID_HANDLE_VALUE) {
- BCryptDestroyKey (state->key_handle);
- }
-
- bson_free (state->key_object);
- bson_free (state->iv);
- bson_free (state);
- }
-}
-
-
-bool
-_native_crypto_aes_256_cbc_encrypt (const _mongocrypt_buffer_t *key,
- const _mongocrypt_buffer_t *iv,
- const _mongocrypt_buffer_t *in,
- _mongocrypt_buffer_t *out,
- uint32_t *bytes_written,
- mongocrypt_status_t *status)
-{
- bool ret = false;
- cng_encrypt_state *state = _crypto_state_init (key, iv, status);
-
- NTSTATUS nt_status;
-
- nt_status = BCryptEncrypt (state->key_handle,
- (PUCHAR) (in->data),
- in->len,
- NULL,
- state->iv,
- state->iv_len,
- out->data,
- out->len,
- bytes_written,
- 0);
-
- if (nt_status != STATUS_SUCCESS) {
- CLIENT_ERR ("error initializing cipher: 0x%x", (int) nt_status);
- goto done;
- }
-
- ret = true;
-done:
- _crypto_state_destroy (state);
- return ret;
-}
-
-
-bool
-_native_crypto_aes_256_cbc_decrypt (const _mongocrypt_buffer_t *key,
- const _mongocrypt_buffer_t *iv,
- const _mongocrypt_buffer_t *in,
- _mongocrypt_buffer_t *out,
- uint32_t *bytes_written,
- mongocrypt_status_t *status)
-{
- bool ret = false;
- cng_encrypt_state *state = _crypto_state_init (key, iv, status);
-
- NTSTATUS nt_status;
-
- nt_status = BCryptDecrypt (state->key_handle,
- (PUCHAR) (in->data),
- in->len,
- NULL,
- state->iv,
- state->iv_len,
- out->data,
- out->len,
- bytes_written,
- 0);
-
-
- if (nt_status != STATUS_SUCCESS) {
- CLIENT_ERR ("error initializing cipher: 0x%x", (int) nt_status);
- goto done;
- }
-
- ret = true;
-done:
- _crypto_state_destroy (state);
- return ret;
-}
-
-
-bool
-_native_crypto_hmac_sha_512 (const _mongocrypt_buffer_t *key,
- const _mongocrypt_buffer_t *in,
- _mongocrypt_buffer_t *out,
- mongocrypt_status_t *status)
-{
- bool ret = false;
- BCRYPT_HASH_HANDLE hHash;
- NTSTATUS nt_status;
-
- if (out->len != 64) {
- CLIENT_ERR ("out does not contain 64 bytes");
- return false;
- }
-
- nt_status = BCryptCreateHash (_algo_sha512_hmac,
- &hHash,
- NULL,
- 0,
- (PUCHAR) key->data,
- (ULONG) key->len,
- 0);
- if (nt_status != STATUS_SUCCESS) {
- CLIENT_ERR ("error initializing hmac: 0x%x", (int) nt_status);
- goto done;
- }
-
- nt_status = BCryptHashData (hHash, (PUCHAR) in->data, (ULONG) in->len, 0);
- if (nt_status != STATUS_SUCCESS) {
- CLIENT_ERR ("error hashing data: 0x%x", (int) nt_status);
- goto done;
- }
-
- nt_status = BCryptFinishHash (hHash, out->data, out->len, 0);
- if (nt_status != STATUS_SUCCESS) {
- CLIENT_ERR ("error finishing hmac: 0x%x", (int) nt_status);
- goto done;
- }
-
- ret = true;
-done:
- (void) BCryptDestroyHash (hHash);
- return ret;
-}
-
-
-bool
-_native_crypto_random (_mongocrypt_buffer_t *out,
- uint32_t count,
- mongocrypt_status_t *status)
-{
- NTSTATUS nt_status = BCryptGenRandom (_random, out->data, count, 0);
- if (nt_status != STATUS_SUCCESS) {
- CLIENT_ERR ("BCryptGenRandom Failed: 0x%x", (int) nt_status);
- return false;
- }
-
- return true;
-}
-
-#endif /* MONGOCRYPT_ENABLE_CRYPTO_CNG */
\ No newline at end of file
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/crypto/commoncrypto.c b/mongodb-1.12.0/src/libmongocrypt/src/crypto/commoncrypto.c
deleted file mode 100644
index ed964829..00000000
--- a/mongodb-1.12.0/src/libmongocrypt/src/crypto/commoncrypto.c
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright 2019-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "../mongocrypt-crypto-private.h"
-#include "../mongocrypt-private.h"
-
-#ifdef MONGOCRYPT_ENABLE_CRYPTO_COMMON_CRYPTO
-
-#include <CommonCrypto/CommonCryptor.h>
-#include <CommonCrypto/CommonHMAC.h>
-#include <CommonCrypto/CommonRandom.h>
-
-bool _native_crypto_initialized = false;
-
-void
-_native_crypto_init ()
-{
- _native_crypto_initialized = true;
-}
-
-
-bool
-_native_crypto_aes_256_cbc_encrypt (const _mongocrypt_buffer_t *key,
- const _mongocrypt_buffer_t *iv,
- const _mongocrypt_buffer_t *in,
- _mongocrypt_buffer_t *out,
- uint32_t *bytes_written,
- mongocrypt_status_t *status)
-{
- bool ret = false;
- CCCryptorRef ctx = NULL;
- CCCryptorStatus cc_status;
- size_t intermediate_bytes_written;
-
- cc_status = CCCryptorCreate (kCCEncrypt,
- kCCAlgorithmAES,
- 0 /* defaults to CBC w/ no padding */,
- key->data,
- kCCKeySizeAES256,
- iv->data,
- &ctx);
-
- if (cc_status != kCCSuccess) {
- CLIENT_ERR ("error initializing cipher: %d", (int) cc_status);
- goto done;
- }
-
- *bytes_written = 0;
-
- cc_status = CCCryptorUpdate (
- ctx, in->data, in->len, out->data, out->len, &intermediate_bytes_written);
- if (cc_status != kCCSuccess) {
- CLIENT_ERR ("error encrypting: %d", (int) cc_status);
- goto done;
- }
- *bytes_written = intermediate_bytes_written;
-
-
- cc_status = CCCryptorFinal (ctx,
- out->data + *bytes_written,
- out->len - *bytes_written,
- &intermediate_bytes_written);
- *bytes_written += intermediate_bytes_written;
-
- if (cc_status != kCCSuccess) {
- CLIENT_ERR ("error finalizing: %d", (int) cc_status);
- goto done;
- }
-
- ret = true;
-done:
- CCCryptorRelease (ctx);
- return ret;
-}
-
-
-/* Note, the decrypt function is almost exactly the same as the encrypt
- * functions except for the kCCDecrypt and the error message. */
-bool
-_native_crypto_aes_256_cbc_decrypt (const _mongocrypt_buffer_t *key,
- const _mongocrypt_buffer_t *iv,
- const _mongocrypt_buffer_t *in,
- _mongocrypt_buffer_t *out,
- uint32_t *bytes_written,
- mongocrypt_status_t *status)
-{
- bool ret = false;
- CCCryptorRef ctx = NULL;
- CCCryptorStatus cc_status;
- size_t intermediate_bytes_written;
-
- cc_status = CCCryptorCreate (kCCDecrypt,
- kCCAlgorithmAES,
- 0 /* defaults to CBC w/ no padding */,
- key->data,
- kCCKeySizeAES256,
- iv->data,
- &ctx);
-
- if (cc_status != kCCSuccess) {
- CLIENT_ERR ("error initializing cipher: %d", (int) cc_status);
- goto done;
- }
-
- *bytes_written = 0;
- cc_status = CCCryptorUpdate (
- ctx, in->data, in->len, out->data, out->len, &intermediate_bytes_written);
- if (cc_status != kCCSuccess) {
- CLIENT_ERR ("error decrypting: %d", (int) cc_status);
- goto done;
- }
- *bytes_written = intermediate_bytes_written;
-
- cc_status = CCCryptorFinal (ctx,
- out->data + *bytes_written,
- out->len - *bytes_written,
- &intermediate_bytes_written);
- *bytes_written += intermediate_bytes_written;
-
- if (cc_status != kCCSuccess) {
- CLIENT_ERR ("error finalizing: %d", (int) cc_status);
- goto done;
- }
-
- ret = true;
-done:
- CCCryptorRelease (ctx);
- return ret;
-}
-
-
-/* CCHmac functions don't return errors. */
-bool
-_native_crypto_hmac_sha_512 (const _mongocrypt_buffer_t *key,
- const _mongocrypt_buffer_t *in,
- _mongocrypt_buffer_t *out,
- mongocrypt_status_t *status)
-{
- CCHmacContext *ctx;
-
- if (out->len != MONGOCRYPT_HMAC_SHA512_LEN) {
- CLIENT_ERR ("out does not contain %d bytes", MONGOCRYPT_HMAC_SHA512_LEN);
- return false;
- }
-
- ctx = bson_malloc0 (sizeof (*ctx));
- BSON_ASSERT (ctx);
-
-
- CCHmacInit (ctx, kCCHmacAlgSHA512, key->data, key->len);
- CCHmacUpdate (ctx, in->data, in->len);
- CCHmacFinal (ctx, out->data);
- bson_free (ctx);
- return true;
-}
-
-
-bool
-_native_crypto_random (_mongocrypt_buffer_t *out,
- uint32_t count,
- mongocrypt_status_t *status)
-{
- CCRNGStatus ret = CCRandomGenerateBytes (out->data, (size_t) count);
- if (ret != kCCSuccess) {
- CLIENT_ERR ("failed to generate random iv: %d", (int) ret);
- return false;
- }
- return true;
-}
-
-#endif /* MONGOCRYPT_ENABLE_CRYPTO_COMMON_CRYPTO */
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/crypto/libcrypto.c b/mongodb-1.12.0/src/libmongocrypt/src/crypto/libcrypto.c
deleted file mode 100644
index 61d1c0f6..00000000
--- a/mongodb-1.12.0/src/libmongocrypt/src/crypto/libcrypto.c
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- * Copyright 2019-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * Comments in this implementation refer to:
- * [MCGREW] https://tools.ietf.org/html/draft-mcgrew-aead-aes-cbc-hmac-sha2-05
- */
-
-#include "../mongocrypt-crypto-private.h"
-#include "../mongocrypt-private.h"
-#include "../mongocrypt-log-private.h"
-
-#ifdef MONGOCRYPT_ENABLE_CRYPTO_LIBCRYPTO
-
-#include <bson/bson.h>
-
-#include <openssl/crypto.h>
-#include <openssl/evp.h>
-#include <openssl/err.h>
-#include <openssl/hmac.h>
-#include <openssl/rand.h>
-
-#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
- (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000L)
-EVP_CIPHER_CTX *
-EVP_CIPHER_CTX_new (void)
-{
- return bson_malloc0 (sizeof (EVP_CIPHER_CTX));
-}
-
-void
-EVP_CIPHER_CTX_free (EVP_CIPHER_CTX *ctx)
-{
- EVP_CIPHER_CTX_cleanup (ctx);
- bson_free (ctx);
-}
-
-HMAC_CTX *
-HMAC_CTX_new (void)
-{
- return bson_malloc0 (sizeof (HMAC_CTX));
-}
-
-void
-HMAC_CTX_free (HMAC_CTX *ctx)
-{
- HMAC_CTX_cleanup (ctx);
- bson_free (ctx);
-}
-#endif
-
-bool _native_crypto_initialized = false;
-
-void
-_native_crypto_init ()
-{
- _native_crypto_initialized = true;
-}
-
-bool
-_native_crypto_aes_256_cbc_encrypt (const _mongocrypt_buffer_t *key,
- const _mongocrypt_buffer_t *iv,
- const _mongocrypt_buffer_t *in,
- _mongocrypt_buffer_t *out,
- uint32_t *bytes_written,
- mongocrypt_status_t *status)
-{
- const EVP_CIPHER *cipher;
- EVP_CIPHER_CTX *ctx;
- bool ret = false;
- int intermediate_bytes_written;
-
- ctx = EVP_CIPHER_CTX_new ();
- cipher = EVP_aes_256_cbc ();
-
- BSON_ASSERT (ctx);
- BSON_ASSERT (cipher);
- BSON_ASSERT (EVP_CIPHER_iv_length (cipher) == iv->len);
- BSON_ASSERT (EVP_CIPHER_key_length (cipher) == key->len);
- BSON_ASSERT (EVP_CIPHER_block_size (cipher) == 16);
-
- if (!EVP_EncryptInit_ex (
- ctx, cipher, NULL /* engine */, key->data, iv->data)) {
- CLIENT_ERR ("error initializing cipher: %s",
- ERR_error_string (ERR_get_error (), NULL));
- goto done;
- }
-
- /* Disable the default OpenSSL padding. */
- EVP_CIPHER_CTX_set_padding (ctx, 0);
-
- *bytes_written = 0;
- if (!EVP_EncryptUpdate (
- ctx, out->data, &intermediate_bytes_written, in->data, in->len)) {
- CLIENT_ERR ("error encrypting: %s",
- ERR_error_string (ERR_get_error (), NULL));
- goto done;
- }
-
- *bytes_written = (uint32_t) intermediate_bytes_written;
-
- if (!EVP_EncryptFinal_ex (ctx, out->data, &intermediate_bytes_written)) {
- CLIENT_ERR ("error finalizing: %s",
- ERR_error_string (ERR_get_error (), NULL));
- goto done;
- }
-
- *bytes_written += (uint32_t) intermediate_bytes_written;
-
- ret = true;
-done:
- EVP_CIPHER_CTX_free (ctx);
- return ret;
-}
-
-
-bool
-_native_crypto_aes_256_cbc_decrypt (const _mongocrypt_buffer_t *key,
- const _mongocrypt_buffer_t *iv,
- const _mongocrypt_buffer_t *in,
- _mongocrypt_buffer_t *out,
- uint32_t *bytes_written,
- mongocrypt_status_t *status)
-{
- const EVP_CIPHER *cipher;
- EVP_CIPHER_CTX *ctx;
- bool ret = false;
- int intermediate_bytes_written;
-
- ctx = EVP_CIPHER_CTX_new ();
- cipher = EVP_aes_256_cbc ();
-
- BSON_ASSERT (EVP_CIPHER_iv_length (cipher) == iv->len);
- BSON_ASSERT (EVP_CIPHER_key_length (cipher) == key->len);
- BSON_ASSERT (EVP_CIPHER_block_size (cipher) == MONGOCRYPT_BLOCK_SIZE);
-
- if (!EVP_DecryptInit_ex (
- ctx, cipher, NULL /* engine */, key->data, iv->data)) {
- CLIENT_ERR ("error initializing cipher: %s",
- ERR_error_string (ERR_get_error (), NULL));
- goto done;
- }
-
- /* Disable padding. */
- EVP_CIPHER_CTX_set_padding (ctx, 0);
-
- *bytes_written = 0;
-
- if (!EVP_DecryptUpdate (
- ctx, out->data, &intermediate_bytes_written, in->data, in->len)) {
- CLIENT_ERR ("error decrypting: %s",
- ERR_error_string (ERR_get_error (), NULL));
- goto done;
- }
-
- *bytes_written = intermediate_bytes_written;
-
- if (!EVP_DecryptFinal_ex (ctx, out->data, &intermediate_bytes_written)) {
- CLIENT_ERR ("error decrypting: %s",
- ERR_error_string (ERR_get_error (), NULL));
- goto done;
- }
-
- *bytes_written += intermediate_bytes_written;
-
- ret = true;
-done:
- EVP_CIPHER_CTX_free (ctx);
- return ret;
-}
-
-
-bool
-_native_crypto_hmac_sha_512 (const _mongocrypt_buffer_t *key,
- const _mongocrypt_buffer_t *in,
- _mongocrypt_buffer_t *out,
- mongocrypt_status_t *status)
-{
- const EVP_MD *algo;
- HMAC_CTX *ctx;
- bool ret = false;
-
- ctx = HMAC_CTX_new ();
- algo = EVP_sha512 ();
- BSON_ASSERT (EVP_MD_block_size (algo) == 128);
- BSON_ASSERT (EVP_MD_size (algo) == MONGOCRYPT_HMAC_SHA512_LEN);
-
- if (out->len != MONGOCRYPT_HMAC_SHA512_LEN) {
- CLIENT_ERR ("out does not contain %d bytes", MONGOCRYPT_HMAC_SHA512_LEN);
- return false;
- }
-
- if (!HMAC_Init_ex (ctx, key->data, key->len, algo, NULL /* engine */)) {
- CLIENT_ERR ("error initializing HMAC: %s",
- ERR_error_string (ERR_get_error (), NULL));
- goto done;
- }
-
- if (!HMAC_Update (ctx, in->data, in->len)) {
- CLIENT_ERR ("error updating HMAC: %s",
- ERR_error_string (ERR_get_error (), NULL));
- goto done;
- }
-
- if (!HMAC_Final (ctx, out->data, NULL /* unused out len */)) {
- CLIENT_ERR ("error finalizing: %s",
- ERR_error_string (ERR_get_error (), NULL));
- goto done;
- }
-
- ret = true;
-done:
- HMAC_CTX_free (ctx);
- return ret;
-}
-
-
-bool
-_native_crypto_random (_mongocrypt_buffer_t *out,
- uint32_t count,
- mongocrypt_status_t *status)
-{
- int ret = RAND_bytes (out->data, count);
- /* From man page: "RAND_bytes() and RAND_priv_bytes() return 1 on success, -1
- * if not supported by the current RAND method, or 0 on other failure. The
- * error code can be obtained by ERR_get_error(3)" */
- if (ret == -1) {
- CLIENT_ERR ("secure random IV not supported: %s",
- ERR_error_string (ERR_get_error (), NULL));
- return false;
- } else if (ret == 0) {
- CLIENT_ERR ("failed to generate random IV: %s",
- ERR_error_string (ERR_get_error (), NULL));
- return false;
- }
- return true;
-}
-
-#endif /* MONGOCRYPT_ENABLE_CRYPTO_LIBCRYPTO */
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/crypto/none.c b/mongodb-1.12.0/src/libmongocrypt/src/crypto/none.c
deleted file mode 100644
index 04f75565..00000000
--- a/mongodb-1.12.0/src/libmongocrypt/src/crypto/none.c
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright 2019-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/* everything is a no-op */
-
-#include "../mongocrypt-crypto-private.h"
-#include "../mongocrypt-private.h"
-
-#ifndef MONGOCRYPT_ENABLE_CRYPTO
-
-bool _native_crypto_initialized = false;
-
-void
-_native_crypto_init ()
-{
- _native_crypto_initialized = true;
-}
-
-
-bool
-_native_crypto_aes_256_cbc_encrypt (const _mongocrypt_buffer_t *key,
- const _mongocrypt_buffer_t *iv,
- const _mongocrypt_buffer_t *in,
- _mongocrypt_buffer_t *out,
- uint32_t *bytes_written,
- mongocrypt_status_t *status)
-{
- CLIENT_ERR ("hook not set for aes_256_cbc_encrypt");
- return false;
-}
-
-
-bool
-_native_crypto_aes_256_cbc_decrypt (const _mongocrypt_buffer_t *key,
- const _mongocrypt_buffer_t *iv,
- const _mongocrypt_buffer_t *in,
- _mongocrypt_buffer_t *out,
- uint32_t *bytes_written,
- mongocrypt_status_t *status)
-{
- CLIENT_ERR ("hook not set for aes_256_cbc_decrypt");
- return false;
-}
-
-
-bool
-_native_crypto_hmac_sha_512 (const _mongocrypt_buffer_t *key,
- const _mongocrypt_buffer_t *in,
- _mongocrypt_buffer_t *out,
- mongocrypt_status_t *status)
-{
- CLIENT_ERR ("hook not set for hmac_sha_512");
- return false;
-}
-
-
-bool
-_native_crypto_random (_mongocrypt_buffer_t *out,
- uint32_t count,
- mongocrypt_status_t *status)
-{
- CLIENT_ERR ("hook not set for random");
- return false;
-}
-
-#endif /* MONGOCRYPT_ENABLE_CRYPTO */
\ No newline at end of file
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-crypto-private.h b/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-crypto-private.h
deleted file mode 100644
index 93cf9a62..00000000
--- a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-crypto-private.h
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Copyright 2019-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef MONGOCRYPT_CRYPTO_PRIVATE_H
-#define MONGOCRYPT_CRYPTO_PRIVATE_H
-
-#include "mongocrypt.h"
-#include "mongocrypt-buffer-private.h"
-
-#define MONGOCRYPT_KEY_LEN 96
-#define MONGOCRYPT_IV_KEY_LEN 32
-#define MONGOCRYPT_MAC_KEY_LEN 32
-#define MONGOCRYPT_ENC_KEY_LEN 32
-#define MONGOCRYPT_IV_LEN 16
-#define MONGOCRYPT_HMAC_SHA512_LEN 64
-#define MONGOCRYPT_HMAC_LEN 32
-#define MONGOCRYPT_BLOCK_SIZE 16
-
-typedef struct {
- int hooks_enabled;
- mongocrypt_crypto_fn aes_256_cbc_encrypt;
- mongocrypt_crypto_fn aes_256_cbc_decrypt;
- mongocrypt_random_fn random;
- mongocrypt_hmac_fn hmac_sha_512;
- mongocrypt_hmac_fn hmac_sha_256;
- mongocrypt_hash_fn sha_256;
- void *ctx;
-} _mongocrypt_crypto_t;
-
-uint32_t
-_mongocrypt_calculate_ciphertext_len (uint32_t plaintext_len);
-
-uint32_t
-_mongocrypt_calculate_plaintext_len (uint32_t ciphertext_len);
-
-bool
-_mongocrypt_do_encryption (_mongocrypt_crypto_t *crypto,
- const _mongocrypt_buffer_t *iv,
- const _mongocrypt_buffer_t *associated_data,
- const _mongocrypt_buffer_t *key,
- const _mongocrypt_buffer_t *plaintext,
- _mongocrypt_buffer_t *ciphertext,
- uint32_t *bytes_written,
- mongocrypt_status_t *status)
- MONGOCRYPT_WARN_UNUSED_RESULT;
-
-bool
-_mongocrypt_do_decryption (_mongocrypt_crypto_t *crypto,
- const _mongocrypt_buffer_t *associated_data,
- const _mongocrypt_buffer_t *key,
- const _mongocrypt_buffer_t *ciphertext,
- _mongocrypt_buffer_t *plaintext,
- uint32_t *bytes_written,
- mongocrypt_status_t *status)
- MONGOCRYPT_WARN_UNUSED_RESULT;
-
-bool
-_mongocrypt_random (_mongocrypt_crypto_t *crypto,
- _mongocrypt_buffer_t *out,
- uint32_t count,
- mongocrypt_status_t *status) MONGOCRYPT_WARN_UNUSED_RESULT;
-
-/* Returns 0 if equal, non-zero otherwise */
-int
-_mongocrypt_memequal (const void *const b1, const void *const b2, size_t len);
-
-
-/*
- * _mongocrypt_wrap_key encrypts a DEK with a KEK.
-
- * kek is an input Key Encryption Key.
- * dek is an input Data Encryption Key.
- * encrypted_dek the result of encrypting dek with kek.
- * encrypted_dek is always initialized.
- * Returns true if no error occurred.
- * Returns false and sets @status if an error occurred.
- */
-bool
-_mongocrypt_wrap_key (_mongocrypt_crypto_t *crypto,
- _mongocrypt_buffer_t *kek,
- _mongocrypt_buffer_t *dek,
- _mongocrypt_buffer_t *encrypted_dek,
- mongocrypt_status_t *status)
- MONGOCRYPT_WARN_UNUSED_RESULT;
-
-/*
- * _mongocrypt_unwrap_key decrypts an encrypted DEK with a KEK.
- *
- * kek is an input Key Encryption Key.
- * encrypted_dek is an input encrypted Data Encryption Key.
- * dek is the result of decrypting encrypted_dek with kek.
- * dek is always initialized.
- * Returns true if no error occurred.
- * Returns false and sets @status if an error occurred.
- */
-bool
-_mongocrypt_unwrap_key (_mongocrypt_crypto_t *crypto,
- _mongocrypt_buffer_t *kek,
- _mongocrypt_buffer_t *encrypted_dek,
- _mongocrypt_buffer_t *dek,
- mongocrypt_status_t *status)
- MONGOCRYPT_WARN_UNUSED_RESULT;
-
-bool
-_mongocrypt_calculate_deterministic_iv (
- _mongocrypt_crypto_t *crypto,
- const _mongocrypt_buffer_t *key,
- const _mongocrypt_buffer_t *plaintext,
- const _mongocrypt_buffer_t *associated_data,
- _mongocrypt_buffer_t *out,
- mongocrypt_status_t *status) MONGOCRYPT_WARN_UNUSED_RESULT;
-
-/* Crypto implementations must implement these functions. */
-
-/* This variable must be defined in implementation
- files, and must be set to true when _crypto_init
- is successful. */
-extern bool _native_crypto_initialized;
-
-void
-_native_crypto_init ();
-
-
-bool
-_native_crypto_aes_256_cbc_encrypt (const _mongocrypt_buffer_t *key,
- const _mongocrypt_buffer_t *iv,
- const _mongocrypt_buffer_t *in,
- _mongocrypt_buffer_t *out,
- uint32_t *bytes_written,
- mongocrypt_status_t *status)
- MONGOCRYPT_WARN_UNUSED_RESULT;
-
-bool
-_native_crypto_aes_256_cbc_decrypt (const _mongocrypt_buffer_t *key,
- const _mongocrypt_buffer_t *iv,
- const _mongocrypt_buffer_t *in,
- _mongocrypt_buffer_t *out,
- uint32_t *bytes_written,
- mongocrypt_status_t *status)
- MONGOCRYPT_WARN_UNUSED_RESULT;
-
-bool
-_native_crypto_hmac_sha_512 (const _mongocrypt_buffer_t *key,
- const _mongocrypt_buffer_t *in,
- _mongocrypt_buffer_t *out,
- mongocrypt_status_t *status)
- MONGOCRYPT_WARN_UNUSED_RESULT;
-
-bool
-_native_crypto_random (_mongocrypt_buffer_t *out,
- uint32_t count,
- mongocrypt_status_t *status)
- MONGOCRYPT_WARN_UNUSED_RESULT;
-
-#endif /* MONGOCRYPT_CRYPTO_PRIVATE_H */
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-crypto.c b/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-crypto.c
deleted file mode 100644
index 5fdc9ae4..00000000
--- a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-crypto.c
+++ /dev/null
@@ -1,996 +0,0 @@
-/*
- * Copyright 2019-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * Comments in this implementation refer to:
- * [MCGREW] https://tools.ietf.org/html/draft-mcgrew-aead-aes-cbc-hmac-sha2-05
- */
-
-#include <bson/bson.h>
-
-#include "mongocrypt-binary-private.h"
-#include "mongocrypt-buffer-private.h"
-#include "mongocrypt-crypto-private.h"
-#include "mongocrypt-log-private.h"
-#include "mongocrypt-private.h"
-#include "mongocrypt-status-private.h"
-
-#include <inttypes.h>
-
-/* Crypto primitives. These either call the native built in crypto primitives or
- * user supplied hooks. */
-static bool
-_crypto_aes_256_cbc_encrypt (_mongocrypt_crypto_t *crypto,
- const _mongocrypt_buffer_t *enc_key,
- const _mongocrypt_buffer_t *iv,
- const _mongocrypt_buffer_t *in,
- _mongocrypt_buffer_t *out,
- uint32_t *bytes_written,
- mongocrypt_status_t *status)
-{
- if (enc_key->len != MONGOCRYPT_ENC_KEY_LEN) {
- CLIENT_ERR ("invalid encryption key length");
- return false;
- }
-
- if (iv->len != MONGOCRYPT_IV_LEN) {
- CLIENT_ERR ("invalid iv length");
- return false;
- }
-
- if (crypto->hooks_enabled) {
- mongocrypt_binary_t enc_key_bin, iv_bin, out_bin, in_bin;
- bool ret;
-
- _mongocrypt_buffer_to_binary (enc_key, &enc_key_bin);
- _mongocrypt_buffer_to_binary (iv, &iv_bin);
- _mongocrypt_buffer_to_binary (out, &out_bin);
- _mongocrypt_buffer_to_binary (in, &in_bin);
-
- ret = crypto->aes_256_cbc_encrypt (crypto->ctx,
- &enc_key_bin,
- &iv_bin,
- &in_bin,
- &out_bin,
- bytes_written,
- status);
- return ret;
- }
- return _native_crypto_aes_256_cbc_encrypt (
- enc_key, iv, in, out, bytes_written, status);
-}
-
-
-static bool
-_crypto_aes_256_cbc_decrypt (_mongocrypt_crypto_t *crypto,
- const _mongocrypt_buffer_t *iv,
- const _mongocrypt_buffer_t *enc_key,
- const _mongocrypt_buffer_t *in,
- _mongocrypt_buffer_t *out,
- uint32_t *bytes_written,
- mongocrypt_status_t *status)
-{
- if (enc_key->len != MONGOCRYPT_ENC_KEY_LEN) {
- CLIENT_ERR ("invalid encryption key length");
- return false;
- }
-
- if (crypto->hooks_enabled) {
- mongocrypt_binary_t enc_key_bin, iv_bin, out_bin, in_bin;
- bool ret;
-
- _mongocrypt_buffer_to_binary (enc_key, &enc_key_bin);
- _mongocrypt_buffer_to_binary (iv, &iv_bin);
- _mongocrypt_buffer_to_binary (out, &out_bin);
- _mongocrypt_buffer_to_binary (in, &in_bin);
-
- ret = crypto->aes_256_cbc_decrypt (crypto->ctx,
- &enc_key_bin,
- &iv_bin,
- &in_bin,
- &out_bin,
- bytes_written,
- status);
- return ret;
- }
- return _native_crypto_aes_256_cbc_decrypt (
- enc_key, iv, in, out, bytes_written, status);
-}
-
-
-static bool
-_crypto_hmac_sha_512 (_mongocrypt_crypto_t *crypto,
- const _mongocrypt_buffer_t *hmac_key,
- const _mongocrypt_buffer_t *in,
- _mongocrypt_buffer_t *out,
- mongocrypt_status_t *status)
-{
- if (hmac_key->len != MONGOCRYPT_MAC_KEY_LEN) {
- CLIENT_ERR ("invalid hmac key length");
- return false;
- }
-
- if (out->len != MONGOCRYPT_HMAC_SHA512_LEN) {
- CLIENT_ERR ("out does not contain %d bytes", MONGOCRYPT_HMAC_SHA512_LEN);
- return false;
- }
-
- if (crypto->hooks_enabled) {
- mongocrypt_binary_t hmac_key_bin, out_bin, in_bin;
- bool ret;
-
- _mongocrypt_buffer_to_binary (hmac_key, &hmac_key_bin);
- _mongocrypt_buffer_to_binary (out, &out_bin);
- _mongocrypt_buffer_to_binary (in, &in_bin);
-
- ret = crypto->hmac_sha_512 (
- crypto->ctx, &hmac_key_bin, &in_bin, &out_bin, status);
- return ret;
- }
- return _native_crypto_hmac_sha_512 (hmac_key, in, out, status);
-}
-
-
-static bool
-_crypto_random (_mongocrypt_crypto_t *crypto,
- _mongocrypt_buffer_t *out,
- uint32_t count,
- mongocrypt_status_t *status)
-{
- if (out->len != count) {
- CLIENT_ERR ("out does not contain %u bytes", count);
- return false;
- }
-
- if (crypto->hooks_enabled) {
- mongocrypt_binary_t out_bin;
-
- _mongocrypt_buffer_to_binary (out, &out_bin);
- return crypto->random (crypto->ctx, &out_bin, count, status);
- }
- return _native_crypto_random (out, count, status);
-}
-
-
-/*
- * Secure memcmp copied from the C driver.
- */
-int
-_mongocrypt_memequal (const void *const b1, const void *const b2, size_t len)
-{
- const unsigned char *p1 = b1, *p2 = b2;
- int ret = 0;
-
- for (; len > 0; len--) {
- ret |= *p1++ ^ *p2++;
- }
-
- return ret;
-}
-
-/* ----------------------------------------------------------------------------
- *
- * _mongocrypt_calculate_ciphertext_len --
- *
- * For a given plaintext length, return the length of the ciphertext.
- * This includes IV and HMAC.
- *
- * To compute that I'm following section 2.3 in [MCGREW]:
- * L = 16 * ( floor(M / 16) + 2)
- * This formula includes space for the IV, but not the sha512 HMAC.
- * Add 32 for the sha512 HMAC.
- *
- * Parameters:
- * @plaintext_len then length of the plaintext.
- *
- * Returns:
- * The calculated length of the ciphertext.
- *
- * ----------------------------------------------------------------------------
- */
-uint32_t
-_mongocrypt_calculate_ciphertext_len (uint32_t plaintext_len)
-{
- return 16 * ((plaintext_len / 16) + 2) + MONGOCRYPT_HMAC_LEN;
-}
-
-
-/* ----------------------------------------------------------------------------
- *
- * _mongocrypt_calculate_plaintext_len --
- *
- * For a given ciphertext length, return the length of the plaintext.
- * This excludes the IV and HMAC, but includes the padding.
- *
- * Parameters:
- * @ciphertext_len then length of the ciphertext.
- *
- * Returns:
- * The calculated length of the plaintext.
- *
- * ----------------------------------------------------------------------------
- */
-uint32_t
-_mongocrypt_calculate_plaintext_len (uint32_t ciphertext_len)
-{
- BSON_ASSERT (ciphertext_len >= MONGOCRYPT_HMAC_LEN + MONGOCRYPT_IV_LEN +
- MONGOCRYPT_BLOCK_SIZE);
- return ciphertext_len - (MONGOCRYPT_IV_LEN + MONGOCRYPT_HMAC_LEN);
-}
-
-
-/* ----------------------------------------------------------------------------
- *
- * _aes256_cbc_encrypt --
- *
- * Encrypts using AES256 CBC using a secret key and a known IV.
- *
- * Parameters:
- * @iv a 16 byte IV.
- * @enc_key a 32 byte key.
- * @plaintext the plaintext to encrypt.
- * @ciphertext the resulting ciphertext.
- * @bytes_written a location for the resulting number of bytes written into
- * ciphertext->data.
- * @status set on error.
- *
- * Returns:
- * True on success. On error, sets @status and returns false.
- *
- * Preconditions:
- * 1. ciphertext->data has been pre-allocated with enough space for the
- * resulting ciphertext.
- *
- * Postconditions:
- * 1. bytes_written is set to the length of the written ciphertext. This
- * is the same as _mongocrypt_calculate_ciphertext_len (plaintext->len).
- *
- * ----------------------------------------------------------------------------
- */
-static bool
-_encrypt_step (_mongocrypt_crypto_t *crypto,
- const _mongocrypt_buffer_t *iv,
- const _mongocrypt_buffer_t *enc_key,
- const _mongocrypt_buffer_t *plaintext,
- _mongocrypt_buffer_t *ciphertext,
- uint32_t *bytes_written,
- mongocrypt_status_t *status)
-{
- uint32_t unaligned;
- uint32_t padding_byte;
- _mongocrypt_buffer_t intermediates[2];
- _mongocrypt_buffer_t to_encrypt;
- uint8_t final_block_storage[MONGOCRYPT_BLOCK_SIZE];
- bool ret = false;
-
- _mongocrypt_buffer_init (&to_encrypt);
-
- BSON_ASSERT (bytes_written);
- *bytes_written = 0;
-
- if (MONGOCRYPT_IV_LEN != iv->len) {
- CLIENT_ERR ("IV should have length %d, but has length %d",
- MONGOCRYPT_IV_LEN,
- iv->len);
- goto done;
- }
-
- if (MONGOCRYPT_ENC_KEY_LEN != enc_key->len) {
- CLIENT_ERR ("Encryption key should have length %d, but has length %d",
- MONGOCRYPT_ENC_KEY_LEN,
- enc_key->len);
- goto done;
- }
-
- /* calculate how many extra bytes there are after a block boundary */
- unaligned = plaintext->len % MONGOCRYPT_BLOCK_SIZE;
-
- /* Some crypto providers disallow variable length inputs, and require
- * the input to be a multiple of the block size. So add everything up
- * to but excluding the last block if not block aligned, then add
- * the last block with padding. */
- _mongocrypt_buffer_init (&intermediates[0]);
- _mongocrypt_buffer_init (&intermediates[1]);
- intermediates[0].data = (uint8_t *) plaintext->data;
- intermediates[0].len = plaintext->len - unaligned;
- intermediates[1].data = final_block_storage;
- intermediates[1].len = sizeof (final_block_storage);
-
- /* [MCGREW]: "Prior to CBC encryption, the plaintext P is padded by appending
- * a padding string PS to that data, to ensure that len(P || PS) is a
- * multiple of 128". This is also known as PKCS #7 padding. */
- if (unaligned) {
- /* Copy the unaligned bytes. */
- memcpy (intermediates[1].data,
- plaintext->data + (plaintext->len - unaligned),
- unaligned);
- /* Fill the rest with the padding byte. */
- padding_byte = MONGOCRYPT_BLOCK_SIZE - unaligned;
- memset (intermediates[1].data + unaligned, padding_byte, padding_byte);
- } else {
- /* Fill the rest with the padding byte. */
- padding_byte = MONGOCRYPT_BLOCK_SIZE;
- memset (intermediates[1].data, padding_byte, padding_byte);
- }
-
- if (!_mongocrypt_buffer_concat (&to_encrypt, intermediates, 2)) {
- CLIENT_ERR ("failed to allocate buffer");
- goto done;
- }
-
- if (!_crypto_aes_256_cbc_encrypt (crypto,
- enc_key,
- iv,
- &to_encrypt,
- ciphertext,
- bytes_written,
- status)) {
- goto done;
- }
-
-
- if (*bytes_written % MONGOCRYPT_BLOCK_SIZE != 0) {
- CLIENT_ERR ("encryption failure, wrote %d bytes, not a multiple of %d",
- *bytes_written,
- MONGOCRYPT_BLOCK_SIZE);
- goto done;
- }
-
- ret = true;
-done:
- _mongocrypt_buffer_cleanup (&to_encrypt);
- return ret;
-}
-
-
-/* ----------------------------------------------------------------------------
- *
- * _hmac_sha512 --
- *
- * Compute the SHA512 HMAC with a secret key.
- *
- * Parameters:
- * @mac_key a 32 byte key.
- * @associated_data associated data to add into the HMAC. This may be
- * an empty buffer.
- * @ciphertext the ciphertext to add into the HMAC.
- * @out a location for the resulting HMAC tag.
- * @status set on error.
- *
- * Returns:
- * True on success. On error, sets @status and returns false.
- *
- * Preconditions:
- * 1. out->data has been pre-allocated with at least 64 bytes.
- *
- * Postconditions:
- * 1. out->data will have a 64 byte tag appended.
- *
- * ----------------------------------------------------------------------------
- */
-static bool
-_hmac_step (_mongocrypt_crypto_t *crypto,
- const _mongocrypt_buffer_t *mac_key,
- const _mongocrypt_buffer_t *associated_data,
- const _mongocrypt_buffer_t *ciphertext,
- _mongocrypt_buffer_t *out,
- mongocrypt_status_t *status)
-{
- _mongocrypt_buffer_t intermediates[3];
- _mongocrypt_buffer_t to_hmac;
- uint64_t associated_data_len_be;
- uint8_t tag_storage[64];
- _mongocrypt_buffer_t tag;
- bool ret = false;
-
- _mongocrypt_buffer_init (&to_hmac);
-
- if (MONGOCRYPT_MAC_KEY_LEN != mac_key->len) {
- CLIENT_ERR ("HMAC key wrong length: %d", mac_key->len);
- goto done;
- }
-
- if (out->len != MONGOCRYPT_HMAC_LEN) {
- CLIENT_ERR ("out wrong length: %d", out->len);
- goto done;
- }
-
- /* [MCGREW]:
- * """
- * 4. The octet string AL is equal to the number of bits in A expressed as a
- * 64-bit unsigned integer in network byte order.
- * 5. A message authentication tag T is computed by applying HMAC [RFC2104]
- * to the following data, in order:
- * the associated data A,
- * the ciphertext S computed in the previous step, and
- * the octet string AL defined above.
- * """
- */
-
- /* Add associated data. */
- _mongocrypt_buffer_init (&intermediates[0]);
- _mongocrypt_buffer_init (&intermediates[1]);
- _mongocrypt_buffer_init (&intermediates[2]);
- intermediates[0].data = associated_data->data;
- intermediates[0].len = associated_data->len;
- /* Add ciphertext. */
- intermediates[1].data = ciphertext->data;
- intermediates[1].len = ciphertext->len;
- /* Add associated data length in bits. */
- associated_data_len_be = 8 * (uint64_t) associated_data->len;
- associated_data_len_be = BSON_UINT64_TO_BE (associated_data_len_be);
- intermediates[2].data = (uint8_t *) &associated_data_len_be;
- intermediates[2].len = sizeof (uint64_t);
- tag.data = tag_storage;
- tag.len = sizeof (tag_storage);
-
-
- if (!_mongocrypt_buffer_concat (&to_hmac, intermediates, 3)) {
- CLIENT_ERR ("failed to allocate buffer");
- goto done;
- }
- if (!_crypto_hmac_sha_512 (crypto, mac_key, &to_hmac, &tag, status)) {
- goto done;
- }
-
- /* [MCGREW 2.7] "The HMAC-SHA-512 value is truncated to T_LEN=32 octets" */
- memcpy (out->data, tag.data, MONGOCRYPT_HMAC_LEN);
- ret = true;
-done:
- _mongocrypt_buffer_cleanup (&to_hmac);
- return ret;
-}
-
-/* ----------------------------------------------------------------------------
- *
- * _mongocrypt_do_encryption --
- *
- * Defer encryption to whichever crypto library libmongocrypt is using.
- *
- * Parameters:
- * @iv a 16 byte IV.
- * @associated_data associated data for the HMAC. May be NULL.
- * @key a 96 byte key.
- * @plaintext the plaintext to encrypt.
- * @ciphertext a location for the resulting ciphertext and HMAC tag.
- * @bytes_written a location for the resulting bytes written.
- * @status set on error.
- *
- * Returns:
- * True on success. On error, sets @status and returns false.
- *
- * Preconditions:
- * 1. ciphertext->data has been pre-allocated with enough space for the
- * resulting ciphertext. Use _mongocrypt_calculate_ciphertext_len.
- *
- * Postconditions:
- * 1. bytes_written is set to the length of the written ciphertext. This
- * is the same as _mongocrypt_calculate_ciphertext_len (plaintext->len).
- *
- * ----------------------------------------------------------------------------
- */
-bool
-_mongocrypt_do_encryption (_mongocrypt_crypto_t *crypto,
- const _mongocrypt_buffer_t *iv,
- const _mongocrypt_buffer_t *associated_data,
- const _mongocrypt_buffer_t *key,
- const _mongocrypt_buffer_t *plaintext,
- _mongocrypt_buffer_t *ciphertext,
- uint32_t *bytes_written,
- mongocrypt_status_t *status)
-{
- _mongocrypt_buffer_t mac_key = {0}, enc_key = {0}, intermediate = {0},
- intermediate_hmac = {0}, empty_buffer = {0};
- uint32_t intermediate_bytes_written = 0;
-
- memset (ciphertext->data, 0, ciphertext->len);
-
- BSON_ASSERT (iv);
- BSON_ASSERT (key);
- BSON_ASSERT (plaintext);
- BSON_ASSERT (ciphertext);
- if (ciphertext->len !=
- _mongocrypt_calculate_ciphertext_len (plaintext->len)) {
- CLIENT_ERR ("output ciphertext should have been allocated with %d bytes",
- _mongocrypt_calculate_ciphertext_len (plaintext->len));
- return false;
- }
-
- *bytes_written = 0;
-
- if (MONGOCRYPT_IV_LEN != iv->len) {
- CLIENT_ERR ("IV should have length %d, but has length %d",
- MONGOCRYPT_IV_LEN,
- iv->len);
- return false;
- }
- if (MONGOCRYPT_KEY_LEN != key->len) {
- CLIENT_ERR ("key should have length %d, but has length %d",
- MONGOCRYPT_KEY_LEN,
- key->len);
- return false;
- }
-
- intermediate.len = ciphertext->len;
- intermediate.data = ciphertext->data;
-
- /* [MCGREW]: Step 1. "MAC_KEY consists of the initial MAC_KEY_LEN octets of
- * K, in order. ENC_KEY consists of the final ENC_KEY_LEN octets of K, in
- * order." */
- mac_key.data = (uint8_t *) key->data;
- mac_key.len = MONGOCRYPT_MAC_KEY_LEN;
- enc_key.data = (uint8_t *) key->data + MONGOCRYPT_MAC_KEY_LEN;
- enc_key.len = MONGOCRYPT_ENC_KEY_LEN;
-
- /* Prepend the IV. */
- memcpy (intermediate.data, iv->data, iv->len);
- intermediate.data += iv->len;
- intermediate.len -= iv->len;
- *bytes_written += iv->len;
-
- /* [MCGREW]: Steps 2 & 3. */
- if (!_encrypt_step (crypto,
- iv,
- &enc_key,
- plaintext,
- &intermediate,
- &intermediate_bytes_written,
- status)) {
- return false;
- }
-
- *bytes_written += intermediate_bytes_written;
-
- /* Append the HMAC tag. */
- intermediate_hmac.data = ciphertext->data + *bytes_written;
- intermediate_hmac.len = MONGOCRYPT_HMAC_LEN;
-
- intermediate.data = ciphertext->data;
- intermediate.len = *bytes_written;
-
- /* [MCGREW]: Steps 4 & 5, compute the HMAC. */
- if (!_hmac_step (crypto,
- &mac_key,
- associated_data ? associated_data : &empty_buffer,
- &intermediate,
- &intermediate_hmac,
- status)) {
- return false;
- }
-
- *bytes_written += MONGOCRYPT_HMAC_LEN;
- return true;
-}
-
-
-/* ----------------------------------------------------------------------------
- *
- * _aes256_cbc_decrypt --
- *
- * Decrypts using AES256 CBC using a secret key and a known IV.
- *
- * Parameters:
- * @enc_key a 32 byte key.
- * @ciphertext the ciphertext to decrypt.
- * @plaintext the resulting plaintext.
- * @bytes_written a location for the resulting number of bytes written into
- * plaintext->data.
- * @status set on error.
- *
- * Returns:
- * True on success. On error, sets @status and returns false.
- *
- * Preconditions:
- * 1. plaintext->data has been pre-allocated with enough space for the
- * resulting plaintext.
- *
- * Postconditions:
- * 1. bytes_written is set to the length of the written plaintext, excluding
- * padding. This may be less than
- * _mongocrypt_calculate_plaintext_len (ciphertext->len).
- *
- * ----------------------------------------------------------------------------
- */
-static bool
-_decrypt_step (_mongocrypt_crypto_t *crypto,
- const _mongocrypt_buffer_t *iv,
- const _mongocrypt_buffer_t *enc_key,
- const _mongocrypt_buffer_t *ciphertext,
- _mongocrypt_buffer_t *plaintext,
- uint32_t *bytes_written,
- mongocrypt_status_t *status)
-{
- uint8_t padding_byte;
-
- BSON_ASSERT (bytes_written);
- *bytes_written = 0;
-
- if (MONGOCRYPT_IV_LEN != iv->len) {
- CLIENT_ERR ("IV should have length %d, but has length %d",
- MONGOCRYPT_IV_LEN,
- iv->len);
- return false;
- }
- if (MONGOCRYPT_ENC_KEY_LEN != enc_key->len) {
- CLIENT_ERR ("encryption key should have length %d, but has length %d",
- MONGOCRYPT_ENC_KEY_LEN,
- enc_key->len);
- return false;
- }
-
-
- if (ciphertext->len % MONGOCRYPT_BLOCK_SIZE > 0) {
- CLIENT_ERR ("error, ciphertext length is not a multiple of block size");
- return false;
- }
-
- if (!_crypto_aes_256_cbc_decrypt (
- crypto, iv, enc_key, ciphertext, plaintext, bytes_written, status)) {
- return false;
- }
-
- padding_byte = plaintext->data[*bytes_written - 1];
- if (padding_byte > 16) {
- CLIENT_ERR ("error, ciphertext malformed padding");
- return false;
- }
- *bytes_written -= padding_byte;
- return true;
-}
-
-
-/* ----------------------------------------------------------------------------
- *
- * _mongocrypt_do_decryption --
- *
- * Defer decryption to whichever crypto library libmongocrypt is using.
- *
- * Parameters:
- * @associated_data associated data for the HMAC. May be NULL.
- * @key a 96 byte key.
- * @ciphertext the ciphertext to decrypt. This contains the IV prepended.
- * @plaintext a location for the resulting plaintext.
- * @bytes_written a location for the resulting bytes written.
- * @status set on error.
- *
- * Returns:
- * True on success. On error, sets @status and returns false.
- *
- * Preconditions:
- * 1. plaintext->data has been pre-allocated with enough space for the
- * resulting plaintext and padding. See _mongocrypt_calculate_plaintext_len.
- *
- * Postconditions:
- * 1. bytes_written is set to the length of the written plaintext, excluding
- * padding. This may be less than
- * _mongocrypt_calculate_plaintext_len (ciphertext->len).
- *
- * ----------------------------------------------------------------------------
- */
-bool
-_mongocrypt_do_decryption (_mongocrypt_crypto_t *crypto,
- const _mongocrypt_buffer_t *associated_data,
- const _mongocrypt_buffer_t *key,
- const _mongocrypt_buffer_t *ciphertext,
- _mongocrypt_buffer_t *plaintext,
- uint32_t *bytes_written,
- mongocrypt_status_t *status)
-{
- bool ret = false;
- _mongocrypt_buffer_t mac_key = {0}, enc_key = {0}, intermediate = {0},
- hmac_tag = {0}, iv = {0}, empty_buffer = {0};
- uint8_t hmac_tag_storage[MONGOCRYPT_HMAC_LEN];
-
- BSON_ASSERT (key);
- BSON_ASSERT (ciphertext);
- BSON_ASSERT (plaintext);
- BSON_ASSERT (bytes_written);
- BSON_ASSERT (status);
-
- if (plaintext->len !=
- _mongocrypt_calculate_plaintext_len (ciphertext->len)) {
- CLIENT_ERR ("output plaintext should have been allocated with %d bytes, "
- "but has: %d",
- _mongocrypt_calculate_plaintext_len (ciphertext->len),
- plaintext->len);
- return false;
- }
-
- if (MONGOCRYPT_KEY_LEN != key->len) {
- CLIENT_ERR ("key should have length %d, but has length %d",
- MONGOCRYPT_KEY_LEN,
- key->len);
- return false;
- }
-
- if (ciphertext->len <
- MONGOCRYPT_HMAC_LEN + MONGOCRYPT_IV_LEN + MONGOCRYPT_BLOCK_SIZE) {
- CLIENT_ERR ("corrupt ciphertext - must be > %d bytes",
- MONGOCRYPT_HMAC_LEN + MONGOCRYPT_IV_LEN +
- MONGOCRYPT_BLOCK_SIZE);
- goto done;
- }
-
- mac_key.data = (uint8_t *) key->data;
- mac_key.len = MONGOCRYPT_MAC_KEY_LEN;
- enc_key.data = (uint8_t *) key->data + MONGOCRYPT_MAC_KEY_LEN;
- enc_key.len = MONGOCRYPT_ENC_KEY_LEN;
-
- iv.data = ciphertext->data;
- iv.len = MONGOCRYPT_IV_LEN;
-
- intermediate.data = (uint8_t *) ciphertext->data;
- intermediate.len = ciphertext->len - MONGOCRYPT_HMAC_LEN;
-
- hmac_tag.data = hmac_tag_storage;
- hmac_tag.len = MONGOCRYPT_HMAC_LEN;
-
- /* [MCGREW 2.2]: Step 3: HMAC check. */
- if (!_hmac_step (crypto,
- &mac_key,
- associated_data ? associated_data : &empty_buffer,
- &intermediate,
- &hmac_tag,
- status)) {
- goto done;
- }
-
- /* [MCGREW] "using a comparison routine that takes constant time". */
- if (0 != _mongocrypt_memequal (hmac_tag.data,
- ciphertext->data +
- (ciphertext->len - MONGOCRYPT_HMAC_LEN),
- MONGOCRYPT_HMAC_LEN)) {
- CLIENT_ERR ("HMAC validation failure");
- goto done;
- }
-
- /* Decrypt data excluding IV + HMAC. */
- intermediate.data = (uint8_t *) ciphertext->data + MONGOCRYPT_IV_LEN;
- intermediate.len =
- ciphertext->len - (MONGOCRYPT_IV_LEN + MONGOCRYPT_HMAC_LEN);
-
- if (!_decrypt_step (crypto,
- &iv,
- &enc_key,
- &intermediate,
- plaintext,
- bytes_written,
- status)) {
- goto done;
- }
-
- ret = true;
-done:
- return ret;
-}
-
-
-/* ----------------------------------------------------------------------------
- *
- * _mongocrypt_random --
- *
- * Generates a string of random bytes.
- *
- * Parameters:
- * @out an output buffer that has been pre-allocated.
- * @status set on error.
- * @count the size of the random string in bytes.
- *
- * Returns:
- * True on success. On error, sets @status and returns false.
- *
- * Preconditions:
- * 1. out has been pre-allocated with at least 'count' bytes of space.
- *
- * ----------------------------------------------------------------------------
- */
-bool
-_mongocrypt_random (_mongocrypt_crypto_t *crypto,
- _mongocrypt_buffer_t *out,
- uint32_t count,
- mongocrypt_status_t *status)
-{
- BSON_ASSERT (out);
- BSON_ASSERT (status);
- if (count != out->len) {
- CLIENT_ERR (
- "out should have length %d, but has length %d", count, out->len);
- return false;
- }
-
- return _crypto_random (crypto, out, count, status);
-}
-
-
-/* ----------------------------------------------------------------------------
- *
- * _mongocrypt_calculate_deterministic_iv --
- *
- * Compute the IV for deterministic encryption from the plaintext and IV
- * key by using HMAC function.
- *
- * Parameters:
- * @key the 96 byte key. The last 32 represent the IV key.
- * @plaintext the plaintext to be encrypted.
- * @associated_data associated data to include in the HMAC.
- * @out an output buffer that has been pre-allocated.
- * @status set on error.
- *
- * Returns:
- * True on success. On error, sets @status and returns false.
- *
- * Preconditions:
- * 1. out has been pre-allocated with at least MONGOCRYPT_IV_LEN bytes.
- *
- * ----------------------------------------------------------------------------
- */
-bool
-_mongocrypt_calculate_deterministic_iv (
- _mongocrypt_crypto_t *crypto,
- const _mongocrypt_buffer_t *key,
- const _mongocrypt_buffer_t *plaintext,
- const _mongocrypt_buffer_t *associated_data,
- _mongocrypt_buffer_t *out,
- mongocrypt_status_t *status)
-{
- _mongocrypt_buffer_t intermediates[3];
- _mongocrypt_buffer_t to_hmac;
- _mongocrypt_buffer_t iv_key;
- uint64_t associated_data_len_be;
- uint8_t tag_storage[64];
- _mongocrypt_buffer_t tag;
- bool ret = false;
-
- _mongocrypt_buffer_init (&to_hmac);
-
- BSON_ASSERT (key);
- BSON_ASSERT (plaintext);
- BSON_ASSERT (associated_data);
- BSON_ASSERT (out);
- BSON_ASSERT (status);
-
- if (MONGOCRYPT_KEY_LEN != key->len) {
- CLIENT_ERR ("key should have length %d, but has length %d\n",
- MONGOCRYPT_KEY_LEN,
- key->len);
- goto done;
- }
- if (MONGOCRYPT_IV_LEN != out->len) {
- CLIENT_ERR ("out should have length %d, but has length %d\n",
- MONGOCRYPT_IV_LEN,
- out->len);
- goto done;
- }
-
- _mongocrypt_buffer_init (&iv_key);
- iv_key.data = key->data + MONGOCRYPT_ENC_KEY_LEN + MONGOCRYPT_MAC_KEY_LEN;
- iv_key.len = MONGOCRYPT_IV_KEY_LEN;
-
- _mongocrypt_buffer_init (&intermediates[0]);
- _mongocrypt_buffer_init (&intermediates[1]);
- _mongocrypt_buffer_init (&intermediates[2]);
- /* Add associated data. */
- intermediates[0].data = associated_data->data;
- intermediates[0].len = associated_data->len;
- /* Add associated data length in bits. */
- associated_data_len_be = 8 * (uint64_t) associated_data->len;
- associated_data_len_be = BSON_UINT64_TO_BE (associated_data_len_be);
- intermediates[1].data = (uint8_t *) &associated_data_len_be;
- intermediates[1].len = sizeof (uint64_t);
- /* Add plaintext. */
- intermediates[2].data = (uint8_t *) plaintext->data;
- intermediates[2].len = plaintext->len;
-
- tag.data = tag_storage;
- tag.len = sizeof (tag_storage);
-
- if (!_mongocrypt_buffer_concat (&to_hmac, intermediates, 3)) {
- CLIENT_ERR ("failed to allocate buffer");
- goto done;
- }
-
- if (!_crypto_hmac_sha_512 (crypto, &iv_key, &to_hmac, &tag, status)) {
- goto done;
- }
-
- /* Truncate to IV length */
- memcpy (out->data, tag.data, MONGOCRYPT_IV_LEN);
-
- ret = true;
-done:
- _mongocrypt_buffer_cleanup (&to_hmac);
- return ret;
-}
-
-bool
-_mongocrypt_wrap_key (_mongocrypt_crypto_t *crypto,
- _mongocrypt_buffer_t *kek,
- _mongocrypt_buffer_t *dek,
- _mongocrypt_buffer_t *encrypted_dek,
- mongocrypt_status_t *status)
-{
- uint32_t bytes_written;
- _mongocrypt_buffer_t iv = {0};
- bool ret = false;
-
- _mongocrypt_buffer_init (encrypted_dek);
-
- if (dek->len != MONGOCRYPT_KEY_LEN) {
- CLIENT_ERR ("data encryption key is incorrect length, expected: %" PRIu32
- ", got: %" PRIu32,
- MONGOCRYPT_KEY_LEN,
- dek->len);
- goto done;
- }
-
- _mongocrypt_buffer_resize (encrypted_dek,
- _mongocrypt_calculate_ciphertext_len (dek->len));
- _mongocrypt_buffer_resize (&iv, MONGOCRYPT_IV_LEN);
-
- if (!_mongocrypt_random (crypto, &iv, MONGOCRYPT_IV_LEN, status)) {
- goto done;
- }
-
- if (!_mongocrypt_do_encryption (crypto,
- &iv,
- NULL /* associated data. */,
- kek,
- dek,
- encrypted_dek,
- &bytes_written,
- status)) {
- goto done;
- }
-
- ret = true;
-done:
- _mongocrypt_buffer_cleanup (&iv);
- return ret;
-}
-
-bool
-_mongocrypt_unwrap_key (_mongocrypt_crypto_t *crypto,
- _mongocrypt_buffer_t *kek,
- _mongocrypt_buffer_t *encrypted_dek,
- _mongocrypt_buffer_t *dek,
- mongocrypt_status_t *status)
-{
- uint32_t bytes_written;
-
- _mongocrypt_buffer_init (dek);
- _mongocrypt_buffer_resize (
- dek, _mongocrypt_calculate_plaintext_len (encrypted_dek->len));
-
- if (!_mongocrypt_do_decryption (crypto,
- NULL /* associated data. */,
- kek,
- encrypted_dek,
- dek,
- &bytes_written,
- status)) {
- return false;
- }
- dek->len = bytes_written;
-
- if (dek->len != MONGOCRYPT_KEY_LEN) {
- CLIENT_ERR ("decrypted key is incorrect length, expected: %" PRIu32
- ", got: %" PRIu32,
- MONGOCRYPT_KEY_LEN,
- dek->len);
- return false;
- }
- return true;
-}
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-ctx-datakey.c b/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-ctx-datakey.c
deleted file mode 100644
index ce83de9a..00000000
--- a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-ctx-datakey.c
+++ /dev/null
@@ -1,494 +0,0 @@
-/*
- * Copyright 2019-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "mongocrypt.h"
-#include "mongocrypt-private.h"
-#include "mongocrypt-ctx-private.h"
-#include "mongocrypt-crypto-private.h"
-
-static void
-_cleanup (mongocrypt_ctx_t *ctx)
-{
- _mongocrypt_ctx_datakey_t *dkctx;
-
- dkctx = (_mongocrypt_ctx_datakey_t *) ctx;
- _mongocrypt_buffer_cleanup (&dkctx->key_doc);
- _mongocrypt_kms_ctx_cleanup (&dkctx->kms);
- _mongocrypt_buffer_cleanup (&dkctx->encrypted_key_material);
- _mongocrypt_buffer_cleanup (&dkctx->plaintext_key_material);
- _mongocrypt_buffer_cleanup (&dkctx->kmip_secretdata);
- bson_free ((void *) dkctx->kmip_unique_identifier);
-}
-
-static mongocrypt_kms_ctx_t *
-_next_kms_ctx (mongocrypt_ctx_t *ctx)
-{
- _mongocrypt_ctx_datakey_t *dkctx;
-
- dkctx = (_mongocrypt_ctx_datakey_t *) ctx;
- if (dkctx->kms_returned) {
- return NULL;
- }
- dkctx->kms_returned = true;
- return &dkctx->kms;
-}
-
-static bool
-_kms_kmip_start (mongocrypt_ctx_t *ctx)
-{
- bool ret = false;
- _mongocrypt_ctx_datakey_t *dkctx = (_mongocrypt_ctx_datakey_t *) ctx;
- char *user_supplied_keyid = NULL;
- _mongocrypt_endpoint_t *endpoint = NULL;
- mongocrypt_status_t *status = ctx->status;
- _mongocrypt_buffer_t secretdata = {0};
-
- if (ctx->opts.kek.kms_provider != MONGOCRYPT_KMS_PROVIDER_KMIP) {
- CLIENT_ERR ("KMS provider is not KMIP");
- goto fail;
- }
-
- user_supplied_keyid = ctx->opts.kek.provider.kmip.key_id;
-
- if (ctx->opts.kek.provider.kmip.endpoint) {
- endpoint = ctx->opts.kek.provider.kmip.endpoint;
- } else if (ctx->crypt->opts.kms_provider_kmip.endpoint) {
- endpoint = ctx->crypt->opts.kms_provider_kmip.endpoint;
- } else {
- CLIENT_ERR ("endpoint not set for KMIP request");
- goto fail;
- }
-
- /* The KMIP createDataKey flow is the following:
- *
- * 1. Send a KMIP Register request with a new 96 byte key as a SecretData
- * managed object. This returns a Unique Identifier.
- * 2. Send a KMIP Activate request with the Unique Identifier.
- * This returns the same Unique Identifier.
- * 3. Send a KMIP Get request with the Unique Identifier.
- * This returns the 96 byte SecretData.
- * 4. Use the 96 byte SecretData to encrypt a new DEK.
- *
- * If the user set a 'keyId' to use, the flow begins at step 3.
- */
-
- if (user_supplied_keyid && !dkctx->kmip_unique_identifier) {
- /* User set a 'keyId'. */
- dkctx->kmip_unique_identifier = bson_strdup (user_supplied_keyid);
- dkctx->kmip_activated = true;
- /* Fall through to Step 3. */
- }
-
- if (!dkctx->kmip_unique_identifier) {
- /* User did not set a 'keyId'. */
- /* Step 1. Send a KMIP Register request with a new 96 byte SecretData. */
- _mongocrypt_buffer_init (&secretdata);
- _mongocrypt_buffer_resize (&secretdata, MONGOCRYPT_KEY_LEN);
- if (!_mongocrypt_random (ctx->crypt->crypto,
- &secretdata,
- MONGOCRYPT_KEY_LEN,
- ctx->status)) {
- goto fail;
- }
-
- if (!_mongocrypt_kms_ctx_init_kmip_register (&dkctx->kms,
- endpoint,
- secretdata.data,
- secretdata.len,
- &ctx->crypt->log)) {
- mongocrypt_kms_ctx_status (&dkctx->kms, ctx->status);
- goto fail;
- }
-
- ctx->state = MONGOCRYPT_CTX_NEED_KMS;
- goto success;
- }
-
- if (!dkctx->kmip_activated) {
- /* Step 2. Send a KMIP Activate request. */
- if (!_mongocrypt_kms_ctx_init_kmip_activate (
- &dkctx->kms,
- endpoint,
- dkctx->kmip_unique_identifier,
- &ctx->crypt->log)) {
- mongocrypt_kms_ctx_status (&dkctx->kms, ctx->status);
- goto fail;
- }
- ctx->state = MONGOCRYPT_CTX_NEED_KMS;
- goto success;
- }
-
- if (!dkctx->kmip_secretdata.data) {
- /* Step 3. Send a KMIP Get request with the Unique Identifier. */
- if (!_mongocrypt_kms_ctx_init_kmip_get (&dkctx->kms,
- endpoint,
- dkctx->kmip_unique_identifier,
- &ctx->crypt->log)) {
- mongocrypt_kms_ctx_status (&dkctx->kms, ctx->status);
- goto fail;
- }
- ctx->state = MONGOCRYPT_CTX_NEED_KMS;
- goto success;
- }
-
- /* Step 4. Use the 96 byte SecretData to encrypt a new DEK. */
- if (!_mongocrypt_wrap_key (ctx->crypt->crypto,
- &dkctx->kmip_secretdata,
- &dkctx->plaintext_key_material,
- &dkctx->encrypted_key_material,
- ctx->status)) {
- goto fail;
- }
-
- if (!ctx->opts.kek.provider.kmip.key_id) {
- /* If there was no user supplied key_id, set it from the
- * UniqueIdentifer of the newly registered SecretData. */
- ctx->opts.kek.provider.kmip.key_id =
- bson_strdup (dkctx->kmip_unique_identifier);
- }
- ctx->state = MONGOCRYPT_CTX_READY;
-
-success:
- ret = true;
-fail:
- if (!ret) {
- _mongocrypt_ctx_fail (ctx);
- }
- _mongocrypt_buffer_cleanup (&secretdata);
- return ret;
-}
-
-/* For local, immediately encrypt.
- * For AWS, create the KMS request to encrypt.
- * For Azure/GCP, auth first if needed, otherwise encrypt.
- */
-static bool
-_kms_start (mongocrypt_ctx_t *ctx)
-{
- bool ret = false;
- _mongocrypt_ctx_datakey_t *dkctx;
- char *access_token = NULL;
-
- dkctx = (_mongocrypt_ctx_datakey_t *) ctx;
-
- /* Clear out any pre-existing initialized KMS context, and zero it (so it is
- * safe to call cleanup again). */
- _mongocrypt_kms_ctx_cleanup (&dkctx->kms);
- memset (&dkctx->kms, 0, sizeof (dkctx->kms));
- dkctx->kms_returned = false;
- if (ctx->opts.kek.kms_provider == MONGOCRYPT_KMS_PROVIDER_LOCAL) {
- if (!_mongocrypt_wrap_key (ctx->crypt->crypto,
- &ctx->crypt->opts.kms_provider_local.key,
- &dkctx->plaintext_key_material,
- &dkctx->encrypted_key_material,
- ctx->status)) {
- _mongocrypt_ctx_fail (ctx);
- goto done;
- }
- ctx->state = MONGOCRYPT_CTX_READY;
- } else if (ctx->opts.kek.kms_provider == MONGOCRYPT_KMS_PROVIDER_AWS) {
- /* For AWS provider, AWS credentials are supplied in
- * mongocrypt_setopt_kms_provider_aws. Data keys are encrypted with an
- * "encrypt" HTTP message to KMS. */
- if (!_mongocrypt_kms_ctx_init_aws_encrypt (&dkctx->kms,
- &ctx->crypt->opts,
- &ctx->opts,
- &dkctx->plaintext_key_material,
- &ctx->crypt->log,
- ctx->crypt->crypto)) {
- mongocrypt_kms_ctx_status (&dkctx->kms, ctx->status);
- _mongocrypt_ctx_fail (ctx);
- goto done;
- }
-
- ctx->state = MONGOCRYPT_CTX_NEED_KMS;
- } else if (ctx->opts.kek.kms_provider == MONGOCRYPT_KMS_PROVIDER_AZURE) {
- access_token =
- _mongocrypt_cache_oauth_get (ctx->crypt->cache_oauth_azure);
- if (access_token) {
- if (!_mongocrypt_kms_ctx_init_azure_wrapkey (
- &dkctx->kms,
- &ctx->crypt->log,
- &ctx->crypt->opts,
- &ctx->opts,
- access_token,
- &dkctx->plaintext_key_material)) {
- mongocrypt_kms_ctx_status (&dkctx->kms, ctx->status);
- _mongocrypt_ctx_fail (ctx);
- goto done;
- }
- } else {
- if (!_mongocrypt_kms_ctx_init_azure_auth (
- &dkctx->kms,
- &ctx->crypt->log,
- &ctx->crypt->opts,
- ctx->opts.kek.provider.azure.key_vault_endpoint)) {
- mongocrypt_kms_ctx_status (&dkctx->kms, ctx->status);
- _mongocrypt_ctx_fail (ctx);
- goto done;
- }
- }
- ctx->state = MONGOCRYPT_CTX_NEED_KMS;
- } else if (ctx->opts.kek.kms_provider == MONGOCRYPT_KMS_PROVIDER_GCP) {
- access_token = _mongocrypt_cache_oauth_get (ctx->crypt->cache_oauth_gcp);
- if (access_token) {
- if (!_mongocrypt_kms_ctx_init_gcp_encrypt (
- &dkctx->kms,
- &ctx->crypt->log,
- &ctx->crypt->opts,
- &ctx->opts,
- access_token,
- &dkctx->plaintext_key_material)) {
- mongocrypt_kms_ctx_status (&dkctx->kms, ctx->status);
- _mongocrypt_ctx_fail (ctx);
- goto done;
- }
- } else {
- if (!_mongocrypt_kms_ctx_init_gcp_auth (
- &dkctx->kms,
- &ctx->crypt->log,
- &ctx->crypt->opts,
- ctx->opts.kek.provider.gcp.endpoint)) {
- mongocrypt_kms_ctx_status (&dkctx->kms, ctx->status);
- _mongocrypt_ctx_fail (ctx);
- goto done;
- }
- }
- ctx->state = MONGOCRYPT_CTX_NEED_KMS;
- } else if (ctx->opts.kek.kms_provider == MONGOCRYPT_KMS_PROVIDER_KMIP) {
- if (!_kms_kmip_start (ctx)) {
- goto done;
- }
- } else {
- _mongocrypt_ctx_fail_w_msg (ctx, "unsupported KMS provider");
- goto done;
- }
-
- ret = true;
-done:
- bson_free (access_token);
- return ret;
-}
-
-static bool
-_kms_done (mongocrypt_ctx_t *ctx)
-{
- _mongocrypt_ctx_datakey_t *dkctx;
- mongocrypt_status_t *status;
-
- dkctx = (_mongocrypt_ctx_datakey_t *) ctx;
- status = ctx->status;
- if (!mongocrypt_kms_ctx_status (&dkctx->kms, ctx->status)) {
- return _mongocrypt_ctx_fail (ctx);
- }
-
- if (mongocrypt_kms_ctx_bytes_needed (&dkctx->kms) != 0) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "KMS response unfinished");
- }
-
- /* If this was an oauth request, store the response and proceed to encrypt.
- */
- if (dkctx->kms.req_type == MONGOCRYPT_KMS_AZURE_OAUTH) {
- bson_t oauth_response;
-
- BSON_ASSERT (
- _mongocrypt_buffer_to_bson (&dkctx->kms.result, &oauth_response));
- if (!_mongocrypt_cache_oauth_add (
- ctx->crypt->cache_oauth_azure, &oauth_response, status)) {
- return _mongocrypt_ctx_fail (ctx);
- }
- return _kms_start (ctx);
- } else if (dkctx->kms.req_type == MONGOCRYPT_KMS_GCP_OAUTH) {
- bson_t oauth_response;
-
- BSON_ASSERT (
- _mongocrypt_buffer_to_bson (&dkctx->kms.result, &oauth_response));
- if (!_mongocrypt_cache_oauth_add (
- ctx->crypt->cache_oauth_gcp, &oauth_response, status)) {
- return _mongocrypt_ctx_fail (ctx);
- }
- return _kms_start (ctx);
- } else if (dkctx->kms.req_type == MONGOCRYPT_KMS_KMIP_REGISTER) {
- dkctx->kmip_unique_identifier =
- bson_strdup ((const char *) dkctx->kms.result.data);
- return _kms_start (ctx);
- } else if (dkctx->kms.req_type == MONGOCRYPT_KMS_KMIP_ACTIVATE) {
- dkctx->kmip_activated = true;
- return _kms_start (ctx);
- } else if (dkctx->kms.req_type == MONGOCRYPT_KMS_KMIP_GET) {
- _mongocrypt_buffer_copy_to (&dkctx->kms.result, &dkctx->kmip_secretdata);
- return _kms_start (ctx);
- }
-
- /* Store the result. */
- if (!_mongocrypt_kms_ctx_result (&dkctx->kms,
- &dkctx->encrypted_key_material)) {
- BSON_ASSERT (!mongocrypt_kms_ctx_status (&dkctx->kms, ctx->status));
- return _mongocrypt_ctx_fail (ctx);
- }
-
- /* The encrypted key material must be at least as large as the plaintext. */
- if (dkctx->encrypted_key_material.len < MONGOCRYPT_KEY_LEN) {
- return _mongocrypt_ctx_fail_w_msg (ctx,
- "key material not expected length");
- }
-
- ctx->state = MONGOCRYPT_CTX_READY;
- return true;
-}
-
-/* Append a UUID _id. Confer with libmongoc's `_mongoc_server_session_uuid`. */
-static bool
-_append_id (mongocrypt_t *crypt, bson_t *bson, mongocrypt_status_t *status)
-{
- _mongocrypt_buffer_t uuid;
-#define UUID_LEN 16
-
- _mongocrypt_buffer_init (&uuid);
- uuid.data = bson_malloc (UUID_LEN);
- BSON_ASSERT (uuid.data);
-
- uuid.len = UUID_LEN;
- uuid.subtype = BSON_SUBTYPE_UUID;
- uuid.owned = true;
-
- if (!_mongocrypt_random (crypt->crypto, &uuid, UUID_LEN, status)) {
- _mongocrypt_buffer_cleanup (&uuid);
- return false;
- }
-
- uuid.data[6] = (uint8_t) (0x40 | (uuid.data[6] & 0xf));
- uuid.data[8] = (uint8_t) (0x80 | (uuid.data[8] & 0x3f));
- if (!_mongocrypt_buffer_append (&uuid, bson, "_id", 3)) {
- _mongocrypt_buffer_cleanup (&uuid);
- return false;
- }
-
- _mongocrypt_buffer_cleanup (&uuid);
-
- return true;
-}
-
-static bool
-_finalize (mongocrypt_ctx_t *ctx, mongocrypt_binary_t *out)
-{
- _mongocrypt_ctx_datakey_t *dkctx;
- bson_t key_doc, child;
- struct timeval tp;
-
-#define BSON_CHECK(_stmt) \
- if (!(_stmt)) { \
- bson_destroy (&key_doc); \
- return _mongocrypt_ctx_fail_w_msg (ctx, "unable to construct BSON doc"); \
- }
-
- dkctx = (_mongocrypt_ctx_datakey_t *) ctx;
-
- bson_init (&key_doc);
- if (!_append_id (ctx->crypt, &key_doc, ctx->status)) {
- return _mongocrypt_ctx_fail (ctx);
- }
-
- if (ctx->opts.key_alt_names) {
- _mongocrypt_key_alt_name_t *alt_name = ctx->opts.key_alt_names;
- int i;
-
- bson_append_array_begin (&key_doc, "keyAltNames", -1, &child);
- for (i = 0; alt_name; i++) {
- char *key = bson_strdup_printf ("%d", i);
- bson_append_value (&child, key, -1, &alt_name->value);
- bson_free (key);
- alt_name = alt_name->next;
- }
- bson_append_array_end (&key_doc, &child);
- }
- if (!_mongocrypt_buffer_append (&dkctx->encrypted_key_material,
- &key_doc,
- MONGOCRYPT_STR_AND_LEN ("keyMaterial"))) {
- bson_destroy (&key_doc);
- return _mongocrypt_ctx_fail_w_msg (ctx, "could not append keyMaterial");
- }
- bson_gettimeofday (&tp);
- BSON_CHECK (bson_append_timeval (
- &key_doc, MONGOCRYPT_STR_AND_LEN ("creationDate"), &tp));
- BSON_CHECK (bson_append_timeval (
- &key_doc, MONGOCRYPT_STR_AND_LEN ("updateDate"), &tp));
- BSON_CHECK (bson_append_int32 (
- &key_doc, MONGOCRYPT_STR_AND_LEN ("status"), 0)); /* 0 = enabled. */
- BSON_CHECK (bson_append_document_begin (
- &key_doc, MONGOCRYPT_STR_AND_LEN ("masterKey"), &child));
- if (!_mongocrypt_kek_append (&ctx->opts.kek, &child, ctx->status)) {
- bson_destroy (&key_doc);
- return _mongocrypt_ctx_fail (ctx);
- }
- BSON_CHECK (bson_append_document_end (&key_doc, &child));
- _mongocrypt_buffer_steal_from_bson (&dkctx->key_doc, &key_doc);
- _mongocrypt_buffer_to_binary (&dkctx->key_doc, out);
- ctx->state = MONGOCRYPT_CTX_DONE;
- return true;
-}
-
-bool
-mongocrypt_ctx_datakey_init (mongocrypt_ctx_t *ctx)
-{
- _mongocrypt_ctx_datakey_t *dkctx;
- _mongocrypt_ctx_opts_spec_t opts_spec;
- bool ret;
-
- if (!ctx) {
- return false;
- }
- ret = false;
- memset (&opts_spec, 0, sizeof (opts_spec));
- opts_spec.kek = OPT_REQUIRED;
- opts_spec.key_alt_names = OPT_OPTIONAL;
-
- if (!_mongocrypt_ctx_init (ctx, &opts_spec)) {
- return false;
- }
-
- dkctx = (_mongocrypt_ctx_datakey_t *) ctx;
- ctx->type = _MONGOCRYPT_TYPE_CREATE_DATA_KEY;
- ctx->vtable.mongo_op_keys = NULL;
- ctx->vtable.mongo_feed_keys = NULL;
- ctx->vtable.mongo_done_keys = NULL;
- ctx->vtable.next_kms_ctx = _next_kms_ctx;
- ctx->vtable.kms_done = _kms_done;
- ctx->vtable.finalize = _finalize;
- ctx->vtable.cleanup = _cleanup;
-
- _mongocrypt_buffer_init (&dkctx->plaintext_key_material);
- dkctx->plaintext_key_material.data = bson_malloc (MONGOCRYPT_KEY_LEN);
- BSON_ASSERT (dkctx->plaintext_key_material.data);
-
- dkctx->plaintext_key_material.len = MONGOCRYPT_KEY_LEN;
- dkctx->plaintext_key_material.owned = true;
- if (!_mongocrypt_random (ctx->crypt->crypto,
- &dkctx->plaintext_key_material,
- MONGOCRYPT_KEY_LEN,
- ctx->status)) {
- _mongocrypt_ctx_fail (ctx);
- goto done;
- }
-
- if (!_kms_start (ctx)) {
- goto done;
- }
-
- ret = true;
-done:
- return ret;
-}
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-ctx-encrypt.c b/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-ctx-encrypt.c
deleted file mode 100644
index 32bbf253..00000000
--- a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-ctx-encrypt.c
+++ /dev/null
@@ -1,917 +0,0 @@
-/*
- * Copyright 2019-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "mongocrypt-ciphertext-private.h"
-#include "mongocrypt-crypto-private.h"
-#include "mongocrypt-ctx-private.h"
-#include "mongocrypt-key-broker-private.h"
-#include "mongocrypt-marking-private.h"
-#include "mongocrypt-traverse-util-private.h"
-
-/* Construct the list collections command to send. */
-static bool
-_mongo_op_collinfo (mongocrypt_ctx_t *ctx, mongocrypt_binary_t *out)
-{
- _mongocrypt_ctx_encrypt_t *ectx;
- bson_t *cmd;
-
- ectx = (_mongocrypt_ctx_encrypt_t *) ctx;
- cmd = BCON_NEW ("name", BCON_UTF8 (ectx->coll_name));
- CRYPT_TRACEF (&ectx->parent.crypt->log, "constructed: %s\n", tmp_json (cmd));
- _mongocrypt_buffer_steal_from_bson (&ectx->list_collections_filter, cmd);
- out->data = ectx->list_collections_filter.data;
- out->len = ectx->list_collections_filter.len;
- return true;
-}
-
-static bool
-_set_schema_from_collinfo (mongocrypt_ctx_t *ctx, bson_t *collinfo)
-{
- bson_iter_t iter;
- _mongocrypt_ctx_encrypt_t *ectx;
- bool found_jsonschema = false;
-
- /* Parse out the schema. */
- ectx = (_mongocrypt_ctx_encrypt_t *) ctx;
-
- /* Disallow views. */
- if (bson_iter_init_find (&iter, collinfo, "type") &&
- BSON_ITER_HOLDS_UTF8 (&iter) && bson_iter_utf8 (&iter, NULL) &&
- 0 == strcmp ("view", bson_iter_utf8 (&iter, NULL))) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "cannot auto encrypt a view");
- }
-
- if (!bson_iter_init (&iter, collinfo)) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "BSON malformed");
- }
-
- if (bson_iter_find_descendant (&iter, "options.validator", &iter) &&
- BSON_ITER_HOLDS_DOCUMENT (&iter)) {
- if (!bson_iter_recurse (&iter, &iter)) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "BSON malformed");
- }
- while (bson_iter_next (&iter)) {
- const char *key;
-
- key = bson_iter_key (&iter);
- BSON_ASSERT (key);
- if (0 == strcmp ("$jsonSchema", key)) {
- if (found_jsonschema) {
- return _mongocrypt_ctx_fail_w_msg (
- ctx, "duplicate $jsonSchema fields found");
- }
- if (!_mongocrypt_buffer_copy_from_document_iter (&ectx->schema,
- &iter)) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "malformed $jsonSchema");
- }
- found_jsonschema = true;
- } else {
- ectx->collinfo_has_siblings = true;
- }
- }
- }
-
- if (!found_jsonschema) {
- bson_t empty = BSON_INITIALIZER;
-
- _mongocrypt_buffer_steal_from_bson (&ectx->schema, &empty);
- }
-
-
- return true;
-}
-
-static bool
-_mongo_feed_collinfo (mongocrypt_ctx_t *ctx, mongocrypt_binary_t *in)
-{
- bson_t as_bson;
-
- _mongocrypt_ctx_encrypt_t *ectx;
-
- ectx = (_mongocrypt_ctx_encrypt_t *) ctx;
- if (!bson_init_static (&as_bson, in->data, in->len)) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "BSON malformed");
- }
-
- /* Cache the received collinfo. */
- if (!_mongocrypt_cache_add_copy (
- &ctx->crypt->cache_collinfo, ectx->ns, &as_bson, ctx->status)) {
- return _mongocrypt_ctx_fail (ctx);
- }
-
- if (!_set_schema_from_collinfo (ctx, &as_bson)) {
- return false;
- }
-
- return true;
-}
-
-
-static bool
-_mongo_done_collinfo (mongocrypt_ctx_t *ctx)
-{
- _mongocrypt_ctx_encrypt_t *ectx;
-
- ectx = (_mongocrypt_ctx_encrypt_t *) ctx;
- if (_mongocrypt_buffer_empty (&ectx->schema)) {
- bson_t empty_collinfo = BSON_INITIALIZER;
-
- /* If no collinfo was fed, cache an empty collinfo. */
- if (!_mongocrypt_cache_add_copy (
- &ctx->crypt->cache_collinfo, ectx->ns, &empty_collinfo, ctx->status)) {
- bson_destroy (&empty_collinfo);
- return _mongocrypt_ctx_fail (ctx);
- }
- bson_destroy (&empty_collinfo);
- }
-
- ectx->parent.state = MONGOCRYPT_CTX_NEED_MONGO_MARKINGS;
- return true;
-}
-
-
-static bool
-_mongo_op_markings (mongocrypt_ctx_t *ctx, mongocrypt_binary_t *out)
-{
- _mongocrypt_ctx_encrypt_t *ectx;
- bson_t cmd_bson, schema_bson, mongocryptd_cmd_bson;
-
- ectx = (_mongocrypt_ctx_encrypt_t *) ctx;
- if (_mongocrypt_buffer_empty (&ectx->mongocryptd_cmd)) {
- /* first, get the original command. */
- if (!_mongocrypt_buffer_to_bson (&ectx->original_cmd, &cmd_bson)) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "invalid BSON cmd");
- }
-
- if (_mongocrypt_buffer_empty (&ectx->schema)) {
- bson_init (&schema_bson);
- } else if (!_mongocrypt_buffer_to_bson (&ectx->schema, &schema_bson)) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "invalid BSON schema");
- }
-
- bson_copy_to (&cmd_bson, &mongocryptd_cmd_bson);
- BSON_APPEND_DOCUMENT (&mongocryptd_cmd_bson, "jsonSchema", &schema_bson);
-
- /* if a local schema was not set, set isRemoteSchema=true */
- BSON_APPEND_BOOL (
- &mongocryptd_cmd_bson, "isRemoteSchema", !ectx->used_local_schema);
- _mongocrypt_buffer_steal_from_bson (&ectx->mongocryptd_cmd,
- &mongocryptd_cmd_bson);
-
- bson_destroy (&cmd_bson);
- bson_destroy (&schema_bson);
- }
- out->data = ectx->mongocryptd_cmd.data;
- out->len = ectx->mongocryptd_cmd.len;
- return true;
-}
-
-
-static bool
-_collect_key_from_marking (void *ctx,
- _mongocrypt_buffer_t *in,
- mongocrypt_status_t *status)
-{
- _mongocrypt_marking_t marking;
- _mongocrypt_key_broker_t *kb;
- bool res;
-
- kb = (_mongocrypt_key_broker_t *) ctx;
-
- if (!_mongocrypt_marking_parse_unowned (in, &marking, status)) {
- _mongocrypt_marking_cleanup (&marking);
- return false;
- }
-
- if (marking.has_alt_name) {
- res = _mongocrypt_key_broker_request_name (kb, &marking.key_alt_name);
- } else {
- res = _mongocrypt_key_broker_request_id (kb, &marking.key_id);
- }
-
- if (!res) {
- _mongocrypt_key_broker_status (kb, status);
- _mongocrypt_marking_cleanup (&marking);
- return false;
- }
-
- _mongocrypt_marking_cleanup (&marking);
-
- return true;
-}
-
-
-static bool
-_mongo_feed_markings (mongocrypt_ctx_t *ctx, mongocrypt_binary_t *in)
-{
- /* Find keys. */
- bson_t as_bson;
- bson_iter_t iter;
- _mongocrypt_ctx_encrypt_t *ectx;
-
- ectx = (_mongocrypt_ctx_encrypt_t *) ctx;
- if (!_mongocrypt_binary_to_bson (in, &as_bson)) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "malformed BSON");
- }
-
- if (bson_iter_init_find (&iter, &as_bson, "schemaRequiresEncryption") &&
- !bson_iter_as_bool (&iter)) {
- /* TODO: update cache: this schema does not require encryption. */
-
- /* If using a local schema, warn if there are no encrypted fields. */
- if (ectx->used_local_schema) {
- _mongocrypt_log (
- &ctx->crypt->log,
- MONGOCRYPT_LOG_LEVEL_WARNING,
- "local schema used but does not have encryption specifiers");
- }
- return true;
- } else {
- /* if the schema requires encryption, but has sibling validators, error.
- */
- if (ectx->collinfo_has_siblings) {
- return _mongocrypt_ctx_fail_w_msg (ctx,
- "schema requires encryption, "
- "but collection JSON schema "
- "validator has siblings");
- }
- }
-
- if (bson_iter_init_find (&iter, &as_bson, "hasEncryptedPlaceholders") &&
- !bson_iter_as_bool (&iter)) {
- return true;
- }
-
- if (!bson_iter_init_find (&iter, &as_bson, "result")) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "malformed marking, no 'result'");
- }
-
- if (!_mongocrypt_buffer_copy_from_document_iter (&ectx->marked_cmd, &iter)) {
- return _mongocrypt_ctx_fail_w_msg (
- ctx, "malformed marking, 'result' must be a document");
- }
-
- if (!bson_iter_recurse (&iter, &iter)) {
- return _mongocrypt_ctx_fail_w_msg (
- ctx, "malformed marking, could not recurse into 'result'");
- }
- if (!_mongocrypt_traverse_binary_in_bson (_collect_key_from_marking,
- (void *) &ctx->kb,
- TRAVERSE_MATCH_MARKING,
- &iter,
- ctx->status)) {
- return _mongocrypt_ctx_fail (ctx);
- }
-
- return true;
-}
-
-
-static bool
-_mongo_done_markings (mongocrypt_ctx_t *ctx)
-{
- (void) _mongocrypt_key_broker_requests_done (&ctx->kb);
- return _mongocrypt_ctx_state_from_key_broker (ctx);
-}
-
-
-static bool
-_marking_to_bson_value (void *ctx,
- _mongocrypt_marking_t *marking,
- bson_value_t *out,
- mongocrypt_status_t *status)
-{
- _mongocrypt_ciphertext_t ciphertext;
- _mongocrypt_buffer_t serialized_ciphertext = {0};
- bool ret = false;
-
- BSON_ASSERT (out);
-
- _mongocrypt_ciphertext_init (&ciphertext);
-
- if (!_mongocrypt_marking_to_ciphertext (ctx, marking, &ciphertext, status)) {
- goto fail;
- }
-
- if (!_mongocrypt_serialize_ciphertext (&ciphertext,
- &serialized_ciphertext)) {
- CLIENT_ERR ("malformed ciphertext");
- goto fail;
- };
-
- /* ownership of serialized_ciphertext is transferred to caller. */
- out->value_type = BSON_TYPE_BINARY;
- out->value.v_binary.data = serialized_ciphertext.data;
- out->value.v_binary.data_len = serialized_ciphertext.len;
- out->value.v_binary.subtype = (bson_subtype_t) 6;
-
- ret = true;
-
-fail:
- _mongocrypt_ciphertext_cleanup (&ciphertext);
- return ret;
-}
-
-
-static bool
-_replace_marking_with_ciphertext (void *ctx,
- _mongocrypt_buffer_t *in,
- bson_value_t *out,
- mongocrypt_status_t *status)
-{
- _mongocrypt_marking_t marking;
- bool ret;
-
- BSON_ASSERT (in);
-
- memset (&marking, 0, sizeof (marking));
-
- if (!_mongocrypt_marking_parse_unowned (in, &marking, status)) {
- _mongocrypt_marking_cleanup (&marking);
- return false;
- }
-
- ret = _marking_to_bson_value (ctx, &marking, out, status);
- _mongocrypt_marking_cleanup (&marking);
- return ret;
-}
-
-static bool
-_finalize (mongocrypt_ctx_t *ctx, mongocrypt_binary_t *out)
-{
- bson_t as_bson, converted;
- bson_iter_t iter;
- _mongocrypt_ctx_encrypt_t *ectx;
- bool res;
-
- ectx = (_mongocrypt_ctx_encrypt_t *) ctx;
-
- if (!ectx->explicit) {
- if (ctx->nothing_to_do) {
- _mongocrypt_buffer_to_binary (&ectx->original_cmd, out);
- ctx->state = MONGOCRYPT_CTX_DONE;
- return true;
- }
- if (!_mongocrypt_buffer_to_bson (&ectx->marked_cmd, &as_bson)) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "malformed bson");
- }
-
- bson_iter_init (&iter, &as_bson);
- bson_init (&converted);
- if (!_mongocrypt_transform_binary_in_bson (
- _replace_marking_with_ciphertext,
- &ctx->kb,
- TRAVERSE_MATCH_MARKING,
- &iter,
- &converted,
- ctx->status)) {
- return _mongocrypt_ctx_fail (ctx);
- }
- } else {
- /* For explicit encryption, we have no marking, but we can fake one */
- _mongocrypt_marking_t marking;
- bson_value_t value;
-
- memset (&value, 0, sizeof (value));
-
- _mongocrypt_marking_init (&marking);
-
- if (!_mongocrypt_buffer_to_bson (&ectx->original_cmd, &as_bson)) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "malformed bson");
- }
-
- if (!bson_iter_init_find (&iter, &as_bson, "v")) {
- return _mongocrypt_ctx_fail_w_msg (ctx,
- "invalid msg, must contain 'v'");
- }
-
-
- memcpy (&marking.v_iter, &iter, sizeof (bson_iter_t));
- marking.algorithm = ctx->opts.algorithm;
- _mongocrypt_buffer_set_to (&ctx->opts.key_id, &marking.key_id);
- if (ctx->opts.key_alt_names) {
- bson_value_copy (&ctx->opts.key_alt_names->value,
- &marking.key_alt_name);
- marking.has_alt_name = true;
- }
-
- bson_init (&converted);
- res = _marking_to_bson_value (&ctx->kb, &marking, &value, ctx->status);
- if (res) {
- bson_append_value (&converted, MONGOCRYPT_STR_AND_LEN ("v"), &value);
- }
-
- bson_value_destroy (&value);
- _mongocrypt_marking_cleanup (&marking);
-
- if (!res) {
- bson_destroy (&converted);
- return _mongocrypt_ctx_fail (ctx);
- }
- }
-
- _mongocrypt_buffer_steal_from_bson (&ectx->encrypted_cmd, &converted);
- _mongocrypt_buffer_to_binary (&ectx->encrypted_cmd, out);
- ctx->state = MONGOCRYPT_CTX_DONE;
-
- return true;
-}
-
-
-static void
-_cleanup (mongocrypt_ctx_t *ctx)
-{
- _mongocrypt_ctx_encrypt_t *ectx;
-
- ectx = (_mongocrypt_ctx_encrypt_t *) ctx;
- bson_free (ectx->ns);
- bson_free (ectx->db_name);
- bson_free (ectx->coll_name);
- _mongocrypt_buffer_cleanup (&ectx->list_collections_filter);
- _mongocrypt_buffer_cleanup (&ectx->schema);
- _mongocrypt_buffer_cleanup (&ectx->original_cmd);
- _mongocrypt_buffer_cleanup (&ectx->mongocryptd_cmd);
- _mongocrypt_buffer_cleanup (&ectx->marked_cmd);
- _mongocrypt_buffer_cleanup (&ectx->encrypted_cmd);
-}
-
-
-static bool
-_try_schema_from_schema_map (mongocrypt_ctx_t *ctx)
-{
- mongocrypt_t *crypt;
- _mongocrypt_ctx_encrypt_t *ectx;
- bson_t schema_map;
- bson_iter_t iter;
-
- crypt = ctx->crypt;
- ectx = (_mongocrypt_ctx_encrypt_t *) ctx;
-
- if (_mongocrypt_buffer_empty (&crypt->opts.schema_map)) {
- /* No schema map set. */
- return true;
- }
-
- if (!_mongocrypt_buffer_to_bson (&crypt->opts.schema_map, &schema_map)) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "malformed schema map");
- }
-
- if (bson_iter_init_find (&iter, &schema_map, ectx->ns)) {
- if (!_mongocrypt_buffer_copy_from_document_iter (&ectx->schema, &iter)) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "malformed schema map");
- }
- ectx->used_local_schema = true;
- ctx->state = MONGOCRYPT_CTX_NEED_MONGO_MARKINGS;
- }
-
- /* No schema found in map. */
- return true;
-}
-
-
-static bool
-_try_schema_from_cache (mongocrypt_ctx_t *ctx)
-{
- _mongocrypt_ctx_encrypt_t *ectx;
- bson_t *collinfo = NULL;
-
- ectx = (_mongocrypt_ctx_encrypt_t *) ctx;
-
- /* Otherwise, we need a remote schema. Check if we have a response to
- * listCollections cached. */
- if (!_mongocrypt_cache_get (&ctx->crypt->cache_collinfo,
- ectx->ns /* null terminated */,
- (void **) &collinfo)) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "failed to retrieve from cache");
- }
-
- if (collinfo) {
- if (!_set_schema_from_collinfo (ctx, collinfo)) {
- return _mongocrypt_ctx_fail (ctx);
- }
- ctx->state = MONGOCRYPT_CTX_NEED_MONGO_MARKINGS;
- } else {
- /* we need to get it. */
- ctx->state = MONGOCRYPT_CTX_NEED_MONGO_COLLINFO;
- }
-
- bson_destroy (collinfo);
- return true;
-}
-
-static bool
-_permitted_for_encryption (bson_iter_t *iter,
- mongocrypt_encryption_algorithm_t algo,
- mongocrypt_status_t *status)
-{
- bson_type_t bson_type;
- const bson_value_t *bson_value = bson_iter_value (iter);
- bool ret = false;
-
- if (!bson_value) {
- CLIENT_ERR ("Unknown BSON type");
- goto fail;
- }
- bson_type = bson_value->value_type;
- switch (bson_type) {
- case BSON_TYPE_NULL:
- case BSON_TYPE_MINKEY:
- case BSON_TYPE_MAXKEY:
- case BSON_TYPE_UNDEFINED:
- CLIENT_ERR ("BSON type invalid for encryption");
- goto fail;
- case BSON_TYPE_BINARY:
- if (bson_value->value.v_binary.subtype == 6) {
- CLIENT_ERR ("BSON binary subtype 6 is invalid for encryption");
- goto fail;
- }
- /* ok */
- break;
- case BSON_TYPE_DOUBLE:
- case BSON_TYPE_DOCUMENT:
- case BSON_TYPE_ARRAY:
- case BSON_TYPE_CODEWSCOPE:
- case BSON_TYPE_BOOL:
- case BSON_TYPE_DECIMAL128:
- if (algo == MONGOCRYPT_ENCRYPTION_ALGORITHM_DETERMINISTIC) {
- CLIENT_ERR ("BSON type invalid for deterministic encryption");
- goto fail;
- }
- break;
- case BSON_TYPE_UTF8:
- case BSON_TYPE_OID:
- case BSON_TYPE_DATE_TIME:
- case BSON_TYPE_REGEX:
- case BSON_TYPE_DBPOINTER:
- case BSON_TYPE_CODE:
- case BSON_TYPE_SYMBOL:
- case BSON_TYPE_INT32:
- case BSON_TYPE_TIMESTAMP:
- case BSON_TYPE_INT64:
- /* ok */
- break;
- case BSON_TYPE_EOD:
- default:
- CLIENT_ERR ("invalid BSON value type 00");
- goto fail;
- }
-
- ret = true;
-fail:
- return ret;
-}
-
-bool
-mongocrypt_ctx_explicit_encrypt_init (mongocrypt_ctx_t *ctx,
- mongocrypt_binary_t *msg)
-{
- _mongocrypt_ctx_encrypt_t *ectx;
- bson_t as_bson;
- bson_iter_t iter;
- _mongocrypt_ctx_opts_spec_t opts_spec;
-
- if (!ctx) {
- return false;
- }
- memset (&opts_spec, 0, sizeof (opts_spec));
- opts_spec.key_descriptor = OPT_REQUIRED;
- opts_spec.algorithm = OPT_REQUIRED;
-
- if (!_mongocrypt_ctx_init (ctx, &opts_spec)) {
- return false;
- }
-
- ectx = (_mongocrypt_ctx_encrypt_t *) ctx;
- ctx->type = _MONGOCRYPT_TYPE_ENCRYPT;
- ectx->explicit = true;
- ctx->vtable.finalize = _finalize;
- ctx->vtable.cleanup = _cleanup;
-
- if (!msg || !msg->data) {
- return _mongocrypt_ctx_fail_w_msg (
- ctx, "msg required for explicit encryption");
- }
-
- if (ctx->opts.key_alt_names) {
- if (!_mongocrypt_key_broker_request_name (
- &ctx->kb, &ctx->opts.key_alt_names->value)) {
- return _mongocrypt_ctx_fail (ctx);
- }
- } else {
- if (!_mongocrypt_key_broker_request_id (&ctx->kb, &ctx->opts.key_id)) {
- return _mongocrypt_ctx_fail (ctx);
- }
- }
-
- _mongocrypt_buffer_init (&ectx->original_cmd);
-
- _mongocrypt_buffer_copy_from_binary (&ectx->original_cmd, msg);
- if (!_mongocrypt_buffer_to_bson (&ectx->original_cmd, &as_bson)) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "msg must be bson");
- }
-
- if (ctx->crypt->log.trace_enabled) {
- char *cmd_val;
- cmd_val = _mongocrypt_new_json_string_from_binary (msg);
- _mongocrypt_log (&ctx->crypt->log,
- MONGOCRYPT_LOG_LEVEL_TRACE,
- "%s (%s=\"%s\")",
- BSON_FUNC,
- "msg",
- cmd_val);
- bson_free (cmd_val);
- }
-
- if (!bson_iter_init_find (&iter, &as_bson, "v")) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "invalid msg, must contain 'v'");
- }
-
- if (!_permitted_for_encryption (&iter, ctx->opts.algorithm, ctx->status)) {
- return _mongocrypt_ctx_fail (ctx);
- }
-
- (void) _mongocrypt_key_broker_requests_done (&ctx->kb);
- return _mongocrypt_ctx_state_from_key_broker (ctx);
-}
-
-static bool
-_check_cmd_for_auto_encrypt (mongocrypt_binary_t *cmd,
- bool *bypass,
- char **collname,
- mongocrypt_status_t *status)
-{
- bson_t as_bson;
- bson_iter_t iter, ns_iter;
- const char *cmd_name;
- bool eligible = false;
-
- *bypass = false;
-
- if (!_mongocrypt_binary_to_bson (cmd, &as_bson) ||
- !bson_iter_init (&iter, &as_bson)) {
- CLIENT_ERR ("invalid BSON");
- return false;
- }
-
- /* The command name is the first key. */
- if (!bson_iter_next (&iter)) {
- CLIENT_ERR ("invalid empty BSON");
- return false;
- }
-
- cmd_name = bson_iter_key (&iter);
- BSON_ASSERT (cmd_name);
-
- /* get the collection name (or NULL if database/client command). */
- if (0 == strcmp (cmd_name, "explain")) {
- if (!BSON_ITER_HOLDS_DOCUMENT (&iter)) {
- CLIENT_ERR ("explain value is not a document");
- return false;
- }
- if (!bson_iter_recurse (&iter, &ns_iter)) {
- CLIENT_ERR ("malformed BSON for encrypt command");
- return false;
- }
- if (!bson_iter_next (&ns_iter)) {
- CLIENT_ERR ("invalid empty BSON");
- return false;
- }
- } else {
- memcpy (&ns_iter, &iter, sizeof (iter));
- }
-
- if (BSON_ITER_HOLDS_UTF8 (&ns_iter)) {
- *collname = bson_strdup (bson_iter_utf8 (&ns_iter, NULL));
- } else {
- *collname = NULL;
- }
-
- /* check if command is eligible for auto encryption, bypassed, or ineligible.
- */
- if (0 == strcmp (cmd_name, "aggregate")) {
- /* collection level aggregate ok, database/client is not. */
- eligible = true;
- } else if (0 == strcmp (cmd_name, "count")) {
- eligible = true;
- } else if (0 == strcmp (cmd_name, "distinct")) {
- eligible = true;
- } else if (0 == strcmp (cmd_name, "delete")) {
- eligible = true;
- } else if (0 == strcmp (cmd_name, "find")) {
- eligible = true;
- } else if (0 == strcmp (cmd_name, "findAndModify")) {
- eligible = true;
- } else if (0 == strcmp (cmd_name, "getMore")) {
- *bypass = true;
- } else if (0 == strcmp (cmd_name, "insert")) {
- eligible = true;
- } else if (0 == strcmp (cmd_name, "update")) {
- eligible = true;
- } else if (0 == strcmp (cmd_name, "authenticate")) {
- *bypass = true;
- } else if (0 == strcmp (cmd_name, "getnonce")) {
- *bypass = true;
- } else if (0 == strcmp (cmd_name, "logout")) {
- *bypass = true;
- } else if (0 == bson_strcasecmp (cmd_name, "isMaster")) {
- /* use case insensitive compare for ismaster, since some drivers send
- * "ismaster" and others send "isMaster" */
- *bypass = true;
- } else if (0 == strcmp (cmd_name, "abortTransaction")) {
- *bypass = true;
- } else if (0 == strcmp (cmd_name, "commitTransaction")) {
- *bypass = true;
- } else if (0 == strcmp (cmd_name, "endSessions")) {
- *bypass = true;
- } else if (0 == strcmp (cmd_name, "startSession")) {
- *bypass = true;
- } else if (0 == strcmp (cmd_name, "create")) {
- *bypass = true;
- } else if (0 == strcmp (cmd_name, "createIndexes")) {
- *bypass = true;
- } else if (0 == strcmp (cmd_name, "drop")) {
- *bypass = true;
- } else if (0 == strcmp (cmd_name, "dropDatabase")) {
- *bypass = true;
- } else if (0 == strcmp (cmd_name, "dropIndexes")) {
- *bypass = true;
- } else if (0 == strcmp (cmd_name, "killCursors")) {
- *bypass = true;
- } else if (0 == strcmp (cmd_name, "listCollections")) {
- *bypass = true;
- } else if (0 == strcmp (cmd_name, "listDatabases")) {
- *bypass = true;
- } else if (0 == strcmp (cmd_name, "listIndexes")) {
- *bypass = true;
- } else if (0 == strcmp (cmd_name, "renameCollection")) {
- *bypass = true;
- } else if (0 == strcmp (cmd_name, "explain")) {
- eligible = true;
- } else if (0 == strcmp (cmd_name, "ping")) {
- *bypass = true;
- } else if (0 == strcmp (cmd_name, "saslStart")) {
- *bypass = true;
- } else if (0 == strcmp (cmd_name, "saslContinue")) {
- *bypass = true;
- } else if (0 == strcmp (cmd_name, "killAllSessions")) {
- *bypass = true;
- } else if (0 == strcmp (cmd_name, "killSessions")) {
- *bypass = true;
- } else if (0 == strcmp (cmd_name, "killAllSessionsByPattern")) {
- *bypass = true;
- } else if (0 == strcmp (cmd_name, "refreshSessions")) {
- *bypass = true;
- }
-
- /* database/client commands are ineligible. */
- if (eligible) {
- if (!*collname) {
- CLIENT_ERR (
- "non-collection command not supported for auto encryption: %s",
- cmd_name);
- return false;
- }
- if (0 == strlen (*collname)) {
- CLIENT_ERR ("empty collection name on command: %s", cmd_name);
- return false;
- }
- }
-
- if (eligible || *bypass) {
- return true;
- }
-
- CLIENT_ERR ("command not supported for auto encryption: %s", cmd_name);
- return false;
-}
-
-bool
-mongocrypt_ctx_encrypt_init (mongocrypt_ctx_t *ctx,
- const char *db,
- int32_t db_len,
- mongocrypt_binary_t *cmd)
-{
- _mongocrypt_ctx_encrypt_t *ectx;
- _mongocrypt_ctx_opts_spec_t opts_spec;
- bool bypass;
-
- if (!ctx) {
- return false;
- }
- memset (&opts_spec, 0, sizeof (opts_spec));
- opts_spec.schema = OPT_OPTIONAL;
- if (!_mongocrypt_ctx_init (ctx, &opts_spec)) {
- return false;
- }
-
- ectx = (_mongocrypt_ctx_encrypt_t *) ctx;
- ctx->type = _MONGOCRYPT_TYPE_ENCRYPT;
- ectx->explicit = false;
- ctx->vtable.mongo_op_collinfo = _mongo_op_collinfo;
- ctx->vtable.mongo_feed_collinfo = _mongo_feed_collinfo;
- ctx->vtable.mongo_done_collinfo = _mongo_done_collinfo;
- ctx->vtable.mongo_op_collinfo = _mongo_op_collinfo;
- ctx->vtable.mongo_op_markings = _mongo_op_markings;
- ctx->vtable.mongo_feed_markings = _mongo_feed_markings;
- ctx->vtable.mongo_done_markings = _mongo_done_markings;
- ctx->vtable.finalize = _finalize;
- ctx->vtable.cleanup = _cleanup;
- ctx->vtable.mongo_op_collinfo = _mongo_op_collinfo;
- ctx->vtable.mongo_feed_collinfo = _mongo_feed_collinfo;
- ctx->vtable.mongo_done_collinfo = _mongo_done_collinfo;
-
-
- if (!cmd || !cmd->data) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "invalid command");
- }
-
- _mongocrypt_buffer_copy_from_binary (&ectx->original_cmd, cmd);
-
- if (!_check_cmd_for_auto_encrypt (
- cmd, &bypass, &ectx->coll_name, ctx->status)) {
- return _mongocrypt_ctx_fail (ctx);
- }
-
- if (bypass) {
- ctx->nothing_to_do = true;
- ctx->state = MONGOCRYPT_CTX_READY;
- return true;
- }
-
- /* if _check_cmd_for_auto_encrypt did not bypass or error, a collection name
- * must have been set. */
- if (!ectx->coll_name) {
- return _mongocrypt_ctx_fail_w_msg (
- ctx,
- "unexpected error: did not bypass or error but no collection name");
- }
-
- if (!_mongocrypt_validate_and_copy_string (db, db_len, &ectx->db_name) ||
- 0 == strlen (ectx->db_name)) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "invalid db");
- }
-
- ectx->ns = bson_strdup_printf ("%s.%s", ectx->db_name, ectx->coll_name);
-
- if (ctx->opts.kek.provider.aws.region || ctx->opts.kek.provider.aws.cmk) {
- return _mongocrypt_ctx_fail_w_msg (
- ctx, "aws masterkey options must not be set");
- }
-
- if (!_mongocrypt_buffer_empty (&ctx->opts.key_id)) {
- return _mongocrypt_ctx_fail_w_msg (
- ctx, "key_id must not be set for auto encryption");
- }
-
- if (ctx->opts.algorithm != MONGOCRYPT_ENCRYPTION_ALGORITHM_NONE) {
- return _mongocrypt_ctx_fail_w_msg (
- ctx, "algorithm must not be set for auto encryption");
- }
-
- if (ctx->crypt->log.trace_enabled) {
- char *cmd_val;
- cmd_val = _mongocrypt_new_json_string_from_binary (cmd);
- _mongocrypt_log (&ctx->crypt->log,
- MONGOCRYPT_LOG_LEVEL_TRACE,
- "%s (%s=\"%s\", %s=%d, %s=\"%s\")",
- BSON_FUNC,
- "db",
- ectx->db_name,
- "db_len",
- db_len,
- "cmd",
- cmd_val);
- bson_free (cmd_val);
- }
-
- /* Check if we have a local schema from schema_map */
- if (!_try_schema_from_schema_map (ctx)) {
- return false;
- }
-
- /* If we didn't have a local schema, try the cache. */
- if (_mongocrypt_buffer_empty (&ectx->schema)) {
- if (!_try_schema_from_cache (ctx)) {
- return false;
- }
- }
-
- /* Otherwise, we need the the driver to fetch the schema. */
- if (_mongocrypt_buffer_empty (&ectx->schema)) {
- ctx->state = MONGOCRYPT_CTX_NEED_MONGO_COLLINFO;
- }
- return true;
-}
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-ctx-private.h b/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-ctx-private.h
deleted file mode 100644
index 16939f6b..00000000
--- a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-ctx-private.h
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Copyright 2019-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef MONGOCRYPT_CTX_PRIVATE_H
-#define MONGOCRYPT_CTX_PRIVATE_H
-
-#include "mongocrypt.h"
-#include "mongocrypt-private.h"
-#include "mongocrypt-buffer-private.h"
-#include "mongocrypt-key-broker-private.h"
-#include "mongocrypt-key-private.h"
-#include "mongocrypt-endpoint-private.h"
-
-typedef enum {
- _MONGOCRYPT_TYPE_NONE,
- _MONGOCRYPT_TYPE_ENCRYPT,
- _MONGOCRYPT_TYPE_DECRYPT,
- _MONGOCRYPT_TYPE_CREATE_DATA_KEY,
-} _mongocrypt_ctx_type_t;
-
-/* Option values are validated when set.
- * Different contexts accept/require different options,
- * validated when a context is initialized.
- */
-typedef struct __mongocrypt_ctx_opts_t {
- _mongocrypt_buffer_t key_id;
- _mongocrypt_key_alt_name_t *key_alt_names;
- mongocrypt_encryption_algorithm_t algorithm;
- _mongocrypt_kek_t kek;
-} _mongocrypt_ctx_opts_t;
-
-
-/* All derived contexts may override these methods. */
-typedef struct {
- bool (*mongo_op_collinfo) (mongocrypt_ctx_t *ctx, mongocrypt_binary_t *out);
- bool (*mongo_feed_collinfo) (mongocrypt_ctx_t *ctx, mongocrypt_binary_t *in);
- bool (*mongo_done_collinfo) (mongocrypt_ctx_t *ctx);
- bool (*mongo_op_markings) (mongocrypt_ctx_t *ctx, mongocrypt_binary_t *out);
- bool (*mongo_feed_markings) (mongocrypt_ctx_t *ctx, mongocrypt_binary_t *in);
- bool (*mongo_done_markings) (mongocrypt_ctx_t *ctx);
- bool (*mongo_op_keys) (mongocrypt_ctx_t *ctx, mongocrypt_binary_t *out);
- bool (*mongo_feed_keys) (mongocrypt_ctx_t *ctx, mongocrypt_binary_t *in);
- bool (*mongo_done_keys) (mongocrypt_ctx_t *ctx);
- mongocrypt_kms_ctx_t *(*next_kms_ctx) (mongocrypt_ctx_t *ctx);
- bool (*kms_done) (mongocrypt_ctx_t *ctx);
- bool (*finalize) (mongocrypt_ctx_t *ctx, mongocrypt_binary_t *out);
- void (*cleanup) (mongocrypt_ctx_t *ctx);
-} _mongocrypt_vtable_t;
-
-
-struct _mongocrypt_ctx_t {
- mongocrypt_t *crypt;
- mongocrypt_ctx_state_t state;
- _mongocrypt_ctx_type_t type;
- mongocrypt_status_t *status;
- _mongocrypt_key_broker_t kb;
- _mongocrypt_vtable_t vtable;
- _mongocrypt_ctx_opts_t opts;
- bool initialized;
- bool
- nothing_to_do; /* set to true if no encryption/decryption is required. */
-};
-
-
-/* Transition to the error state. An error status must have been set. */
-bool
-_mongocrypt_ctx_fail (mongocrypt_ctx_t *ctx);
-
-
-/* Set an error status and transition to the error state. */
-bool
-_mongocrypt_ctx_fail_w_msg (mongocrypt_ctx_t *ctx, const char *msg);
-
-
-typedef struct {
- mongocrypt_ctx_t parent;
- bool explicit;
- char *coll_name;
- char *db_name;
- char *ns;
- _mongocrypt_buffer_t list_collections_filter;
- _mongocrypt_buffer_t schema;
- /* TODO CDRIVER-3150: audit + rename these buffers.
- * original_cmd for explicit is {v: <BSON value>}, for auto is the command to
- * be encrypted.
- *
- * mongocryptd_cmd is only applicable for auto encryption. It is the original
- * command with JSONSchema appended.
- *
- * marked_cmd is the value of the 'result' field in mongocryptd response
- *
- * encrypted_cmd is the final output, the original command encrypted, or for
- * explicit, the {v: <ciphertext>} doc.
- */
- _mongocrypt_buffer_t original_cmd;
- _mongocrypt_buffer_t mongocryptd_cmd;
- _mongocrypt_buffer_t marked_cmd;
- _mongocrypt_buffer_t encrypted_cmd;
- _mongocrypt_buffer_t key_id;
- bool used_local_schema;
- /* collinfo_has_siblings is true if the schema came from a remote JSON
- * schema, and there were siblings. */
- bool collinfo_has_siblings;
-} _mongocrypt_ctx_encrypt_t;
-
-
-typedef struct {
- mongocrypt_ctx_t parent;
- bool explicit;
- /* TODO CDRIVER-3150: audit + rename these buffers.
- * Unlike ctx_encrypt, unwrapped_doc holds the binary value of the {v:
- * <ciphertext>} doc.
- * */
- _mongocrypt_buffer_t original_doc;
- _mongocrypt_buffer_t unwrapped_doc; /* explicit only */
- _mongocrypt_buffer_t decrypted_doc;
-} _mongocrypt_ctx_decrypt_t;
-
-
-typedef struct {
- mongocrypt_ctx_t parent;
- mongocrypt_kms_ctx_t kms;
- bool kms_returned;
- _mongocrypt_buffer_t key_doc;
- _mongocrypt_buffer_t plaintext_key_material;
- _mongocrypt_buffer_t encrypted_key_material;
-
- const char *kmip_unique_identifier;
- bool kmip_activated;
- _mongocrypt_buffer_t kmip_secretdata;
-} _mongocrypt_ctx_datakey_t;
-
-
-/* Used for option validation. True means required. False means prohibited. */
-typedef enum {
- OPT_PROHIBITED = 0,
- OPT_REQUIRED,
- OPT_OPTIONAL
-} _mongocrypt_ctx_opt_spec_t;
-typedef struct {
- _mongocrypt_ctx_opt_spec_t kek;
- _mongocrypt_ctx_opt_spec_t schema;
- _mongocrypt_ctx_opt_spec_t key_descriptor; /* a key_id or key_alt_name */
- _mongocrypt_ctx_opt_spec_t key_alt_names;
- _mongocrypt_ctx_opt_spec_t algorithm;
-} _mongocrypt_ctx_opts_spec_t;
-
-/* Common initialization. */
-bool
-_mongocrypt_ctx_init (mongocrypt_ctx_t *ctx,
- _mongocrypt_ctx_opts_spec_t *opt_spec)
- MONGOCRYPT_WARN_UNUSED_RESULT;
-
-/* Set the state of the context from the state of keys in the key broker. */
-bool
-_mongocrypt_ctx_state_from_key_broker (mongocrypt_ctx_t *ctx)
- MONGOCRYPT_WARN_UNUSED_RESULT;
-
-#endif /* MONGOCRYPT_CTX_PRIVATE_H */
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-ctx.c b/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-ctx.c
deleted file mode 100644
index 43ac216f..00000000
--- a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-ctx.c
+++ /dev/null
@@ -1,887 +0,0 @@
-/*
- * Copyright 2019-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <bson/bson.h>
-
-#include "mongocrypt-ctx-private.h"
-#include "mongocrypt-key-broker-private.h"
-
-#define ALGORITHM_DETERMINISTIC "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic"
-#define ALGORITHM_DETERMINISTIC_LEN 43
-#define ALGORITHM_RANDOM "AEAD_AES_256_CBC_HMAC_SHA_512-Random"
-#define ALGORITHM_RANDOM_LEN 36
-
-bool
-_mongocrypt_ctx_fail_w_msg (mongocrypt_ctx_t *ctx, const char *msg)
-{
- _mongocrypt_set_error (ctx->status,
- MONGOCRYPT_STATUS_ERROR_CLIENT,
- MONGOCRYPT_GENERIC_ERROR_CODE,
- "%s",
- msg);
- return _mongocrypt_ctx_fail (ctx);
-}
-
-/* A failure status has already been set. */
-bool
-_mongocrypt_ctx_fail (mongocrypt_ctx_t *ctx)
-{
- if (mongocrypt_status_ok (ctx->status)) {
- return _mongocrypt_ctx_fail_w_msg (
- ctx, "unexpected, failing but no error status set");
- }
- ctx->state = MONGOCRYPT_CTX_ERROR;
- return false;
-}
-
-
-static bool
-_set_binary_opt (mongocrypt_ctx_t *ctx,
- mongocrypt_binary_t *binary,
- _mongocrypt_buffer_t *buf,
- bson_subtype_t subtype)
-{
- BSON_ASSERT (ctx);
-
- if (ctx->state == MONGOCRYPT_CTX_ERROR) {
- return false;
- }
-
- if (!binary || !binary->data) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "option must be non-NULL");
- }
-
- if (!_mongocrypt_buffer_empty (buf)) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "option already set");
- }
-
- if (ctx->initialized) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "cannot set options after init");
- }
-
- if (subtype == BSON_SUBTYPE_UUID && binary->len != 16) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "expected 16 byte UUID");
- }
-
- _mongocrypt_buffer_copy_from_binary (buf, binary);
- buf->subtype = subtype;
-
- return true;
-}
-
-
-bool
-mongocrypt_ctx_setopt_key_id (mongocrypt_ctx_t *ctx,
- mongocrypt_binary_t *key_id)
-{
- if (!ctx) {
- return false;
- }
-
- if (ctx->crypt->log.trace_enabled && key_id && key_id->data) {
- char *key_id_val;
- key_id_val =
- _mongocrypt_new_string_from_bytes (key_id->data, key_id->len);
- _mongocrypt_log (&ctx->crypt->log,
- MONGOCRYPT_LOG_LEVEL_TRACE,
- "%s (%s=\"%s\")",
- BSON_FUNC,
- "key_id",
- key_id_val);
- bson_free (key_id_val);
- }
-
- return _set_binary_opt (ctx, key_id, &ctx->opts.key_id, BSON_SUBTYPE_UUID);
-}
-
-
-bool
-mongocrypt_ctx_setopt_key_alt_name (mongocrypt_ctx_t *ctx,
- mongocrypt_binary_t *key_alt_name)
-{
- bson_t as_bson;
- bson_iter_t iter;
- _mongocrypt_key_alt_name_t *new_key_alt_name;
- const char *key;
-
- if (!ctx) {
- return false;
- }
-
- if (ctx->initialized) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "cannot set options after init");
- }
-
- if (ctx->state == MONGOCRYPT_CTX_ERROR) {
- return false;
- }
-
- if (!key_alt_name || !key_alt_name->data) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "option must be non-NULL");
- }
-
- if (!_mongocrypt_binary_to_bson (key_alt_name, &as_bson)) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "invalid keyAltName bson object");
- }
-
- if (!bson_iter_init (&iter, &as_bson) || !bson_iter_next (&iter)) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "invalid bson");
- }
-
- key = bson_iter_key (&iter);
- BSON_ASSERT (key);
- if (0 != strcmp (key, "keyAltName")) {
- return _mongocrypt_ctx_fail_w_msg (
- ctx, "keyAltName must have field 'keyAltName'");
- }
-
- if (!BSON_ITER_HOLDS_UTF8 (&iter)) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "keyAltName expected to be UTF8");
- }
-
- new_key_alt_name = _mongocrypt_key_alt_name_new (bson_iter_value (&iter));
-
- if (ctx->opts.key_alt_names &&
- _mongocrypt_key_alt_name_intersects (ctx->opts.key_alt_names,
- new_key_alt_name)) {
- _mongocrypt_key_alt_name_destroy_all (new_key_alt_name);
- return _mongocrypt_ctx_fail_w_msg (ctx, "duplicate keyAltNames found");
- }
- new_key_alt_name->next = ctx->opts.key_alt_names;
- ctx->opts.key_alt_names = new_key_alt_name;
-
- if (bson_iter_next (&iter)) {
- return _mongocrypt_ctx_fail_w_msg (
- ctx, "unrecognized field, only keyAltName expected");
- }
-
- return true;
-}
-
-
-bool
-mongocrypt_ctx_setopt_algorithm (mongocrypt_ctx_t *ctx,
- const char *algorithm,
- int len)
-{
- size_t calculated_len;
-
- if (!ctx) {
- return false;
- }
-
- if (ctx->initialized) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "cannot set options after init");
- }
-
- if (ctx->state == MONGOCRYPT_CTX_ERROR) {
- return false;
- }
-
- if (ctx->opts.algorithm != MONGOCRYPT_ENCRYPTION_ALGORITHM_NONE) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "already set algorithm");
- }
-
- if (len < -1) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "invalid algorithm length");
- }
-
- if (!algorithm) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "passed null algorithm");
- }
-
- calculated_len = len == -1 ? strlen (algorithm) : (size_t) len;
- if (ctx->crypt->log.trace_enabled) {
- _mongocrypt_log (&ctx->crypt->log,
- MONGOCRYPT_LOG_LEVEL_TRACE,
- "%s (%s=\"%.*s\")",
- BSON_FUNC,
- "algorithm",
- (int) calculated_len,
- algorithm);
- }
-
- if (calculated_len == ALGORITHM_DETERMINISTIC_LEN &&
- strncmp (algorithm,
- ALGORITHM_DETERMINISTIC,
- ALGORITHM_DETERMINISTIC_LEN) == 0) {
- ctx->opts.algorithm = MONGOCRYPT_ENCRYPTION_ALGORITHM_DETERMINISTIC;
- return true;
- }
-
- if (calculated_len == ALGORITHM_RANDOM_LEN &&
- strncmp (algorithm, ALGORITHM_RANDOM, ALGORITHM_RANDOM_LEN) == 0) {
- ctx->opts.algorithm = MONGOCRYPT_ENCRYPTION_ALGORITHM_RANDOM;
- return true;
- }
-
- return _mongocrypt_ctx_fail_w_msg (ctx, "unsupported algorithm");
-}
-
-
-mongocrypt_ctx_t *
-mongocrypt_ctx_new (mongocrypt_t *crypt)
-{
- mongocrypt_ctx_t *ctx;
- size_t ctx_size;
-
- if (!crypt) {
- return NULL;
- }
- if (!crypt->initialized) {
- mongocrypt_status_t *status;
-
- status = crypt->status;
- CLIENT_ERR ("cannot create context from uninitialized crypt");
- return NULL;
- }
- ctx_size = sizeof (_mongocrypt_ctx_encrypt_t);
- if (sizeof (_mongocrypt_ctx_decrypt_t) > ctx_size) {
- ctx_size = sizeof (_mongocrypt_ctx_decrypt_t);
- }
- if (sizeof (_mongocrypt_ctx_datakey_t) > ctx_size) {
- ctx_size = sizeof (_mongocrypt_ctx_datakey_t);
- }
- ctx = bson_malloc0 (ctx_size);
- BSON_ASSERT (ctx);
-
- ctx->crypt = crypt;
- ctx->status = mongocrypt_status_new ();
- ctx->opts.algorithm = MONGOCRYPT_ENCRYPTION_ALGORITHM_NONE;
- ctx->state = MONGOCRYPT_CTX_DONE;
- return ctx;
-}
-
-#define CHECK_AND_CALL(fn, ...) \
- do { \
- if (!ctx->vtable.fn) { \
- return _mongocrypt_ctx_fail_w_msg (ctx, "not applicable to context"); \
- } \
- return ctx->vtable.fn (__VA_ARGS__); \
- } while (0)
-
-/* Common to both encrypt and decrypt context. */
-static bool
-_mongo_op_keys (mongocrypt_ctx_t *ctx, mongocrypt_binary_t *out)
-{
- /* Construct the find filter to fetch keys. */
- if (!_mongocrypt_key_broker_filter (&ctx->kb, out)) {
- BSON_ASSERT (!_mongocrypt_key_broker_status (&ctx->kb, ctx->status));
- return _mongocrypt_ctx_fail (ctx);
- }
- return true;
-}
-
-
-static bool
-_mongo_feed_keys (mongocrypt_ctx_t *ctx, mongocrypt_binary_t *in)
-{
- _mongocrypt_buffer_t buf;
-
- _mongocrypt_buffer_from_binary (&buf, in);
- if (!_mongocrypt_key_broker_add_doc (&ctx->kb, &buf)) {
- BSON_ASSERT (!_mongocrypt_key_broker_status (&ctx->kb, ctx->status));
- return _mongocrypt_ctx_fail (ctx);
- }
- return true;
-}
-
-
-static bool
-_mongo_done_keys (mongocrypt_ctx_t *ctx)
-{
- (void) _mongocrypt_key_broker_docs_done (&ctx->kb);
- return _mongocrypt_ctx_state_from_key_broker (ctx);
-}
-
-static mongocrypt_kms_ctx_t *
-_next_kms_ctx (mongocrypt_ctx_t *ctx)
-{
- return _mongocrypt_key_broker_next_kms (&ctx->kb);
-}
-
-
-static bool
-_kms_done (mongocrypt_ctx_t *ctx)
-{
- if (!_mongocrypt_key_broker_kms_done (&ctx->kb)) {
- BSON_ASSERT (!_mongocrypt_key_broker_status (&ctx->kb, ctx->status));
- return _mongocrypt_ctx_fail (ctx);
- }
- return _mongocrypt_ctx_state_from_key_broker (ctx);
-}
-
-
-bool
-mongocrypt_ctx_mongo_op (mongocrypt_ctx_t *ctx, mongocrypt_binary_t *out)
-{
- if (!ctx) {
- return false;
- }
- if (!ctx->initialized) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "ctx NULL or uninitialized");
- }
-
- if (!out) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "invalid NULL input");
- }
-
- switch (ctx->state) {
- case MONGOCRYPT_CTX_NEED_MONGO_COLLINFO:
- CHECK_AND_CALL (mongo_op_collinfo, ctx, out);
- case MONGOCRYPT_CTX_NEED_MONGO_MARKINGS:
- CHECK_AND_CALL (mongo_op_markings, ctx, out);
- case MONGOCRYPT_CTX_NEED_MONGO_KEYS:
- CHECK_AND_CALL (mongo_op_keys, ctx, out);
- case MONGOCRYPT_CTX_ERROR:
- return false;
- default:
- return _mongocrypt_ctx_fail_w_msg (ctx, "wrong state");
- }
-}
-
-
-bool
-mongocrypt_ctx_mongo_feed (mongocrypt_ctx_t *ctx, mongocrypt_binary_t *in)
-{
- if (!ctx) {
- return false;
- }
- if (!ctx->initialized) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "ctx NULL or uninitialized");
- }
-
- if (!in) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "invalid NULL input");
- }
-
- if (ctx->crypt->log.trace_enabled) {
- char *in_val;
-
- in_val = _mongocrypt_new_json_string_from_binary (in);
- _mongocrypt_log (&ctx->crypt->log,
- MONGOCRYPT_LOG_LEVEL_TRACE,
- "%s (%s=\"%s\")",
- BSON_FUNC,
- "in",
- in_val);
- bson_free (in_val);
- }
-
- switch (ctx->state) {
- case MONGOCRYPT_CTX_NEED_MONGO_COLLINFO:
- CHECK_AND_CALL (mongo_feed_collinfo, ctx, in);
- case MONGOCRYPT_CTX_NEED_MONGO_MARKINGS:
- CHECK_AND_CALL (mongo_feed_markings, ctx, in);
- case MONGOCRYPT_CTX_NEED_MONGO_KEYS:
- CHECK_AND_CALL (mongo_feed_keys, ctx, in);
- case MONGOCRYPT_CTX_ERROR:
- return false;
- default:
- return _mongocrypt_ctx_fail_w_msg (ctx, "wrong state");
- }
-}
-
-
-bool
-mongocrypt_ctx_mongo_done (mongocrypt_ctx_t *ctx)
-{
- if (!ctx) {
- return false;
- }
- if (!ctx->initialized) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "ctx NULL or uninitialized");
- }
-
- switch (ctx->state) {
- case MONGOCRYPT_CTX_NEED_MONGO_COLLINFO:
- CHECK_AND_CALL (mongo_done_collinfo, ctx);
- case MONGOCRYPT_CTX_NEED_MONGO_MARKINGS:
- CHECK_AND_CALL (mongo_done_markings, ctx);
- case MONGOCRYPT_CTX_NEED_MONGO_KEYS:
- CHECK_AND_CALL (mongo_done_keys, ctx);
- case MONGOCRYPT_CTX_ERROR:
- return false;
- default:
- return _mongocrypt_ctx_fail_w_msg (ctx, "wrong state");
- }
-}
-
-
-mongocrypt_ctx_state_t
-mongocrypt_ctx_state (mongocrypt_ctx_t *ctx)
-{
- if (!ctx) {
- return MONGOCRYPT_CTX_ERROR;
- }
- if (!ctx->initialized) {
- _mongocrypt_ctx_fail_w_msg (ctx, "ctx NULL or uninitialized");
- return MONGOCRYPT_CTX_ERROR;
- }
-
- return ctx->state;
-}
-
-
-mongocrypt_kms_ctx_t *
-mongocrypt_ctx_next_kms_ctx (mongocrypt_ctx_t *ctx)
-{
- if (!ctx) {
- return NULL;
- }
- if (!ctx->initialized) {
- _mongocrypt_ctx_fail_w_msg (ctx, "ctx NULL or uninitialized");
- return NULL;
- }
-
- if (!ctx->vtable.next_kms_ctx) {
- _mongocrypt_ctx_fail_w_msg (ctx, "not applicable to context");
- return NULL;
- }
-
- switch (ctx->state) {
- case MONGOCRYPT_CTX_NEED_KMS:
- return ctx->vtable.next_kms_ctx (ctx);
- case MONGOCRYPT_CTX_ERROR:
- return NULL;
- default:
- _mongocrypt_ctx_fail_w_msg (ctx, "wrong state");
- return NULL;
- }
-}
-
-
-bool
-mongocrypt_ctx_kms_done (mongocrypt_ctx_t *ctx)
-{
- if (!ctx) {
- return false;
- }
- if (!ctx->initialized) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "ctx NULL or uninitialized");
- }
-
- if (!ctx->vtable.kms_done) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "not applicable to context");
- }
-
- switch (ctx->state) {
- case MONGOCRYPT_CTX_NEED_KMS:
- return ctx->vtable.kms_done (ctx);
- case MONGOCRYPT_CTX_ERROR:
- return false;
- default:
- return _mongocrypt_ctx_fail_w_msg (ctx, "wrong state");
- }
-}
-
-
-bool
-mongocrypt_ctx_finalize (mongocrypt_ctx_t *ctx, mongocrypt_binary_t *out)
-{
- if (!ctx) {
- return false;
- }
- if (!ctx->initialized) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "ctx NULL or uninitialized");
- }
-
- if (!out) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "invalid NULL input");
- }
-
- if (!ctx->vtable.finalize) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "not applicable to context");
- }
-
- switch (ctx->state) {
- case MONGOCRYPT_CTX_READY:
- return ctx->vtable.finalize (ctx, out);
- case MONGOCRYPT_CTX_ERROR:
- return false;
- default:
- return _mongocrypt_ctx_fail_w_msg (ctx, "wrong state");
- }
-}
-
-bool
-mongocrypt_ctx_status (mongocrypt_ctx_t *ctx, mongocrypt_status_t *out)
-{
- if (!ctx) {
- return false;
- }
-
- if (!mongocrypt_status_ok (ctx->status)) {
- _mongocrypt_status_copy_to (ctx->status, out);
- return false;
- }
- _mongocrypt_status_reset (out);
- return true;
-}
-
-
-void
-mongocrypt_ctx_destroy (mongocrypt_ctx_t *ctx)
-{
- if (!ctx) {
- return;
- }
-
- if (ctx->vtable.cleanup) {
- ctx->vtable.cleanup (ctx);
- }
-
- _mongocrypt_kek_cleanup (&ctx->opts.kek);
- mongocrypt_status_destroy (ctx->status);
- _mongocrypt_key_broker_cleanup (&ctx->kb);
- _mongocrypt_key_alt_name_destroy_all (ctx->opts.key_alt_names);
- _mongocrypt_buffer_cleanup (&ctx->opts.key_id);
- bson_free (ctx);
- return;
-}
-
-
-bool
-mongocrypt_ctx_setopt_masterkey_aws (mongocrypt_ctx_t *ctx,
- const char *region,
- int32_t region_len,
- const char *cmk,
- int32_t cmk_len)
-{
- mongocrypt_binary_t *bin;
- bson_t as_bson;
- bool ret;
- char *temp = NULL;
-
- if (!ctx) {
- return false;
- }
- if (ctx->initialized) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "cannot set options after init");
- }
-
- if (ctx->state == MONGOCRYPT_CTX_ERROR) {
- return false;
- }
-
- if (ctx->opts.kek.kms_provider != MONGOCRYPT_KMS_PROVIDER_AWS &&
- ctx->opts.kek.kms_provider != MONGOCRYPT_KMS_PROVIDER_NONE) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "master key already set");
- }
-
- if (ctx->opts.kek.kms_provider == MONGOCRYPT_KMS_PROVIDER_AWS &&
- ctx->opts.kek.provider.aws.region) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "master key already set");
- }
-
- if (!_mongocrypt_validate_and_copy_string (region, region_len, &temp) ||
- region_len == 0) {
- bson_free (temp);
- return _mongocrypt_ctx_fail_w_msg (ctx, "invalid region");
- }
- bson_free (temp);
-
- temp = NULL;
- if (!_mongocrypt_validate_and_copy_string (cmk, cmk_len, &temp) ||
- cmk_len == 0) {
- bson_free (temp);
- return _mongocrypt_ctx_fail_w_msg (ctx, "invalid cmk");
- }
- bson_free (temp);
-
- bson_init (&as_bson);
- bson_append_utf8 (&as_bson,
- MONGOCRYPT_STR_AND_LEN ("provider"),
- MONGOCRYPT_STR_AND_LEN ("aws"));
- bson_append_utf8 (
- &as_bson, MONGOCRYPT_STR_AND_LEN ("region"), region, region_len);
- bson_append_utf8 (&as_bson, MONGOCRYPT_STR_AND_LEN ("key"), cmk, cmk_len);
- bin = mongocrypt_binary_new_from_data ((uint8_t *) bson_get_data (&as_bson),
- as_bson.len);
-
- ret = mongocrypt_ctx_setopt_key_encryption_key (ctx, bin);
- mongocrypt_binary_destroy (bin);
- bson_destroy (&as_bson);
-
- if (ctx->crypt->log.trace_enabled) {
- _mongocrypt_log (&ctx->crypt->log,
- MONGOCRYPT_LOG_LEVEL_TRACE,
- "%s (%s=\"%s\", %s=%d, %s=\"%s\", %s=%d)",
- BSON_FUNC,
- "region",
- ctx->opts.kek.provider.aws.region,
- "region_len",
- region_len,
- "cmk",
- ctx->opts.kek.provider.aws.cmk,
- "cmk_len",
- cmk_len);
- }
-
- return ret;
-}
-
-
-bool
-mongocrypt_ctx_setopt_masterkey_local (mongocrypt_ctx_t *ctx)
-{
- if (!ctx) {
- return false;
- }
- if (ctx->initialized) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "cannot set options after init");
- }
-
- if (ctx->state == MONGOCRYPT_CTX_ERROR) {
- return false;
- }
-
- if (ctx->opts.kek.kms_provider) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "master key already set");
- }
-
- ctx->opts.kek.kms_provider = MONGOCRYPT_KMS_PROVIDER_LOCAL;
- return true;
-}
-
-
-bool
-_mongocrypt_ctx_init (mongocrypt_ctx_t *ctx,
- _mongocrypt_ctx_opts_spec_t *opts_spec)
-{
- bool has_id = false, has_alt_name = false, has_multiple_alt_names = false;
-
- if (ctx->initialized) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "cannot double initialize");
- }
- ctx->initialized = true;
-
- if (ctx->state == MONGOCRYPT_CTX_ERROR) {
- return false;
- }
- /* Set some default functions */
- ctx->vtable.mongo_op_keys = _mongo_op_keys;
- ctx->vtable.mongo_feed_keys = _mongo_feed_keys;
- ctx->vtable.mongo_done_keys = _mongo_done_keys;
- ctx->vtable.next_kms_ctx = _next_kms_ctx;
- ctx->vtable.kms_done = _kms_done;
-
- /* Check that required options are included and prohibited options are
- * not.
- */
-
- if (opts_spec->kek == OPT_REQUIRED) {
- if (!ctx->opts.kek.kms_provider) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "master key required");
- }
- if (!(ctx->opts.kek.kms_provider & ctx->crypt->opts.kms_providers)) {
- return _mongocrypt_ctx_fail_w_msg (
- ctx, "requested kms provider not configured");
- }
- }
-
- if (opts_spec->kek == OPT_PROHIBITED && ctx->opts.kek.kms_provider) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "master key prohibited");
- }
-
- /* Special case. key_descriptor applies to explicit encryption. It must be
- * either a key id or *one* key alt name, but not both.
- * key_alt_names applies to creating a data key. It may be one or multiple
- * key alt names.
- */
- has_id = !_mongocrypt_buffer_empty (&ctx->opts.key_id);
- has_alt_name = !!(ctx->opts.key_alt_names);
- has_multiple_alt_names = has_alt_name && !!(ctx->opts.key_alt_names->next);
-
- if (opts_spec->key_descriptor == OPT_REQUIRED) {
- if (!has_id && !has_alt_name) {
- return _mongocrypt_ctx_fail_w_msg (
- ctx, "either key id or key alt name required");
- }
-
- if (has_id && has_alt_name) {
- return _mongocrypt_ctx_fail_w_msg (
- ctx, "cannot have both key id and key alt name");
- }
-
- if (has_multiple_alt_names) {
- return _mongocrypt_ctx_fail_w_msg (
- ctx, "must not specify multiple key alt names");
- }
- }
-
- if (opts_spec->key_descriptor == OPT_PROHIBITED) {
- /* still okay if key_alt_names are allowed and only alt names were
- * specified. */
- if ((opts_spec->key_alt_names == OPT_PROHIBITED && has_alt_name) ||
- has_id) {
- return _mongocrypt_ctx_fail_w_msg (ctx,
- "key id and alt name prohibited");
- }
- }
-
- if (opts_spec->algorithm == OPT_REQUIRED &&
- ctx->opts.algorithm == MONGOCRYPT_ENCRYPTION_ALGORITHM_NONE) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "algorithm required");
- }
-
- if (opts_spec->algorithm == OPT_PROHIBITED &&
- ctx->opts.algorithm != MONGOCRYPT_ENCRYPTION_ALGORITHM_NONE) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "algorithm prohibited");
- }
-
- _mongocrypt_key_broker_init (&ctx->kb, ctx->crypt);
- return true;
-}
-
-bool
-_mongocrypt_ctx_state_from_key_broker (mongocrypt_ctx_t *ctx)
-{
- _mongocrypt_key_broker_t *kb;
- mongocrypt_status_t *status;
- mongocrypt_ctx_state_t new_state = MONGOCRYPT_CTX_ERROR;
- bool ret = false;
-
- status = ctx->status;
- kb = &ctx->kb;
-
- if (ctx->state == MONGOCRYPT_CTX_ERROR) {
- return false;
- }
-
-
- switch (kb->state) {
- case KB_ERROR:
- _mongocrypt_status_copy_to (kb->status, status);
- new_state = MONGOCRYPT_CTX_ERROR;
- ret = false;
- break;
- case KB_ADDING_DOCS:
- /* Require key documents from driver. */
- new_state = MONGOCRYPT_CTX_NEED_MONGO_KEYS;
- ret = true;
- break;
- case KB_AUTHENTICATING:
- case KB_DECRYPTING_KEY_MATERIAL:
- /* Encrypted keys need KMS. */
- new_state = MONGOCRYPT_CTX_NEED_KMS;
- ret = true;
- break;
- case KB_DONE:
- new_state = MONGOCRYPT_CTX_READY;
- if (kb->key_requests == NULL) {
- /* No key requests were ever added. */
- ctx->nothing_to_do = true; /* nothing to encrypt/decrypt */
- }
- ret = true;
- break;
- /* As currently implemented, we do not expect to ever be in KB_REQUESTING
- * state when calling this function. */
- case KB_REQUESTING:
- CLIENT_ERR ("key broker in unexpected state");
- new_state = MONGOCRYPT_CTX_ERROR;
- ret = false;
- break;
- }
-
- if (new_state != ctx->state) {
- ctx->state = new_state;
- }
-
- return ret;
-}
-
-
-bool
-mongocrypt_ctx_setopt_masterkey_aws_endpoint (mongocrypt_ctx_t *ctx,
- const char *endpoint,
- int32_t endpoint_len)
-{
- if (!ctx) {
- return false;
- }
-
- if (ctx->initialized) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "cannot set options after init");
- }
-
- if (ctx->state == MONGOCRYPT_CTX_ERROR) {
- return false;
- }
-
- if (ctx->opts.kek.kms_provider != MONGOCRYPT_KMS_PROVIDER_AWS &&
- ctx->opts.kek.kms_provider != MONGOCRYPT_KMS_PROVIDER_NONE) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "endpoint prohibited");
- }
-
- ctx->opts.kek.kms_provider = MONGOCRYPT_KMS_PROVIDER_AWS;
-
- if (ctx->opts.kek.provider.aws.endpoint) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "already set masterkey endpoint");
- }
-
- ctx->opts.kek.provider.aws.endpoint = _mongocrypt_endpoint_new (
- endpoint, endpoint_len, NULL /* opts */, ctx->status);
- if (!ctx->opts.kek.provider.aws.endpoint) {
- return _mongocrypt_ctx_fail (ctx);
- }
-
- return true;
-}
-
-bool
-mongocrypt_ctx_setopt_key_encryption_key (mongocrypt_ctx_t *ctx,
- mongocrypt_binary_t *bin)
-{
- bson_t as_bson;
-
- if (!ctx) {
- return false;
- }
-
- if (ctx->initialized) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "cannot set options after init");
- }
-
- if (ctx->state == MONGOCRYPT_CTX_ERROR) {
- return false;
- }
-
- if (ctx->opts.kek.kms_provider) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "key encryption key already set");
- }
-
- if (!_mongocrypt_binary_to_bson (bin, &as_bson)) {
- return _mongocrypt_ctx_fail_w_msg (ctx, "invalid BSON");
- }
-
- if (!_mongocrypt_kek_parse_owned (&as_bson, &ctx->opts.kek, ctx->status)) {
- return _mongocrypt_ctx_fail (ctx);
- }
-
- if (ctx->crypt->log.trace_enabled) {
- char *bin_str = bson_as_canonical_extended_json (&as_bson, NULL);
- _mongocrypt_log (&ctx->crypt->log,
- MONGOCRYPT_LOG_LEVEL_TRACE,
- "%s (%s=\"%s\")",
- BSON_FUNC,
- "bin",
- bin_str);
- bson_free (bin_str);
- }
-
- return true;
-}
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-opts-private.h b/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-opts-private.h
deleted file mode 100644
index 70db6111..00000000
--- a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-opts-private.h
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * Copyright 2018-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef MONGOCRYPT_OPTS_PRIVATE_H
-#define MONGOCRYPT_OPTS_PRIVATE_H
-
-#include <bson/bson.h>
-
-#include "mongocrypt.h"
-#include "mongocrypt-buffer-private.h"
-#include "mongocrypt-log-private.h"
-#include "mongocrypt-endpoint-private.h"
-#include "mongocrypt-kek-private.h"
-
-typedef struct {
- char *tenant_id;
- char *client_id;
- char *client_secret;
- _mongocrypt_endpoint_t *identity_platform_endpoint;
-} _mongocrypt_opts_kms_provider_azure_t;
-
-typedef struct {
- char *email;
- _mongocrypt_buffer_t private_key;
- _mongocrypt_endpoint_t *endpoint;
-} _mongocrypt_opts_kms_provider_gcp_t;
-
-typedef struct {
- char *secret_access_key;
- char *access_key_id;
- char *session_token;
-} _mongocrypt_opts_kms_provider_aws_t;
-
-typedef struct {
- _mongocrypt_buffer_t key;
-} _mongocrypt_opts_kms_provider_local_t;
-
-typedef struct {
- _mongocrypt_endpoint_t *endpoint;
-} _mongocrypt_opts_kms_provider_kmip_t;
-
-typedef struct {
- mongocrypt_log_fn_t log_fn;
- void *log_ctx;
- _mongocrypt_buffer_t schema_map;
-
- int kms_providers; /* A bit set of _mongocrypt_kms_provider_t */
- _mongocrypt_opts_kms_provider_local_t kms_provider_local;
- _mongocrypt_opts_kms_provider_aws_t kms_provider_aws;
- _mongocrypt_opts_kms_provider_azure_t kms_provider_azure;
- _mongocrypt_opts_kms_provider_gcp_t kms_provider_gcp;
- _mongocrypt_opts_kms_provider_kmip_t kms_provider_kmip;
- mongocrypt_hmac_fn sign_rsaes_pkcs1_v1_5;
- void *sign_ctx;
-} _mongocrypt_opts_t;
-
-
-void
-_mongocrypt_opts_init (_mongocrypt_opts_t *opts);
-
-
-void
-_mongocrypt_opts_cleanup (_mongocrypt_opts_t *opts);
-
-
-bool
-_mongocrypt_opts_validate (_mongocrypt_opts_t *opts,
- mongocrypt_status_t *status)
- MONGOCRYPT_WARN_UNUSED_RESULT;
-
-/*
- * Parse an optional UTF-8 value from BSON.
- * @dotkey may be a dot separated key like: "a.b.c".
- * @*out is set to a copy of the string if found, NULL otherwise. Caller must
- * clean up with bson_free (*out).
- * Returns true if no error occured.
- */
-bool
-_mongocrypt_parse_optional_utf8 (const bson_t *bson,
- const char *dotkey,
- char **out,
- mongocrypt_status_t *status);
-
-/*
- * Parse a required UTF-8 value from BSON.
- * @dotkey may be a dot separated key like: "a.b.c".
- * @*out is set to a copy of the string if found, NULL otherwise. Caller must
- * clean up with bson_free (*out).
- * Returns true if no error occured.
- */
-bool
-_mongocrypt_parse_required_utf8 (const bson_t *bson,
- const char *dotkey,
- char **out,
- mongocrypt_status_t *status);
-
-/*
- * Parse an optional endpoint UTF-8 from BSON.
- * @dotkey may be a dot separated key like: "a.b.c".
- * @*out is set to a new _mongocrypt_endpoint_t of the if found, NULL otherwise.
- * @*opts may be set to configure endpoint parsing. It is optional and may be NULL.
- * Caller must clean up with _mongocrypt_endpoint_destroy (*out).
- * Returns true if no error occured.
- */
-bool
-_mongocrypt_parse_optional_endpoint (const bson_t *bson,
- const char *dotkey,
- _mongocrypt_endpoint_t **out,
- _mongocrypt_endpoint_parse_opts_t *opts,
- mongocrypt_status_t *status);
-
-/*
- * Parse a required endpoint UTF-8 from BSON.
- * @dotkey may be a dot separated key like: "a.b.c".
- * @*out is set to a new _mongocrypt_endpoint_t of the if found, NULL otherwise.
- * @*opts may be set to configure endpoint parsing. It is optional and may be NULL.
- * Caller must clean up with _mongocrypt_endpoint_destroy (*out).
- * Returns true if no error occured.
- */
-bool
-_mongocrypt_parse_required_endpoint (const bson_t *bson,
- const char *dotkey,
- _mongocrypt_endpoint_t **out,
- _mongocrypt_endpoint_parse_opts_t *opts,
- mongocrypt_status_t *status);
-
-/*
- * Parse an optional binary type from BSON.
- * The field parsed is accepted as:
- * - A BSON binary value (of any subtype).
- * - A BSON UTF-8 value, set to base64 encoded data.
- *
- * @dotkey may be a dot separated key like: "a.b.c"
- * @out is initialized with the parsed data, or initialized to empty on error.
- * Caller must clean up with _mongocrypt_buffer_cleanup (out).
- * Returns true if no error occurred.
- */
-bool
-_mongocrypt_parse_optional_binary (const bson_t *bson,
- const char *dotkey,
- _mongocrypt_buffer_t *out,
- mongocrypt_status_t *status);
-
-/*
- * Parse a required binary type from BSON.
- * The field parsed is accepted as:
- * - A BSON binary value (of any subtype).
- * - A BSON UTF-8 value, set to base64 encoded data.
- *
- * @dotkey may be a dot separated key like: "a.b.c"
- * @out is initialized with the parsed data, or initialized to empty on error.
- * Caller must clean up with _mongocrypt_buffer_cleanup (out).
- * Returns true if no error occurred.
- */
-bool
-_mongocrypt_parse_required_binary (const bson_t *bson,
- const char *dotkey,
- _mongocrypt_buffer_t *out,
- mongocrypt_status_t *status);
-
-/*
- * Checks for unrecognized fields in parsing @bson.
- * @dotkey is a dot separated path to a document field, like "a.b.c" or NULL.
- * Pass a list of allowed fields.
- * Returns true if no error occurred.
- */
-bool
-_mongocrypt_check_allowed_fields_va (const bson_t *bson,
- const char *dotkey,
- mongocrypt_status_t *status,
- ...);
-
-#define _mongocrypt_check_allowed_fields(bson, path, status, ...) \
- _mongocrypt_check_allowed_fields_va (bson, path, status, __VA_ARGS__, NULL)
-
-#endif /* MONGOCRYPT_OPTS_PRIVATE_H */
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-opts.c b/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-opts.c
deleted file mode 100644
index f384de5d..00000000
--- a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-opts.c
+++ /dev/null
@@ -1,290 +0,0 @@
-/*
- * Copyright 2018-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <bson/bson.h>
-
-#include "mongocrypt-opts-private.h"
-#include "mongocrypt-log-private.h"
-#include "mongocrypt-private.h"
-
-#include <kms_message/kms_b64.h>
-
-void
-_mongocrypt_opts_init (_mongocrypt_opts_t *opts)
-{
- memset (opts, 0, sizeof (*opts));
-}
-
-static void
-_mongocrypt_opts_kms_provider_azure_cleanup (
- _mongocrypt_opts_kms_provider_azure_t *kms_provider_azure)
-{
- bson_free (kms_provider_azure->client_id);
- bson_free (kms_provider_azure->client_secret);
- bson_free (kms_provider_azure->tenant_id);
- _mongocrypt_endpoint_destroy (
- kms_provider_azure->identity_platform_endpoint);
-}
-
-static void
-_mongocrypt_opts_kms_provider_gcp_cleanup (
- _mongocrypt_opts_kms_provider_gcp_t *kms_provider_gcp)
-{
- bson_free (kms_provider_gcp->email);
- _mongocrypt_endpoint_destroy (kms_provider_gcp->endpoint);
- _mongocrypt_buffer_cleanup (&kms_provider_gcp->private_key);
-}
-
-void
-_mongocrypt_opts_cleanup (_mongocrypt_opts_t *opts)
-{
- bson_free (opts->kms_provider_aws.secret_access_key);
- bson_free (opts->kms_provider_aws.access_key_id);
- bson_free (opts->kms_provider_aws.session_token);
- _mongocrypt_buffer_cleanup (&opts->kms_provider_local.key);
- _mongocrypt_buffer_cleanup (&opts->schema_map);
- _mongocrypt_opts_kms_provider_azure_cleanup (&opts->kms_provider_azure);
- _mongocrypt_opts_kms_provider_gcp_cleanup (&opts->kms_provider_gcp);
- _mongocrypt_endpoint_destroy (opts->kms_provider_kmip.endpoint);
-}
-
-
-bool
-_mongocrypt_opts_validate (_mongocrypt_opts_t *opts,
- mongocrypt_status_t *status)
-{
- if (!opts->kms_providers) {
- CLIENT_ERR ("no kms provider set");
- return false;
- }
-
- if (opts->kms_providers & MONGOCRYPT_KMS_PROVIDER_AWS) {
- if (!opts->kms_provider_aws.access_key_id ||
- !opts->kms_provider_aws.secret_access_key) {
- CLIENT_ERR ("aws credentials unset");
- return false;
- }
- }
-
- if (opts->kms_providers & MONGOCRYPT_KMS_PROVIDER_LOCAL) {
- if (_mongocrypt_buffer_empty (&opts->kms_provider_local.key)) {
- CLIENT_ERR ("local data key unset");
- return false;
- }
- }
-
- return true;
-}
-
-bool
-_mongocrypt_parse_optional_utf8 (const bson_t *bson,
- const char *dotkey,
- char **out,
- mongocrypt_status_t *status)
-{
- bson_iter_t iter;
- bson_iter_t child;
-
- *out = NULL;
-
- if (!bson_iter_init (&iter, bson)) {
- CLIENT_ERR ("invalid BSON");
- return false;
- }
- if (!bson_iter_find_descendant (&iter, dotkey, &child)) {
- /* Not found. Not an error. */
- return true;
- }
- if (!BSON_ITER_HOLDS_UTF8 (&child)) {
- CLIENT_ERR ("expected UTF-8 %s", dotkey);
- return false;
- }
-
- *out = bson_strdup (bson_iter_utf8 (&child, NULL));
- return true;
-}
-
-
-bool
-_mongocrypt_parse_required_utf8 (const bson_t *bson,
- const char *dotkey,
- char **out,
- mongocrypt_status_t *status)
-{
- if (!_mongocrypt_parse_optional_utf8 (bson, dotkey, out, status)) {
- return false;
- }
-
- if (!*out) {
- CLIENT_ERR ("expected UTF-8 %s", dotkey);
- return false;
- }
-
- return true;
-}
-
-bool
-_mongocrypt_parse_optional_endpoint (const bson_t *bson,
- const char *dotkey,
- _mongocrypt_endpoint_t **out,
- _mongocrypt_endpoint_parse_opts_t *opts,
- mongocrypt_status_t *status)
-{
- char *endpoint_raw;
-
- *out = NULL;
-
- if (!_mongocrypt_parse_optional_utf8 (bson, dotkey, &endpoint_raw, status)) {
- return false;
- }
-
- /* Not found. Not an error. */
- if (!endpoint_raw) {
- return true;
- }
-
- *out = _mongocrypt_endpoint_new (endpoint_raw, -1, opts, status);
- bson_free (endpoint_raw);
- return (*out) != NULL;
-}
-
-bool
-_mongocrypt_parse_required_endpoint (const bson_t *bson,
- const char *dotkey,
- _mongocrypt_endpoint_t **out,
- _mongocrypt_endpoint_parse_opts_t *opts,
- mongocrypt_status_t *status)
-{
- if (!_mongocrypt_parse_optional_endpoint (bson, dotkey, out, opts, status)) {
- return false;
- }
-
- if (!*out) {
- CLIENT_ERR ("expected endpoint %s", dotkey);
- return false;
- }
-
- return true;
-}
-
-
-bool
-_mongocrypt_parse_optional_binary (const bson_t *bson,
- const char *dotkey,
- _mongocrypt_buffer_t *out,
- mongocrypt_status_t *status)
-{
- bson_iter_t iter;
- bson_iter_t child;
-
- _mongocrypt_buffer_init (out);
-
- if (!bson_iter_init (&iter, bson)) {
- CLIENT_ERR ("invalid BSON");
- return false;
- }
- if (!bson_iter_find_descendant (&iter, dotkey, &child)) {
- /* Not found. Not an error. */
- return true;
- }
- if (BSON_ITER_HOLDS_UTF8 (&child)) {
- size_t out_len;
- /* Attempt to base64 decode. */
- out->data =
- kms_message_b64_to_raw (bson_iter_utf8 (&child, NULL), &out_len);
- if (!out->data) {
- CLIENT_ERR ("unable to parse base64 from UTF-8 field %s", dotkey);
- return false;
- }
- out->len = (uint32_t) out_len;
- out->owned = true;
- } else if (BSON_ITER_HOLDS_BINARY (&child)) {
- if (!_mongocrypt_buffer_copy_from_binary_iter (out, &child)) {
- CLIENT_ERR ("unable to parse binary from field %s", dotkey);
- return false;
- }
- } else {
- CLIENT_ERR ("expected UTF-8 or binary %s", dotkey);
- return false;
- }
-
-
- return true;
-}
-
-bool
-_mongocrypt_parse_required_binary (const bson_t *bson,
- const char *dotkey,
- _mongocrypt_buffer_t *out,
- mongocrypt_status_t *status)
-{
- if (!_mongocrypt_parse_optional_binary (bson, dotkey, out, status)) {
- return false;
- }
-
- if (out->len == 0) {
- CLIENT_ERR ("expected UTF-8 or binary %s", dotkey);
- return false;
- }
-
- return true;
-}
-
-bool
-_mongocrypt_check_allowed_fields_va (const bson_t *bson,
- const char *dotkey,
- mongocrypt_status_t *status,
- ...)
-{
- va_list args;
- const char *field;
- bson_iter_t iter;
-
- if (dotkey) {
- bson_iter_t parent;
-
- bson_iter_init (&parent, bson);
- if (!bson_iter_find_descendant (&parent, dotkey, &iter) ||
- !BSON_ITER_HOLDS_DOCUMENT (&iter)) {
- CLIENT_ERR ("invalid BSON, expected %s", dotkey);
- return false;
- }
- bson_iter_recurse (&iter, &iter);
- } else {
- bson_iter_init (&iter, bson);
- }
-
- while (bson_iter_next (&iter)) {
- bool found = false;
-
- va_start (args, status);
- field = va_arg (args, const char *);
- while (field) {
- if (0 == strcmp (field, bson_iter_key (&iter))) {
- found = true;
- break;
- }
- field = va_arg (args, const char *);
- }
- va_end (args);
-
- if (!found) {
- CLIENT_ERR ("Unexpected field: '%s'", bson_iter_key (&iter));
- return false;
- }
- }
- return true;
-}
\ No newline at end of file
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-os-private.h b/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-os-private.h
deleted file mode 100644
index cf4d3620..00000000
--- a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-os-private.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright 2019-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef MONGOCRYPT_OS_PRIVATE_H
-#define MONGOCRYPT_OS_PRIVATE_H
-
-int
-_mongocrypt_once(void (*init_routine)(void));
-
-
-#endif /* MONGOCRYPT_OS_PRIVATE_H */
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-private.h b/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-private.h
deleted file mode 100644
index 00d368ce..00000000
--- a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-private.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright 2019-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef MONGOCRYPT_PRIVATE_H
-#define MONGOCRYPT_PRIVATE_H
-
-#include "mongocrypt.h"
-#include "mongocrypt-config.h"
-#include "bson/bson.h"
-
-#include "mongocrypt-log-private.h"
-#include "mongocrypt-buffer-private.h"
-#include "mongocrypt-cache-private.h"
-#include "mongocrypt-cache-key-private.h"
-#include "mongocrypt-mutex-private.h"
-#include "mongocrypt-opts-private.h"
-#include "mongocrypt-crypto-private.h"
-#include "mongocrypt-cache-oauth-private.h"
-
-
-#define MONGOCRYPT_GENERIC_ERROR_CODE 1
-
-#define CLIENT_ERR_W_CODE(code, ...) \
- _mongocrypt_set_error ( \
- status, MONGOCRYPT_STATUS_ERROR_CLIENT, code, __VA_ARGS__)
-
-#define CLIENT_ERR(...) \
- CLIENT_ERR_W_CODE (MONGOCRYPT_GENERIC_ERROR_CODE, __VA_ARGS__)
-
-#define KMS_ERR_W_CODE(code, ...) \
- _mongocrypt_set_error ( \
- status, MONGOCRYPT_STATUS_ERROR_KMS, code, __VA_ARGS__)
-
-#define KMS_ERR(...) KMS_ERR_W_CODE (MONGOCRYPT_GENERIC_ERROR_CODE, __VA_ARGS__)
-
-#define MONGOCRYPT_STR_AND_LEN(x) (x), (sizeof (x) / sizeof ((x)[0]) - 1)
-
-#define MONGOCRYPT_DATA_AND_LEN(x) \
- ((uint8_t *) x), (sizeof (x) / sizeof ((x)[0]) - 1)
-
-/* TODO: remove after integrating into libmongoc */
-#define BSON_SUBTYPE_ENCRYPTED 6
-
-/* TODO: Move these to mongocrypt-log-private.h? */
-const char *
-tmp_json (const bson_t *bson);
-
-const char *
-tmp_buf (const _mongocrypt_buffer_t *buf);
-
-
-void
-_mongocrypt_set_error (mongocrypt_status_t *status,
- mongocrypt_status_type_t type,
- uint32_t code,
- const char *format,
- ...);
-
-
-struct _mongocrypt_t {
- bool initialized;
- _mongocrypt_opts_t opts;
- mongocrypt_mutex_t mutex;
- /* The collinfo and key cache are protected with an internal mutex. */
- _mongocrypt_cache_t cache_collinfo;
- _mongocrypt_cache_t cache_key;
- _mongocrypt_log_t log;
- mongocrypt_status_t *status;
- _mongocrypt_crypto_t *crypto;
- /* A counter, protected by mutex, for generating unique context ids */
- uint32_t ctx_counter;
- _mongocrypt_cache_oauth_t *cache_oauth_azure;
- _mongocrypt_cache_oauth_t *cache_oauth_gcp;
-};
-
-typedef enum {
- MONGOCRYPT_ENCRYPTION_ALGORITHM_NONE = 0,
- MONGOCRYPT_ENCRYPTION_ALGORITHM_DETERMINISTIC = 1,
- MONGOCRYPT_ENCRYPTION_ALGORITHM_RANDOM = 2
-} mongocrypt_encryption_algorithm_t;
-
-
-bool
-_mongocrypt_validate_and_copy_string (const char *in,
- int32_t in_len,
- char **out) MONGOCRYPT_WARN_UNUSED_RESULT;
-
-char *
-_mongocrypt_new_string_from_bytes (const void *in, int len);
-
-char *
-_mongocrypt_new_json_string_from_binary (mongocrypt_binary_t *binary);
-
-#endif /* MONGOCRYPT_PRIVATE_H */
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-util-private.h b/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-util-private.h
deleted file mode 100644
index 97c8bf3c..00000000
--- a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-util-private.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2021-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef MONGOCRYPT_UTIL_PRIVATE_H
-#define MONGOCRYPT_UTIL_PRIVATE_H
-
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdint.h>
-
-/* A utility for safely casting from size_t to uint32_t.
- * Returns false if @in exceeds the maximum value of a uint32_t. */
-bool
-size_to_uint32 (size_t in, uint32_t *out);
-
-#endif /* MONGOCRYPT_UTIL_PRIVATE_H */
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-util.c b/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-util.c
deleted file mode 100644
index e47ef89e..00000000
--- a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-util.c
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright 2021-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "mongocrypt-util-private.h"
-
-bool size_to_uint32 (size_t in, uint32_t *out)
-{
- if (in > UINT32_MAX) {
- return false;
- }
- *out = (uint32_t) in;
- return true;
-}
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt.c b/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt.c
deleted file mode 100644
index 5f1d037e..00000000
--- a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt.c
+++ /dev/null
@@ -1,777 +0,0 @@
-/*
- * Copyright 2018-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <kms_message/kms_message.h>
-#include <bson/bson.h>
-
-#include "mongocrypt-private.h"
-#include "mongocrypt-binary-private.h"
-#include "mongocrypt-cache-collinfo-private.h"
-#include "mongocrypt-cache-key-private.h"
-#include "mongocrypt-config.h"
-#include "mongocrypt-crypto-private.h"
-#include "mongocrypt-log-private.h"
-#include "mongocrypt-opts-private.h"
-#include "mongocrypt-os-private.h"
-#include "mongocrypt-status-private.h"
-
-/* Assert size for interop with wrapper purposes */
-BSON_STATIC_ASSERT (sizeof (mongocrypt_log_level_t) == 4);
-
-
-const char *
-mongocrypt_version (uint32_t *len)
-{
- if (len) {
- *len = (uint32_t) strlen (MONGOCRYPT_VERSION);
- }
- return MONGOCRYPT_VERSION;
-}
-
-
-void
-_mongocrypt_set_error (mongocrypt_status_t *status,
- mongocrypt_status_type_t type,
- uint32_t code,
- const char *format,
- ...)
-{
- va_list args;
- char *prepared_message;
-
- if (status) {
- va_start (args, format);
- prepared_message = bson_strdupv_printf (format, args);
- if (!prepared_message) {
- mongocrypt_status_set (status, type, code, "Out of memory", -1);
- } else {
- mongocrypt_status_set (status, type, code, prepared_message, -1);
- bson_free (prepared_message);
- }
- va_end (args);
- }
-}
-
-
-const char *
-tmp_json (const bson_t *bson)
-{
- static char storage[1024];
- char *json;
-
- memset (storage, 0, 1024);
- json = bson_as_canonical_extended_json (bson, NULL);
- bson_snprintf (storage, sizeof (storage), "%s", json);
- bson_free (json);
- return (const char *) storage;
-}
-
-
-const char *
-tmp_buf (const _mongocrypt_buffer_t *buf)
-{
- static char storage[1024];
- uint32_t i, n;
-
- memset (storage, 0, 1024);
- /* capped at two characters per byte, minus 1 for trailing \0 */
- n = sizeof (storage) / 2 - 1;
- if (buf->len < n) {
- n = buf->len;
- }
-
- for (i = 0; i < n; i++) {
- bson_snprintf (storage + (i * 2), 3, "%02x", buf->data[i]);
- }
-
- return (const char *) storage;
-}
-
-void
-_mongocrypt_do_init (void)
-{
- (void) kms_message_init ();
- _native_crypto_init ();
-}
-
-
-mongocrypt_t *
-mongocrypt_new (void)
-{
- mongocrypt_t *crypt;
-
- crypt = bson_malloc0 (sizeof (mongocrypt_t));
- BSON_ASSERT (crypt);
-
- _mongocrypt_mutex_init (&crypt->mutex);
- _mongocrypt_cache_collinfo_init (&crypt->cache_collinfo);
- _mongocrypt_cache_key_init (&crypt->cache_key);
- crypt->status = mongocrypt_status_new ();
- _mongocrypt_opts_init (&crypt->opts);
- _mongocrypt_log_init (&crypt->log);
- crypt->ctx_counter = 1;
- crypt->cache_oauth_azure = _mongocrypt_cache_oauth_new ();
- crypt->cache_oauth_gcp = _mongocrypt_cache_oauth_new ();
-
- if (0 != _mongocrypt_once (_mongocrypt_do_init) ||
- !(_native_crypto_initialized)) {
- mongocrypt_status_t *status = crypt->status;
-
- CLIENT_ERR ("failed to initialize");
- /* Return crypt with failure status so caller can obtain error when
- * calling mongocrypt_init */
- }
-
- return crypt;
-}
-
-
-bool
-mongocrypt_setopt_log_handler (mongocrypt_t *crypt,
- mongocrypt_log_fn_t log_fn,
- void *log_ctx)
-{
- if (!crypt) {
- return false;
- }
-
- if (crypt->initialized) {
- mongocrypt_status_t *status = crypt->status;
- CLIENT_ERR ("options cannot be set after initialization");
- return false;
- }
- crypt->opts.log_fn = log_fn;
- crypt->opts.log_ctx = log_ctx;
- return true;
-}
-
-bool
-mongocrypt_setopt_kms_provider_aws (mongocrypt_t *crypt,
- const char *aws_access_key_id,
- int32_t aws_access_key_id_len,
- const char *aws_secret_access_key,
- int32_t aws_secret_access_key_len)
-{
- mongocrypt_status_t *status;
-
- if (!crypt) {
- return false;
- }
- status = crypt->status;
-
- if (crypt->initialized) {
- CLIENT_ERR ("options cannot be set after initialization");
- return false;
- }
-
- if (0 != (crypt->opts.kms_providers & MONGOCRYPT_KMS_PROVIDER_AWS)) {
- CLIENT_ERR ("aws kms provider already set");
- return false;
- }
-
- if (!_mongocrypt_validate_and_copy_string (
- aws_access_key_id,
- aws_access_key_id_len,
- &crypt->opts.kms_provider_aws.access_key_id)) {
- CLIENT_ERR ("invalid aws access key id");
- return false;
- }
-
- if (!_mongocrypt_validate_and_copy_string (
- aws_secret_access_key,
- aws_secret_access_key_len,
- &crypt->opts.kms_provider_aws.secret_access_key)) {
- CLIENT_ERR ("invalid aws secret access key");
- return false;
- }
-
- if (crypt->log.trace_enabled) {
- _mongocrypt_log (&crypt->log,
- MONGOCRYPT_LOG_LEVEL_TRACE,
- "%s (%s=\"%s\", %s=%d, %s=\"%s\", %s=%d)",
- BSON_FUNC,
- "aws_access_key_id",
- crypt->opts.kms_provider_aws.access_key_id,
- "aws_access_key_id_len",
- aws_access_key_id_len,
- "aws_secret_access_key",
- crypt->opts.kms_provider_aws.secret_access_key,
- "aws_secret_access_key_len",
- aws_secret_access_key_len);
- }
- crypt->opts.kms_providers |= MONGOCRYPT_KMS_PROVIDER_AWS;
- return true;
-}
-
-char *
-_mongocrypt_new_string_from_bytes (const void *in, int len)
-{
- const int max_bytes = 100;
- const int chars_per_byte = 2;
- int out_size = max_bytes * chars_per_byte;
- const unsigned char *src = in;
- char *out;
- char *ret;
-
- out_size += len > max_bytes ? sizeof ("...") : 1 /* for null */;
- out = bson_malloc0 (out_size);
- BSON_ASSERT (out);
-
- ret = out;
-
- for (int i = 0; i < len && i < max_bytes; i++, out += chars_per_byte) {
- sprintf (out, "%02X", src[i]);
- }
-
- sprintf (out, (len > max_bytes) ? "..." : "");
- return ret;
-}
-
-char *
-_mongocrypt_new_json_string_from_binary (mongocrypt_binary_t *binary)
-{
- bson_t bson;
- uint32_t len;
-
- if (!_mongocrypt_binary_to_bson (binary, &bson) ||
- !bson_validate (&bson, BSON_VALIDATE_NONE, NULL)) {
- char *hex;
- char *full_str;
-
- hex = _mongocrypt_new_string_from_bytes (binary->data, binary->len);
- full_str = bson_strdup_printf ("(malformed) %s", hex);
- bson_free (hex);
- return full_str;
- }
- return bson_as_canonical_extended_json (&bson, (size_t *) &len);
-}
-
-bool
-mongocrypt_setopt_schema_map (mongocrypt_t *crypt,
- mongocrypt_binary_t *schema_map)
-{
- bson_t tmp;
- bson_error_t bson_err;
- mongocrypt_status_t *status;
-
- if (!crypt) {
- return false;
- }
- status = crypt->status;
-
- if (crypt->initialized) {
- CLIENT_ERR ("options cannot be set after initialization");
- return false;
- }
-
- if (!schema_map || !mongocrypt_binary_data (schema_map)) {
- CLIENT_ERR ("passed null schema map");
- return false;
- }
-
- if (!_mongocrypt_buffer_empty (&crypt->opts.schema_map)) {
- CLIENT_ERR ("already set schema map");
- return false;
- }
-
- _mongocrypt_buffer_copy_from_binary (&crypt->opts.schema_map, schema_map);
-
- /* validate bson */
- if (!_mongocrypt_buffer_to_bson (&crypt->opts.schema_map, &tmp)) {
- CLIENT_ERR ("invalid bson");
- return false;
- }
-
- if (!bson_validate_with_error (&tmp, BSON_VALIDATE_NONE, &bson_err)) {
- CLIENT_ERR (bson_err.message);
- return false;
- }
-
- return true;
-}
-
-
-bool
-mongocrypt_setopt_kms_provider_local (mongocrypt_t *crypt,
- mongocrypt_binary_t *key)
-{
- mongocrypt_status_t *status;
-
- if (!crypt) {
- return false;
- }
- status = crypt->status;
-
- if (crypt->initialized) {
- CLIENT_ERR ("options cannot be set after initialization");
- return false;
- }
-
- if (0 != (crypt->opts.kms_providers & MONGOCRYPT_KMS_PROVIDER_LOCAL)) {
- CLIENT_ERR ("local kms provider already set");
- return false;
- }
-
- if (!key) {
- CLIENT_ERR ("passed null key");
- return false;
- }
-
- if (mongocrypt_binary_len (key) != MONGOCRYPT_KEY_LEN) {
- CLIENT_ERR ("local key must be %d bytes", MONGOCRYPT_KEY_LEN);
- return false;
- }
-
- if (crypt->log.trace_enabled) {
- char *key_val;
- key_val = _mongocrypt_new_string_from_bytes (key->data, key->len);
-
- _mongocrypt_log (&crypt->log,
- MONGOCRYPT_LOG_LEVEL_TRACE,
- "%s (%s=\"%s\")",
- BSON_FUNC,
- "key",
- key_val);
- bson_free (key_val);
- }
-
- _mongocrypt_buffer_copy_from_binary (&crypt->opts.kms_provider_local.key,
- key);
- crypt->opts.kms_providers |= MONGOCRYPT_KMS_PROVIDER_LOCAL;
- return true;
-}
-
-
-bool
-mongocrypt_init (mongocrypt_t *crypt)
-{
- mongocrypt_status_t *status;
-
- if (!crypt) {
- return false;
- }
- status = crypt->status;
- if (crypt->initialized) {
- CLIENT_ERR ("already initialized");
- return false;
- }
-
- crypt->initialized = true;
-
- if (!mongocrypt_status_ok (crypt->status)) {
- return false;
- }
-
- if (!_mongocrypt_opts_validate (&crypt->opts, status)) {
- return false;
- }
-
- if (crypt->opts.log_fn) {
- _mongocrypt_log_set_fn (
- &crypt->log, crypt->opts.log_fn, crypt->opts.log_ctx);
- }
-
- if (!crypt->crypto) {
-#ifndef MONGOCRYPT_ENABLE_CRYPTO
- CLIENT_ERR ("libmongocrypt built with native crypto disabled. crypto "
- "hooks required");
- return false;
-#else
- /* set default hooks. */
- crypt->crypto = bson_malloc0 (sizeof (*crypt->crypto));
- BSON_ASSERT (crypt->crypto);
-
-#endif
- }
- return true;
-}
-
-
-bool
-mongocrypt_status (mongocrypt_t *crypt, mongocrypt_status_t *out)
-{
- if (!crypt) {
- return false;
- }
-
- if (!out) {
- mongocrypt_status_t *status = crypt->status;
- CLIENT_ERR ("argument 'out' is required");
- return false;
- }
-
- if (!mongocrypt_status_ok (crypt->status)) {
- _mongocrypt_status_copy_to (crypt->status, out);
- return false;
- }
- _mongocrypt_status_reset (out);
- return true;
-}
-
-
-void
-mongocrypt_destroy (mongocrypt_t *crypt)
-{
- if (!crypt) {
- return;
- }
- _mongocrypt_opts_cleanup (&crypt->opts);
- _mongocrypt_cache_cleanup (&crypt->cache_collinfo);
- _mongocrypt_cache_cleanup (&crypt->cache_key);
- _mongocrypt_mutex_cleanup (&crypt->mutex);
- _mongocrypt_log_cleanup (&crypt->log);
- mongocrypt_status_destroy (crypt->status);
- bson_free (crypt->crypto);
- _mongocrypt_cache_oauth_destroy (crypt->cache_oauth_azure);
- _mongocrypt_cache_oauth_destroy (crypt->cache_oauth_gcp);
- bson_free (crypt);
-}
-
-
-bool
-_mongocrypt_validate_and_copy_string (const char *in,
- int32_t in_len,
- char **out)
-{
- if (!in) {
- return false;
- }
-
- if (in_len < -1) {
- return false;
- }
-
- if (in_len == -1) {
- in_len = (uint32_t) strlen (in);
- }
-
- if (!bson_utf8_validate (in, in_len, false)) {
- return false;
- }
- *out = bson_strndup (in, in_len);
- return true;
-}
-
-
-bool
-mongocrypt_setopt_crypto_hooks (mongocrypt_t *crypt,
- mongocrypt_crypto_fn aes_256_cbc_encrypt,
- mongocrypt_crypto_fn aes_256_cbc_decrypt,
- mongocrypt_random_fn random,
- mongocrypt_hmac_fn hmac_sha_512,
- mongocrypt_hmac_fn hmac_sha_256,
- mongocrypt_hash_fn sha_256,
- void *ctx)
-{
- mongocrypt_status_t *status;
-
- if (!crypt) {
- return false;
- }
-
- status = crypt->status;
-
- if (crypt->initialized) {
- CLIENT_ERR ("options cannot be set after initialization");
- return false;
- }
-
- if (crypt->crypto) {
- CLIENT_ERR ("crypto_hooks already set");
- return false;
- }
-
- crypt->crypto = bson_malloc0 (sizeof (*crypt->crypto));
- BSON_ASSERT (crypt->crypto);
-
- crypt->crypto->hooks_enabled = true;
- crypt->crypto->ctx = ctx;
-
- if (!aes_256_cbc_encrypt) {
- CLIENT_ERR ("aes_256_cbc_encrypt not set");
- return false;
- }
- crypt->crypto->aes_256_cbc_encrypt = aes_256_cbc_encrypt;
-
- if (!aes_256_cbc_decrypt) {
- CLIENT_ERR ("aes_256_cbc_decrypt not set");
- return false;
- }
- crypt->crypto->aes_256_cbc_decrypt = aes_256_cbc_decrypt;
-
- if (!random) {
- CLIENT_ERR ("random not set");
- return false;
- }
- crypt->crypto->random = random;
-
- if (!hmac_sha_512) {
- CLIENT_ERR ("hmac_sha_512 not set");
- return false;
- }
- crypt->crypto->hmac_sha_512 = hmac_sha_512;
-
- if (!hmac_sha_256) {
- CLIENT_ERR ("hmac_sha_256 not set");
- return false;
- }
- crypt->crypto->hmac_sha_256 = hmac_sha_256;
-
- if (!sha_256) {
- CLIENT_ERR ("sha_256 not set");
- return false;
- }
- crypt->crypto->sha_256 = sha_256;
-
- return true;
-}
-
-bool
-mongocrypt_setopt_crypto_hook_sign_rsaes_pkcs1_v1_5 (
- mongocrypt_t *crypt,
- mongocrypt_hmac_fn sign_rsaes_pkcs1_v1_5,
- void *sign_ctx)
-{
- mongocrypt_status_t *status;
-
- if (!crypt) {
- return false;
- }
-
- status = crypt->status;
-
- if (crypt->initialized) {
- CLIENT_ERR ("options cannot be set after initialization");
- return false;
- }
-
- if (crypt->opts.sign_rsaes_pkcs1_v1_5) {
- CLIENT_ERR ("signature hook already set");
- return false;
- }
-
- crypt->opts.sign_rsaes_pkcs1_v1_5 = sign_rsaes_pkcs1_v1_5;
- crypt->opts.sign_ctx = sign_ctx;
- return true;
-}
-
-bool
-mongocrypt_setopt_kms_providers (mongocrypt_t *crypt,
- mongocrypt_binary_t *kms_providers)
-{
- mongocrypt_status_t *status;
- bson_t as_bson;
- bson_iter_t iter;
-
- if (!crypt) {
- return false;
- }
- status = crypt->status;
-
- if (crypt->initialized) {
- CLIENT_ERR ("options cannot be set after initialization");
- return false;
- }
-
- if (!_mongocrypt_binary_to_bson (kms_providers, &as_bson) ||
- !bson_iter_init (&iter, &as_bson)) {
- CLIENT_ERR ("invalid BSON");
- return false;
- }
-
- while (bson_iter_next (&iter)) {
- const char *field_name;
-
- field_name = bson_iter_key (&iter);
-
- if (0 == strcmp (field_name, "azure")) {
- if (0 != (crypt->opts.kms_providers & MONGOCRYPT_KMS_PROVIDER_AZURE)) {
- CLIENT_ERR ("azure KMS provider already set");
- return false;
- }
-
- if (!_mongocrypt_parse_required_utf8 (
- &as_bson,
- "azure.tenantId",
- &crypt->opts.kms_provider_azure.tenant_id,
- crypt->status)) {
- return false;
- }
-
- if (!_mongocrypt_parse_required_utf8 (
- &as_bson,
- "azure.clientId",
- &crypt->opts.kms_provider_azure.client_id,
- crypt->status)) {
- return false;
- }
-
- if (!_mongocrypt_parse_required_utf8 (
- &as_bson,
- "azure.clientSecret",
- &crypt->opts.kms_provider_azure.client_secret,
- crypt->status)) {
- return false;
- }
-
- if (!_mongocrypt_parse_optional_endpoint (
- &as_bson,
- "azure.identityPlatformEndpoint",
- &crypt->opts.kms_provider_azure.identity_platform_endpoint,
- NULL /* opts */,
- crypt->status)) {
- return false;
- }
-
- if (!_mongocrypt_check_allowed_fields (&as_bson,
- "azure",
- crypt->status,
- "tenantId",
- "clientId",
- "clientSecret",
- "identityPlatformEndpoint")) {
- return false;
- }
- crypt->opts.kms_providers |= MONGOCRYPT_KMS_PROVIDER_AZURE;
- } else if (0 == strcmp (field_name, "gcp")) {
- if (0 != (crypt->opts.kms_providers & MONGOCRYPT_KMS_PROVIDER_GCP)) {
- CLIENT_ERR ("gcp KMS provider already set");
- return false;
- }
-
- if (!_mongocrypt_parse_required_utf8 (
- &as_bson,
- "gcp.email",
- &crypt->opts.kms_provider_gcp.email,
- crypt->status)) {
- return false;
- }
-
- if (!_mongocrypt_parse_required_binary (
- &as_bson,
- "gcp.privateKey",
- &crypt->opts.kms_provider_gcp.private_key,
- crypt->status)) {
- return false;
- }
-
- if (!_mongocrypt_parse_optional_endpoint (
- &as_bson,
- "gcp.endpoint",
- &crypt->opts.kms_provider_gcp.endpoint,
- NULL /* opts */,
- crypt->status)) {
- return false;
- }
-
- if (!_mongocrypt_check_allowed_fields (&as_bson,
- "gcp",
- crypt->status,
- "email",
- "privateKey",
- "endpoint")) {
- return false;
- }
- crypt->opts.kms_providers |= MONGOCRYPT_KMS_PROVIDER_GCP;
- } else if (0 == strcmp (field_name, "local")) {
- if (!_mongocrypt_parse_required_binary (
- &as_bson,
- "local.key",
- &crypt->opts.kms_provider_local.key,
- crypt->status)) {
- return false;
- }
-
- if (crypt->opts.kms_provider_local.key.len != MONGOCRYPT_KEY_LEN) {
- CLIENT_ERR ("local key must be %d bytes", MONGOCRYPT_KEY_LEN);
- return false;
- }
-
- if (!_mongocrypt_check_allowed_fields (
- &as_bson, "local", crypt->status, "key")) {
- return false;
- }
- crypt->opts.kms_providers |= MONGOCRYPT_KMS_PROVIDER_LOCAL;
- } else if (0 == strcmp (field_name, "aws")) {
- if (!_mongocrypt_parse_required_utf8 (
- &as_bson,
- "aws.accessKeyId",
- &crypt->opts.kms_provider_aws.access_key_id,
- crypt->status)) {
- return false;
- }
- if (!_mongocrypt_parse_required_utf8 (
- &as_bson,
- "aws.secretAccessKey",
- &crypt->opts.kms_provider_aws.secret_access_key,
- crypt->status)) {
- return false;
- }
-
- if (!_mongocrypt_parse_optional_utf8 (
- &as_bson,
- "aws.sessionToken",
- &crypt->opts.kms_provider_aws.session_token,
- crypt->status)) {
- return false;
- }
-
- if (!_mongocrypt_check_allowed_fields (&as_bson,
- "aws",
- crypt->status,
- "accessKeyId",
- "secretAccessKey",
- "sessionToken")) {
- return false;
- }
- crypt->opts.kms_providers |= MONGOCRYPT_KMS_PROVIDER_AWS;
- } else if (0 == strcmp (field_name, "kmip")) {
- _mongocrypt_endpoint_parse_opts_t opts = {0};
-
- opts.allow_empty_subdomain = true;
- if (!_mongocrypt_parse_required_endpoint (
- &as_bson,
- "kmip.endpoint",
- &crypt->opts.kms_provider_kmip.endpoint,
- &opts,
- crypt->status)) {
- return false;
- }
-
- if (!_mongocrypt_check_allowed_fields (
- &as_bson, "kmip", crypt->status, "endpoint")) {
- return false;
- }
- crypt->opts.kms_providers |= MONGOCRYPT_KMS_PROVIDER_KMIP;
- } else {
- CLIENT_ERR ("unsupported KMS provider: %s", field_name);
- return false;
- }
- }
-
- if (crypt->log.trace_enabled) {
- char *as_str = bson_as_json (&as_bson, NULL);
- _mongocrypt_log (&crypt->log,
- MONGOCRYPT_LOG_LEVEL_TRACE,
- "%s (%s=\"%s\")",
- BSON_FUNC,
- "kms_providers",
- as_str);
- bson_free (as_str);
- }
-
- return true;
-}
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt.h b/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt.h
deleted file mode 100644
index e080094d..00000000
--- a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt.h
+++ /dev/null
@@ -1,1173 +0,0 @@
-/*
- * Copyright 2019-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef MONGOCRYPT_H
-#define MONGOCRYPT_H
-
-/** @file mongocrypt.h The top-level handle to libmongocrypt. */
-
-/**
- * @mainpage libmongocrypt
- * See all public API documentation in: @ref mongocrypt.h
- */
-
-#include "mongocrypt-export.h"
-#include "mongocrypt-compat.h"
-#include "mongocrypt-config.h"
-
-/**
- * @def MONGOCRYPT_VERSION
- * The version string describing libmongocrypt.
- * Has the form x.y.z-<pre>+<date>+git<sha>.
- */
-#define MONGOCRYPT_VERSION "1.3.0"
-
-/**
- * Returns the version string for libmongocrypt.
- *
- * @param[out] len An optional length of the returned string. May be NULL.
- * @returns a NULL terminated version string for libmongocrypt.
- */
-MONGOCRYPT_EXPORT
-const char *
-mongocrypt_version (uint32_t *len);
-
-
-/**
- * A non-owning view of a byte buffer.
- *
- * When constructing a mongocrypt_binary_t it is the responsibility of the
- * caller to maintain the lifetime of the viewed data. However, all public
- * functions that take a mongocrypt_binary_t as an argument will make a copy of
- * the viewed data. For example, the following is valid:
- *
- * @code{.c}
- * mongocrypt_binary_t bin = mongocrypt_binary_new_from_data(mydata, mylen);
- * assert (mongocrypt_setopt_kms_provider_local (crypt), bin);
- * // The viewed data of bin has been copied. Ok to free the view and the data.
- * mongocrypt_binary_destroy (bin);
- * my_free_fn (mydata);
- * @endcode
- *
- * Functions with a mongocrypt_binary_t* out guarantee the lifetime of the
- * viewed data to live as long as the parent object. For example, @ref
- * mongocrypt_ctx_mongo_op guarantees that the viewed data of
- * mongocrypt_binary_t is valid until the parent ctx is destroyed with @ref
- * mongocrypt_ctx_destroy.
- */
-typedef struct _mongocrypt_binary_t mongocrypt_binary_t;
-
-
-/**
- * Create a new non-owning view of a buffer (data + length).
- *
- * Use this to create a mongocrypt_binary_t used for output parameters.
- *
- * @returns A new mongocrypt_binary_t.
- */
-MONGOCRYPT_EXPORT
-mongocrypt_binary_t *
-mongocrypt_binary_new (void);
-
-
-/**
- * Create a new non-owning view of a buffer (data + length).
- *
- * @param[in] data A pointer to an array of bytes. This data is not copied. @p
- * data must outlive the binary object.
- * @param[in] len The length of the @p data byte array.
- *
- * @returns A new @ref mongocrypt_binary_t.
- */
-MONGOCRYPT_EXPORT
-mongocrypt_binary_t *
-mongocrypt_binary_new_from_data (uint8_t *data, uint32_t len);
-
-
-/**
- * Get a pointer to the viewed data.
- *
- * @param[in] binary The @ref mongocrypt_binary_t.
- *
- * @returns A pointer to the viewed data.
- */
-MONGOCRYPT_EXPORT
-uint8_t *
-mongocrypt_binary_data (const mongocrypt_binary_t *binary);
-
-
-/**
- * Get the length of the viewed data.
- *
- * @param[in] binary The @ref mongocrypt_binary_t.
- *
- * @returns The length of the viewed data.
- */
-MONGOCRYPT_EXPORT
-uint32_t
-mongocrypt_binary_len (const mongocrypt_binary_t *binary);
-
-
-/**
- * Free the @ref mongocrypt_binary_t.
- *
- * This does not free the viewed data.
- *
- * @param[in] binary The mongocrypt_binary_t destroy.
- */
-MONGOCRYPT_EXPORT
-void
-mongocrypt_binary_destroy (mongocrypt_binary_t *binary);
-
-
-/**
- * Indicates success or contains error information.
- *
- * Functions like @ref mongocrypt_ctx_encrypt_init follow a pattern to expose a
- * status. A boolean is returned. True indicates success, and false indicates
- * failure. On failure a status on the handle is set, and is accessible with a
- * corresponding (handle)_status function. E.g. @ref mongocrypt_ctx_status.
- */
-typedef struct _mongocrypt_status_t mongocrypt_status_t;
-
-/**
- * Indicates the type of error.
- */
-typedef enum {
- MONGOCRYPT_STATUS_OK = 0,
- MONGOCRYPT_STATUS_ERROR_CLIENT = 1,
- MONGOCRYPT_STATUS_ERROR_KMS = 2
-} mongocrypt_status_type_t;
-
-
-/**
- * Create a new status object.
- *
- * Use a new status object to retrieve the status from a handle by passing
- * this as an out-parameter to functions like @ref mongocrypt_ctx_status.
- * When done, destroy it with @ref mongocrypt_status_destroy.
- *
- * @returns A new status object.
- */
-MONGOCRYPT_EXPORT
-mongocrypt_status_t *
-mongocrypt_status_new (void);
-
-
-/**
- * Set a status object with message, type, and code.
- *
- * Use this to set the @ref mongocrypt_status_t given in the crypto hooks.
- *
- * @param[in] type The status type.
- * @param[in] code The status code.
- * @param[in] message The message.
- * @param[in] message_len Due to historical behavior, pass 1 + the string length
- * of @p message (which differs from other functions accepting string
- * arguments).
- * Alternatively, if message is NULL terminated this may be -1 to tell
- * mongocrypt
- * to determine the string's length with strlen.
- *
- */
-MONGOCRYPT_EXPORT
-void
-mongocrypt_status_set (mongocrypt_status_t *status,
- mongocrypt_status_type_t type,
- uint32_t code,
- const char *message,
- int32_t message_len);
-
-
-/**
- * Indicates success or the type of error.
- *
- * @param[in] status The status object.
- *
- * @returns A @ref mongocrypt_status_type_t.
- */
-MONGOCRYPT_EXPORT
-mongocrypt_status_type_t
-mongocrypt_status_type (mongocrypt_status_t *status);
-
-
-/**
- * Get an error code or 0.
- *
- * @param[in] status The status object.
- *
- * @returns An error code.
- */
-MONGOCRYPT_EXPORT
-uint32_t
-mongocrypt_status_code (mongocrypt_status_t *status);
-
-
-/**
- * Get the error message associated with a status or NULL.
- *
- * @param[in] status The status object.
- * @param[out] len An optional length of the returned string (excluding the
- * trailing NULL byte). May be NULL.
- *
- * @returns A NULL terminated error message or NULL.
- */
-MONGOCRYPT_EXPORT
-const char *
-mongocrypt_status_message (mongocrypt_status_t *status, uint32_t *len);
-
-
-/**
- * Returns true if the status indicates success.
- *
- * @param[in] status The status to check.
- *
- * @returns A boolean indicating success. If false, an error status is set.
- * Retrieve it with @ref mongocrypt_ctx_status
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_status_ok (mongocrypt_status_t *status);
-
-
-/**
- * Free the memory for a status object.
- *
- * @param[in] status The status to destroy.
- */
-MONGOCRYPT_EXPORT
-void
-mongocrypt_status_destroy (mongocrypt_status_t *status);
-
-/**
- * Indicates the type of log message.
- */
-typedef enum {
- MONGOCRYPT_LOG_LEVEL_FATAL = 0,
- MONGOCRYPT_LOG_LEVEL_ERROR = 1,
- MONGOCRYPT_LOG_LEVEL_WARNING = 2,
- MONGOCRYPT_LOG_LEVEL_INFO = 3,
- MONGOCRYPT_LOG_LEVEL_TRACE = 4
-} mongocrypt_log_level_t;
-
-
-/**
- * A log callback function. Set a custom log callback with @ref
- * mongocrypt_setopt_log_handler.
- *
- * @param[in] message A NULL terminated message.
- * @param[in] message_len The length of message.
- * @param[in] ctx A context provided by the caller of @ref
- * mongocrypt_setopt_log_handler.
- */
-typedef void (*mongocrypt_log_fn_t) (mongocrypt_log_level_t level,
- const char *message,
- uint32_t message_len,
- void *ctx);
-
-
-/**
- * The top-level handle to libmongocrypt.
- *
- * Create a mongocrypt_t handle to perform operations within libmongocrypt:
- * encryption, decryption, registering log callbacks, etc.
- *
- * Functions on a mongocrypt_t are thread safe, though functions on derived
- * handles (e.g. mongocrypt_ctx_t) are not and must be owned by a single
- * thread. See each handle's documentation for thread-safety considerations.
- *
- * Multiple mongocrypt_t handles may be created.
- */
-typedef struct _mongocrypt_t mongocrypt_t;
-
-
-/**
- * Allocate a new @ref mongocrypt_t object.
- *
- * Set options using mongocrypt_setopt_* functions, then initialize with @ref
- * mongocrypt_init. When done with the @ref mongocrypt_t, free with @ref
- * mongocrypt_destroy.
- *
- * @returns A new @ref mongocrypt_t object.
- */
-MONGOCRYPT_EXPORT
-mongocrypt_t *
-mongocrypt_new (void);
-
-
-/**
- * Set a handler on the @ref mongocrypt_t object to get called on every log
- * message.
- *
- * @param[in] crypt The @ref mongocrypt_t object.
- * @param[in] log_fn The log callback.
- * @param[in] log_ctx A context passed as an argument to the log callback every
- * invocation.
- * @pre @ref mongocrypt_init has not been called on @p crypt.
- * @returns A boolean indicating success. If false, an error status is set.
- * Retrieve it with @ref mongocrypt_ctx_status
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_setopt_log_handler (mongocrypt_t *crypt,
- mongocrypt_log_fn_t log_fn,
- void *log_ctx);
-
-
-/**
- * Configure an AWS KMS provider on the @ref mongocrypt_t object.
- *
- * This has been superseded by the more flexible:
- * @ref mongocrypt_setopt_kms_providers
- *
- * @param[in] crypt The @ref mongocrypt_t object.
- * @param[in] aws_access_key_id The AWS access key ID used to generate KMS
- * messages.
- * @param[in] aws_access_key_id_len The string length (in bytes) of @p
- * aws_access_key_id. Pass -1 to determine the string length with strlen (must
- * be NULL terminated).
- * @param[in] aws_secret_access_key The AWS secret access key used to generate
- * KMS messages.
- * @param[in] aws_secret_access_key_len The string length (in bytes) of @p
- * aws_secret_access_key. Pass -1 to determine the string length with strlen
- * (must be NULL terminated).
- * @pre @ref mongocrypt_init has not been called on @p crypt.
- * @returns A boolean indicating success. If false, an error status is set.
- * Retrieve it with @ref mongocrypt_ctx_status
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_setopt_kms_provider_aws (mongocrypt_t *crypt,
- const char *aws_access_key_id,
- int32_t aws_access_key_id_len,
- const char *aws_secret_access_key,
- int32_t aws_secret_access_key_len);
-
-
-/**
- * Configure a local KMS provider on the @ref mongocrypt_t object.
- *
- * This has been superseded by the more flexible:
- * @ref mongocrypt_setopt_kms_providers
- *
- * @param[in] crypt The @ref mongocrypt_t object.
- * @param[in] key A 96 byte master key used to encrypt and decrypt key vault
- * keys. The viewed data is copied. It is valid to destroy @p key with @ref
- * mongocrypt_binary_destroy immediately after.
- * @pre @ref mongocrypt_init has not been called on @p crypt.
- * @returns A boolean indicating success. If false, an error status is set.
- * Retrieve it with @ref mongocrypt_ctx_status
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_setopt_kms_provider_local (mongocrypt_t *crypt,
- mongocrypt_binary_t *key);
-
-/**
- * Configure KMS providers with a BSON document.
- *
- * @param[in] crypt The @ref mongocrypt_t object.
- * @param[in] kms_providers A BSON document mapping the KMS provider names
- * to credentials.
- * @pre @ref mongocrypt_init has not been called on @p crypt.
- * @returns A boolean indicating success. If false, an error status is set.
- * Retrieve it with @ref mongocrypt_ctx_status
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_setopt_kms_providers (mongocrypt_t *crypt,
- mongocrypt_binary_t *kms_providers);
-
-/**
- * Set a local schema map for encryption.
- *
- * @param[in] crypt The @ref mongocrypt_t object.
- * @param[in] schema_map A BSON document representing the schema map supplied by
- * the user. The keys are collection namespaces and values are JSON schemas. The
- * viewed data copied. It is valid to destroy @p schema_map with @ref
- * mongocrypt_binary_destroy immediately after.
- * @pre @p crypt has not been initialized.
- * @returns A boolean indicating success. If false, an error status is set.
- * Retrieve it with @ref mongocrypt_status
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_setopt_schema_map (mongocrypt_t *crypt,
- mongocrypt_binary_t *schema_map);
-
-
-/**
- * Initialize new @ref mongocrypt_t object.
- *
- * Set options before using @ref mongocrypt_setopt_kms_provider_local, @ref
- * mongocrypt_setopt_kms_provider_aws, or @ref mongocrypt_setopt_log_handler.
- *
- * @param[in] crypt The @ref mongocrypt_t object.
- *
- * @returns A boolean indicating success. If false, an error status is set.
- * Retrieve it with @ref mongocrypt_ctx_status Failure may occur if previously
- * set
- * options are invalid.
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_init (mongocrypt_t *crypt);
-
-
-/**
- * Get the status associated with a @ref mongocrypt_t object.
- *
- * @param[in] crypt The @ref mongocrypt_t object.
- * @param[out] status Receives the status.
- *
- * @returns A boolean indicating success. If false, an error status is set.
- * Retrieve it with @ref mongocrypt_ctx_status
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_status (mongocrypt_t *crypt, mongocrypt_status_t *status);
-
-
-/**
- * Destroy the @ref mongocrypt_t object.
- *
- * @param[in] crypt The @ref mongocrypt_t object to destroy.
- */
-MONGOCRYPT_EXPORT
-void
-mongocrypt_destroy (mongocrypt_t *crypt);
-
-
-/**
- * Manages the state machine for encryption or decryption.
- */
-typedef struct _mongocrypt_ctx_t mongocrypt_ctx_t;
-
-
-/**
- * Create a new uninitialized @ref mongocrypt_ctx_t.
- *
- * Initialize the context with functions like @ref mongocrypt_ctx_encrypt_init.
- * When done, destroy it with @ref mongocrypt_ctx_destroy.
- *
- * @param[in] crypt The @ref mongocrypt_t object.
- * @returns A new context.
- */
-MONGOCRYPT_EXPORT
-mongocrypt_ctx_t *
-mongocrypt_ctx_new (mongocrypt_t *crypt);
-
-
-/**
- * Get the status associated with a @ref mongocrypt_ctx_t object.
- *
- * @param[in] ctx The @ref mongocrypt_ctx_t object.
- * @param[out] status Receives the status.
- *
- * @returns True if the output is an ok status, false if it is an error
- * status.
- *
- * @see mongocrypt_status_ok
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_ctx_status (mongocrypt_ctx_t *ctx, mongocrypt_status_t *status);
-
-
-/**
- * Set the key id to use for explicit encryption.
- *
- * It is an error to set both this and the key alt name.
- *
- * @param[in] ctx The @ref mongocrypt_ctx_t object.
- * @param[in] key_id The binary corresponding to the _id (a UUID) of the data
- * key to use from the key vault collection. Note, the UUID must be encoded with
- * RFC-4122 byte order. The viewed data is copied. It is valid to destroy
- * @p key_id with @ref mongocrypt_binary_destroy immediately after.
- * @pre @p ctx has not been initialized.
- * @returns A boolean indicating success. If false, an error status is set.
- * Retrieve it with @ref mongocrypt_ctx_status
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_ctx_setopt_key_id (mongocrypt_ctx_t *ctx,
- mongocrypt_binary_t *key_id);
-
-/**
- * Set the keyAltName to use for explicit encryption or
- * data key creation.
- *
- * Pass the binary encoding a BSON document like the following:
- *
- * { "keyAltName" : (BSON UTF8 value) }
- *
- * For explicit encryption, it is an error to set both the keyAltName
- * and the key id.
- *
- * For creating data keys, call this function repeatedly to set
- * multiple keyAltNames.
- *
- * @param[in] ctx The @ref mongocrypt_ctx_t object.
- * @param[in] key_alt_name The name to use. The viewed data is copied. It is
- * valid to destroy @p key_alt_name with @ref mongocrypt_binary_destroy
- * immediately after.
- * @pre @p ctx has not been initialized.
- * @returns A boolean indicating success. If false, an error status is set.
- * Retrieve it with @ref mongocrypt_ctx_status
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_ctx_setopt_key_alt_name (mongocrypt_ctx_t *ctx,
- mongocrypt_binary_t *key_alt_name);
-
-/**
- * Set the algorithm used for encryption to either
- * deterministic or random encryption. This value
- * should only be set when using explicit encryption.
- *
- * If -1 is passed in for "len", then "algorithm" is
- * assumed to be a null-terminated string.
- *
- * Valid values for algorithm are:
- * "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic"
- * "AEAD_AES_256_CBC_HMAC_SHA_512-Random"
- *
- * @param[in] ctx The @ref mongocrypt_ctx_t object.
- * @param[in] algorithm A string specifying the algorithm to
- * use for encryption.
- * @param[in] len The length of the algorithm string.
- * @pre @p ctx has not been initialized.
- * @returns A boolean indicating success. If false, an error status is set.
- * Retrieve it with @ref mongocrypt_ctx_status
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_ctx_setopt_algorithm (mongocrypt_ctx_t *ctx,
- const char *algorithm,
- int len);
-
-
-/**
- * Identify the AWS KMS master key to use for creating a data key.
- *
- * This has been superseded by the more flexible:
- * @ref mongocrypt_ctx_setopt_key_encryption_key
- *
- * @param[in] ctx The @ref mongocrypt_ctx_t object.
- * @param[in] region The AWS region.
- * @param[in] region_len The string length of @p region. Pass -1 to determine
- * the string length with strlen (must be NULL terminated).
- * @param[in] cmk The Amazon Resource Name (ARN) of the customer master key
- * (CMK).
- * @param[in] cmk_len The string length of @p cmk_len. Pass -1 to determine the
- * string length with strlen (must be NULL terminated).
- * @pre @p ctx has not been initialized.
- * @returns A boolean indicating success. If false, an error status is set.
- * Retrieve it with @ref mongocrypt_ctx_status
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_ctx_setopt_masterkey_aws (mongocrypt_ctx_t *ctx,
- const char *region,
- int32_t region_len,
- const char *cmk,
- int32_t cmk_len);
-
-
-/**
- * Identify a custom AWS endpoint when creating a data key.
- * This is used internally to construct the correct HTTP request
- * (with the Host header set to this endpoint). This endpoint
- * is persisted in the new data key, and will be returned via
- * @ref mongocrypt_kms_ctx_endpoint.
- *
- * This has been superseded by the more flexible:
- * @ref mongocrypt_ctx_setopt_key_encryption_key
- *
- * @param[in] ctx The @ref mongocrypt_ctx_t object.
- * @param[in] endpoint The endpoint.
- * @param[in] endpoint_len The string length of @p endpoint. Pass -1 to
- * determine the string length with strlen (must be NULL terminated).
- * @returns A boolean indicating success. If false, an error status is set.
- * Retrieve it with @ref mongocrypt_ctx_status
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_ctx_setopt_masterkey_aws_endpoint (mongocrypt_ctx_t *ctx,
- const char *endpoint,
- int32_t endpoint_len);
-
-/**
- * Set the master key to "local" for creating a data key.
- * This has been superseded by the more flexible:
- * @ref mongocrypt_ctx_setopt_key_encryption_key
- *
- * @param[in] ctx The @ref mongocrypt_ctx_t object.
- * @pre @p ctx has not been initialized.
- * @returns A boolean indicating success. If false, an error status is set.
- * Retrieve it with @ref mongocrypt_ctx_status
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_ctx_setopt_masterkey_local (mongocrypt_ctx_t *ctx);
-
-/**
- * Set key encryption key document for creating a data key.
- *
- * @param[in] ctx The @ref mongocrypt_ctx_t object.
- * @param[in] bin BSON representing the key encryption key document with
- * an additional "provider" field. The following forms are accepted:
- *
- * AWS
- * {
- * provider: "aws",
- * region: <string>,
- * key: <string>,
- * endpoint: <optional string>
- * }
- *
- * Azure
- * {
- * provider: "azure",
- * keyVaultEndpoint: <string>,
- * keyName: <string>,
- * keyVersion: <optional string>
- * }
- *
- * GCP
- * {
- * provider: "gcp",
- * projectId: <string>,
- * location: <string>,
- * keyRing: <string>,
- * keyName: <string>,
- * keyVersion: <string>,
- * endpoint: <optional string>
- * }
- *
- * Local
- * {
- * provider: "local"
- * }
- *
- * KMIP
- * {
- * provider: "kmip",
- * keyId: <optional string>
- * endpoint: <string>
- * }
- *
- * @pre @p ctx has not been initialized.
- * @returns A boolean indicating success. If false, and error status is set.
- * Retrieve it with @ref mongocrypt_ctx_status.
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_ctx_setopt_key_encryption_key (mongocrypt_ctx_t *ctx,
- mongocrypt_binary_t *bin);
-
-
-/**
- * Initialize a context to create a data key.
- *
- * Associated options:
- * - @ref mongocrypt_ctx_setopt_masterkey_aws
- * - @ref mongocrypt_ctx_setopt_masterkey_aws_endpoint
- * - @ref mongocrypt_ctx_setopt_masterkey_local
- *
- * @param[in] ctx The @ref mongocrypt_ctx_t object.
- * @returns A boolean indicating success. If false, an error status is set.
- * Retrieve it with @ref mongocrypt_ctx_status
- * @pre A master key option has been set, and an associated KMS provider
- * has been set on the parent @ref mongocrypt_t.
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_ctx_datakey_init (mongocrypt_ctx_t *ctx);
-
-/**
- * Initialize a context for encryption.
- *
- * @param[in] ctx The @ref mongocrypt_ctx_t object.
- * @param[in] db The database name.
- * @param[in] db_len The byte length of @p db. Pass -1 to determine the string
- * length with strlen (must
- * be NULL terminated).
- * @param[in] cmd The BSON command to be encrypted. The viewed data is copied.
- * It is valid to destroy @p cmd with @ref mongocrypt_binary_destroy immediately
- * after.
- * @returns A boolean indicating success. If false, an error status is set.
- * Retrieve it with @ref mongocrypt_ctx_status
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_ctx_encrypt_init (mongocrypt_ctx_t *ctx,
- const char *db,
- int32_t db_len,
- mongocrypt_binary_t *cmd);
-
-/**
- * Explicit helper method to encrypt a single BSON object. Contexts
- * created for explicit encryption will not go through mongocryptd.
- *
- * To specify a key_id, algorithm, or iv to use, please use the
- * corresponding mongocrypt_setopt methods before calling this.
- *
- * This method expects the passed-in BSON to be of the form:
- * { "v" : BSON value to encrypt }
- *
- * Associated options:
- * - @ref mongocrypt_ctx_setopt_key_id
- * - @ref mongocrypt_ctx_setopt_key_alt_name
- * - @ref mongocrypt_ctx_setopt_algorithm
- *
- * @param[in] ctx A @ref mongocrypt_ctx_t.
- * @param[in] msg A @ref mongocrypt_binary_t the plaintext BSON value. The
- * viewed data is copied. It is valid to destroy @p msg with @ref
- * mongocrypt_binary_destroy immediately after.
- * @returns A boolean indicating success. If false, an error status is set.
- * Retrieve it with @ref mongocrypt_ctx_status
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_ctx_explicit_encrypt_init (mongocrypt_ctx_t *ctx,
- mongocrypt_binary_t *msg);
-
-
-/**
- * Initialize a context for decryption.
- *
- * This method expects the passed-in BSON to be of the form:
- * { "v" : BSON value to encrypt }
- *
- * @param[in] ctx The @ref mongocrypt_ctx_t object.
- * @param[in] doc The document to be decrypted. The viewed data is copied. It is
- * valid to destroy @p doc with @ref mongocrypt_binary_destroy immediately
- * after.
- * @returns A boolean indicating success. If false, an error status is set.
- * Retrieve it with @ref mongocrypt_ctx_status
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_ctx_decrypt_init (mongocrypt_ctx_t *ctx, mongocrypt_binary_t *doc);
-
-
-/**
- * Explicit helper method to decrypt a single BSON object.
- *
- *
- * @param[in] ctx A @ref mongocrypt_ctx_t.
- * @param[in] msg A @ref mongocrypt_binary_t the encrypted BSON. The viewed data
- * is copied. It is valid to destroy @p msg with @ref mongocrypt_binary_destroy
- * immediately after.
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_ctx_explicit_decrypt_init (mongocrypt_ctx_t *ctx,
- mongocrypt_binary_t *msg);
-
-
-/**
- * Indicates the state of the @ref mongocrypt_ctx_t. Each state requires
- * different handling. See [the integration
- * guide](https://github.com/mongodb/libmongocrypt/blob/master/integrating.md#state-machine)
- * for information on what to do for each state.
- */
-typedef enum {
- MONGOCRYPT_CTX_ERROR = 0,
- MONGOCRYPT_CTX_NEED_MONGO_COLLINFO = 1, /* run on main MongoClient */
- MONGOCRYPT_CTX_NEED_MONGO_MARKINGS = 2, /* run on mongocryptd. */
- MONGOCRYPT_CTX_NEED_MONGO_KEYS = 3, /* run on key vault */
- MONGOCRYPT_CTX_NEED_KMS = 4,
- MONGOCRYPT_CTX_READY = 5, /* ready for encryption/decryption */
- MONGOCRYPT_CTX_DONE = 6
-} mongocrypt_ctx_state_t;
-
-
-/**
- * Get the current state of a context.
- *
- * @param[in] ctx The @ref mongocrypt_ctx_t object.
- * @returns A @ref mongocrypt_ctx_state_t.
- */
-MONGOCRYPT_EXPORT
-mongocrypt_ctx_state_t
-mongocrypt_ctx_state (mongocrypt_ctx_t *ctx);
-
-
-/**
- * Get BSON necessary to run the mongo operation when mongocrypt_ctx_t
- * is in MONGOCRYPT_CTX_NEED_MONGO_* states.
- *
- * @p op_bson is a BSON document to be used for the operation.
- * - For MONGOCRYPT_CTX_NEED_MONGO_COLLINFO it is a listCollections filter.
- * - For MONGOCRYPT_CTX_NEED_MONGO_KEYS it is a find filter.
- * - For MONGOCRYPT_CTX_NEED_MONGO_MARKINGS it is a command to send to
- * mongocryptd.
- *
- * The lifetime of @p op_bson is tied to the lifetime of @p ctx. It is valid
- * until @ref mongocrypt_ctx_destroy is called.
- *
- * @param[in] ctx The @ref mongocrypt_ctx_t object.
- * @param[out] op_bson A BSON document for the MongoDB operation. The data
- * viewed by @p op_bson is guaranteed to be valid until @p ctx is destroyed with
- * @ref mongocrypt_ctx_destroy.
- * @returns A boolean indicating success. If false, an error status is set.
- * Retrieve it with @ref mongocrypt_ctx_status
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_ctx_mongo_op (mongocrypt_ctx_t *ctx, mongocrypt_binary_t *op_bson);
-
-
-/**
- * Feed a BSON reply or result when mongocrypt_ctx_t is in
- * MONGOCRYPT_CTX_NEED_MONGO_* states. This may be called multiple times
- * depending on the operation.
- *
- * reply is a BSON document result being fed back for this operation.
- * - For MONGOCRYPT_CTX_NEED_MONGO_COLLINFO it is a doc from a listCollections
- * cursor. (Note, if listCollections returned no result, do not call this
- * function.)
- * - For MONGOCRYPT_CTX_NEED_MONGO_KEYS it is a doc from a find cursor.
- * (Note, if find returned no results, do not call this function. reply must
- * not
- * be NULL.)
- * - For MONGOCRYPT_CTX_NEED_MONGO_MARKINGS it is a reply from mongocryptd.
- *
- * @param[in] ctx The @ref mongocrypt_ctx_t object.
- * @param[in] reply A BSON document for the MongoDB operation. The viewed data
- * is copied. It is valid to destroy @p reply with @ref
- * mongocrypt_binary_destroy immediately after.
- * @returns A boolean indicating success. If false, an error status is set.
- * Retrieve it with @ref mongocrypt_ctx_status
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_ctx_mongo_feed (mongocrypt_ctx_t *ctx, mongocrypt_binary_t *reply);
-
-
-/**
- * Call when done feeding the reply (or replies) back to the context.
- *
- * @param[in] ctx The @ref mongocrypt_ctx_t object.
- * @returns A boolean indicating success. If false, an error status is set.
- * Retrieve it with @ref mongocrypt_ctx_status
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_ctx_mongo_done (mongocrypt_ctx_t *ctx);
-
-
-/**
- * Manages a single KMS HTTP request/response.
- */
-typedef struct _mongocrypt_kms_ctx_t mongocrypt_kms_ctx_t;
-
-
-/**
- * Get the next KMS handle.
- *
- * Multiple KMS handles may be retrieved at once. Drivers may do this to fan
- * out multiple concurrent KMS HTTP requests. Feeding multiple KMS requests
- * is thread-safe.
- *
- * If KMS handles are being handled synchronously, the driver can reuse the same
- * TLS socket to send HTTP requests and receive responses.
- *
- * @param[in] ctx A @ref mongocrypt_ctx_t.
- * @returns a new @ref mongocrypt_kms_ctx_t or NULL.
- */
-MONGOCRYPT_EXPORT
-mongocrypt_kms_ctx_t *
-mongocrypt_ctx_next_kms_ctx (mongocrypt_ctx_t *ctx);
-
-
-/**
- * Get the HTTP request message for a KMS handle.
- *
- * The lifetime of @p msg is tied to the lifetime of @p kms. It is valid
- * until @ref mongocrypt_ctx_kms_done is called.
- *
- * @param[in] kms A @ref mongocrypt_kms_ctx_t.
- * @param[out] msg The HTTP request to send to KMS. The data viewed by @p msg is
- * guaranteed to be valid until the call of @ref mongocrypt_ctx_kms_done of the
- * parent @ref mongocrypt_ctx_t.
- * @returns A boolean indicating success. If false, an error status is set.
- * Retrieve it with @ref mongocrypt_kms_ctx_status
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_kms_ctx_message (mongocrypt_kms_ctx_t *kms,
- mongocrypt_binary_t *msg);
-
-
-/**
- * Get the hostname from which to connect over TLS.
- *
- * The storage for @p endpoint is not owned by the caller, but
- * is valid until calling @ref mongocrypt_ctx_kms_done.
- *
- * @param[in] kms A @ref mongocrypt_kms_ctx_t.
- * @param[out] endpoint The output endpoint as a NULL terminated string.
- * The endpoint consists of a hostname and port separated by a colon.
- * E.g. "example.com:123". A port is always present.
- *
- * @returns A boolean indicating success. If false, an error status is set.
- * Retrieve it with @ref mongocrypt_kms_ctx_status
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_kms_ctx_endpoint (mongocrypt_kms_ctx_t *kms, const char **endpoint);
-
-
-/**
- * Indicates how many bytes to feed into @ref mongocrypt_kms_ctx_feed.
- *
- * @param[in] kms The @ref mongocrypt_kms_ctx_t.
- * @returns The number of requested bytes.
- */
-MONGOCRYPT_EXPORT
-uint32_t
-mongocrypt_kms_ctx_bytes_needed (mongocrypt_kms_ctx_t *kms);
-
-
-/**
- * Feed bytes from the HTTP response.
- *
- * Feeding more bytes than what has been returned in @ref
- * mongocrypt_kms_ctx_bytes_needed is an error.
- *
- * @param[in] kms The @ref mongocrypt_kms_ctx_t.
- * @param[in] bytes The bytes to feed. The viewed data is copied. It is valid to
- * destroy @p bytes with @ref mongocrypt_binary_destroy immediately after.
- * @returns A boolean indicating success. If false, an error status is set.
- * Retrieve it with @ref mongocrypt_kms_ctx_status
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_kms_ctx_feed (mongocrypt_kms_ctx_t *kms, mongocrypt_binary_t *bytes);
-
-
-/**
- * Get the status associated with a @ref mongocrypt_kms_ctx_t object.
- *
- * @param[in] kms The @ref mongocrypt_kms_ctx_t object.
- * @param[out] status Receives the status.
- *
- * @returns A boolean indicating success. If false, an error status is set.
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_kms_ctx_status (mongocrypt_kms_ctx_t *kms,
- mongocrypt_status_t *status);
-
-/**
- * Get the KMS provider identifier associated with this KMS request.
- *
- * This is used to conditionally configure TLS connections based on the KMS
- * request. It is useful for KMIP, which authenticates with a client
- * certificate.
- *
- * @param[in] kms The @ref mongocrypt_kms_ctx_t object.
- * @param[out] len Receives the length of the returned string. It may be NULL.
- * If it is not NULL, it is set to the length of the returned string without
- * the NULL terminator.
- *
- * @returns One of the NULL terminated static strings: "aws", "azure", "gcp", or
- * "kmip".
- */
-MONGOCRYPT_EXPORT
-const char *
-mongocrypt_kms_ctx_get_kms_provider (mongocrypt_kms_ctx_t *kms, uint32_t *len);
-
-
-/**
- * Call when done handling all KMS contexts.
- *
- * @param[in] ctx The @ref mongocrypt_ctx_t object.
- *
- * @returns A boolean indicating success. If false, an error status is set.
- * Retrieve it with @ref mongocrypt_ctx_status
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_ctx_kms_done (mongocrypt_ctx_t *ctx);
-
-
-/**
- * Perform the final encryption or decryption.
- *
- * @param[in] ctx A @ref mongocrypt_ctx_t.
- * @param[out] out The final BSON. The data viewed by @p out is guaranteed
- * to be valid until @p ctx is destroyed with @ref mongocrypt_ctx_destroy.
- * The meaning of this BSON depends on the type of @p ctx.
- *
- * If @p ctx was initialized with @ref mongocrypt_ctx_encrypt_init, then
- * this BSON is the (possibly) encrypted command to send to the server.
- *
- * If @p ctx was initialized with @ref mongocrypt_ctx_decrypt_init, then
- * this BSON is the decrypted result to return to the user.
- *
- * If @p ctx was initialized with @ref mongocrypt_ctx_explicit_encrypt_init,
- * then this BSON has the form { "v": (BSON binary) } where the BSON binary
- * is the resulting encrypted value.
- *
- * If @p ctx was initialized with @ref mongocrypt_ctx_explicit_decrypt_init,
- * then this BSON has the form { "v": (BSON value) } where the BSON value
- * is the resulting decrypted value.
- *
- * If @p ctx was initialized with @ref mongocrypt_ctx_datakey_init, then
- * this BSON is the document containing the new data key to be inserted into
- * the key vault collection.
- *
- * @returns a bool indicating success. If false, an error status is set.
- * Retrieve it with @ref mongocrypt_ctx_status
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_ctx_finalize (mongocrypt_ctx_t *ctx, mongocrypt_binary_t *out);
-
-
-/**
- * Destroy and free all memory associated with a @ref mongocrypt_ctx_t.
- *
- * @param[in] ctx A @ref mongocrypt_ctx_t.
- */
-MONGOCRYPT_EXPORT
-void
-mongocrypt_ctx_destroy (mongocrypt_ctx_t *ctx);
-
-/**
- * An crypto AES-256-CBC encrypt or decrypt function.
- *
- * Note, @p in is already padded. Encrypt with padding disabled.
- * @param[in] ctx An optional context object that may have been set when hooks
- * were enabled.
- * @param[in] key An encryption key (32 bytes for AES_256).
- * @param[in] iv An initialization vector (16 bytes for AES_256);
- * @param[in] in The input.
- * @param[out] out A preallocated byte array for the output. See @ref
- * mongocrypt_binary_data.
- * @param[out] bytes_written Set this to the number of bytes written to @p out.
- * @param[out] status An optional status to pass error messages. See @ref
- * mongocrypt_status_set.
- * @returns A boolean indicating success. If returning false, set @p status
- * with a message indiciating the error using @ref mongocrypt_status_set.
- */
-typedef bool (*mongocrypt_crypto_fn) (void *ctx,
- mongocrypt_binary_t *key,
- mongocrypt_binary_t *iv,
- mongocrypt_binary_t *in,
- mongocrypt_binary_t *out,
- uint32_t *bytes_written,
- mongocrypt_status_t *status);
-
-/**
- * A crypto signature or HMAC function.
- *
- * Currently used in callbacks for HMAC SHA-512, HMAC SHA-256, and RSA SHA-256
- * signature.
- *
- * @param[in] ctx An optional context object that may have been set when hooks
- * were enabled.
- * @param[in] key An encryption key (32 bytes for HMAC_SHA512).
- * @param[in] in The input.
- * @param[out] out A preallocated byte array for the output. See @ref
- * mongocrypt_binary_data.
- * @param[out] status An optional status to pass error messages. See @ref
- * mongocrypt_status_set.
- * @returns A boolean indicating success. If returning false, set @p status
- * with a message indiciating the error using @ref mongocrypt_status_set.
- */
-typedef bool (*mongocrypt_hmac_fn) (void *ctx,
- mongocrypt_binary_t *key,
- mongocrypt_binary_t *in,
- mongocrypt_binary_t *out,
- mongocrypt_status_t *status);
-
-
-/**
- * A crypto hash (SHA-256) function.
- *
- * @param[in] ctx An optional context object that may have been set when hooks
- * were enabled.
- * @param[in] in The input.
- * @param[out] out A preallocated byte array for the output. See @ref
- * mongocrypt_binary_data.
- * @param[out] status An optional status to pass error messages. See @ref
- * mongocrypt_status_set.
- * @returns A boolean indicating success. If returning false, set @p status
- * with a message indiciating the error using @ref mongocrypt_status_set.
- */
-typedef bool (*mongocrypt_hash_fn) (void *ctx,
- mongocrypt_binary_t *in,
- mongocrypt_binary_t *out,
- mongocrypt_status_t *status);
-
-/**
- * A crypto secure random function.
- *
- * @param[in] ctx An optional context object that may have been set when hooks
- * were enabled.
- * @param[out] out A preallocated byte array for the output. See @ref
- * mongocrypt_binary_data.
- * @param[in] count The number of random bytes requested.
- * @param[out] status An optional status to pass error messages. See @ref
- * mongocrypt_status_set.
- * @returns A boolean indicating success. If returning false, set @p status
- * with a message indiciating the error using @ref mongocrypt_status_set.
- */
-typedef bool (*mongocrypt_random_fn) (void *ctx,
- mongocrypt_binary_t *out,
- uint32_t count,
- mongocrypt_status_t *status);
-
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_setopt_crypto_hooks (mongocrypt_t *crypt,
- mongocrypt_crypto_fn aes_256_cbc_encrypt,
- mongocrypt_crypto_fn aes_256_cbc_decrypt,
- mongocrypt_random_fn random,
- mongocrypt_hmac_fn hmac_sha_512,
- mongocrypt_hmac_fn hmac_sha_256,
- mongocrypt_hash_fn sha_256,
- void *ctx);
-
-/**
- * Set a crypto hook for the RSASSA-PKCS1-v1_5 algorithm with a SHA-256 hash.
- *
- * See: https://tools.ietf.org/html/rfc3447#section-8.2
- *
- * Note: this function has the wrong name. It should be:
- * mongocrypt_setopt_crypto_hook_sign_rsassa_pkcs1_v1_5
- *
- * @param[in] crypt The @ref mongocrypt_t object.
- * @param[in] sign_rsaes_pkcs1_v1_5 The crypto callback function.
- * @param[in] sign_ctx A context passed as an argument to the crypto callback every
- * invocation.
- * @pre @ref mongocrypt_init has not been called on @p crypt.
- * @returns A boolean indicating success. If false, an error status is set.
- * Retrieve it with @ref mongocrypt_status
- *
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_setopt_crypto_hook_sign_rsaes_pkcs1_v1_5 (
- mongocrypt_t *crypt,
- mongocrypt_hmac_fn sign_rsaes_pkcs1_v1_5,
- void *sign_ctx);
-
-#endif /* MONGOCRYPT_H */
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt.h.in b/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt.h.in
deleted file mode 100644
index a342c3d4..00000000
--- a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt.h.in
+++ /dev/null
@@ -1,1173 +0,0 @@
-/*
- * Copyright 2019-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef MONGOCRYPT_H
-#define MONGOCRYPT_H
-
-/** @file mongocrypt.h The top-level handle to libmongocrypt. */
-
-/**
- * @mainpage libmongocrypt
- * See all public API documentation in: @ref mongocrypt.h
- */
-
-#include "mongocrypt-export.h"
-#include "mongocrypt-compat.h"
-#include "mongocrypt-config.h"
-
-/**
- * @def MONGOCRYPT_VERSION
- * The version string describing libmongocrypt.
- * Has the form x.y.z-<pre>+<date>+git<sha>.
- */
-#define MONGOCRYPT_VERSION "@MONGOCRYPT_BUILD_VERSION@"
-
-/**
- * Returns the version string for libmongocrypt.
- *
- * @param[out] len An optional length of the returned string. May be NULL.
- * @returns a NULL terminated version string for libmongocrypt.
- */
-MONGOCRYPT_EXPORT
-const char *
-mongocrypt_version (uint32_t *len);
-
-
-/**
- * A non-owning view of a byte buffer.
- *
- * When constructing a mongocrypt_binary_t it is the responsibility of the
- * caller to maintain the lifetime of the viewed data. However, all public
- * functions that take a mongocrypt_binary_t as an argument will make a copy of
- * the viewed data. For example, the following is valid:
- *
- * @code{.c}
- * mongocrypt_binary_t bin = mongocrypt_binary_new_from_data(mydata, mylen);
- * assert (mongocrypt_setopt_kms_provider_local (crypt), bin);
- * // The viewed data of bin has been copied. Ok to free the view and the data.
- * mongocrypt_binary_destroy (bin);
- * my_free_fn (mydata);
- * @endcode
- *
- * Functions with a mongocrypt_binary_t* out guarantee the lifetime of the
- * viewed data to live as long as the parent object. For example, @ref
- * mongocrypt_ctx_mongo_op guarantees that the viewed data of
- * mongocrypt_binary_t is valid until the parent ctx is destroyed with @ref
- * mongocrypt_ctx_destroy.
- */
-typedef struct _mongocrypt_binary_t mongocrypt_binary_t;
-
-
-/**
- * Create a new non-owning view of a buffer (data + length).
- *
- * Use this to create a mongocrypt_binary_t used for output parameters.
- *
- * @returns A new mongocrypt_binary_t.
- */
-MONGOCRYPT_EXPORT
-mongocrypt_binary_t *
-mongocrypt_binary_new (void);
-
-
-/**
- * Create a new non-owning view of a buffer (data + length).
- *
- * @param[in] data A pointer to an array of bytes. This data is not copied. @p
- * data must outlive the binary object.
- * @param[in] len The length of the @p data byte array.
- *
- * @returns A new @ref mongocrypt_binary_t.
- */
-MONGOCRYPT_EXPORT
-mongocrypt_binary_t *
-mongocrypt_binary_new_from_data (uint8_t *data, uint32_t len);
-
-
-/**
- * Get a pointer to the viewed data.
- *
- * @param[in] binary The @ref mongocrypt_binary_t.
- *
- * @returns A pointer to the viewed data.
- */
-MONGOCRYPT_EXPORT
-uint8_t *
-mongocrypt_binary_data (const mongocrypt_binary_t *binary);
-
-
-/**
- * Get the length of the viewed data.
- *
- * @param[in] binary The @ref mongocrypt_binary_t.
- *
- * @returns The length of the viewed data.
- */
-MONGOCRYPT_EXPORT
-uint32_t
-mongocrypt_binary_len (const mongocrypt_binary_t *binary);
-
-
-/**
- * Free the @ref mongocrypt_binary_t.
- *
- * This does not free the viewed data.
- *
- * @param[in] binary The mongocrypt_binary_t destroy.
- */
-MONGOCRYPT_EXPORT
-void
-mongocrypt_binary_destroy (mongocrypt_binary_t *binary);
-
-
-/**
- * Indicates success or contains error information.
- *
- * Functions like @ref mongocrypt_ctx_encrypt_init follow a pattern to expose a
- * status. A boolean is returned. True indicates success, and false indicates
- * failure. On failure a status on the handle is set, and is accessible with a
- * corresponding (handle)_status function. E.g. @ref mongocrypt_ctx_status.
- */
-typedef struct _mongocrypt_status_t mongocrypt_status_t;
-
-/**
- * Indicates the type of error.
- */
-typedef enum {
- MONGOCRYPT_STATUS_OK = 0,
- MONGOCRYPT_STATUS_ERROR_CLIENT = 1,
- MONGOCRYPT_STATUS_ERROR_KMS = 2
-} mongocrypt_status_type_t;
-
-
-/**
- * Create a new status object.
- *
- * Use a new status object to retrieve the status from a handle by passing
- * this as an out-parameter to functions like @ref mongocrypt_ctx_status.
- * When done, destroy it with @ref mongocrypt_status_destroy.
- *
- * @returns A new status object.
- */
-MONGOCRYPT_EXPORT
-mongocrypt_status_t *
-mongocrypt_status_new (void);
-
-
-/**
- * Set a status object with message, type, and code.
- *
- * Use this to set the @ref mongocrypt_status_t given in the crypto hooks.
- *
- * @param[in] type The status type.
- * @param[in] code The status code.
- * @param[in] message The message.
- * @param[in] message_len Due to historical behavior, pass 1 + the string length
- * of @p message (which differs from other functions accepting string
- * arguments).
- * Alternatively, if message is NULL terminated this may be -1 to tell
- * mongocrypt
- * to determine the string's length with strlen.
- *
- */
-MONGOCRYPT_EXPORT
-void
-mongocrypt_status_set (mongocrypt_status_t *status,
- mongocrypt_status_type_t type,
- uint32_t code,
- const char *message,
- int32_t message_len);
-
-
-/**
- * Indicates success or the type of error.
- *
- * @param[in] status The status object.
- *
- * @returns A @ref mongocrypt_status_type_t.
- */
-MONGOCRYPT_EXPORT
-mongocrypt_status_type_t
-mongocrypt_status_type (mongocrypt_status_t *status);
-
-
-/**
- * Get an error code or 0.
- *
- * @param[in] status The status object.
- *
- * @returns An error code.
- */
-MONGOCRYPT_EXPORT
-uint32_t
-mongocrypt_status_code (mongocrypt_status_t *status);
-
-
-/**
- * Get the error message associated with a status or NULL.
- *
- * @param[in] status The status object.
- * @param[out] len An optional length of the returned string (excluding the
- * trailing NULL byte). May be NULL.
- *
- * @returns A NULL terminated error message or NULL.
- */
-MONGOCRYPT_EXPORT
-const char *
-mongocrypt_status_message (mongocrypt_status_t *status, uint32_t *len);
-
-
-/**
- * Returns true if the status indicates success.
- *
- * @param[in] status The status to check.
- *
- * @returns A boolean indicating success. If false, an error status is set.
- * Retrieve it with @ref mongocrypt_ctx_status
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_status_ok (mongocrypt_status_t *status);
-
-
-/**
- * Free the memory for a status object.
- *
- * @param[in] status The status to destroy.
- */
-MONGOCRYPT_EXPORT
-void
-mongocrypt_status_destroy (mongocrypt_status_t *status);
-
-/**
- * Indicates the type of log message.
- */
-typedef enum {
- MONGOCRYPT_LOG_LEVEL_FATAL = 0,
- MONGOCRYPT_LOG_LEVEL_ERROR = 1,
- MONGOCRYPT_LOG_LEVEL_WARNING = 2,
- MONGOCRYPT_LOG_LEVEL_INFO = 3,
- MONGOCRYPT_LOG_LEVEL_TRACE = 4
-} mongocrypt_log_level_t;
-
-
-/**
- * A log callback function. Set a custom log callback with @ref
- * mongocrypt_setopt_log_handler.
- *
- * @param[in] message A NULL terminated message.
- * @param[in] message_len The length of message.
- * @param[in] ctx A context provided by the caller of @ref
- * mongocrypt_setopt_log_handler.
- */
-typedef void (*mongocrypt_log_fn_t) (mongocrypt_log_level_t level,
- const char *message,
- uint32_t message_len,
- void *ctx);
-
-
-/**
- * The top-level handle to libmongocrypt.
- *
- * Create a mongocrypt_t handle to perform operations within libmongocrypt:
- * encryption, decryption, registering log callbacks, etc.
- *
- * Functions on a mongocrypt_t are thread safe, though functions on derived
- * handles (e.g. mongocrypt_ctx_t) are not and must be owned by a single
- * thread. See each handle's documentation for thread-safety considerations.
- *
- * Multiple mongocrypt_t handles may be created.
- */
-typedef struct _mongocrypt_t mongocrypt_t;
-
-
-/**
- * Allocate a new @ref mongocrypt_t object.
- *
- * Set options using mongocrypt_setopt_* functions, then initialize with @ref
- * mongocrypt_init. When done with the @ref mongocrypt_t, free with @ref
- * mongocrypt_destroy.
- *
- * @returns A new @ref mongocrypt_t object.
- */
-MONGOCRYPT_EXPORT
-mongocrypt_t *
-mongocrypt_new (void);
-
-
-/**
- * Set a handler on the @ref mongocrypt_t object to get called on every log
- * message.
- *
- * @param[in] crypt The @ref mongocrypt_t object.
- * @param[in] log_fn The log callback.
- * @param[in] log_ctx A context passed as an argument to the log callback every
- * invocation.
- * @pre @ref mongocrypt_init has not been called on @p crypt.
- * @returns A boolean indicating success. If false, an error status is set.
- * Retrieve it with @ref mongocrypt_ctx_status
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_setopt_log_handler (mongocrypt_t *crypt,
- mongocrypt_log_fn_t log_fn,
- void *log_ctx);
-
-
-/**
- * Configure an AWS KMS provider on the @ref mongocrypt_t object.
- *
- * This has been superseded by the more flexible:
- * @ref mongocrypt_setopt_kms_providers
- *
- * @param[in] crypt The @ref mongocrypt_t object.
- * @param[in] aws_access_key_id The AWS access key ID used to generate KMS
- * messages.
- * @param[in] aws_access_key_id_len The string length (in bytes) of @p
- * aws_access_key_id. Pass -1 to determine the string length with strlen (must
- * be NULL terminated).
- * @param[in] aws_secret_access_key The AWS secret access key used to generate
- * KMS messages.
- * @param[in] aws_secret_access_key_len The string length (in bytes) of @p
- * aws_secret_access_key. Pass -1 to determine the string length with strlen
- * (must be NULL terminated).
- * @pre @ref mongocrypt_init has not been called on @p crypt.
- * @returns A boolean indicating success. If false, an error status is set.
- * Retrieve it with @ref mongocrypt_ctx_status
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_setopt_kms_provider_aws (mongocrypt_t *crypt,
- const char *aws_access_key_id,
- int32_t aws_access_key_id_len,
- const char *aws_secret_access_key,
- int32_t aws_secret_access_key_len);
-
-
-/**
- * Configure a local KMS provider on the @ref mongocrypt_t object.
- *
- * This has been superseded by the more flexible:
- * @ref mongocrypt_setopt_kms_providers
- *
- * @param[in] crypt The @ref mongocrypt_t object.
- * @param[in] key A 96 byte master key used to encrypt and decrypt key vault
- * keys. The viewed data is copied. It is valid to destroy @p key with @ref
- * mongocrypt_binary_destroy immediately after.
- * @pre @ref mongocrypt_init has not been called on @p crypt.
- * @returns A boolean indicating success. If false, an error status is set.
- * Retrieve it with @ref mongocrypt_ctx_status
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_setopt_kms_provider_local (mongocrypt_t *crypt,
- mongocrypt_binary_t *key);
-
-/**
- * Configure KMS providers with a BSON document.
- *
- * @param[in] crypt The @ref mongocrypt_t object.
- * @param[in] kms_providers A BSON document mapping the KMS provider names
- * to credentials.
- * @pre @ref mongocrypt_init has not been called on @p crypt.
- * @returns A boolean indicating success. If false, an error status is set.
- * Retrieve it with @ref mongocrypt_ctx_status
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_setopt_kms_providers (mongocrypt_t *crypt,
- mongocrypt_binary_t *kms_providers);
-
-/**
- * Set a local schema map for encryption.
- *
- * @param[in] crypt The @ref mongocrypt_t object.
- * @param[in] schema_map A BSON document representing the schema map supplied by
- * the user. The keys are collection namespaces and values are JSON schemas. The
- * viewed data copied. It is valid to destroy @p schema_map with @ref
- * mongocrypt_binary_destroy immediately after.
- * @pre @p crypt has not been initialized.
- * @returns A boolean indicating success. If false, an error status is set.
- * Retrieve it with @ref mongocrypt_status
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_setopt_schema_map (mongocrypt_t *crypt,
- mongocrypt_binary_t *schema_map);
-
-
-/**
- * Initialize new @ref mongocrypt_t object.
- *
- * Set options before using @ref mongocrypt_setopt_kms_provider_local, @ref
- * mongocrypt_setopt_kms_provider_aws, or @ref mongocrypt_setopt_log_handler.
- *
- * @param[in] crypt The @ref mongocrypt_t object.
- *
- * @returns A boolean indicating success. If false, an error status is set.
- * Retrieve it with @ref mongocrypt_ctx_status Failure may occur if previously
- * set
- * options are invalid.
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_init (mongocrypt_t *crypt);
-
-
-/**
- * Get the status associated with a @ref mongocrypt_t object.
- *
- * @param[in] crypt The @ref mongocrypt_t object.
- * @param[out] status Receives the status.
- *
- * @returns A boolean indicating success. If false, an error status is set.
- * Retrieve it with @ref mongocrypt_ctx_status
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_status (mongocrypt_t *crypt, mongocrypt_status_t *status);
-
-
-/**
- * Destroy the @ref mongocrypt_t object.
- *
- * @param[in] crypt The @ref mongocrypt_t object to destroy.
- */
-MONGOCRYPT_EXPORT
-void
-mongocrypt_destroy (mongocrypt_t *crypt);
-
-
-/**
- * Manages the state machine for encryption or decryption.
- */
-typedef struct _mongocrypt_ctx_t mongocrypt_ctx_t;
-
-
-/**
- * Create a new uninitialized @ref mongocrypt_ctx_t.
- *
- * Initialize the context with functions like @ref mongocrypt_ctx_encrypt_init.
- * When done, destroy it with @ref mongocrypt_ctx_destroy.
- *
- * @param[in] crypt The @ref mongocrypt_t object.
- * @returns A new context.
- */
-MONGOCRYPT_EXPORT
-mongocrypt_ctx_t *
-mongocrypt_ctx_new (mongocrypt_t *crypt);
-
-
-/**
- * Get the status associated with a @ref mongocrypt_ctx_t object.
- *
- * @param[in] ctx The @ref mongocrypt_ctx_t object.
- * @param[out] status Receives the status.
- *
- * @returns True if the output is an ok status, false if it is an error
- * status.
- *
- * @see mongocrypt_status_ok
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_ctx_status (mongocrypt_ctx_t *ctx, mongocrypt_status_t *status);
-
-
-/**
- * Set the key id to use for explicit encryption.
- *
- * It is an error to set both this and the key alt name.
- *
- * @param[in] ctx The @ref mongocrypt_ctx_t object.
- * @param[in] key_id The binary corresponding to the _id (a UUID) of the data
- * key to use from the key vault collection. Note, the UUID must be encoded with
- * RFC-4122 byte order. The viewed data is copied. It is valid to destroy
- * @p key_id with @ref mongocrypt_binary_destroy immediately after.
- * @pre @p ctx has not been initialized.
- * @returns A boolean indicating success. If false, an error status is set.
- * Retrieve it with @ref mongocrypt_ctx_status
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_ctx_setopt_key_id (mongocrypt_ctx_t *ctx,
- mongocrypt_binary_t *key_id);
-
-/**
- * Set the keyAltName to use for explicit encryption or
- * data key creation.
- *
- * Pass the binary encoding a BSON document like the following:
- *
- * { "keyAltName" : (BSON UTF8 value) }
- *
- * For explicit encryption, it is an error to set both the keyAltName
- * and the key id.
- *
- * For creating data keys, call this function repeatedly to set
- * multiple keyAltNames.
- *
- * @param[in] ctx The @ref mongocrypt_ctx_t object.
- * @param[in] key_alt_name The name to use. The viewed data is copied. It is
- * valid to destroy @p key_alt_name with @ref mongocrypt_binary_destroy
- * immediately after.
- * @pre @p ctx has not been initialized.
- * @returns A boolean indicating success. If false, an error status is set.
- * Retrieve it with @ref mongocrypt_ctx_status
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_ctx_setopt_key_alt_name (mongocrypt_ctx_t *ctx,
- mongocrypt_binary_t *key_alt_name);
-
-/**
- * Set the algorithm used for encryption to either
- * deterministic or random encryption. This value
- * should only be set when using explicit encryption.
- *
- * If -1 is passed in for "len", then "algorithm" is
- * assumed to be a null-terminated string.
- *
- * Valid values for algorithm are:
- * "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic"
- * "AEAD_AES_256_CBC_HMAC_SHA_512-Random"
- *
- * @param[in] ctx The @ref mongocrypt_ctx_t object.
- * @param[in] algorithm A string specifying the algorithm to
- * use for encryption.
- * @param[in] len The length of the algorithm string.
- * @pre @p ctx has not been initialized.
- * @returns A boolean indicating success. If false, an error status is set.
- * Retrieve it with @ref mongocrypt_ctx_status
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_ctx_setopt_algorithm (mongocrypt_ctx_t *ctx,
- const char *algorithm,
- int len);
-
-
-/**
- * Identify the AWS KMS master key to use for creating a data key.
- *
- * This has been superseded by the more flexible:
- * @ref mongocrypt_ctx_setopt_key_encryption_key
- *
- * @param[in] ctx The @ref mongocrypt_ctx_t object.
- * @param[in] region The AWS region.
- * @param[in] region_len The string length of @p region. Pass -1 to determine
- * the string length with strlen (must be NULL terminated).
- * @param[in] cmk The Amazon Resource Name (ARN) of the customer master key
- * (CMK).
- * @param[in] cmk_len The string length of @p cmk_len. Pass -1 to determine the
- * string length with strlen (must be NULL terminated).
- * @pre @p ctx has not been initialized.
- * @returns A boolean indicating success. If false, an error status is set.
- * Retrieve it with @ref mongocrypt_ctx_status
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_ctx_setopt_masterkey_aws (mongocrypt_ctx_t *ctx,
- const char *region,
- int32_t region_len,
- const char *cmk,
- int32_t cmk_len);
-
-
-/**
- * Identify a custom AWS endpoint when creating a data key.
- * This is used internally to construct the correct HTTP request
- * (with the Host header set to this endpoint). This endpoint
- * is persisted in the new data key, and will be returned via
- * @ref mongocrypt_kms_ctx_endpoint.
- *
- * This has been superseded by the more flexible:
- * @ref mongocrypt_ctx_setopt_key_encryption_key
- *
- * @param[in] ctx The @ref mongocrypt_ctx_t object.
- * @param[in] endpoint The endpoint.
- * @param[in] endpoint_len The string length of @p endpoint. Pass -1 to
- * determine the string length with strlen (must be NULL terminated).
- * @returns A boolean indicating success. If false, an error status is set.
- * Retrieve it with @ref mongocrypt_ctx_status
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_ctx_setopt_masterkey_aws_endpoint (mongocrypt_ctx_t *ctx,
- const char *endpoint,
- int32_t endpoint_len);
-
-/**
- * Set the master key to "local" for creating a data key.
- * This has been superseded by the more flexible:
- * @ref mongocrypt_ctx_setopt_key_encryption_key
- *
- * @param[in] ctx The @ref mongocrypt_ctx_t object.
- * @pre @p ctx has not been initialized.
- * @returns A boolean indicating success. If false, an error status is set.
- * Retrieve it with @ref mongocrypt_ctx_status
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_ctx_setopt_masterkey_local (mongocrypt_ctx_t *ctx);
-
-/**
- * Set key encryption key document for creating a data key.
- *
- * @param[in] ctx The @ref mongocrypt_ctx_t object.
- * @param[in] bin BSON representing the key encryption key document with
- * an additional "provider" field. The following forms are accepted:
- *
- * AWS
- * {
- * provider: "aws",
- * region: <string>,
- * key: <string>,
- * endpoint: <optional string>
- * }
- *
- * Azure
- * {
- * provider: "azure",
- * keyVaultEndpoint: <string>,
- * keyName: <string>,
- * keyVersion: <optional string>
- * }
- *
- * GCP
- * {
- * provider: "gcp",
- * projectId: <string>,
- * location: <string>,
- * keyRing: <string>,
- * keyName: <string>,
- * keyVersion: <string>,
- * endpoint: <optional string>
- * }
- *
- * Local
- * {
- * provider: "local"
- * }
- *
- * KMIP
- * {
- * provider: "kmip",
- * keyId: <optional string>
- * endpoint: <string>
- * }
- *
- * @pre @p ctx has not been initialized.
- * @returns A boolean indicating success. If false, and error status is set.
- * Retrieve it with @ref mongocrypt_ctx_status.
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_ctx_setopt_key_encryption_key (mongocrypt_ctx_t *ctx,
- mongocrypt_binary_t *bin);
-
-
-/**
- * Initialize a context to create a data key.
- *
- * Associated options:
- * - @ref mongocrypt_ctx_setopt_masterkey_aws
- * - @ref mongocrypt_ctx_setopt_masterkey_aws_endpoint
- * - @ref mongocrypt_ctx_setopt_masterkey_local
- *
- * @param[in] ctx The @ref mongocrypt_ctx_t object.
- * @returns A boolean indicating success. If false, an error status is set.
- * Retrieve it with @ref mongocrypt_ctx_status
- * @pre A master key option has been set, and an associated KMS provider
- * has been set on the parent @ref mongocrypt_t.
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_ctx_datakey_init (mongocrypt_ctx_t *ctx);
-
-/**
- * Initialize a context for encryption.
- *
- * @param[in] ctx The @ref mongocrypt_ctx_t object.
- * @param[in] db The database name.
- * @param[in] db_len The byte length of @p db. Pass -1 to determine the string
- * length with strlen (must
- * be NULL terminated).
- * @param[in] cmd The BSON command to be encrypted. The viewed data is copied.
- * It is valid to destroy @p cmd with @ref mongocrypt_binary_destroy immediately
- * after.
- * @returns A boolean indicating success. If false, an error status is set.
- * Retrieve it with @ref mongocrypt_ctx_status
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_ctx_encrypt_init (mongocrypt_ctx_t *ctx,
- const char *db,
- int32_t db_len,
- mongocrypt_binary_t *cmd);
-
-/**
- * Explicit helper method to encrypt a single BSON object. Contexts
- * created for explicit encryption will not go through mongocryptd.
- *
- * To specify a key_id, algorithm, or iv to use, please use the
- * corresponding mongocrypt_setopt methods before calling this.
- *
- * This method expects the passed-in BSON to be of the form:
- * { "v" : BSON value to encrypt }
- *
- * Associated options:
- * - @ref mongocrypt_ctx_setopt_key_id
- * - @ref mongocrypt_ctx_setopt_key_alt_name
- * - @ref mongocrypt_ctx_setopt_algorithm
- *
- * @param[in] ctx A @ref mongocrypt_ctx_t.
- * @param[in] msg A @ref mongocrypt_binary_t the plaintext BSON value. The
- * viewed data is copied. It is valid to destroy @p msg with @ref
- * mongocrypt_binary_destroy immediately after.
- * @returns A boolean indicating success. If false, an error status is set.
- * Retrieve it with @ref mongocrypt_ctx_status
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_ctx_explicit_encrypt_init (mongocrypt_ctx_t *ctx,
- mongocrypt_binary_t *msg);
-
-
-/**
- * Initialize a context for decryption.
- *
- * This method expects the passed-in BSON to be of the form:
- * { "v" : BSON value to encrypt }
- *
- * @param[in] ctx The @ref mongocrypt_ctx_t object.
- * @param[in] doc The document to be decrypted. The viewed data is copied. It is
- * valid to destroy @p doc with @ref mongocrypt_binary_destroy immediately
- * after.
- * @returns A boolean indicating success. If false, an error status is set.
- * Retrieve it with @ref mongocrypt_ctx_status
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_ctx_decrypt_init (mongocrypt_ctx_t *ctx, mongocrypt_binary_t *doc);
-
-
-/**
- * Explicit helper method to decrypt a single BSON object.
- *
- *
- * @param[in] ctx A @ref mongocrypt_ctx_t.
- * @param[in] msg A @ref mongocrypt_binary_t the encrypted BSON. The viewed data
- * is copied. It is valid to destroy @p msg with @ref mongocrypt_binary_destroy
- * immediately after.
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_ctx_explicit_decrypt_init (mongocrypt_ctx_t *ctx,
- mongocrypt_binary_t *msg);
-
-
-/**
- * Indicates the state of the @ref mongocrypt_ctx_t. Each state requires
- * different handling. See [the integration
- * guide](https://github.com/mongodb/libmongocrypt/blob/master/integrating.md#state-machine)
- * for information on what to do for each state.
- */
-typedef enum {
- MONGOCRYPT_CTX_ERROR = 0,
- MONGOCRYPT_CTX_NEED_MONGO_COLLINFO = 1, /* run on main MongoClient */
- MONGOCRYPT_CTX_NEED_MONGO_MARKINGS = 2, /* run on mongocryptd. */
- MONGOCRYPT_CTX_NEED_MONGO_KEYS = 3, /* run on key vault */
- MONGOCRYPT_CTX_NEED_KMS = 4,
- MONGOCRYPT_CTX_READY = 5, /* ready for encryption/decryption */
- MONGOCRYPT_CTX_DONE = 6
-} mongocrypt_ctx_state_t;
-
-
-/**
- * Get the current state of a context.
- *
- * @param[in] ctx The @ref mongocrypt_ctx_t object.
- * @returns A @ref mongocrypt_ctx_state_t.
- */
-MONGOCRYPT_EXPORT
-mongocrypt_ctx_state_t
-mongocrypt_ctx_state (mongocrypt_ctx_t *ctx);
-
-
-/**
- * Get BSON necessary to run the mongo operation when mongocrypt_ctx_t
- * is in MONGOCRYPT_CTX_NEED_MONGO_* states.
- *
- * @p op_bson is a BSON document to be used for the operation.
- * - For MONGOCRYPT_CTX_NEED_MONGO_COLLINFO it is a listCollections filter.
- * - For MONGOCRYPT_CTX_NEED_MONGO_KEYS it is a find filter.
- * - For MONGOCRYPT_CTX_NEED_MONGO_MARKINGS it is a command to send to
- * mongocryptd.
- *
- * The lifetime of @p op_bson is tied to the lifetime of @p ctx. It is valid
- * until @ref mongocrypt_ctx_destroy is called.
- *
- * @param[in] ctx The @ref mongocrypt_ctx_t object.
- * @param[out] op_bson A BSON document for the MongoDB operation. The data
- * viewed by @p op_bson is guaranteed to be valid until @p ctx is destroyed with
- * @ref mongocrypt_ctx_destroy.
- * @returns A boolean indicating success. If false, an error status is set.
- * Retrieve it with @ref mongocrypt_ctx_status
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_ctx_mongo_op (mongocrypt_ctx_t *ctx, mongocrypt_binary_t *op_bson);
-
-
-/**
- * Feed a BSON reply or result when mongocrypt_ctx_t is in
- * MONGOCRYPT_CTX_NEED_MONGO_* states. This may be called multiple times
- * depending on the operation.
- *
- * reply is a BSON document result being fed back for this operation.
- * - For MONGOCRYPT_CTX_NEED_MONGO_COLLINFO it is a doc from a listCollections
- * cursor. (Note, if listCollections returned no result, do not call this
- * function.)
- * - For MONGOCRYPT_CTX_NEED_MONGO_KEYS it is a doc from a find cursor.
- * (Note, if find returned no results, do not call this function. reply must
- * not
- * be NULL.)
- * - For MONGOCRYPT_CTX_NEED_MONGO_MARKINGS it is a reply from mongocryptd.
- *
- * @param[in] ctx The @ref mongocrypt_ctx_t object.
- * @param[in] reply A BSON document for the MongoDB operation. The viewed data
- * is copied. It is valid to destroy @p reply with @ref
- * mongocrypt_binary_destroy immediately after.
- * @returns A boolean indicating success. If false, an error status is set.
- * Retrieve it with @ref mongocrypt_ctx_status
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_ctx_mongo_feed (mongocrypt_ctx_t *ctx, mongocrypt_binary_t *reply);
-
-
-/**
- * Call when done feeding the reply (or replies) back to the context.
- *
- * @param[in] ctx The @ref mongocrypt_ctx_t object.
- * @returns A boolean indicating success. If false, an error status is set.
- * Retrieve it with @ref mongocrypt_ctx_status
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_ctx_mongo_done (mongocrypt_ctx_t *ctx);
-
-
-/**
- * Manages a single KMS HTTP request/response.
- */
-typedef struct _mongocrypt_kms_ctx_t mongocrypt_kms_ctx_t;
-
-
-/**
- * Get the next KMS handle.
- *
- * Multiple KMS handles may be retrieved at once. Drivers may do this to fan
- * out multiple concurrent KMS HTTP requests. Feeding multiple KMS requests
- * is thread-safe.
- *
- * If KMS handles are being handled synchronously, the driver can reuse the same
- * TLS socket to send HTTP requests and receive responses.
- *
- * @param[in] ctx A @ref mongocrypt_ctx_t.
- * @returns a new @ref mongocrypt_kms_ctx_t or NULL.
- */
-MONGOCRYPT_EXPORT
-mongocrypt_kms_ctx_t *
-mongocrypt_ctx_next_kms_ctx (mongocrypt_ctx_t *ctx);
-
-
-/**
- * Get the HTTP request message for a KMS handle.
- *
- * The lifetime of @p msg is tied to the lifetime of @p kms. It is valid
- * until @ref mongocrypt_ctx_kms_done is called.
- *
- * @param[in] kms A @ref mongocrypt_kms_ctx_t.
- * @param[out] msg The HTTP request to send to KMS. The data viewed by @p msg is
- * guaranteed to be valid until the call of @ref mongocrypt_ctx_kms_done of the
- * parent @ref mongocrypt_ctx_t.
- * @returns A boolean indicating success. If false, an error status is set.
- * Retrieve it with @ref mongocrypt_kms_ctx_status
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_kms_ctx_message (mongocrypt_kms_ctx_t *kms,
- mongocrypt_binary_t *msg);
-
-
-/**
- * Get the hostname from which to connect over TLS.
- *
- * The storage for @p endpoint is not owned by the caller, but
- * is valid until calling @ref mongocrypt_ctx_kms_done.
- *
- * @param[in] kms A @ref mongocrypt_kms_ctx_t.
- * @param[out] endpoint The output endpoint as a NULL terminated string.
- * The endpoint consists of a hostname and port separated by a colon.
- * E.g. "example.com:123". A port is always present.
- *
- * @returns A boolean indicating success. If false, an error status is set.
- * Retrieve it with @ref mongocrypt_kms_ctx_status
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_kms_ctx_endpoint (mongocrypt_kms_ctx_t *kms, const char **endpoint);
-
-
-/**
- * Indicates how many bytes to feed into @ref mongocrypt_kms_ctx_feed.
- *
- * @param[in] kms The @ref mongocrypt_kms_ctx_t.
- * @returns The number of requested bytes.
- */
-MONGOCRYPT_EXPORT
-uint32_t
-mongocrypt_kms_ctx_bytes_needed (mongocrypt_kms_ctx_t *kms);
-
-
-/**
- * Feed bytes from the HTTP response.
- *
- * Feeding more bytes than what has been returned in @ref
- * mongocrypt_kms_ctx_bytes_needed is an error.
- *
- * @param[in] kms The @ref mongocrypt_kms_ctx_t.
- * @param[in] bytes The bytes to feed. The viewed data is copied. It is valid to
- * destroy @p bytes with @ref mongocrypt_binary_destroy immediately after.
- * @returns A boolean indicating success. If false, an error status is set.
- * Retrieve it with @ref mongocrypt_kms_ctx_status
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_kms_ctx_feed (mongocrypt_kms_ctx_t *kms, mongocrypt_binary_t *bytes);
-
-
-/**
- * Get the status associated with a @ref mongocrypt_kms_ctx_t object.
- *
- * @param[in] kms The @ref mongocrypt_kms_ctx_t object.
- * @param[out] status Receives the status.
- *
- * @returns A boolean indicating success. If false, an error status is set.
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_kms_ctx_status (mongocrypt_kms_ctx_t *kms,
- mongocrypt_status_t *status);
-
-/**
- * Get the KMS provider identifier associated with this KMS request.
- *
- * This is used to conditionally configure TLS connections based on the KMS
- * request. It is useful for KMIP, which authenticates with a client
- * certificate.
- *
- * @param[in] kms The @ref mongocrypt_kms_ctx_t object.
- * @param[out] len Receives the length of the returned string. It may be NULL.
- * If it is not NULL, it is set to the length of the returned string without
- * the NULL terminator.
- *
- * @returns One of the NULL terminated static strings: "aws", "azure", "gcp", or
- * "kmip".
- */
-MONGOCRYPT_EXPORT
-const char *
-mongocrypt_kms_ctx_get_kms_provider (mongocrypt_kms_ctx_t *kms, uint32_t *len);
-
-
-/**
- * Call when done handling all KMS contexts.
- *
- * @param[in] ctx The @ref mongocrypt_ctx_t object.
- *
- * @returns A boolean indicating success. If false, an error status is set.
- * Retrieve it with @ref mongocrypt_ctx_status
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_ctx_kms_done (mongocrypt_ctx_t *ctx);
-
-
-/**
- * Perform the final encryption or decryption.
- *
- * @param[in] ctx A @ref mongocrypt_ctx_t.
- * @param[out] out The final BSON. The data viewed by @p out is guaranteed
- * to be valid until @p ctx is destroyed with @ref mongocrypt_ctx_destroy.
- * The meaning of this BSON depends on the type of @p ctx.
- *
- * If @p ctx was initialized with @ref mongocrypt_ctx_encrypt_init, then
- * this BSON is the (possibly) encrypted command to send to the server.
- *
- * If @p ctx was initialized with @ref mongocrypt_ctx_decrypt_init, then
- * this BSON is the decrypted result to return to the user.
- *
- * If @p ctx was initialized with @ref mongocrypt_ctx_explicit_encrypt_init,
- * then this BSON has the form { "v": (BSON binary) } where the BSON binary
- * is the resulting encrypted value.
- *
- * If @p ctx was initialized with @ref mongocrypt_ctx_explicit_decrypt_init,
- * then this BSON has the form { "v": (BSON value) } where the BSON value
- * is the resulting decrypted value.
- *
- * If @p ctx was initialized with @ref mongocrypt_ctx_datakey_init, then
- * this BSON is the document containing the new data key to be inserted into
- * the key vault collection.
- *
- * @returns a bool indicating success. If false, an error status is set.
- * Retrieve it with @ref mongocrypt_ctx_status
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_ctx_finalize (mongocrypt_ctx_t *ctx, mongocrypt_binary_t *out);
-
-
-/**
- * Destroy and free all memory associated with a @ref mongocrypt_ctx_t.
- *
- * @param[in] ctx A @ref mongocrypt_ctx_t.
- */
-MONGOCRYPT_EXPORT
-void
-mongocrypt_ctx_destroy (mongocrypt_ctx_t *ctx);
-
-/**
- * An crypto AES-256-CBC encrypt or decrypt function.
- *
- * Note, @p in is already padded. Encrypt with padding disabled.
- * @param[in] ctx An optional context object that may have been set when hooks
- * were enabled.
- * @param[in] key An encryption key (32 bytes for AES_256).
- * @param[in] iv An initialization vector (16 bytes for AES_256);
- * @param[in] in The input.
- * @param[out] out A preallocated byte array for the output. See @ref
- * mongocrypt_binary_data.
- * @param[out] bytes_written Set this to the number of bytes written to @p out.
- * @param[out] status An optional status to pass error messages. See @ref
- * mongocrypt_status_set.
- * @returns A boolean indicating success. If returning false, set @p status
- * with a message indiciating the error using @ref mongocrypt_status_set.
- */
-typedef bool (*mongocrypt_crypto_fn) (void *ctx,
- mongocrypt_binary_t *key,
- mongocrypt_binary_t *iv,
- mongocrypt_binary_t *in,
- mongocrypt_binary_t *out,
- uint32_t *bytes_written,
- mongocrypt_status_t *status);
-
-/**
- * A crypto signature or HMAC function.
- *
- * Currently used in callbacks for HMAC SHA-512, HMAC SHA-256, and RSA SHA-256
- * signature.
- *
- * @param[in] ctx An optional context object that may have been set when hooks
- * were enabled.
- * @param[in] key An encryption key (32 bytes for HMAC_SHA512).
- * @param[in] in The input.
- * @param[out] out A preallocated byte array for the output. See @ref
- * mongocrypt_binary_data.
- * @param[out] status An optional status to pass error messages. See @ref
- * mongocrypt_status_set.
- * @returns A boolean indicating success. If returning false, set @p status
- * with a message indiciating the error using @ref mongocrypt_status_set.
- */
-typedef bool (*mongocrypt_hmac_fn) (void *ctx,
- mongocrypt_binary_t *key,
- mongocrypt_binary_t *in,
- mongocrypt_binary_t *out,
- mongocrypt_status_t *status);
-
-
-/**
- * A crypto hash (SHA-256) function.
- *
- * @param[in] ctx An optional context object that may have been set when hooks
- * were enabled.
- * @param[in] in The input.
- * @param[out] out A preallocated byte array for the output. See @ref
- * mongocrypt_binary_data.
- * @param[out] status An optional status to pass error messages. See @ref
- * mongocrypt_status_set.
- * @returns A boolean indicating success. If returning false, set @p status
- * with a message indiciating the error using @ref mongocrypt_status_set.
- */
-typedef bool (*mongocrypt_hash_fn) (void *ctx,
- mongocrypt_binary_t *in,
- mongocrypt_binary_t *out,
- mongocrypt_status_t *status);
-
-/**
- * A crypto secure random function.
- *
- * @param[in] ctx An optional context object that may have been set when hooks
- * were enabled.
- * @param[out] out A preallocated byte array for the output. See @ref
- * mongocrypt_binary_data.
- * @param[in] count The number of random bytes requested.
- * @param[out] status An optional status to pass error messages. See @ref
- * mongocrypt_status_set.
- * @returns A boolean indicating success. If returning false, set @p status
- * with a message indiciating the error using @ref mongocrypt_status_set.
- */
-typedef bool (*mongocrypt_random_fn) (void *ctx,
- mongocrypt_binary_t *out,
- uint32_t count,
- mongocrypt_status_t *status);
-
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_setopt_crypto_hooks (mongocrypt_t *crypt,
- mongocrypt_crypto_fn aes_256_cbc_encrypt,
- mongocrypt_crypto_fn aes_256_cbc_decrypt,
- mongocrypt_random_fn random,
- mongocrypt_hmac_fn hmac_sha_512,
- mongocrypt_hmac_fn hmac_sha_256,
- mongocrypt_hash_fn sha_256,
- void *ctx);
-
-/**
- * Set a crypto hook for the RSASSA-PKCS1-v1_5 algorithm with a SHA-256 hash.
- *
- * See: https://tools.ietf.org/html/rfc3447#section-8.2
- *
- * Note: this function has the wrong name. It should be:
- * mongocrypt_setopt_crypto_hook_sign_rsassa_pkcs1_v1_5
- *
- * @param[in] crypt The @ref mongocrypt_t object.
- * @param[in] sign_rsaes_pkcs1_v1_5 The crypto callback function.
- * @param[in] sign_ctx A context passed as an argument to the crypto callback every
- * invocation.
- * @pre @ref mongocrypt_init has not been called on @p crypt.
- * @returns A boolean indicating success. If false, an error status is set.
- * Retrieve it with @ref mongocrypt_status
- *
- */
-MONGOCRYPT_EXPORT
-bool
-mongocrypt_setopt_crypto_hook_sign_rsaes_pkcs1_v1_5 (
- mongocrypt_t *crypt,
- mongocrypt_hmac_fn sign_rsaes_pkcs1_v1_5,
- void *sign_ctx);
-
-#endif /* MONGOCRYPT_H */
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/os_posix/os_once.c b/mongodb-1.12.0/src/libmongocrypt/src/os_posix/os_once.c
deleted file mode 100644
index c6ec8e43..00000000
--- a/mongodb-1.12.0/src/libmongocrypt/src/os_posix/os_once.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2019-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-#include "../mongocrypt-os-private.h"
-
-#ifndef _WIN32
-
-#include <pthread.h>
-
-static pthread_once_t once_control = PTHREAD_ONCE_INIT;
-
-int
-_mongocrypt_once (void (*init_routine) (void))
-{
- return (pthread_once (&once_control, init_routine));
-}
-
-#endif /* _WIN32 */
\ No newline at end of file
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/os_win/os_once.c b/mongodb-1.12.0/src/libmongocrypt/src/os_win/os_once.c
deleted file mode 100644
index 83d13afc..00000000
--- a/mongodb-1.12.0/src/libmongocrypt/src/os_win/os_once.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2019-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <bson/bson.h>
-
-#include "../mongocrypt-os-private.h"
-
-#ifdef _WIN32
-
-static INIT_ONCE once_control = INIT_ONCE_STATIC_INIT;
-
-static BOOL WINAPI
-_mongocrypt_init_once_callback (_Inout_ PINIT_ONCE InitOnce,
- _Inout_opt_ PVOID Parameter,
- _Out_opt_ PVOID *Context)
-{
- void (*init_routine) (void) = Parameter;
-
- init_routine ();
-
- return (TRUE);
-}
-
-int
-_mongocrypt_once (void (*init_routine) (void))
-{
- PVOID lpContext = NULL;
-
- return !InitOnceExecuteOnce (
- &once_control, &_mongocrypt_init_once_callback, init_routine, lpContext);
-}
-
-#endif /* _WIN32 */
\ No newline at end of file
diff --git a/mongodb-1.12.0/src/phongo_apm.c b/mongodb-1.12.0/src/phongo_apm.c
deleted file mode 100644
index aa728213..00000000
--- a/mongodb-1.12.0/src/phongo_apm.c
+++ /dev/null
@@ -1,368 +0,0 @@
-/*
- * Copyright 2021-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "bson/bson.h"
-#include "mongoc/mongoc.h"
-
-#include <php.h>
-#include <Zend/zend_exceptions.h>
-#include <Zend/zend_interfaces.h>
-#include <Zend/zend_operators.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-#include "phongo_apm.h"
-
-#undef MONGOC_LOG_DOMAIN
-#define MONGOC_LOG_DOMAIN "PHONGO"
-
-ZEND_EXTERN_MODULE_GLOBALS(mongodb)
-
-/* Ensures that instances of @subscriber_ce in @from (those registered with a
- * Manager or globally) are added to the set @to. This is used to build the list
- * of subscribers notify for an event. */
-static void phongo_apm_add_subscribers_to_notify(zend_class_entry* subscriber_ce, HashTable* from, HashTable* to)
-{
- zval* subscriber;
-
- ZEND_HASH_FOREACH_VAL_IND(from, subscriber)
- {
- if (Z_TYPE_P(subscriber) != IS_OBJECT || !instanceof_function(Z_OBJCE_P(subscriber), subscriber_ce)) {
- continue;
- }
-
- if (zend_hash_index_exists(to, Z_OBJ_HANDLE_P(subscriber))) {
- continue;
- }
-
- zend_hash_index_update(to, Z_OBJ_HANDLE_P(subscriber), subscriber);
- Z_ADDREF_P(subscriber);
- }
- ZEND_HASH_FOREACH_END();
-}
-
-/* Returns a newly allocated HashTable, which will contain all subscribers of a
- * certain type that should be notified for an event on the specified client. */
-static HashTable* phongo_apm_get_subscribers_to_notify(zend_class_entry* subscriber_ce, mongoc_client_t* client)
-{
- HashTable* subscribers = NULL;
-
- ALLOC_HASHTABLE(subscribers);
- zend_hash_init(subscribers, 0, NULL, ZVAL_PTR_DTOR, 0);
-
- if (MONGODB_G(subscribers)) {
- phongo_apm_add_subscribers_to_notify(subscriber_ce, MONGODB_G(subscribers), subscribers);
- }
-
- if (MONGODB_G(managers)) {
- php_phongo_manager_t* manager;
-
- ZEND_HASH_FOREACH_PTR(MONGODB_G(managers), manager)
- {
- if (manager->client == client && manager->subscribers) {
- phongo_apm_add_subscribers_to_notify(subscriber_ce, manager->subscribers, subscribers);
- }
- }
- ZEND_HASH_FOREACH_END();
- }
-
- return subscribers;
-}
-
-/* Search for a Manager associated with the given client in the request-scoped
- * registry. If any Manager is found, copy it to @out, increment its ref-count,
- * and return true; otherwise, set @out to undefined and return false. */
-static bool phongo_apm_copy_manager_for_client(mongoc_client_t* client, zval* out)
-{
- php_phongo_manager_t* manager;
-
- ZVAL_UNDEF(out);
-
- if (!MONGODB_G(managers) || zend_hash_num_elements(MONGODB_G(managers)) == 0) {
- return false;
- }
-
- ZEND_HASH_FOREACH_PTR(MONGODB_G(managers), manager)
- {
- if (manager->client == client) {
- ZVAL_OBJ(out, &manager->std);
- Z_ADDREF_P(out);
-
- return true;
- }
- }
- ZEND_HASH_FOREACH_END();
-
- return false;
-}
-
-/* Dispatch an event to all subscribers in a HashTable. The caller is
- * responsible for ensuring that subscribers implement the correct interface. */
-static void phongo_apm_dispatch_event(HashTable* subscribers, const char* function_name, zval* event)
-{
- zval* subscriber;
-
- ZEND_HASH_FOREACH_VAL_IND(subscribers, subscriber)
- {
- if (EG(exception)) {
- break;
- }
-
- /* We can't use the zend_call_method_with_1_params macro here, as it
- * assumes the function name is a string literal. */
- zend_call_method(PHONGO_COMPAT_OBJ_P(subscriber), NULL, NULL, function_name, strlen(function_name), NULL, 1, event, NULL);
- }
- ZEND_HASH_FOREACH_END();
-}
-
-static void phongo_apm_command_started(const mongoc_apm_command_started_t* event)
-{
- mongoc_client_t* client;
- HashTable* subscribers;
- php_phongo_commandstartedevent_t* p_event;
- zval z_event;
-
- client = mongoc_apm_command_started_get_context(event);
- subscribers = phongo_apm_get_subscribers_to_notify(php_phongo_commandsubscriber_ce, client);
-
- /* Return early if there are no APM subscribers to notify */
- if (zend_hash_num_elements(subscribers) == 0) {
- goto cleanup;
- }
-
- object_init_ex(&z_event, php_phongo_commandstartedevent_ce);
- p_event = Z_COMMANDSTARTEDEVENT_OBJ_P(&z_event);
-
- p_event->command_name = estrdup(mongoc_apm_command_started_get_command_name(event));
- p_event->server_id = mongoc_apm_command_started_get_server_id(event);
- p_event->operation_id = mongoc_apm_command_started_get_operation_id(event);
- p_event->request_id = mongoc_apm_command_started_get_request_id(event);
- p_event->command = bson_copy(mongoc_apm_command_started_get_command(event));
- p_event->database_name = estrdup(mongoc_apm_command_started_get_database_name(event));
- p_event->has_service_id = mongoc_apm_command_started_get_service_id(event) != NULL;
-
- if (p_event->has_service_id) {
- bson_oid_copy(mongoc_apm_command_started_get_service_id(event), &p_event->service_id);
- }
-
- if (!phongo_apm_copy_manager_for_client(client, &p_event->manager)) {
- phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "Found no Manager for client in APM event context");
- zval_ptr_dtor(&z_event);
-
- goto cleanup;
- }
-
- phongo_apm_dispatch_event(subscribers, "commandStarted", &z_event);
- zval_ptr_dtor(&z_event);
-
-cleanup:
- zend_hash_destroy(subscribers);
- FREE_HASHTABLE(subscribers);
-}
-
-static void phongo_apm_command_succeeded(const mongoc_apm_command_succeeded_t* event)
-{
- mongoc_client_t* client;
- HashTable* subscribers;
- php_phongo_commandsucceededevent_t* p_event;
- zval z_event;
-
- client = mongoc_apm_command_succeeded_get_context(event);
- subscribers = phongo_apm_get_subscribers_to_notify(php_phongo_commandsubscriber_ce, client);
-
- /* Return early if there are no APM subscribers to notify */
- if (zend_hash_num_elements(subscribers) == 0) {
- goto cleanup;
- }
-
- object_init_ex(&z_event, php_phongo_commandsucceededevent_ce);
- p_event = Z_COMMANDSUCCEEDEDEVENT_OBJ_P(&z_event);
-
- p_event->command_name = estrdup(mongoc_apm_command_succeeded_get_command_name(event));
- p_event->server_id = mongoc_apm_command_succeeded_get_server_id(event);
- p_event->operation_id = mongoc_apm_command_succeeded_get_operation_id(event);
- p_event->request_id = mongoc_apm_command_succeeded_get_request_id(event);
- p_event->duration_micros = mongoc_apm_command_succeeded_get_duration(event);
- p_event->reply = bson_copy(mongoc_apm_command_succeeded_get_reply(event));
- p_event->has_service_id = mongoc_apm_command_succeeded_get_service_id(event) != NULL;
-
- if (p_event->has_service_id) {
- bson_oid_copy(mongoc_apm_command_succeeded_get_service_id(event), &p_event->service_id);
- }
-
- if (!phongo_apm_copy_manager_for_client(client, &p_event->manager)) {
- phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "Found no Manager for client in APM event context");
- zval_ptr_dtor(&z_event);
-
- goto cleanup;
- }
-
- phongo_apm_dispatch_event(subscribers, "commandSucceeded", &z_event);
- zval_ptr_dtor(&z_event);
-
-cleanup:
- zend_hash_destroy(subscribers);
- FREE_HASHTABLE(subscribers);
-}
-
-static void phongo_apm_command_failed(const mongoc_apm_command_failed_t* event)
-{
- mongoc_client_t* client;
- HashTable* subscribers;
- php_phongo_commandfailedevent_t* p_event;
- zval z_event;
- bson_error_t tmp_error = { 0 };
-
- client = mongoc_apm_command_failed_get_context(event);
- subscribers = phongo_apm_get_subscribers_to_notify(php_phongo_commandsubscriber_ce, client);
-
- /* Return early if there are no APM subscribers to notify */
- if (zend_hash_num_elements(subscribers) == 0) {
- goto cleanup;
- }
-
- object_init_ex(&z_event, php_phongo_commandfailedevent_ce);
- p_event = Z_COMMANDFAILEDEVENT_OBJ_P(&z_event);
-
- p_event->command_name = estrdup(mongoc_apm_command_failed_get_command_name(event));
- p_event->server_id = mongoc_apm_command_failed_get_server_id(event);
- p_event->operation_id = mongoc_apm_command_failed_get_operation_id(event);
- p_event->request_id = mongoc_apm_command_failed_get_request_id(event);
- p_event->duration_micros = mongoc_apm_command_failed_get_duration(event);
- p_event->reply = bson_copy(mongoc_apm_command_failed_get_reply(event));
- p_event->has_service_id = mongoc_apm_command_failed_get_service_id(event) != NULL;
-
- if (p_event->has_service_id) {
- bson_oid_copy(mongoc_apm_command_failed_get_service_id(event), &p_event->service_id);
- }
-
- if (!phongo_apm_copy_manager_for_client(client, &p_event->manager)) {
- phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "Found no Manager for client in APM event context");
- zval_ptr_dtor(&z_event);
-
- goto cleanup;
- }
-
- /* We need to process and convert the error right here, otherwise
- * debug_info will turn into a recursive loop, and with the wrong trace
- * locations */
- mongoc_apm_command_failed_get_error(event, &tmp_error);
-
- object_init_ex(&p_event->z_error, phongo_exception_from_mongoc_domain(tmp_error.domain, tmp_error.code));
- zend_update_property_string(zend_ce_exception, PHONGO_COMPAT_OBJ_P(&p_event->z_error), ZEND_STRL("message"), tmp_error.message);
- zend_update_property_long(zend_ce_exception, PHONGO_COMPAT_OBJ_P(&p_event->z_error), ZEND_STRL("code"), tmp_error.code);
-
- phongo_apm_dispatch_event(subscribers, "commandFailed", &z_event);
- zval_ptr_dtor(&z_event);
-
-cleanup:
- zend_hash_destroy(subscribers);
- FREE_HASHTABLE(subscribers);
-}
-
-/* Assigns APM callbacks to a client, which will notify any global or per-client
- * subscribers. This should be called for all clients created by the driver.
- * Returns true on success; otherwise, throws an exception and returns false. */
-bool phongo_apm_set_callbacks(mongoc_client_t* client)
-{
- bool retval;
-
- mongoc_apm_callbacks_t* callbacks = mongoc_apm_callbacks_new();
-
- mongoc_apm_set_command_started_cb(callbacks, phongo_apm_command_started);
- mongoc_apm_set_command_succeeded_cb(callbacks, phongo_apm_command_succeeded);
- mongoc_apm_set_command_failed_cb(callbacks, phongo_apm_command_failed);
-
- retval = mongoc_client_set_apm_callbacks(client, callbacks, client);
-
- if (!retval) {
- phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "Failed to set APM callbacks");
- }
-
- mongoc_apm_callbacks_destroy(callbacks);
-
- return retval;
-}
-
-/* Checks args for adding/removing a subscriber. Returns true on success;
- * otherwise, throws an exception and returns false. */
-static bool phongo_apm_check_args_for_add_and_remove(HashTable* subscribers, zval* subscriber)
-{
- if (!subscribers) {
- phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "Subscriber HashTable is not initialized");
- return false;
- }
-
- if (!subscriber || Z_TYPE_P(subscriber) != IS_OBJECT || !instanceof_function(Z_OBJCE_P(subscriber), php_phongo_subscriber_ce)) {
- phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "Subscriber is not an instance of %s", ZSTR_VAL(php_phongo_subscriber_ce->name));
- return false;
- }
-
- return true;
-}
-
-/* Adds a subscriber to the HashTable (global or Manager). Returns true on
- * success (including NOP if already registered); otherwise, throws an exception
- * and returns false. */
-bool phongo_apm_add_subscriber(HashTable* subscribers, zval* subscriber)
-{
- if (!phongo_apm_check_args_for_add_and_remove(subscribers, subscriber)) {
- /* Exception should already have been thrown */
- return false;
- }
-
- /* NOP if the subscriber was already registered */
- if (zend_hash_index_exists(subscribers, Z_OBJ_HANDLE_P(subscriber))) {
- return true;
- }
-
- zend_hash_index_update(subscribers, Z_OBJ_HANDLE_P(subscriber), subscriber);
- Z_ADDREF_P(subscriber);
-
- return true;
-}
-
-/* Removes a subscriber from the HashTable (global or Manager). Returns true on
- * success (including NOP if never registered); otherwise, throws an exception
- * and returns false. */
-bool phongo_apm_remove_subscriber(HashTable* subscribers, zval* subscriber)
-{
- if (!phongo_apm_check_args_for_add_and_remove(subscribers, subscriber)) {
- /* Exception should already have been thrown */
- return false;
- }
-
- /* Note: HashTables should specify ZVAL_PTR_DTOR as their element destructor
- * so there is no need to decrement the subscriber's reference count here.
- * We also don't care about whether zend_hash_index_del returns SUCCESS or
- * FAILURE, as removing an unregistered subscriber is a NOP. */
- zend_hash_index_del(subscribers, Z_OBJ_HANDLE_P(subscriber));
-
- return true;
-}
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/phongo_apm.h b/mongodb-1.12.0/src/phongo_apm.h
deleted file mode 100644
index 43562aaf..00000000
--- a/mongodb-1.12.0/src/phongo_apm.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2021-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef PHONGO_APM_H
-#define PHONGO_APM_H
-
-#include "mongoc/mongoc.h"
-
-#include <php.h>
-
-bool phongo_apm_set_callbacks(mongoc_client_t* client);
-bool phongo_apm_add_subscriber(HashTable* subscribers, zval* subscriber);
-bool phongo_apm_remove_subscriber(HashTable* subscribers, zval* subscriber);
-
-#endif /* PHONGO_APM_H */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/phongo_ini.c b/mongodb-1.12.0/src/phongo_ini.c
deleted file mode 100644
index a1886cd9..00000000
--- a/mongodb-1.12.0/src/phongo_ini.c
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright 2021-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "mongoc/mongoc.h"
-
-#include <php.h>
-#include <main/php_open_temporary_file.h>
-#include <ext/date/php_date.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "phongo_compat.h"
-#include "php_phongo.h"
-#include "phongo_ini.h"
-
-#undef MONGOC_LOG_DOMAIN
-#define MONGOC_LOG_DOMAIN "PHONGO"
-
-extern bool mongoc_global_mock_service_id;
-
-ZEND_EXTERN_MODULE_GLOBALS(mongodb)
-
-static void phongo_log(mongoc_log_level_t log_level, const char* log_domain, const char* message, void* user_data)
-{
- struct timeval tv;
- time_t t;
- zend_long tu;
- zend_string* dt;
-
- bson_gettimeofday(&tv);
- t = tv.tv_sec;
- tu = tv.tv_usec;
-
- dt = php_format_date((char*) ZEND_STRL("Y-m-d\\TH:i:s"), t, 0);
-
- fprintf(MONGODB_G(debug_fd), "[%s.%06" PHONGO_LONG_FORMAT "+00:00] %10s: %-8s> %s\n", ZSTR_VAL(dt), tu, log_domain, mongoc_log_level_str(log_level), message);
- fflush(MONGODB_G(debug_fd));
- efree(dt);
-}
-
-void phongo_log_disable(FILE* stream)
-{
- mongoc_log_trace_disable();
- mongoc_log_set_handler(NULL, NULL);
-
- /* Close any previously opened log file (excluding stderr/stdout) */
- if (stream && stream != stderr && stream != stdout) {
- fclose(stream);
- }
-}
-
-static PHP_INI_MH(OnUpdateDebug)
-{
- char* tmp_dir = NULL;
-
- phongo_log_disable(MONGODB_G(debug_fd));
- MONGODB_G(debug_fd) = NULL;
-
- if (!new_value || (new_value && !ZSTR_VAL(new_value)[0]) || strcasecmp("0", ZSTR_VAL(new_value)) == 0 || strcasecmp("off", ZSTR_VAL(new_value)) == 0 || strcasecmp("no", ZSTR_VAL(new_value)) == 0 || strcasecmp("false", ZSTR_VAL(new_value)) == 0) {
- return OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
- }
-
- if (strcasecmp(ZSTR_VAL(new_value), "stderr") == 0) {
- MONGODB_G(debug_fd) = stderr;
- } else if (strcasecmp(ZSTR_VAL(new_value), "stdout") == 0) {
- MONGODB_G(debug_fd) = stdout;
- } else if (
- strcasecmp("1", ZSTR_VAL(new_value)) == 0 ||
- strcasecmp("on", ZSTR_VAL(new_value)) == 0 ||
- strcasecmp("yes", ZSTR_VAL(new_value)) == 0 ||
- strcasecmp("true", ZSTR_VAL(new_value)) == 0) {
-
- tmp_dir = NULL;
- } else {
- tmp_dir = ZSTR_VAL(new_value);
- }
-
- if (!MONGODB_G(debug_fd)) {
- time_t t;
- int fd = -1;
- char* prefix;
- int len;
- zend_string* filename;
-
- time(&t);
- len = spprintf(&prefix, 0, "PHONGO-%ld", t);
-
- fd = php_open_temporary_fd(tmp_dir, prefix, &filename);
- if (fd != -1) {
- const char* path = ZSTR_VAL(filename);
- MONGODB_G(debug_fd) = VCWD_FOPEN(path, "a");
- }
- efree(filename);
- efree(prefix);
- close(fd);
- }
-
- mongoc_log_trace_enable();
- mongoc_log_set_handler(phongo_log, NULL);
-
- return OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
-}
-
-static PHP_INI_MH(OnUpdateMockServiceId)
-{
- mongoc_global_mock_service_id = zend_ini_parse_bool(new_value);
-
- return SUCCESS;
-}
-
-static PHP_INI_DISP(DisplayMockServiceId)
-{
- if (mongoc_global_mock_service_id) {
- ZEND_PUTS("On");
- } else {
- ZEND_PUTS("Off");
- }
-}
-
-void phongo_display_ini_entries(ZEND_MODULE_INFO_FUNC_ARGS)
-{
- DISPLAY_INI_ENTRIES();
-}
-
-void phongo_register_ini_entries(INIT_FUNC_ARGS)
-{
- PHP_INI_BEGIN()
- STD_PHP_INI_ENTRY("mongodb.debug", "", PHP_INI_ALL, OnUpdateDebug, debug, zend_mongodb_globals, mongodb_globals)
- PHP_INI_ENTRY_EX("mongodb.mock_service_id", "0", PHP_INI_ALL, OnUpdateMockServiceId, DisplayMockServiceId)
- PHP_INI_END()
-
- REGISTER_INI_ENTRIES();
-}
-
-void phongo_unregister_ini_entries(SHUTDOWN_FUNC_ARGS)
-{
- UNREGISTER_INI_ENTRIES();
-}
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/src/phongo_ini.h b/mongodb-1.12.0/src/phongo_ini.h
deleted file mode 100644
index 92f42e92..00000000
--- a/mongodb-1.12.0/src/phongo_ini.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2021-present MongoDB, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef PHONGO_INI_H
-#define PHONGO_INI_H
-
-#include <php.h>
-#include <stdio.h>
-
-void phongo_log_disable(FILE* stream);
-void phongo_display_ini_entries(ZEND_MODULE_INFO_FUNC_ARGS);
-void phongo_register_ini_entries(INIT_FUNC_ARGS);
-void phongo_unregister_ini_entries(SHUTDOWN_FUNC_ARGS);
-
-#endif /* PHONGO_INI_H */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/mongodb-1.12.0/tests/apm/commandFailedEvent-getReply-001.phpt b/mongodb-1.12.0/tests/apm/commandFailedEvent-getReply-001.phpt
deleted file mode 100644
index 6bbc874f..00000000
--- a/mongodb-1.12.0/tests/apm/commandFailedEvent-getReply-001.phpt
+++ /dev/null
@@ -1,60 +0,0 @@
---TEST--
-MongoDB\Driver\Monitoring\CommandFailedEvent::getReply()
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_server_version('<', '3.4'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-
-class MySubscriber implements MongoDB\Driver\Monitoring\CommandSubscriber
-{
- public function commandStarted( \MongoDB\Driver\Monitoring\CommandStartedEvent $event )
- {
- echo "started: ", $event->getCommandName(), "\n";
- }
-
- public function commandSucceeded( \MongoDB\Driver\Monitoring\CommandSucceededEvent $event )
- {
- var_dump($event);
- }
-
- public function commandFailed( \MongoDB\Driver\Monitoring\CommandFailedEvent $event )
- {
- echo "failed: ", $event->getCommandName(), "\n";
- var_dump($event->getReply());
- }
-}
-
-$subscriber = new MySubscriber;
-
-MongoDB\Driver\Monitoring\addSubscriber( $subscriber );
-
-$command = new MongoDB\Driver\Command([
- 'findAndModify' => COLLECTION_NAME,
- 'query' => ['_id' => 'foo'],
- 'upsert' => true,
- 'new' => true,
-]);
-
-try {
- $manager->executeWriteCommand(DATABASE_NAME, $command);
-} catch (MongoDB\Driver\Exception\CommandException $e) {}
-
-?>
---EXPECTF--
-started: findAndModify
-failed: findAndModify
-object(stdClass)#%d (%d) {%A
- ["ok"]=>
- float(0)
- ["errmsg"]=>
- string(49) "Either an update or remove=true must be specified"
- ["code"]=>
- int(9)
- ["codeName"]=>
- string(13) "FailedToParse"%A
-}
diff --git a/mongodb-1.12.0/tests/bulk/bulkwrite-debug-002.phpt b/mongodb-1.12.0/tests/bulk/bulkwrite-debug-002.phpt
deleted file mode 100644
index 26c230d4..00000000
--- a/mongodb-1.12.0/tests/bulk/bulkwrite-debug-002.phpt
+++ /dev/null
@@ -1,68 +0,0 @@
---TEST--
-MongoDB\Driver\BulkWrite debug output after execution
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_not_clean(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-
-$tests = [
- [],
- ['session' => $manager->startSession()],
-];
-
-foreach ($tests as $options) {
- $bulk = new MongoDB\Driver\BulkWrite();
- $bulk->insert(['foo' => 'bar']);
- $manager->executeBulkWrite(NS, $bulk, $options);
- var_dump($bulk);
-}
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-object(MongoDB\Driver\BulkWrite)#%d (%d) {
- ["database"]=>
- %s
- ["collection"]=>
- %s
- ["ordered"]=>
- bool(true)
- ["bypassDocumentValidation"]=>
- NULL
- ["executed"]=>
- bool(true)
- ["server_id"]=>
- int(%d)
- ["session"]=>
- NULL
- ["write_concern"]=>
- NULL
-}
-object(MongoDB\Driver\BulkWrite)#%d (%d) {
- ["database"]=>
- %s
- ["collection"]=>
- %s
- ["ordered"]=>
- bool(true)
- ["bypassDocumentValidation"]=>
- NULL
- ["executed"]=>
- bool(true)
- ["server_id"]=>
- int(%d)
- ["session"]=>
- object(MongoDB\Driver\Session)#%d (%d) {
- %a
- }
- ["write_concern"]=>
- NULL
-}
-===DONE===
diff --git a/mongodb-1.12.0/tests/bulk/bulkwrite-delete_error-004.phpt b/mongodb-1.12.0/tests/bulk/bulkwrite-delete_error-004.phpt
deleted file mode 100644
index 098df8d4..00000000
--- a/mongodb-1.12.0/tests/bulk/bulkwrite-delete_error-004.phpt
+++ /dev/null
@@ -1,30 +0,0 @@
---TEST--
-MongoDB\Driver\BulkWrite::delete() collation option requires MongoDB 3.4
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_server_version('>=', '3.4'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-
-$bulk = new MongoDB\Driver\BulkWrite();
-
-$bulk->delete(
- ['name' => 'foo'],
- ['collation' => ['locale' => 'en_US']]
-);
-
-echo throws(function() use ($manager, $bulk) {
- $manager->executeBulkWrite(DATABASE_NAME . '.' . COLLECTION_NAME, $bulk);
-}, 'MongoDB\Driver\Exception\BulkWriteException'), "\n";
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-OK: Got MongoDB\Driver\Exception\BulkWriteException
-Bulk write failed due to previous MongoDB\Driver\Exception\RuntimeException: The selected server does not support collation
-===DONE===
diff --git a/mongodb-1.12.0/tests/bulk/bulkwrite-delete_error-005.phpt b/mongodb-1.12.0/tests/bulk/bulkwrite-delete_error-005.phpt
deleted file mode 100644
index ef9c3c91..00000000
--- a/mongodb-1.12.0/tests/bulk/bulkwrite-delete_error-005.phpt
+++ /dev/null
@@ -1,27 +0,0 @@
---TEST--
-MongoDB\Driver\BulkWrite::delete() hint option requires MongoDB 4.4 (server-side error)
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_server_version('>=', '4.3.4'); ?>
-<?php skip_if_server_version('<=', '3.6.0'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-
-$bulk = new MongoDB\Driver\BulkWrite;
-$bulk->delete(['_id' => 1], ['hint' => '_id_']);
-
-echo throws(function() use ($manager, $bulk) {
- $manager->executeBulkWrite(NS, $bulk);
-}, 'MongoDB\Driver\Exception\BulkWriteException'), "\n";
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-OK: Got MongoDB\Driver\Exception\BulkWriteException
-BSON field 'delete.deletes.hint' is an unknown field.
-===DONE===
diff --git a/mongodb-1.12.0/tests/bulk/bulkwrite-update-002.phpt b/mongodb-1.12.0/tests/bulk/bulkwrite-update-002.phpt
deleted file mode 100644
index 3619d246..00000000
--- a/mongodb-1.12.0/tests/bulk/bulkwrite-update-002.phpt
+++ /dev/null
@@ -1,84 +0,0 @@
---TEST--
-MongoDB\Driver\BulkWrite::update() with arrayFilters option
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-
-$bulk = new MongoDB\Driver\BulkWrite();
-
-$bulk->insert([ '_id' => 1, 'grades' => [ 95, 92, 90 ] ]);
-$bulk->insert([ '_id' => 2, 'grades' => [ 98, 100, 102 ] ]);
-$bulk->insert([ '_id' => 3, 'grades' => [ 95, 110, 100 ] ]);
-
-$manager->executeBulkWrite(DATABASE_NAME . '.' . COLLECTION_NAME, $bulk);
-
-$updateBulk = new MongoDB\Driver\BulkWrite();
-
-$query = ['grades' => ['$gte' => 100]];
-$update = [ '$set' => [ 'grades.$[element]' => 100 ] ];
-$options = [
- 'arrayFilters' => [ [ 'element' => [ '$gte' => 100 ] ] ],
- 'multi' => true
-];
-
-$updateBulk->update($query, $update, $options);
-$manager->executeBulkWrite(DATABASE_NAME . '.' . COLLECTION_NAME, $updateBulk);
-
-$cursor = $manager->executeQuery( DATABASE_NAME . '.' . COLLECTION_NAME, new \MongoDB\Driver\Query([]));
-var_dump($cursor->toArray());
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-array(%d) {
- [0]=>
- object(stdClass)#%d (%d) {
- ["_id"]=>
- int(1)
- ["grades"]=>
- array(%d) {
- [0]=>
- int(95)
- [1]=>
- int(92)
- [2]=>
- int(90)
- }
- }
- [1]=>
- object(stdClass)#%d (%d) {
- ["_id"]=>
- int(2)
- ["grades"]=>
- array(%d) {
- [0]=>
- int(98)
- [1]=>
- int(100)
- [2]=>
- int(100)
- }
- }
- [2]=>
- object(stdClass)#%d (%d) {
- ["_id"]=>
- int(3)
- ["grades"]=>
- array(%d) {
- [0]=>
- int(95)
- [1]=>
- int(100)
- [2]=>
- int(100)
- }
- }
-}
-===DONE===
diff --git a/mongodb-1.12.0/tests/bulk/bulkwrite-update_error-006.phpt b/mongodb-1.12.0/tests/bulk/bulkwrite-update_error-006.phpt
deleted file mode 100644
index deb34b22..00000000
--- a/mongodb-1.12.0/tests/bulk/bulkwrite-update_error-006.phpt
+++ /dev/null
@@ -1,31 +0,0 @@
---TEST--
-MongoDB\Driver\BulkWrite::update() collation option requires MongoDB 3.4
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_server_version('>=', '3.4'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-
-$bulk = new MongoDB\Driver\BulkWrite();
-
-$bulk->update(
- ['name' => 'foo'],
- ['$inc' => ['size' => 1]],
- ['collation' => ['locale' => 'en_US']]
-);
-
-echo throws(function() use ($manager, $bulk) {
- $manager->executeBulkWrite(DATABASE_NAME . '.' . COLLECTION_NAME, $bulk);
-}, 'MongoDB\Driver\Exception\BulkWriteException'), "\n";
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-OK: Got MongoDB\Driver\Exception\BulkWriteException
-Bulk write failed due to previous MongoDB\Driver\Exception\RuntimeException: The selected server does not support collation
-===DONE===
diff --git a/mongodb-1.12.0/tests/bulk/bulkwrite-update_error-007.phpt b/mongodb-1.12.0/tests/bulk/bulkwrite-update_error-007.phpt
deleted file mode 100644
index ee76c6e4..00000000
--- a/mongodb-1.12.0/tests/bulk/bulkwrite-update_error-007.phpt
+++ /dev/null
@@ -1,34 +0,0 @@
---TEST--
-MongoDB\Driver\BulkWrite::update() arrayFilters option requires MongoDB 3.6
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_server_version('>=', '3.6'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-
-$bulk = new MongoDB\Driver\BulkWrite();
-
-$bulk->update(
- ['grades' => ['$gte' => 100]],
- ['$set' => ['grades.$[element]' => 100 ]],
- [
- 'arrayFilters' => [['element' => ['$gte' => 100]]],
- 'multi' => true,
- ]
-);
-
-echo throws(function() use ($manager, $bulk) {
- $manager->executeBulkWrite(DATABASE_NAME . '.' . COLLECTION_NAME, $bulk);
-}, 'MongoDB\Driver\Exception\BulkWriteException'), "\n";
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-OK: Got MongoDB\Driver\Exception\BulkWriteException
-Bulk write failed due to previous MongoDB\Driver\Exception\RuntimeException: The selected server does not support array filters
-===DONE===
diff --git a/mongodb-1.12.0/tests/bulk/bulkwrite-update_error-008.phpt b/mongodb-1.12.0/tests/bulk/bulkwrite-update_error-008.phpt
deleted file mode 100644
index a7284ab0..00000000
--- a/mongodb-1.12.0/tests/bulk/bulkwrite-update_error-008.phpt
+++ /dev/null
@@ -1,27 +0,0 @@
---TEST--
-MongoDB\Driver\BulkWrite::update() hint option requires MongoDB 4.2 (server-side error)
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_server_version('>=', '4.2'); ?>
-<?php skip_if_server_version('<=', '3.6.0'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-
-$bulk = new MongoDB\Driver\BulkWrite;
-$bulk->update(['_id' => 1], ['$set' => ['x' => 11]], ['hint' => '_id_']);
-
-echo throws(function() use ($manager, $bulk) {
- $manager->executeBulkWrite(NS, $bulk);
-}, 'MongoDB\Driver\Exception\BulkWriteException'), "\n";
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-OK: Got MongoDB\Driver\Exception\BulkWriteException
-BSON field 'update.updates.hint' is an unknown field.
-===DONE===
diff --git a/mongodb-1.12.0/tests/causal-consistency/causal-consistency-001.phpt b/mongodb-1.12.0/tests/causal-consistency/causal-consistency-001.phpt
deleted file mode 100644
index 7050300f..00000000
--- a/mongodb-1.12.0/tests/causal-consistency/causal-consistency-001.phpt
+++ /dev/null
@@ -1,24 +0,0 @@
---TEST--
-Causal consistency: new session has no operation time
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_not_replica_set_or_sharded_cluster_with_replica_set(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-$session = $manager->startSession();
-
-echo "Initial operation time:\n";
-var_dump($session->getOperationTime());
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-Initial operation time:
-NULL
-===DONE===
diff --git a/mongodb-1.12.0/tests/causal-consistency/causal-consistency-002.phpt b/mongodb-1.12.0/tests/causal-consistency/causal-consistency-002.phpt
deleted file mode 100644
index 05bbe3a0..00000000
--- a/mongodb-1.12.0/tests/causal-consistency/causal-consistency-002.phpt
+++ /dev/null
@@ -1,33 +0,0 @@
---TEST--
-Causal consistency: first read in session does not include afterClusterTime
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_not_replica_set_or_sharded_cluster_with_replica_set(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-require_once __DIR__ . "/../utils/observer.php";
-
-(new CommandObserver)->observe(
- function() {
- $manager = create_test_manager();
- $session = $manager->startSession();
-
- $query = new MongoDB\Driver\Query([]);
- $manager->executeQuery(NS, $query, ['session' => $session]);
- },
- function(stdClass $command)
- {
- $hasAfterClusterTime = isset($command->readConcern->afterClusterTime);
- printf("Read includes afterClusterTime: %s\n", ($hasAfterClusterTime ? 'yes' : 'no'));
- }
-);
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-Read includes afterClusterTime: no
-===DONE===
diff --git a/mongodb-1.12.0/tests/causal-consistency/causal-consistency-003.phpt b/mongodb-1.12.0/tests/causal-consistency/causal-consistency-003.phpt
deleted file mode 100644
index c480b682..00000000
--- a/mongodb-1.12.0/tests/causal-consistency/causal-consistency-003.phpt
+++ /dev/null
@@ -1,114 +0,0 @@
---TEST--
-Causal consistency: first read or write in session updates operationTime
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_not_replica_set_or_sharded_cluster_with_replica_set(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-class Test implements MongoDB\Driver\Monitoring\CommandSubscriber
-{
- private $lastSeenOperationTime;
-
- public function executeBulkWrite()
- {
- $this->lastSeenOperationTime = null;
-
- MongoDB\Driver\Monitoring\addSubscriber($this);
-
- $manager = create_test_manager();
- $session = $manager->startSession();
-
- $bulk = new MongoDB\Driver\BulkWrite;
- $bulk->insert(['x' => 1]);
- $manager->executeBulkWrite(NS, $bulk, ['session' => $session]);
-
- printf("Session reports last seen operationTime: %s\n", ($session->getOperationTime() == $this->lastSeenOperationTime) ? 'yes' : 'no');
-
- MongoDB\Driver\Monitoring\removeSubscriber($this);
- }
-
- public function executeCommand()
- {
- $this->lastSeenOperationTime = null;
-
- MongoDB\Driver\Monitoring\addSubscriber($this);
-
- $manager = create_test_manager();
- $session = $manager->startSession();
-
- $command = new MongoDB\Driver\Command(['ping' => 1]);
- $manager->executeCommand(DATABASE_NAME, $command, ['session' => $session]);
-
- printf("Session reports last seen operationTime: %s\n", ($session->getOperationTime() == $this->lastSeenOperationTime) ? 'yes' : 'no');
-
- MongoDB\Driver\Monitoring\removeSubscriber($this);
- }
-
- public function executeQuery()
- {
- $this->lastSeenOperationTime = null;
-
- MongoDB\Driver\Monitoring\addSubscriber($this);
-
- $manager = create_test_manager();
- $session = $manager->startSession();
-
- $query = new MongoDB\Driver\Query([]);
- $manager->executeQuery(NS, $query, ['session' => $session]);
-
- printf("Session reports last seen operationTime: %s\n", ($session->getOperationTime() == $this->lastSeenOperationTime) ? 'yes' : 'no');
-
- MongoDB\Driver\Monitoring\removeSubscriber($this);
- }
-
- public function commandStarted(MongoDB\Driver\Monitoring\CommandStartedEvent $event)
- {
- }
-
- public function commandSucceeded(MongoDB\Driver\Monitoring\CommandSucceededEvent $event)
- {
- $reply = $event->getReply();
- $hasOperationTime = isset($reply->{'operationTime'});
-
- printf("%s command reply includes operationTime: %s\n", $event->getCommandName(), $hasOperationTime ? 'yes' : 'no');
-
- if ($hasOperationTime) {
- $this->lastSeenOperationTime = $reply->operationTime;
- }
- }
-
- public function commandFailed(MongoDB\Driver\Monitoring\CommandFailedEvent $event)
- {
- }
-}
-
-echo "Testing executeBulkWrite()\n";
-(new Test)->executeBulkWrite();
-
-echo "\nTesting executeCommand()\n";
-(new Test)->executeCommand();
-
-echo "\nTesting executeQuery()\n";
-(new Test)->executeQuery();
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-Testing executeBulkWrite()
-insert command reply includes operationTime: yes
-Session reports last seen operationTime: yes
-
-Testing executeCommand()
-ping command reply includes operationTime: yes
-Session reports last seen operationTime: yes
-
-Testing executeQuery()
-find command reply includes operationTime: yes
-Session reports last seen operationTime: yes
-===DONE===
diff --git a/mongodb-1.12.0/tests/causal-consistency/causal-consistency-004.phpt b/mongodb-1.12.0/tests/causal-consistency/causal-consistency-004.phpt
deleted file mode 100644
index 8a5c06f8..00000000
--- a/mongodb-1.12.0/tests/causal-consistency/causal-consistency-004.phpt
+++ /dev/null
@@ -1,137 +0,0 @@
---TEST--
-Causal consistency: first read or write in session updates operationTime (even on error)
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_not_replica_set_or_sharded_cluster_with_replica_set(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-class Test implements MongoDB\Driver\Monitoring\CommandSubscriber
-{
- private $lastSeenOperationTime;
-
- public function executeBulkWrite()
- {
- $this->lastSeenOperationTime = null;
-
- MongoDB\Driver\Monitoring\addSubscriber($this);
-
- $manager = create_test_manager();
- $session = $manager->startSession();
-
- $bulk = new MongoDB\Driver\BulkWrite;
- $bulk->insert(['_id' => 1]);
- $bulk->insert(['_id' => 1]);
-
- throws(function() use ($manager, $bulk, $session) {
- $manager->executeBulkWrite(NS, $bulk, ['session' => $session]);
- }, 'MongoDB\Driver\Exception\BulkWriteException');
-
- printf("Session reports last seen operationTime: %s\n", ($session->getOperationTime() == $this->lastSeenOperationTime) ? 'yes' : 'no');
-
- MongoDB\Driver\Monitoring\removeSubscriber($this);
- }
-
- public function executeCommand()
- {
- $this->lastSeenOperationTime = null;
-
- MongoDB\Driver\Monitoring\addSubscriber($this);
-
- $manager = create_test_manager();
- $session = $manager->startSession();
-
- $command = new MongoDB\Driver\Command([
- 'aggregate' => COLLECTION_NAME,
- 'pipeline' => [
- ['$unsupportedOperator' => 1],
- ],
- 'cursor' => new stdClass,
- ]);
-
- throws(function() use ($manager, $command, $session) {
- $manager->executeCommand(DATABASE_NAME, $command, ['session' => $session]);
- }, 'MongoDB\Driver\Exception\RuntimeException');
-
- /* We cannot access the server reply if an exception is thrown for a
- * failed command (see: PHPC-1076). For the time being, just assert that
- * the operationTime is not null. */
- printf("Session has non-null operationTime: %s\n", ($session->getOperationTime() !== null ? 'yes' : 'no'));
-
- MongoDB\Driver\Monitoring\removeSubscriber($this);
- }
-
- public function executeQuery()
- {
- $this->lastSeenOperationTime = null;
-
- MongoDB\Driver\Monitoring\addSubscriber($this);
-
- $manager = create_test_manager();
- $session = $manager->startSession();
-
- $query = new MongoDB\Driver\Query(['$unsupportedOperator' => 1]);
-
- throws(function() use ($manager, $query, $session) {
- $manager->executeQuery(NS, $query, ['session' => $session]);
- }, 'MongoDB\Driver\Exception\RuntimeException');
-
- /* We cannot access the server reply if an exception is thrown for a
- * failed command (see: PHPC-1076). For the time being, just assert that
- * the operationTime is not null. */
- printf("Session has non-null operationTime: %s\n", ($session->getOperationTime() !== null ? 'yes' : 'no'));
-
- MongoDB\Driver\Monitoring\removeSubscriber($this);
- }
-
- public function commandStarted(MongoDB\Driver\Monitoring\CommandStartedEvent $event)
- {
- }
-
- public function commandSucceeded(MongoDB\Driver\Monitoring\CommandSucceededEvent $event)
- {
- $reply = $event->getReply();
- $hasOperationTime = isset($reply->operationTime);
-
- printf("%s command reply includes operationTime: %s\n", $event->getCommandName(), $hasOperationTime ? 'yes' : 'no');
-
- if ($hasOperationTime) {
- $this->lastSeenOperationTime = $reply->operationTime;
- }
- }
-
- public function commandFailed(MongoDB\Driver\Monitoring\CommandFailedEvent $event)
- {
- }
-}
-
-echo "Testing executeBulkWrite()\n";
-(new Test)->executeBulkWrite();
-
-echo "\nTesting executeCommand()\n";
-(new Test)->executeCommand();
-
-echo "\nTesting executeQuery()\n";
-(new Test)->executeQuery();
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-Testing executeBulkWrite()
-insert command reply includes operationTime: yes
-OK: Got MongoDB\Driver\Exception\BulkWriteException
-Session reports last seen operationTime: yes
-
-Testing executeCommand()
-OK: Got MongoDB\Driver\Exception\RuntimeException
-Session has non-null operationTime: yes
-
-Testing executeQuery()
-OK: Got MongoDB\Driver\Exception\RuntimeException
-Session has non-null operationTime: yes
-===DONE===
diff --git a/mongodb-1.12.0/tests/causal-consistency/causal-consistency-005.phpt b/mongodb-1.12.0/tests/causal-consistency/causal-consistency-005.phpt
deleted file mode 100644
index 6275e2eb..00000000
--- a/mongodb-1.12.0/tests/causal-consistency/causal-consistency-005.phpt
+++ /dev/null
@@ -1,103 +0,0 @@
---TEST--
-Causal consistency: second read's afterClusterTime uses last reply's operationTime
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_not_replica_set_or_sharded_cluster_with_replica_set(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-class Test implements MongoDB\Driver\Monitoring\CommandSubscriber
-{
- private $lastSeenOperationTime;
-
- public function executeReadAfterRead()
- {
- $this->lastSeenOperationTime = null;
-
- MongoDB\Driver\Monitoring\addSubscriber($this);
-
- $manager = create_test_manager();
- $session = $manager->startSession();
-
- $query = new MongoDB\Driver\Query([]);
- $manager->executeQuery(NS, $query, ['session' => $session]);
- $manager->executeQuery(NS, $query, ['session' => $session]);
-
- MongoDB\Driver\Monitoring\removeSubscriber($this);
- }
-
- public function executeReadAfterWrite()
- {
- $this->lastSeenOperationTime = null;
-
- MongoDB\Driver\Monitoring\addSubscriber($this);
-
- $manager = create_test_manager();
- $session = $manager->startSession();
-
- $bulk = new MongoDB\Driver\BulkWrite;
- $bulk->insert(['x' => 1]);
- $manager->executeBulkWrite(NS, $bulk, ['session' => $session]);
-
- $query = new MongoDB\Driver\Query([]);
- $manager->executeQuery(NS, $query, ['session' => $session]);
-
- MongoDB\Driver\Monitoring\removeSubscriber($this);
- }
-
- public function commandStarted(MongoDB\Driver\Monitoring\CommandStartedEvent $event)
- {
- $command = $event->getCommand();
- $hasAfterClusterTime = isset($command->readConcern->afterClusterTime);
- printf("%s command includes afterClusterTime: %s\n", $event->getCommandName(), ($hasAfterClusterTime ? 'yes' : 'no'));
-
- if ($hasAfterClusterTime && $this->lastSeenOperationTime !== null) {
- printf("%s command uses last seen operationTime: %s\n", $event->getCommandName(), ($command->readConcern->afterClusterTime == $this->lastSeenOperationTime) ? 'yes' : 'no');
- }
- }
-
- public function commandSucceeded(MongoDB\Driver\Monitoring\CommandSucceededEvent $event)
- {
- $reply = $event->getReply();
- $hasOperationTime = isset($reply->operationTime);
-
- printf("%s command reply includes operationTime: %s\n", $event->getCommandName(), $hasOperationTime ? 'yes' : 'no');
-
- if ($hasOperationTime) {
- $this->lastSeenOperationTime = $reply->operationTime;
- }
- }
-
- public function commandFailed(MongoDB\Driver\Monitoring\CommandFailedEvent $event)
- {
- }
-}
-
-echo "Testing read after read\n";
-(new Test)->executeReadAfterRead();
-
-echo "\nTesting read after write\n";
-(new Test)->executeReadAfterWrite();
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-Testing read after read
-find command includes afterClusterTime: no
-find command reply includes operationTime: yes
-find command includes afterClusterTime: yes
-find command uses last seen operationTime: yes
-find command reply includes operationTime: yes
-
-Testing read after write
-insert command includes afterClusterTime: no
-insert command reply includes operationTime: yes
-find command includes afterClusterTime: yes
-find command uses last seen operationTime: yes
-find command reply includes operationTime: yes
-===DONE===
diff --git a/mongodb-1.12.0/tests/causal-consistency/causal-consistency-006.phpt b/mongodb-1.12.0/tests/causal-consistency/causal-consistency-006.phpt
deleted file mode 100644
index 763f307c..00000000
--- a/mongodb-1.12.0/tests/causal-consistency/causal-consistency-006.phpt
+++ /dev/null
@@ -1,118 +0,0 @@
---TEST--
-Causal consistency: second read's afterClusterTime uses last reply's operationTime (even on error)
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_not_replica_set_or_sharded_cluster_with_replica_set(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-class Test implements MongoDB\Driver\Monitoring\CommandSubscriber
-{
- private $lastSeenOperationTime;
-
- public function executeReadAfterReadError()
- {
- $this->lastSeenOperationTime = null;
-
- MongoDB\Driver\Monitoring\addSubscriber($this);
-
- $manager = create_test_manager();
- $session = $manager->startSession();
-
- $query = new MongoDB\Driver\Query(['$unsupportedOperator' => 1]);
-
- throws(function() use ($manager, $query, $session) {
- $manager->executeQuery(NS, $query, ['session' => $session]);
- }, 'MongoDB\Driver\Exception\RuntimeException');
-
- /* We cannot access the server reply if an exception is thrown for a
- * failed command (see: PHPC-1076). For the time being, just assert that
- * the operationTime is not null. */
- printf("Session has non-null operationTime: %s\n", ($session->getOperationTime() !== null ? 'yes' : 'no'));
-
- $query = new MongoDB\Driver\Query([]);
- $manager->executeQuery(NS, $query, ['session' => $session]);
-
- MongoDB\Driver\Monitoring\removeSubscriber($this);
- }
-
- public function executeReadAfterWriteError()
- {
- $this->lastSeenOperationTime = null;
-
- MongoDB\Driver\Monitoring\addSubscriber($this);
-
- $manager = create_test_manager();
- $session = $manager->startSession();
-
- $bulk = new MongoDB\Driver\BulkWrite;
- $bulk->insert(['_id' => 1]);
- $bulk->insert(['_id' => 1]);
-
- throws(function() use ($manager, $bulk, $session) {
- $manager->executeBulkWrite(NS, $bulk, ['session' => $session]);
- }, 'MongoDB\Driver\Exception\BulkWriteException');
-
- $query = new MongoDB\Driver\Query([]);
- $manager->executeQuery(NS, $query, ['session' => $session]);
-
- MongoDB\Driver\Monitoring\removeSubscriber($this);
- }
-
- public function commandStarted(MongoDB\Driver\Monitoring\CommandStartedEvent $event)
- {
- $command = $event->getCommand();
- $hasAfterClusterTime = isset($command->readConcern->afterClusterTime);
- printf("%s command includes afterClusterTime: %s\n", $event->getCommandName(), ($hasAfterClusterTime ? 'yes' : 'no'));
-
- if ($hasAfterClusterTime && $this->lastSeenOperationTime !== null) {
- printf("%s command uses last seen operationTime: %s\n", $event->getCommandName(), ($command->readConcern->afterClusterTime == $this->lastSeenOperationTime) ? 'yes' : 'no');
- }
- }
-
- public function commandSucceeded(MongoDB\Driver\Monitoring\CommandSucceededEvent $event)
- {
- $reply = $event->getReply();
- $hasOperationTime = isset($reply->operationTime);
-
- printf("%s command reply includes operationTime: %s\n", $event->getCommandName(), $hasOperationTime ? 'yes' : 'no');
-
- if ($hasOperationTime) {
- $this->lastSeenOperationTime = $reply->operationTime;
- }
- }
-
- public function commandFailed(MongoDB\Driver\Monitoring\CommandFailedEvent $event)
- {
- }
-}
-
-echo "\nTesting read after read error\n";
-(new Test)->executeReadAfterReadError();
-
-echo "\nTesting read after write error\n";
-(new Test)->executeReadAfterWriteError();
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-Testing read after read error
-find command includes afterClusterTime: no
-OK: Got MongoDB\Driver\Exception\RuntimeException
-Session has non-null operationTime: yes
-find command includes afterClusterTime: yes
-find command reply includes operationTime: yes
-
-Testing read after write error
-insert command includes afterClusterTime: no
-insert command reply includes operationTime: yes
-OK: Got MongoDB\Driver\Exception\BulkWriteException
-find command includes afterClusterTime: yes
-find command uses last seen operationTime: yes
-find command reply includes operationTime: yes
-===DONE===
diff --git a/mongodb-1.12.0/tests/causal-consistency/causal-consistency-007.phpt b/mongodb-1.12.0/tests/causal-consistency/causal-consistency-007.phpt
deleted file mode 100644
index 6ed20b3d..00000000
--- a/mongodb-1.12.0/tests/causal-consistency/causal-consistency-007.phpt
+++ /dev/null
@@ -1,35 +0,0 @@
---TEST--
-Causal consistency: reads in non-causally consistent session never include afterClusterTime
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_not_replica_set_or_sharded_cluster_with_replica_set(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-require_once __DIR__ . "/../utils/observer.php";
-
-(new CommandObserver)->observe(
- function() {
- $manager = create_test_manager();
- $session = $manager->startSession(['causalConsistency' => false]);
-
- $query = new MongoDB\Driver\Query([]);
- $manager->executeQuery(NS, $query, ['session' => $session]);
- $manager->executeQuery(NS, $query, ['session' => $session]);
- },
- function(stdClass $command)
- {
- $hasAfterClusterTime = isset($command->readConcern->afterClusterTime);
- printf("Read includes afterClusterTime: %s\n", ($hasAfterClusterTime ? 'yes' : 'no'));
- }
-);
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-Read includes afterClusterTime: no
-Read includes afterClusterTime: no
-===DONE===
diff --git a/mongodb-1.12.0/tests/causal-consistency/causal-consistency-008.phpt b/mongodb-1.12.0/tests/causal-consistency/causal-consistency-008.phpt
deleted file mode 100644
index 2c9a55b8..00000000
--- a/mongodb-1.12.0/tests/causal-consistency/causal-consistency-008.phpt
+++ /dev/null
@@ -1,40 +0,0 @@
---TEST--
-Causal consistency: default read concern includes afterClusterTime but not level
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_not_replica_set_or_sharded_cluster_with_replica_set(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-require_once __DIR__ . "/../utils/observer.php";
-
-(new CommandObserver)->observe(
- function() {
- $manager = create_test_manager();
- $session = $manager->startSession();
-
- $query = new MongoDB\Driver\Query([]);
- $manager->executeQuery(NS, $query, ['session' => $session]);
- $manager->executeQuery(NS, $query, ['session' => $session]);
- },
- function(stdClass $command)
- {
- $hasAfterClusterTime = isset($command->readConcern->afterClusterTime);
- printf("Read concern includes afterClusterTime: %s\n", ($hasAfterClusterTime ? 'yes' : 'no'));
-
- $hasLevel = isset($command->readConcern->level);
- printf("Read concern includes level: %s\n", ($hasLevel ? 'yes' : 'no'));
- }
-);
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-Read concern includes afterClusterTime: no
-Read concern includes level: no
-Read concern includes afterClusterTime: yes
-Read concern includes level: no
-===DONE===
diff --git a/mongodb-1.12.0/tests/causal-consistency/causal-consistency-009.phpt b/mongodb-1.12.0/tests/causal-consistency/causal-consistency-009.phpt
deleted file mode 100644
index 5c858b67..00000000
--- a/mongodb-1.12.0/tests/causal-consistency/causal-consistency-009.phpt
+++ /dev/null
@@ -1,41 +0,0 @@
---TEST--
-Causal consistency: custom read concern merges afterClusterTime and level
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_not_replica_set_or_sharded_cluster_with_replica_set(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-require_once __DIR__ . "/../utils/observer.php";
-
-(new CommandObserver)->observe(
- function() {
- $manager = create_test_manager();
- $session = $manager->startSession();
-
- $readConcern = new MongoDB\Driver\ReadConcern(MongoDB\Driver\ReadConcern::MAJORITY);
- $query = new MongoDB\Driver\Query([], ['readConcern' => $readConcern]);
- $manager->executeQuery(NS, $query, ['session' => $session]);
- $manager->executeQuery(NS, $query, ['session' => $session]);
- },
- function(stdClass $command)
- {
- $hasAfterClusterTime = isset($command->readConcern->afterClusterTime);
- printf("Read concern includes afterClusterTime: %s\n", ($hasAfterClusterTime ? 'yes' : 'no'));
-
- $hasLevel = isset($command->readConcern->level);
- printf("Read concern includes level: %s\n", ($hasLevel ? 'yes' : 'no'));
- }
-);
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-Read concern includes afterClusterTime: no
-Read concern includes level: yes
-Read concern includes afterClusterTime: yes
-Read concern includes level: yes
-===DONE===
diff --git a/mongodb-1.12.0/tests/causal-consistency/causal-consistency-010.phpt b/mongodb-1.12.0/tests/causal-consistency/causal-consistency-010.phpt
deleted file mode 100644
index 64eea19a..00000000
--- a/mongodb-1.12.0/tests/causal-consistency/causal-consistency-010.phpt
+++ /dev/null
@@ -1,41 +0,0 @@
---TEST--
-Causal consistency: unacknowledged write does not update operationTime
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_not_replica_set_or_sharded_cluster_with_replica_set(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-$session = $manager->startSession();
-
-echo "Initial operation time:\n";
-var_dump($session->getOperationTime());
-
-$bulk = new MongoDB\Driver\BulkWrite;
-$bulk->insert(['x' => 1]);
-$writeConcern = new MongoDB\Driver\WriteConcern(0);
-
-/* Ignore the InvalidArgumentException for trying to combine an unacknowledged
- * write concern with an explicit session. */
-try {
- $manager->executeBulkWrite(NS, $bulk, ['session' => $session, 'writeConcern' => $writeConcern]);
-} catch (MongoDB\Driver\Exception\InvalidArgumentException $e) {}
-
-echo "\nOperation time after unacknowledged write:\n";
-var_dump($session->getOperationTime());
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-Initial operation time:
-NULL
-
-Operation time after unacknowledged write:
-NULL
-===DONE===
diff --git a/mongodb-1.12.0/tests/causal-consistency/causal-consistency-011.phpt b/mongodb-1.12.0/tests/causal-consistency/causal-consistency-011.phpt
deleted file mode 100644
index a3f7992f..00000000
--- a/mongodb-1.12.0/tests/causal-consistency/causal-consistency-011.phpt
+++ /dev/null
@@ -1,36 +0,0 @@
---TEST--
-Causal consistency: $clusterTime is not sent in commands to unsupported deployments
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_not_standalone(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-require_once __DIR__ . "/../utils/observer.php";
-
-(new CommandObserver)->observe(
- function() {
- $manager = create_test_manager();
- $session = $manager->startSession();
-
- $query = new MongoDB\Driver\Query([]);
- $manager->executeQuery(NS, $query, ['session' => $session]);
- $manager->executeQuery(NS, $query, ['session' => $session]);
- },
- function(stdClass $command)
- {
- $hasClusterTime = isset($command->{'$clusterTime'});
- printf("Command includes \$clusterTime: %s\n", ($hasClusterTime ? 'yes' : 'no'));
- }
-);
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-Command includes $clusterTime: no
-Command includes $clusterTime: no
-===DONE===
diff --git a/mongodb-1.12.0/tests/causal-consistency/causal-consistency-012.phpt b/mongodb-1.12.0/tests/causal-consistency/causal-consistency-012.phpt
deleted file mode 100644
index 494faa4c..00000000
--- a/mongodb-1.12.0/tests/causal-consistency/causal-consistency-012.phpt
+++ /dev/null
@@ -1,36 +0,0 @@
---TEST--
-Causal consistency: $clusterTime is sent in commands to supported deployments
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_load_balanced(); /* TODO: CDRIVER-4174 */ ?>
-<?php skip_if_not_replica_set_or_sharded_cluster_with_replica_set(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-require_once __DIR__ . "/../utils/observer.php";
-
-(new CommandObserver)->observe(
- function() {
- $manager = create_test_manager();
- $session = $manager->startSession();
-
- $query = new MongoDB\Driver\Query([]);
- $manager->executeQuery(NS, $query, ['session' => $session]);
- $manager->executeQuery(NS, $query, ['session' => $session]);
- },
- function(stdClass $command)
- {
- $hasClusterTime = isset($command->{'$clusterTime'});
- printf("Command includes \$clusterTime: %s\n", ($hasClusterTime ? 'yes' : 'no'));
- }
-);
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-Command includes $clusterTime: yes
-Command includes $clusterTime: yes
-===DONE===
diff --git a/mongodb-1.12.0/tests/clientEncryption/clientEncryption-decrypt-001.phpt b/mongodb-1.12.0/tests/clientEncryption/clientEncryption-decrypt-001.phpt
deleted file mode 100644
index fc1f50db..00000000
--- a/mongodb-1.12.0/tests/clientEncryption/clientEncryption-decrypt-001.phpt
+++ /dev/null
@@ -1,28 +0,0 @@
---TEST--
-MongoDB\Driver\ClientEncryption::decrypt()
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongocrypt(); ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
-<?php skip_if_not_server_storage_engine('wiredTiger'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$key = base64_decode('Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk');
-
-$manager = create_test_manager();
-$clientEncryption = $manager->createClientEncryption(['keyVaultNamespace' => 'default.keys', 'kmsProviders' => ['local' => ['key' => new MongoDB\BSON\Binary($key, 0)]]]);
-
-$key = $clientEncryption->createDataKey('local');
-
-$encrypted = $clientEncryption->encrypt('top-secret', ['keyId' => $key, 'algorithm' => MongoDB\Driver\ClientEncryption::AEAD_AES_256_CBC_HMAC_SHA_512_DETERMINISTIC]);
-var_dump($clientEncryption->decrypt($encrypted));
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-string(10) "top-secret"
-===DONE===
diff --git a/mongodb-1.12.0/tests/clientEncryption/clientEncryption-encrypt-001.phpt b/mongodb-1.12.0/tests/clientEncryption/clientEncryption-encrypt-001.phpt
deleted file mode 100644
index e582876a..00000000
--- a/mongodb-1.12.0/tests/clientEncryption/clientEncryption-encrypt-001.phpt
+++ /dev/null
@@ -1,32 +0,0 @@
---TEST--
-MongoDB\Driver\ClientEncryption::encrypt()
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongocrypt(); ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
-<?php skip_if_not_server_storage_engine('wiredTiger'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$key = base64_decode('Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk');
-
-$manager = create_test_manager();
-$clientEncryption = $manager->createClientEncryption(['keyVaultNamespace' => 'default.keys', 'kmsProviders' => ['local' => ['key' => new MongoDB\BSON\Binary($key, 0)]]]);
-
-$key = $clientEncryption->createDataKey('local');
-
-var_dump($clientEncryption->encrypt('top-secret', ['keyId' => $key, 'algorithm' => MongoDB\Driver\ClientEncryption::AEAD_AES_256_CBC_HMAC_SHA_512_DETERMINISTIC]));
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-object(MongoDB\BSON\Binary)#%d (%d) {
- ["data"]=>
- string(82) "%a"
- ["type"]=>
- int(6)
-}
-===DONE===
diff --git a/mongodb-1.12.0/tests/command/cursor-tailable-001.phpt b/mongodb-1.12.0/tests/command/cursor-tailable-001.phpt
deleted file mode 100644
index 7a205b32..00000000
--- a/mongodb-1.12.0/tests/command/cursor-tailable-001.phpt
+++ /dev/null
@@ -1,72 +0,0 @@
---TEST--
-MongoDB\Driver\Command tailable cursor iteration with maxAwaitTimeMS option
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_replica_set(); ?>
-<?php skip_if_not_clean(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
-<?php skip_if_not_server_storage_engine('wiredTiger'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-$manager = create_test_manager();
-
-$manager->executeCommand(DATABASE_NAME, new MongoDB\Driver\Command([
- 'create' => COLLECTION_NAME,
- 'capped' => true,
- 'size' => 1048576,
-]));
-
-$bulkWrite = new MongoDB\Driver\BulkWrite;
-$bulkWrite->insert(['_id' => 1]);
-$manager->executeBulkWrite(NS, $bulkWrite);
-
-$pipeline = [
- [ '$changeStream' => [ 'fullDocument' => 'updateLookup' ] ]
-];
-
-$command = new MongoDB\Driver\Command([
- 'aggregate' => COLLECTION_NAME,
- 'pipeline' => $pipeline,
- 'cursor' => ['batchSize' => 0],
-], [
- 'maxAwaitTimeMS' => 500,
-]);
-
-$cursor = $manager->executeCommand(DATABASE_NAME, $command);
-$it = new IteratorIterator($cursor);
-
-$it->rewind();
-$it->next();
-
-$bulkWrite = new MongoDB\Driver\BulkWrite;
-$bulkWrite->insert(['_id' => "new-document"]);
-$manager->executeBulkWrite(NS, $bulkWrite);
-
-$startTime = microtime(true);
-echo "Awaiting results...\n";
-$it->next();
-var_dump($it->current()->operationType, $it->current()->documentKey);
-printf("Waited for %.6f seconds\n", microtime(true) - $startTime);
-
-$startTime = microtime(true);
-echo "Awaiting results...\n";
-$it->next();
-var_dump($it->current()); /* Should be NULL */
-printf("Waited for %.6f seconds\n", microtime(true) - $startTime);
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-Awaiting results...
-string(6) "insert"
-object(stdClass)#%d (%d) {
- ["_id"]=>
- string(12) "new-document"
-}
-Waited for 0.%d seconds
-Awaiting results...
-NULL
-Waited for 0.%r(4|5)\d*%r seconds
-===DONE===
diff --git a/mongodb-1.12.0/tests/command/findAndModify-001.phpt b/mongodb-1.12.0/tests/command/findAndModify-001.phpt
deleted file mode 100644
index 65669dec..00000000
--- a/mongodb-1.12.0/tests/command/findAndModify-001.phpt
+++ /dev/null
@@ -1,84 +0,0 @@
---TEST--
-MongoDB\Driver\Command with findAndModify and arrayFilters
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-
-$bulk = new MongoDB\Driver\BulkWrite();
-
-$bulk->insert([ '_id' => 1, 'grades' => [ 95, 92, 90 ] ]);
-$bulk->insert([ '_id' => 2, 'grades' => [ 98, 100, 102 ] ]);
-$bulk->insert([ '_id' => 3, 'grades' => [ 95, 110, 100 ] ]);
-
-$manager->executeBulkWrite(DATABASE_NAME . '.' . COLLECTION_NAME, $bulk);
-
-$command = new MongoDB\Driver\Command([
- 'findAndModify' => COLLECTION_NAME,
- 'query' => ['grades' => [ '$gt' => 100 ] ],
- 'update' => ['$set' => [ 'grades.$[element]' => 100 ] ],
- 'arrayFilters' => [ [ 'element' => [ '$gt' => 100 ] ] ],
-]);
-
-// Running this twice, because findAndModify only updates the first document
-// it finds.
-$manager->executeCommand(DATABASE_NAME, $command);
-$manager->executeCommand(DATABASE_NAME, $command);
-
-$cursor = $manager->executeQuery( DATABASE_NAME . '.' . COLLECTION_NAME, new \MongoDB\Driver\Query([]));
-var_dump($cursor->toArray());
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-array(%d) {
- [0]=>
- object(stdClass)#%d (%d) {
- ["_id"]=>
- int(1)
- ["grades"]=>
- array(%d) {
- [0]=>
- int(95)
- [1]=>
- int(92)
- [2]=>
- int(90)
- }
- }
- [1]=>
- object(stdClass)#%d (%d) {
- ["_id"]=>
- int(2)
- ["grades"]=>
- array(%d) {
- [0]=>
- int(98)
- [1]=>
- int(100)
- [2]=>
- int(100)
- }
- }
- [2]=>
- object(stdClass)#%d (%d) {
- ["_id"]=>
- int(3)
- ["grades"]=>
- array(%d) {
- [0]=>
- int(95)
- [1]=>
- int(100)
- [2]=>
- int(100)
- }
- }
-}
-===DONE===
diff --git a/mongodb-1.12.0/tests/command/update-001.phpt b/mongodb-1.12.0/tests/command/update-001.phpt
deleted file mode 100644
index c27cfe50..00000000
--- a/mongodb-1.12.0/tests/command/update-001.phpt
+++ /dev/null
@@ -1,84 +0,0 @@
---TEST--
-MongoDB\Driver\Command with update and arrayFilters
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-
-$bulk = new MongoDB\Driver\BulkWrite();
-
-$bulk->insert([ '_id' => 1, 'grades' => [ 95, 92, 90 ] ]);
-$bulk->insert([ '_id' => 2, 'grades' => [ 98, 100, 102 ] ]);
-$bulk->insert([ '_id' => 3, 'grades' => [ 95, 110, 100 ] ]);
-
-$manager->executeBulkWrite(DATABASE_NAME . '.' . COLLECTION_NAME, $bulk);
-
-$command = new MongoDB\Driver\Command([
- 'update' => COLLECTION_NAME,
- 'updates' => [[
- 'q' => [ 'grades' => [ '$gte' => 100 ] ],
- 'u' => [ '$set' => [ 'grades.$[element]' => 100 ] ],
- 'arrayFilters' => [ [ 'element' => [ '$gte' => 100 ] ] ],
- 'multi' => true
- ]],
-]);
-
-$manager->executeCommand(DATABASE_NAME, $command);
-
-$cursor = $manager->executeQuery( DATABASE_NAME . '.' . COLLECTION_NAME, new \MongoDB\Driver\Query([]));
-var_dump($cursor->toArray());
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-array(%d) {
- [0]=>
- object(stdClass)#%d (%d) {
- ["_id"]=>
- int(1)
- ["grades"]=>
- array(%d) {
- [0]=>
- int(95)
- [1]=>
- int(92)
- [2]=>
- int(90)
- }
- }
- [1]=>
- object(stdClass)#%d (%d) {
- ["_id"]=>
- int(2)
- ["grades"]=>
- array(%d) {
- [0]=>
- int(98)
- [1]=>
- int(100)
- [2]=>
- int(100)
- }
- }
- [2]=>
- object(stdClass)#%d (%d) {
- ["_id"]=>
- int(3)
- ["grades"]=>
- array(%d) {
- [0]=>
- int(95)
- [1]=>
- int(100)
- [2]=>
- int(100)
- }
- }
-}
-===DONE===
diff --git a/mongodb-1.12.0/tests/connect/bug0720.phpt b/mongodb-1.12.0/tests/connect/bug0720.phpt
deleted file mode 100644
index 79d64ca8..00000000
--- a/mongodb-1.12.0/tests/connect/bug0720.phpt
+++ /dev/null
@@ -1,37 +0,0 @@
---TEST--
-PHPC-720: Do not persist SSL streams to avoid SSL reinitialization errors
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_ssl(); ?>
-<?php skip_if_not_ssl(); ?>
-<?php skip_if_no_ssl_dir(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$driverOptions = [
- // libmongoc does not allow the hostname to be overridden as "server"
- 'allow_invalid_hostname' => true,
- 'ca_file' => SSL_DIR . '/ca.pem',
-];
-
-$manager = create_test_manager(URI, [], $driverOptions);
-$cursor = $manager->executeCommand(DATABASE_NAME, new MongoDB\Driver\Command(['ping' => 1]));
-printf("ping: %d\n", $cursor->toArray()[0]->ok);
-
-unset($manager, $cursor);
-
-$manager = create_test_manager(URI, [], $driverOptions);
-$cursor = $manager->executeCommand(DATABASE_NAME, new MongoDB\Driver\Command(['ping' => 1]));
-printf("ping: %d\n", $cursor->toArray()[0]->ok);
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-Deprecated: MongoDB\Driver\Manager::__construct(): The "allow_invalid_hostname" driver option is deprecated. Please use the "tlsAllowInvalidHostnames" URI option instead.%s
-
-Deprecated: MongoDB\Driver\Manager::__construct(): The "ca_file" driver option is deprecated. Please use the "tlsCAFile" URI option instead.%s
-ping: 1
-ping: 1
-===DONE===
diff --git a/mongodb-1.12.0/tests/connect/bug1045.phpt b/mongodb-1.12.0/tests/connect/bug1045.phpt
deleted file mode 100644
index 5078b48e..00000000
--- a/mongodb-1.12.0/tests/connect/bug1045.phpt
+++ /dev/null
@@ -1,22 +0,0 @@
---TEST--
-PHPC-1045: Segfault if username is not provided for SCRAM-SHA-1 authMechanism
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
---FILE--
-<?php
-
-require_once __DIR__ . "/../utils/basic.inc";
-
-echo throws(function() {
- // URI may or may not support auth, but that is not necessary for the test
- create_test_manager('mongodb://127.0.0.1/', ['authMechanism' => 'SCRAM-SHA-1']);
-}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse URI options: 'SCRAM-SHA-1' authentication mechanism requires username.
-===DONE===
diff --git a/mongodb-1.12.0/tests/connect/standalone-ssl-no_verify-001.phpt b/mongodb-1.12.0/tests/connect/standalone-ssl-no_verify-001.phpt
deleted file mode 100644
index ebd7d794..00000000
--- a/mongodb-1.12.0/tests/connect/standalone-ssl-no_verify-001.phpt
+++ /dev/null
@@ -1,28 +0,0 @@
---TEST--
-Connect to MongoDB with SSL and no host/cert verification
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_ssl(); ?>
-<?php skip_if_not_ssl(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$driverOptions = [
- 'allow_invalid_hostname' => true,
- "weak_cert_validation" => true,
-];
-
-$manager = create_test_manager(URI, [], $driverOptions);
-$cursor = $manager->executeCommand(DATABASE_NAME, new MongoDB\Driver\Command(['ping' => 1]));
-printf("ping: %d\n", $cursor->toArray()[0]->ok);
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-Deprecated: MongoDB\Driver\Manager::__construct(): The "allow_invalid_hostname" driver option is deprecated. Please use the "tlsAllowInvalidHostnames" URI option instead.%s
-
-Deprecated: MongoDB\Driver\Manager::__construct(): The "weak_cert_validation" driver option is deprecated. Please use the "tlsAllowInvalidCertificates" URI option instead.%s
-ping: 1
-===DONE===
diff --git a/mongodb-1.12.0/tests/connect/standalone-ssl-no_verify-002.phpt b/mongodb-1.12.0/tests/connect/standalone-ssl-no_verify-002.phpt
deleted file mode 100644
index 2209b2c6..00000000
--- a/mongodb-1.12.0/tests/connect/standalone-ssl-no_verify-002.phpt
+++ /dev/null
@@ -1,34 +0,0 @@
---TEST--
-Connect to MongoDB with SSL and no host/cert verification (context options)
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_ssl(); ?>
-<?php skip_if_not_ssl(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$driverOptions = [
- 'context' => stream_context_create([
- 'ssl' => [
- 'allow_invalid_hostname' => true,
- 'allow_self_signed' => true, // "weak_cert_validation" alias
- ],
- ]),
-];
-
-$manager = create_test_manager(URI, [], $driverOptions);
-$cursor = $manager->executeCommand(DATABASE_NAME, new MongoDB\Driver\Command(['ping' => 1]));
-printf("ping: %d\n", $cursor->toArray()[0]->ok);
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-Deprecated: MongoDB\Driver\Manager::__construct(): The "context" driver option is deprecated.%s
-
-Deprecated: MongoDB\Driver\Manager::__construct(): The "allow_invalid_hostname" driver option is deprecated. Please use the "tlsAllowInvalidHostnames" URI option instead.%s
-
-Deprecated: MongoDB\Driver\Manager::__construct(): The "allow_self_signed" context driver option is deprecated. Please use the "tlsAllowInvalidCertificates" URI option instead.%s
-ping: 1
-===DONE===
diff --git a/mongodb-1.12.0/tests/connect/standalone-ssl-verify_cert-001.phpt b/mongodb-1.12.0/tests/connect/standalone-ssl-verify_cert-001.phpt
deleted file mode 100644
index 1df0be05..00000000
--- a/mongodb-1.12.0/tests/connect/standalone-ssl-verify_cert-001.phpt
+++ /dev/null
@@ -1,33 +0,0 @@
---TEST--
-Connect to MongoDB with SSL and cert verification
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_ssl(); ?>
-<?php skip_if_not_ssl(); ?>
-<?php skip_if_no_ssl_dir(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$driverOptions = [
- // libmongoc does not allow the hostname to be overridden as "server"
- 'allow_invalid_hostname' => true,
- 'weak_cert_validation' => false,
- 'ca_file' => SSL_DIR . '/ca.pem',
-];
-
-$manager = create_test_manager(URI, [], $driverOptions);
-$cursor = $manager->executeCommand(DATABASE_NAME, new MongoDB\Driver\Command(['ping' => 1]));
-printf("ping: %d\n", $cursor->toArray()[0]->ok);
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-Deprecated: MongoDB\Driver\Manager::__construct(): The "allow_invalid_hostname" driver option is deprecated. Please use the "tlsAllowInvalidHostnames" URI option instead.%s
-
-Deprecated: MongoDB\Driver\Manager::__construct(): The "weak_cert_validation" driver option is deprecated. Please use the "tlsAllowInvalidCertificates" URI option instead.%s
-
-Deprecated: MongoDB\Driver\Manager::__construct(): The "ca_file" driver option is deprecated. Please use the "tlsCAFile" URI option instead.%s
-ping: 1
-===DONE===
diff --git a/mongodb-1.12.0/tests/connect/standalone-ssl-verify_cert-002.phpt b/mongodb-1.12.0/tests/connect/standalone-ssl-verify_cert-002.phpt
deleted file mode 100644
index 15ae3555..00000000
--- a/mongodb-1.12.0/tests/connect/standalone-ssl-verify_cert-002.phpt
+++ /dev/null
@@ -1,39 +0,0 @@
---TEST--
-Connect to MongoDB with SSL and cert verification (context options)
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_ssl(); ?>
-<?php skip_if_not_ssl(); ?>
-<?php skip_if_no_ssl_dir(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$driverOptions = [
- 'context' => stream_context_create([
- 'ssl' => [
- // libmongoc does not allow the hostname to be overridden as "server"
- 'allow_invalid_hostname' => true,
- 'allow_self_signed' => false, // "weak_cert_validation" alias
- 'cafile' => SSL_DIR . '/ca.pem', // "ca_file" alias
- ],
- ]),
-];
-
-$manager = create_test_manager(URI, [], $driverOptions);
-$cursor = $manager->executeCommand(DATABASE_NAME, new MongoDB\Driver\Command(['ping' => 1]));
-printf("ping: %d\n", $cursor->toArray()[0]->ok);
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-Deprecated: MongoDB\Driver\Manager::__construct(): The "context" driver option is deprecated.%s
-
-Deprecated: MongoDB\Driver\Manager::__construct(): The "allow_invalid_hostname" driver option is deprecated. Please use the "tlsAllowInvalidHostnames" URI option instead.%s
-
-Deprecated: MongoDB\Driver\Manager::__construct(): The "allow_self_signed" context driver option is deprecated. Please use the "tlsAllowInvalidCertificates" URI option instead.%s
-
-Deprecated: MongoDB\Driver\Manager::__construct(): The "cafile" context driver option is deprecated. Please use the "tlsCAFile" URI option instead.%s
-ping: 1
-===DONE===
diff --git a/mongodb-1.12.0/tests/connect/standalone-ssl-verify_cert-error-001.phpt b/mongodb-1.12.0/tests/connect/standalone-ssl-verify_cert-error-001.phpt
deleted file mode 100644
index 82d0e8bd..00000000
--- a/mongodb-1.12.0/tests/connect/standalone-ssl-verify_cert-error-001.phpt
+++ /dev/null
@@ -1,32 +0,0 @@
---TEST--
-Connect to MongoDB with SSL and cert verification error
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_ssl(); ?>
-<?php skip_if_not_ssl(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$driverOptions = [
- // libmongoc does not allow the hostname to be overridden as "server"
- 'allow_invalid_hostname' => true,
- 'weak_cert_validation' => false,
-];
-
-echo throws(function() use ($driverOptions) {
- $manager = create_test_manager(URI, [], $driverOptions);
- $cursor = $manager->executeCommand(DATABASE_NAME, new MongoDB\Driver\Command(['ping' => 1]));
- var_dump($cursor->toArray()[0]);
-}, MongoDB\Driver\Exception\ConnectionException::class, 'executeCommand'), "\n";
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-Deprecated: MongoDB\Driver\Manager::__construct(): The "allow_invalid_hostname" driver option is deprecated. Please use the "tlsAllowInvalidHostnames" URI option instead.%s
-
-Deprecated: MongoDB\Driver\Manager::__construct(): The "weak_cert_validation" driver option is deprecated. Please use the "tlsAllowInvalidCertificates" URI option instead.%s
-OK: Got MongoDB\Driver\Exception\ConnectionException thrown from executeCommand
-%sTLS handshake failed%s
-===DONE===
diff --git a/mongodb-1.12.0/tests/cursor/bug1050-001.phpt b/mongodb-1.12.0/tests/cursor/bug1050-001.phpt
deleted file mode 100644
index 52e2390a..00000000
--- a/mongodb-1.12.0/tests/cursor/bug1050-001.phpt
+++ /dev/null
@@ -1,110 +0,0 @@
---TEST--
-PHPC-1050: Command cursor should not invoke getMore at execution
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_replica_set(); ?>
-<?php skip_if_not_clean(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
-<?php skip_if_not_server_storage_engine('wiredTiger'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-class CommandLogger implements MongoDB\Driver\Monitoring\CommandSubscriber
-{
- public function commandStarted(MongoDB\Driver\Monitoring\CommandStartedEvent $event)
- {
- if ($event->getCommandName() !== 'aggregate' && $event->getCommandName() !== 'getMore') {
- return;
- }
-
- printf("Executing command: %s\n", $event->getCommandName());
- }
-
- public function commandSucceeded(MongoDB\Driver\Monitoring\CommandSucceededEvent $event)
- {
- if ($event->getCommandName() !== 'aggregate' && $event->getCommandName() !== 'getMore') {
- return;
- }
-
- printf("Executing command took %0.6f seconds\n", $event->getDurationMicros() / 1000000);
- }
-
- public function commandFailed(MongoDB\Driver\Monitoring\CommandFailedEvent $event)
- {
- }
-}
-
-$manager = create_test_manager();
-
-$cmd = new MongoDB\Driver\Command(
- [
- 'aggregate' => COLLECTION_NAME,
- 'pipeline' => [
- ['$changeStream' => (object) []],
- ],
- 'cursor' => (object) [],
- ],
- [
- 'maxAwaitTimeMS' => 500,
- ]
-);
-
-MongoDB\Driver\Monitoring\addSubscriber(new CommandLogger);
-
-$cursor = $manager->executeReadCommand(DATABASE_NAME, $cmd);
-
-$it = new IteratorIterator($cursor);
-
-printf("Current position is valid: %s\n\n", $it->valid() ? 'yes' : 'no');
-
-echo "Rewinding cursor\n";
-$it->rewind();
-
-printf("Current position is valid: %s\n\n", $it->valid() ? 'yes' : 'no');
-
-$bulk = new MongoDB\Driver\BulkWrite;
-$bulk->insert(['x' => 1]);
-$manager->executeBulkWrite(NS, $bulk);
-
-echo "Advancing cursor\n";
-$it->next();
-
-printf("Current position is valid: %s\n\n", $it->valid() ? 'yes' : 'no');
-
-$document = $it->current();
-
-if (isset($document)) {
- printf("Operation type: %s\n", $document->operationType);
- var_dump($document->fullDocument);
-}
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-Executing command: aggregate
-Executing command took 0.%d seconds
-Current position is valid: no
-
-Rewinding cursor
-Executing command: getMore
-Executing command took 0.%r(4|5)%r%d seconds
-Current position is valid: no
-
-Advancing cursor
-Executing command: getMore
-Executing command took 0.%d seconds
-Current position is valid: yes
-
-Operation type: insert
-object(stdClass)#%d (%d) {
- ["_id"]=>
- object(MongoDB\BSON\ObjectId)#%d (%d) {
- ["oid"]=>
- string(24) "%x"
- }
- ["x"]=>
- int(1)
-}
-===DONE===
diff --git a/mongodb-1.12.0/tests/cursor/bug1050-002.phpt b/mongodb-1.12.0/tests/cursor/bug1050-002.phpt
deleted file mode 100644
index 096e7412..00000000
--- a/mongodb-1.12.0/tests/cursor/bug1050-002.phpt
+++ /dev/null
@@ -1,118 +0,0 @@
---TEST--
-PHPC-1050: Command cursor should not invoke getMore at execution (rewind omitted)
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_php_version('>', '7.99'); ?>
-<?php skip_if_not_replica_set(); ?>
-<?php skip_if_not_clean(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
-<?php skip_if_not_server_storage_engine('wiredTiger'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-/* Note: this test is skipped on PHP 8 because the InternalIterator class
- * returned by Cursor::getIterator() has logic to ensure rewind() is always
- * called. That causes and additional getMore to be observed when starting
- * iteration with next(), since rewind() and next() both trigger a getMore.
- * We may be able to resume running this test on PHP 8 if Cursor implements
- * Iterator directly and allow rewind() to be optional (see: PHPC-1691). */
-
-class CommandLogger implements MongoDB\Driver\Monitoring\CommandSubscriber
-{
- public function commandStarted(MongoDB\Driver\Monitoring\CommandStartedEvent $event)
- {
- if ($event->getCommandName() !== 'aggregate' && $event->getCommandName() !== 'getMore') {
- return;
- }
-
- printf("Executing command: %s\n", $event->getCommandName());
- }
-
- public function commandSucceeded(MongoDB\Driver\Monitoring\CommandSucceededEvent $event)
- {
- if ($event->getCommandName() !== 'aggregate' && $event->getCommandName() !== 'getMore') {
- return;
- }
-
- printf("Executing command took %0.6f seconds\n", $event->getDurationMicros() / 1000000);
- }
-
- public function commandFailed(MongoDB\Driver\Monitoring\CommandFailedEvent $event)
- {
- }
-}
-
-$manager = create_test_manager();
-
-$cmd = new MongoDB\Driver\Command(
- [
- 'aggregate' => COLLECTION_NAME,
- 'pipeline' => [
- ['$changeStream' => (object) []],
- ],
- 'cursor' => (object) [],
- ],
- [
- 'maxAwaitTimeMS' => 500,
- ]
-);
-
-MongoDB\Driver\Monitoring\addSubscriber(new CommandLogger);
-
-$cursor = $manager->executeReadCommand(DATABASE_NAME, $cmd);
-
-$it = new IteratorIterator($cursor);
-
-printf("Current position is valid: %s\n\n", $it->valid() ? 'yes' : 'no');
-
-echo "Advancing cursor\n";
-$it->next();
-
-printf("Current position is valid: %s\n\n", $it->valid() ? 'yes' : 'no');
-
-$bulk = new MongoDB\Driver\BulkWrite;
-$bulk->insert(['x' => 1]);
-$manager->executeBulkWrite(NS, $bulk);
-
-echo "Advancing cursor\n";
-$it->next();
-
-printf("Current position is valid: %s\n\n", $it->valid() ? 'yes' : 'no');
-
-$document = $it->current();
-
-if (isset($document)) {
- printf("Operation type: %s\n", $document->operationType);
- var_dump($document->fullDocument);
-}
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-Executing command: aggregate
-Executing command took 0.%d seconds
-Current position is valid: no
-
-Advancing cursor
-Executing command: getMore
-Executing command took 0.%r(4|5)%r%d seconds
-Current position is valid: no
-
-Advancing cursor
-Executing command: getMore
-Executing command took 0.%d seconds
-Current position is valid: yes
-
-Operation type: insert
-object(stdClass)#%d (%d) {
- ["_id"]=>
- object(MongoDB\BSON\ObjectId)#%d (%d) {
- ["oid"]=>
- string(24) "%x"
- }
- ["x"]=>
- int(1)
-}
-===DONE===
diff --git a/mongodb-1.12.0/tests/cursor/bug1151-001.phpt b/mongodb-1.12.0/tests/cursor/bug1151-001.phpt
deleted file mode 100644
index ab21dcb4..00000000
--- a/mongodb-1.12.0/tests/cursor/bug1151-001.phpt
+++ /dev/null
@@ -1,38 +0,0 @@
---TEST--
-PHPC-1151: Segfault if session unset before first getMore (find)
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-
-$bulk = new MongoDB\Driver\BulkWrite;
-$bulk->insert(['_id' => 1]);
-$bulk->insert(['_id' => 2]);
-$bulk->insert(['_id' => 3]);
-$manager->executeBulkWrite(NS, $bulk);
-
-$query = new MongoDB\Driver\Query([], ['batchSize' => 2]);
-$session = $manager->startSession();
-
-$cursor = $manager->executeQuery(NS, $query, ['session' => $session]);
-
-foreach ($cursor as $document) {
- unset($session);
- echo $document->_id, "\n";
-}
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-1
-2
-3
-===DONE===
diff --git a/mongodb-1.12.0/tests/cursor/bug1151-002.phpt b/mongodb-1.12.0/tests/cursor/bug1151-002.phpt
deleted file mode 100644
index 58474b81..00000000
--- a/mongodb-1.12.0/tests/cursor/bug1151-002.phpt
+++ /dev/null
@@ -1,42 +0,0 @@
---TEST--
-PHPC-1151: Segfault if session unset before first getMore (aggregate)
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-
-$bulk = new MongoDB\Driver\BulkWrite;
-$bulk->insert(['_id' => 1]);
-$bulk->insert(['_id' => 2]);
-$bulk->insert(['_id' => 3]);
-$manager->executeBulkWrite(NS, $bulk);
-
-$command = new MongoDB\Driver\Command([
- 'aggregate' => COLLECTION_NAME,
- 'pipeline' => [],
- 'cursor' => ['batchSize' => 2],
-]);
-$session = $manager->startSession();
-
-$cursor = $manager->executeReadCommand(DATABASE_NAME, $command, ['session' => $session]);
-
-foreach ($cursor as $document) {
- unset($session);
- echo $document->_id, "\n";
-}
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-1
-2
-3
-===DONE===
diff --git a/mongodb-1.12.0/tests/cursor/bug1151-003.phpt b/mongodb-1.12.0/tests/cursor/bug1151-003.phpt
deleted file mode 100644
index c5793c7f..00000000
--- a/mongodb-1.12.0/tests/cursor/bug1151-003.phpt
+++ /dev/null
@@ -1,32 +0,0 @@
---TEST--
-PHPC-1151: Segfault if session unset before cursor is killed (find)
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-
-$bulk = new MongoDB\Driver\BulkWrite;
-$bulk->insert(['_id' => 1]);
-$bulk->insert(['_id' => 2]);
-$bulk->insert(['_id' => 3]);
-$manager->executeBulkWrite(NS, $bulk);
-
-$query = new MongoDB\Driver\Query([], ['batchSize' => 2]);
-$session = $manager->startSession();
-
-$cursor = $manager->executeQuery(NS, $query, ['session' => $session]);
-unset($session);
-unset($cursor);
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-===DONE===
diff --git a/mongodb-1.12.0/tests/cursor/bug1151-004.phpt b/mongodb-1.12.0/tests/cursor/bug1151-004.phpt
deleted file mode 100644
index d0c733f4..00000000
--- a/mongodb-1.12.0/tests/cursor/bug1151-004.phpt
+++ /dev/null
@@ -1,36 +0,0 @@
---TEST--
-PHPC-1151: Segfault if session unset before cursor is killed (aggregate)
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-
-$bulk = new MongoDB\Driver\BulkWrite;
-$bulk->insert(['_id' => 1]);
-$bulk->insert(['_id' => 2]);
-$bulk->insert(['_id' => 3]);
-$manager->executeBulkWrite(NS, $bulk);
-
-$command = new MongoDB\Driver\Command([
- 'aggregate' => COLLECTION_NAME,
- 'pipeline' => [],
- 'cursor' => ['batchSize' => 2],
-]);
-$session = $manager->startSession();
-
-$cursor = $manager->executeReadCommand(DATABASE_NAME, $command, ['session' => $session]);
-unset($session);
-unset($cursor);
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-===DONE===
diff --git a/mongodb-1.12.0/tests/cursor/bug1152-001.phpt b/mongodb-1.12.0/tests/cursor/bug1152-001.phpt
deleted file mode 100644
index 7b54ea2d..00000000
--- a/mongodb-1.12.0/tests/cursor/bug1152-001.phpt
+++ /dev/null
@@ -1,132 +0,0 @@
---TEST--
-PHPC-1152: Command cursors should use the same session for getMore and killCursors (implicit)
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-class Test implements MongoDB\Driver\Monitoring\CommandSubscriber
-{
- private $lsidByCursorId = [];
- private $lsidByRequestId = [];
-
- public function executeCommand()
- {
- $manager = create_test_manager();
-
- $bulk = new MongoDB\Driver\BulkWrite;
- $bulk->insert(['_id' => 1]);
- $bulk->insert(['_id' => 2]);
- $bulk->insert(['_id' => 3]);
- $manager->executeBulkWrite(NS, $bulk);
-
- $command = new MongoDB\Driver\Command([
- 'aggregate' => COLLECTION_NAME,
- 'pipeline' => [['$match' => new stdClass]],
- 'cursor' => ['batchSize' => 2],
- ]);
-
- MongoDB\Driver\Monitoring\addSubscriber($this);
-
- /* By creating two cursors with the same name, PHP's reference counting
- * will destroy the first after the second is created. Note that
- * mongoc_cursor_destroy also destroys implicit sessions and returns
- * them to the LIFO pool. This sequencing allows us to test that getMore
- * and killCursors use the session ID corresponding to the original
- * aggregate command. */
- $cursor = $manager->executeCommand(DATABASE_NAME, $command);
- $cursor->toArray();
-
- $cursor = $manager->executeCommand(DATABASE_NAME, $command);
- $cursor->toArray();
-
- $cursor = $manager->executeCommand(DATABASE_NAME, $command);
- $cursor = $manager->executeCommand(DATABASE_NAME, $command);
- unset($cursor);
-
- MongoDB\Driver\Monitoring\removeSubscriber($this);
-
- /* We should expect two unique session IDs over the course of the test,
- * since at most two implicit sessions would have been in use at any
- * given time. */
- printf("Unique session IDs used: %d\n", count(array_unique($this->lsidByRequestId)));
- }
-
- public function commandStarted(MongoDB\Driver\Monitoring\CommandStartedEvent $event)
- {
- $requestId = $event->getRequestId();
- $sessionId = bin2hex((string) $event->getCommand()->lsid->id);
-
- printf("%s session ID: %s\n", $event->getCommandName(), $sessionId);
-
- if ($event->getCommandName() === 'aggregate') {
- if (isset($this->lsidByRequestId[$requestId])) {
- throw new UnexpectedValueException('Previous command observed for request ID: ' . $requestId);
- }
-
- $this->lsidByRequestId[$requestId] = $sessionId;
- }
-
- if ($event->getCommandName() === 'getMore') {
- $cursorId = (string) $event->getCommand()->getMore;
-
- if ( ! isset($this->lsidByCursorId[$cursorId])) {
- throw new UnexpectedValueException('No previous command observed for cursor ID: ' . $cursorId);
- }
-
- printf("getMore used same session as aggregate: %s\n", $sessionId === $this->lsidByCursorId[$cursorId] ? 'yes' : 'no');
- }
-
- if ($event->getCommandName() === 'killCursors') {
- $cursorId = (string) $event->getCommand()->cursors[0];
-
- if ( ! isset($this->lsidByCursorId[$cursorId])) {
- throw new UnexpectedValueException('No previous command observed for cursor ID: ' . $cursorId);
- }
-
- printf("killCursors used same session as aggregate: %s\n", $sessionId === $this->lsidByCursorId[$cursorId] ? 'yes' : 'no');
- }
- }
-
- public function commandSucceeded(MongoDB\Driver\Monitoring\CommandSucceededEvent $event)
- {
- /* Associate the aggregate's session ID with its cursor ID so it can be
- * looked up by the subsequent getMore or killCursors */
- if ($event->getCommandName() === 'aggregate') {
- $cursorId = (string) $event->getReply()->cursor->id;
- $requestId = $event->getRequestId();
-
- $this->lsidByCursorId[$cursorId] = $this->lsidByRequestId[$requestId];
- }
- }
-
- public function commandFailed(MongoDB\Driver\Monitoring\CommandFailedEvent $event)
- {
- }
-}
-
-(new Test)->executeCommand();
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-aggregate session ID: %x
-getMore session ID: %x
-getMore used same session as aggregate: yes
-aggregate session ID: %x
-getMore session ID: %x
-getMore used same session as aggregate: yes
-aggregate session ID: %x
-aggregate session ID: %x
-killCursors session ID: %x
-killCursors used same session as aggregate: yes
-killCursors session ID: %x
-killCursors used same session as aggregate: yes
-Unique session IDs used: 2
-===DONE===
diff --git a/mongodb-1.12.0/tests/cursor/bug1152-002.phpt b/mongodb-1.12.0/tests/cursor/bug1152-002.phpt
deleted file mode 100644
index 13f1f6dd..00000000
--- a/mongodb-1.12.0/tests/cursor/bug1152-002.phpt
+++ /dev/null
@@ -1,130 +0,0 @@
---TEST--
-PHPC-1152: Command cursors should use the same session for getMore and killCursors (explicit)
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-class Test implements MongoDB\Driver\Monitoring\CommandSubscriber
-{
- private $lsidByCursorId = [];
- private $lsidByRequestId = [];
-
- public function executeCommand()
- {
- $manager = create_test_manager();
-
- $bulk = new MongoDB\Driver\BulkWrite;
- $bulk->insert(['_id' => 1]);
- $bulk->insert(['_id' => 2]);
- $bulk->insert(['_id' => 3]);
- $manager->executeBulkWrite(NS, $bulk);
-
- $command = new MongoDB\Driver\Command([
- 'aggregate' => COLLECTION_NAME,
- 'pipeline' => [['$match' => new stdClass]],
- 'cursor' => ['batchSize' => 2],
- ]);
-
- $session = $manager->startSession();
-
- MongoDB\Driver\Monitoring\addSubscriber($this);
-
- /* This uses the same sequencing as the implicit session test; however,
- * we should expect all commands (aggregate, getMore, and killCursors)
- * to use the same explicit session ID. */
- $cursor = $manager->executeCommand(DATABASE_NAME, $command, ['session' => $session]);
- $cursor->toArray();
-
- $cursor = $manager->executeCommand(DATABASE_NAME, $command, ['session' => $session]);
- $cursor->toArray();
-
- $cursor = $manager->executeCommand(DATABASE_NAME, $command, ['session' => $session]);
- $cursor = $manager->executeCommand(DATABASE_NAME, $command, ['session' => $session]);
- unset($cursor);
-
- MongoDB\Driver\Monitoring\removeSubscriber($this);
-
- /* We should expect one unique session ID over the course of the test,
- * since all commands used the same explicit session. */
- printf("Unique session IDs used: %d\n", count(array_unique($this->lsidByRequestId)));
- }
-
- public function commandStarted(MongoDB\Driver\Monitoring\CommandStartedEvent $event)
- {
- $requestId = $event->getRequestId();
- $sessionId = bin2hex((string) $event->getCommand()->lsid->id);
-
- printf("%s session ID: %s\n", $event->getCommandName(), $sessionId);
-
- if ($event->getCommandName() === 'aggregate') {
- if (isset($this->lsidByRequestId[$requestId])) {
- throw new UnexpectedValueException('Previous command observed for request ID: ' . $requestId);
- }
-
- $this->lsidByRequestId[$requestId] = $sessionId;
- }
-
- if ($event->getCommandName() === 'getMore') {
- $cursorId = (string) $event->getCommand()->getMore;
-
- if ( ! isset($this->lsidByCursorId[$cursorId])) {
- throw new UnexpectedValueException('No previous command observed for cursor ID: ' . $cursorId);
- }
-
- printf("getMore used same session as aggregate: %s\n", $sessionId === $this->lsidByCursorId[$cursorId] ? 'yes' : 'no');
- }
-
- if ($event->getCommandName() === 'killCursors') {
- $cursorId = (string) $event->getCommand()->cursors[0];
-
- if ( ! isset($this->lsidByCursorId[$cursorId])) {
- throw new UnexpectedValueException('No previous command observed for cursor ID: ' . $cursorId);
- }
-
- printf("killCursors used same session as aggregate: %s\n", $sessionId === $this->lsidByCursorId[$cursorId] ? 'yes' : 'no');
- }
- }
-
- public function commandSucceeded(MongoDB\Driver\Monitoring\CommandSucceededEvent $event)
- {
- /* Associate the aggregate's session ID with its cursor ID so it can be
- * looked up by the subsequent getMore or killCursors */
- if ($event->getCommandName() === 'aggregate') {
- $cursorId = (string) $event->getReply()->cursor->id;
- $requestId = $event->getRequestId();
-
- $this->lsidByCursorId[$cursorId] = $this->lsidByRequestId[$requestId];
- }
- }
-
- public function commandFailed(MongoDB\Driver\Monitoring\CommandFailedEvent $event)
- {
- }
-}
-
-(new Test)->executeCommand();
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-aggregate session ID: %x
-getMore session ID: %x
-getMore used same session as aggregate: yes
-aggregate session ID: %x
-getMore session ID: %x
-getMore used same session as aggregate: yes
-aggregate session ID: %x
-aggregate session ID: %x
-killCursors session ID: %x
-killCursors used same session as aggregate: yes
-killCursors session ID: %x
-killCursors used same session as aggregate: yes
-Unique session IDs used: 1
-===DONE===
diff --git a/mongodb-1.12.0/tests/cursor/bug1274-002.phpt b/mongodb-1.12.0/tests/cursor/bug1274-002.phpt
deleted file mode 100644
index 98a0d8b1..00000000
--- a/mongodb-1.12.0/tests/cursor/bug1274-002.phpt
+++ /dev/null
@@ -1,105 +0,0 @@
---TEST--
-PHPC-1274: Child process can still iterate cursor from parent process
---SKIPIF--
-<?php if (!function_exists('pcntl_fork')) { die('skip pcntl_fork() not available'); } ?>
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_ssl(); ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_server_version('<', '3.2'); ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-class CommandLogger implements MongoDB\Driver\Monitoring\CommandSubscriber
-{
- private $pid;
-
- public function __construct()
- {
- $this->pid = getmypid();
- }
-
- public function commandStarted(MongoDB\Driver\Monitoring\CommandStartedEvent $event)
- {
- $command = $event->getCommand();
- $commandName = $event->getCommandName();
- $process = $this->pid === getmypid() ? 'Parent' : 'Child';
-
- if ($commandName === 'find' || $commandName === 'getMore') {
- printf("%s executes %s with batchSize: %d\n", $process, $commandName, $command->batchSize);
- return;
- }
-
- printf("%s executes %s\n", $process, $commandName);
- }
-
- public function commandSucceeded(MongoDB\Driver\Monitoring\CommandSucceededEvent $event)
- {
- }
-
- public function commandFailed(MongoDB\Driver\Monitoring\CommandFailedEvent $event)
- {
- }
-}
-
-$manager = create_test_manager();
-
-$bulk = new MongoDB\Driver\BulkWrite();
-$bulk->insert(['x' => 1]);
-$bulk->insert(['x' => 2]);
-$bulk->insert(['x' => 3]);
-$manager->executeBulkWrite(NS, $bulk);
-
-$subscriber = new CommandLogger;
-MongoDB\Driver\Monitoring\addSubscriber($subscriber);
-
-$query = new MongoDB\Driver\Query([], ['batchSize' => 2]);
-$cursor = $manager->executeQuery(NS, $query);
-
-$childPid = pcntl_fork();
-
-if ($childPid === 0) {
- /* This test asserts that mongoc_client_reset() does not prevent child
- * processes from actively interacting with a parent's cursor. Resetting the
- * client only prevents a child from inadvertently closing a parent cursor
- * via its php_phongo_cursor_free_object handler.
- *
- * Note: this test excludes SSL environments because we cannot interact with
- * the socket in a child without affecting the parent (and vice versa) due
- * to the SSL session. */
- printf("Child fully iterated cursor for %d documents\n", iterator_count($cursor));
- echo "Child exits\n";
- exit;
-}
-
-if ($childPid > 0) {
- $waitPid = pcntl_waitpid($childPid, $status);
-
- if ($waitPid === $childPid) {
- echo "Parent waited for child to exit\n";
- }
-
- echo throws(function() use ($cursor) {
- printf("Parent fully iterated cursor for %d documents\n", iterator_count($cursor));
- }, 'MongoDB\Driver\Exception\RuntimeException'), "\n";
-}
-
-/* This test doesn't need to assert that libmongoc may call killCursors when
- * destroying a cursor that previously encountered a CursorNotFound error.
- * See: https://jira.mongodb.org/browse/CDRIVER-3474 */
-MongoDB\Driver\Monitoring\removeSubscriber($subscriber);
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-Parent executes find with batchSize: 2
-Child executes getMore with batchSize: 2
-Child fully iterated cursor for 3 documents
-Child exits
-Parent waited for child to exit
-Parent executes getMore with batchSize: 2
-OK: Got MongoDB\Driver\Exception\RuntimeException
-%r(Cursor not found, cursor id: \d+|cursor id \d+ not found|Cursor not found \(.*id: \d+\)\.)%r
-===DONE===
diff --git a/mongodb-1.12.0/tests/cursor/bug1274-005.phpt b/mongodb-1.12.0/tests/cursor/bug1274-005.phpt
deleted file mode 100644
index 325a4b73..00000000
--- a/mongodb-1.12.0/tests/cursor/bug1274-005.phpt
+++ /dev/null
@@ -1,105 +0,0 @@
---TEST--
-PHPC-1274: Child process can still iterate cursor from parent process (disableClientPersistence=true)
---SKIPIF--
-<?php if (!function_exists('pcntl_fork')) { die('skip pcntl_fork() not available'); } ?>
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_ssl(); ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_server_version('<', '3.2'); ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-class CommandLogger implements MongoDB\Driver\Monitoring\CommandSubscriber
-{
- private $pid;
-
- public function __construct()
- {
- $this->pid = getmypid();
- }
-
- public function commandStarted(MongoDB\Driver\Monitoring\CommandStartedEvent $event)
- {
- $command = $event->getCommand();
- $commandName = $event->getCommandName();
- $process = $this->pid === getmypid() ? 'Parent' : 'Child';
-
- if ($commandName === 'find' || $commandName === 'getMore') {
- printf("%s executes %s with batchSize: %d\n", $process, $commandName, $command->batchSize);
- return;
- }
-
- printf("%s executes %s\n", $process, $commandName);
- }
-
- public function commandSucceeded(MongoDB\Driver\Monitoring\CommandSucceededEvent $event)
- {
- }
-
- public function commandFailed(MongoDB\Driver\Monitoring\CommandFailedEvent $event)
- {
- }
-}
-
-$manager = create_test_manager(URI, [], ['disableClientPersistence' => true]);
-
-$bulk = new MongoDB\Driver\BulkWrite();
-$bulk->insert(['x' => 1]);
-$bulk->insert(['x' => 2]);
-$bulk->insert(['x' => 3]);
-$manager->executeBulkWrite(NS, $bulk);
-
-$subscriber = new CommandLogger;
-MongoDB\Driver\Monitoring\addSubscriber($subscriber);
-
-$query = new MongoDB\Driver\Query([], ['batchSize' => 2]);
-$cursor = $manager->executeQuery(NS, $query);
-
-$childPid = pcntl_fork();
-
-if ($childPid === 0) {
- /* This test asserts that mongoc_client_reset() does not prevent child
- * processes from actively interacting with a parent's cursor. Resetting the
- * client only prevents a child from inadvertently closing a parent cursor
- * via its php_phongo_cursor_free_object handler.
- *
- * Note: this test excludes SSL environments because we cannot interact with
- * the socket in a child without affecting the parent (and vice versa) due
- * to the SSL session. */
- printf("Child fully iterated cursor for %d documents\n", iterator_count($cursor));
- echo "Child exits\n";
- exit;
-}
-
-if ($childPid > 0) {
- $waitPid = pcntl_waitpid($childPid, $status);
-
- if ($waitPid === $childPid) {
- echo "Parent waited for child to exit\n";
- }
-
- echo throws(function() use ($cursor) {
- printf("Parent fully iterated cursor for %d documents\n", iterator_count($cursor));
- }, 'MongoDB\Driver\Exception\RuntimeException'), "\n";
-}
-
-/* This test doesn't need to assert that libmongoc may call killCursors when
- * destroying a cursor that previously encountered a CursorNotFound error.
- * See: https://jira.mongodb.org/browse/CDRIVER-3474 */
-MongoDB\Driver\Monitoring\removeSubscriber($subscriber);
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-Parent executes find with batchSize: 2
-Child executes getMore with batchSize: 2
-Child fully iterated cursor for 3 documents
-Child exits
-Parent waited for child to exit
-Parent executes getMore with batchSize: 2
-OK: Got MongoDB\Driver\Exception\RuntimeException
-%r(Cursor not found, cursor id: \d+|cursor id \d+ not found|Cursor not found \(.*id: \d+\)\.)%r
-===DONE===
diff --git a/mongodb-1.12.0/tests/cursor/bug1529-001.phpt b/mongodb-1.12.0/tests/cursor/bug1529-001.phpt
deleted file mode 100644
index c390a8a8..00000000
--- a/mongodb-1.12.0/tests/cursor/bug1529-001.phpt
+++ /dev/null
@@ -1,105 +0,0 @@
---TEST--
-PHPC-1529: Resetting a client should also reset the keyVaultClient
---SKIPIF--
-<?php if (!function_exists('pcntl_fork')) { die('skip pcntl_fork() not available'); } ?>
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_not_clean(); ?>
-<?php skip_if_server_version('<', '4.2'); ?>
-<?php skip_if_not_libmongocrypt(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-class CommandLogger implements MongoDB\Driver\Monitoring\CommandSubscriber
-{
- private $pid;
-
- public function __construct()
- {
- $this->pid = getmypid();
- }
-
- public function commandStarted(MongoDB\Driver\Monitoring\CommandStartedEvent $event)
- {
- $command = $event->getCommand();
- $commandName = $event->getCommandName();
- $process = $this->pid === getmypid() ? 'Parent' : 'Child';
-
- if ($commandName === 'find' || $commandName === 'getMore') {
- printf("%s executes %s with batchSize: %d\n", $process, $commandName, $command->batchSize);
- return;
- }
-
- printf("%s executes %s\n", $process, $commandName);
- }
-
- public function commandSucceeded(MongoDB\Driver\Monitoring\CommandSucceededEvent $event)
- {
- }
-
- public function commandFailed(MongoDB\Driver\Monitoring\CommandFailedEvent $event)
- {
- }
-}
-
-$keyVaultClient = create_test_manager(URI, [], ['disableClientPersistence' => true]);
-$autoEncryptionOpts = [
- 'keyVaultClient' => $keyVaultClient,
- 'keyVaultNamespace' => 'default.keys',
- 'kmsProviders' => ['local' => ['key' => new MongoDB\BSON\Binary(str_repeat('0', 96), 0)]],
-];
-
-$manager = create_test_manager(URI, [], ['autoEncryption' => $autoEncryptionOpts, 'disableClientPersistence' => true]);
-
-$bulk = new MongoDB\Driver\BulkWrite();
-$bulk->insert(['x' => 1]);
-$bulk->insert(['x' => 2]);
-$bulk->insert(['x' => 3]);
-$keyVaultClient->executeBulkWrite(NS, $bulk);
-
-MongoDB\Driver\Monitoring\addSubscriber(new CommandLogger);
-
-$query = new MongoDB\Driver\Query([], ['batchSize' => 2]);
-$cursor = $keyVaultClient->executeQuery(NS, $query);
-
-$childPid = pcntl_fork();
-
-if ($childPid === 0) {
- /* Executing any operation with the parent's client resets this client as well as
- * the keyVaultClient. Continuing iteration of the cursor opened on the
- * keyVaultClient before resetting it should then result in an error due to
- * the client having been reset. */
- $manager->executeCommand(DATABASE_NAME, new MongoDB\Driver\Command(['ping' => 1]));
-
- echo throws(
- function () use ($cursor) { iterator_count($cursor); },
- MongoDB\Driver\Exception\RuntimeException::class
- ), "\n";
-
- echo "Child exits\n";
- exit;
-}
-
-if ($childPid > 0) {
- $waitPid = pcntl_waitpid($childPid, $status);
-
- if ($waitPid === $childPid) {
- echo "Parent waited for child to exit\n";
- }
-
- unset($cursor);
-}
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-Parent executes find with batchSize: 2
-Child executes ping
-OK: Got MongoDB\Driver\Exception\RuntimeException
-Cannot advance cursor after client reset
-Child exits
-Parent waited for child to exit
-Parent executes killCursors
-===DONE===
diff --git a/mongodb-1.12.0/tests/cursor/cursor-IteratorIterator-003.phpt b/mongodb-1.12.0/tests/cursor/cursor-IteratorIterator-003.phpt
deleted file mode 100644
index 692dbf48..00000000
--- a/mongodb-1.12.0/tests/cursor/cursor-IteratorIterator-003.phpt
+++ /dev/null
@@ -1,41 +0,0 @@
---TEST--
-MongoDB\Driver\Cursor iteration beyond last document (find command)
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-
-$bulk = new MongoDB\Driver\BulkWrite();
-$bulk->insert(['_id' => 1]);
-$manager->executeBulkWrite(NS, $bulk);
-
-$cursor = $manager->executeQuery(NS, new MongoDB\Driver\Query([]));
-
-$iterator = new IteratorIterator($cursor);
-$iterator->rewind();
-var_dump($iterator->current());
-$iterator->next();
-var_dump($iterator->current());
-
-// libmongoc throws on superfluous iteration of find command cursor (CDRIVER-1234)
-echo throws(function() use ($iterator) {
- $iterator->next();
-}, 'MongoDB\Driver\Exception\RuntimeException'), "\n";
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-object(stdClass)#%d (%d) {
- ["_id"]=>
- int(1)
-}
-NULL
-OK: Got MongoDB\Driver\Exception\RuntimeException
-Cannot advance a completed or failed cursor.
-===DONE===
diff --git a/mongodb-1.12.0/tests/cursor/cursor-IteratorIterator-004.phpt b/mongodb-1.12.0/tests/cursor/cursor-IteratorIterator-004.phpt
deleted file mode 100644
index b1fe9248..00000000
--- a/mongodb-1.12.0/tests/cursor/cursor-IteratorIterator-004.phpt
+++ /dev/null
@@ -1,42 +0,0 @@
---TEST--
-MongoDB\Driver\Cursor iteration beyond last document (OP_QUERY)
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_server_version('>=', '3.1'); ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-
-$bulk = new MongoDB\Driver\BulkWrite();
-$bulk->insert(['_id' => 1]);
-$manager->executeBulkWrite(NS, $bulk);
-
-$cursor = $manager->executeQuery(NS, new MongoDB\Driver\Query(array(), array('batchSize' => 2)));
-
-$iterator = new IteratorIterator($cursor);
-$iterator->rewind();
-var_dump($iterator->current());
-$iterator->next();
-var_dump($iterator->current());
-
-// libmongoc throws on superfluous iteration of OP_QUERY cursor (CDRIVER-1234)
-echo throws(function() use ($iterator) {
- $iterator->next();
-}, 'MongoDB\Driver\Exception\RuntimeException'), "\n";
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-object(stdClass)#%d (%d) {
- ["_id"]=>
- int(1)
-}
-NULL
-OK: Got MongoDB\Driver\Exception\RuntimeException
-Cannot advance a completed or failed cursor.
-===DONE===
diff --git a/mongodb-1.12.0/tests/cursor/cursor-getmore-005.phpt b/mongodb-1.12.0/tests/cursor/cursor-getmore-005.phpt
deleted file mode 100644
index cd3fb865..00000000
--- a/mongodb-1.12.0/tests/cursor/cursor-getmore-005.phpt
+++ /dev/null
@@ -1,54 +0,0 @@
---TEST--
-MongoDB\Driver\Cursor query result iteration with getmore failure
---SKIPIF--
-<?php require __DIR__ . "/" ."../utils/basic-skipif.inc"; ?>
-<?php
-/* This test spins up its own mongod instance, so only run this in the most default "standalone, no
- * auth" configurations. This way, we can test on multiple server versions, but not waste resources
- * on f.e. Travis. */
-?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_not_standalone(); ?>
-<?php skip_if_server_version(">=", "3.6"); ?>
-<?php skip_if_no_getmore_failpoint(); ?>
-<?php skip_if_auth(); ?>
-<?php skip_if_no_mongo_orchestration(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$uri = createTemporaryMongoInstance();
-$manager = create_test_manager($uri);
-
-$bulkWrite = new MongoDB\Driver\BulkWrite;
-
-for ($i = 0; $i < 5; $i++) {
- $bulkWrite->insert(array('_id' => $i));
-}
-
-$writeResult = $manager->executeBulkWrite(NS, $bulkWrite);
-printf("Inserted: %d\n", $writeResult->getInsertedCount());
-
-$query = new MongoDB\Driver\Query([], ['batchSize' => 2]);
-$cursor = $manager->executeQuery(NS, $query);
-
-failGetMore($manager);
-
-throws(function() use ($cursor) {
- foreach ($cursor as $i => $document) {
- printf("%d => {_id: %d}\n", $i, $document->_id);
- }
-}, "MongoDB\Driver\Exception\ConnectionException");
-?>
-===DONE===
-<?php destroyTemporaryMongoInstance(); ?>
-<?php exit(0); ?>
---CLEAN--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php destroyTemporaryMongoInstance(); ?>
---EXPECT--
-Inserted: 5
-0 => {_id: 0}
-1 => {_id: 1}
-OK: Got MongoDB\Driver\Exception\ConnectionException
-===DONE===
diff --git a/mongodb-1.12.0/tests/cursor/cursor-getmore-006.phpt b/mongodb-1.12.0/tests/cursor/cursor-getmore-006.phpt
deleted file mode 100644
index d2df21ac..00000000
--- a/mongodb-1.12.0/tests/cursor/cursor-getmore-006.phpt
+++ /dev/null
@@ -1,62 +0,0 @@
---TEST--
-MongoDB\Driver\Cursor command result iteration with getmore failure
---SKIPIF--
-<?php require __DIR__ . "/" ."../utils/basic-skipif.inc"; ?>
-<?php
-/* This test spins up its own mongod instance, so only run this in the most default "standalone, no
- * auth" configurations. This way, we can test on multiple server versions, but not waste resources
- * on f.e. Travis. */
-?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_not_standalone(); ?>
-<?php skip_if_server_version(">=", "3.6"); ?>
-<?php skip_if_no_getmore_failpoint(); ?>
-<?php skip_if_auth(); ?>
-<?php skip_if_no_mongo_orchestration(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$uri = createTemporaryMongoInstance();
-$manager = create_test_manager($uri);
-
-$bulkWrite = new MongoDB\Driver\BulkWrite;
-
-for ($i = 0; $i < 5; $i++) {
- $bulkWrite->insert(array('_id' => $i));
-}
-
-$writeResult = $manager->executeBulkWrite(NS, $bulkWrite);
-printf("Inserted: %d\n", $writeResult->getInsertedCount());
-
-$command = new MongoDB\Driver\Command([
- 'aggregate' => COLLECTION_NAME,
- 'pipeline' => [
- ['$match' => new stdClass],
- ],
- 'cursor' => ['batchSize' => 2],
-]);
-
-$cursor = $manager->executeCommand(DATABASE_NAME, $command);
-
-failGetMore($manager);
-
-throws(function() use ($cursor) {
- foreach ($cursor as $i => $document) {
- printf("%d => {_id: %d}\n", $i, $document->_id);
- }
-}, "MongoDB\Driver\Exception\ConnectionException");
-
-?>
-===DONE===
-<?php destroyTemporaryMongoInstance(); ?>
-<?php exit(0); ?>
---CLEAN--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php destroyTemporaryMongoInstance(); ?>
---EXPECT--
-Inserted: 5
-0 => {_id: 0}
-1 => {_id: 1}
-OK: Got MongoDB\Driver\Exception\ConnectionException
-===DONE===
diff --git a/mongodb-1.12.0/tests/cursor/cursor-getmore-007.phpt b/mongodb-1.12.0/tests/cursor/cursor-getmore-007.phpt
deleted file mode 100644
index 6154dc0d..00000000
--- a/mongodb-1.12.0/tests/cursor/cursor-getmore-007.phpt
+++ /dev/null
@@ -1,54 +0,0 @@
---TEST--
-MongoDB\Driver\Cursor query result iteration with getmore failure
---SKIPIF--
-<?php require __DIR__ . "/" ."../utils/basic-skipif.inc"; ?>
-<?php
-/* This test spins up its own mongod instance, so only run this in the most default "standalone, no
- * auth" configurations. This way, we can test on multiple server versions, but not waste resources
- * on f.e. Travis. */
-?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_not_standalone(); ?>
-<?php skip_if_server_version("<", "3.6"); ?>
-<?php skip_if_no_getmore_failpoint(); ?>
-<?php skip_if_auth(); ?>
-<?php skip_if_no_mongo_orchestration(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$uri = createTemporaryMongoInstance();
-$manager = create_test_manager($uri);
-
-$bulkWrite = new MongoDB\Driver\BulkWrite;
-
-for ($i = 0; $i < 5; $i++) {
- $bulkWrite->insert(array('_id' => $i));
-}
-
-$writeResult = $manager->executeBulkWrite(NS, $bulkWrite);
-printf("Inserted: %d\n", $writeResult->getInsertedCount());
-
-$query = new MongoDB\Driver\Query([], ['batchSize' => 2]);
-$cursor = $manager->executeQuery(NS, $query);
-
-failGetMore($manager);
-
-throws(function() use ($cursor) {
- foreach ($cursor as $i => $document) {
- printf("%d => {_id: %d}\n", $i, $document->_id);
- }
-}, "MongoDB\Driver\Exception\ServerException");
-?>
-===DONE===
-<?php destroyTemporaryMongoInstance(); ?>
-<?php exit(0); ?>
---CLEAN--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php destroyTemporaryMongoInstance(); ?>
---EXPECT--
-Inserted: 5
-0 => {_id: 0}
-1 => {_id: 1}
-OK: Got MongoDB\Driver\Exception\ServerException
-===DONE===
diff --git a/mongodb-1.12.0/tests/cursor/cursor-getmore-008.phpt b/mongodb-1.12.0/tests/cursor/cursor-getmore-008.phpt
deleted file mode 100644
index 42fe9186..00000000
--- a/mongodb-1.12.0/tests/cursor/cursor-getmore-008.phpt
+++ /dev/null
@@ -1,62 +0,0 @@
---TEST--
-MongoDB\Driver\Cursor command result iteration with getmore failure
---SKIPIF--
-<?php require __DIR__ . "/" ."../utils/basic-skipif.inc"; ?>
-<?php
-/* This test spins up its own mongod instance, so only run this in the most default "standalone, no
- * auth" configurations. This way, we can test on multiple server versions, but not waste resources
- * on f.e. Travis. */
-?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_not_standalone(); ?>
-<?php skip_if_server_version("<", "3.6"); ?>
-<?php skip_if_no_getmore_failpoint(); ?>
-<?php skip_if_auth(); ?>
-<?php skip_if_no_mongo_orchestration(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$uri = createTemporaryMongoInstance();
-$manager = create_test_manager($uri);
-
-$bulkWrite = new MongoDB\Driver\BulkWrite;
-
-for ($i = 0; $i < 5; $i++) {
- $bulkWrite->insert(array('_id' => $i));
-}
-
-$writeResult = $manager->executeBulkWrite(NS, $bulkWrite);
-printf("Inserted: %d\n", $writeResult->getInsertedCount());
-
-$command = new MongoDB\Driver\Command([
- 'aggregate' => COLLECTION_NAME,
- 'pipeline' => [
- ['$match' => new stdClass],
- ],
- 'cursor' => ['batchSize' => 2],
-]);
-
-$cursor = $manager->executeCommand(DATABASE_NAME, $command);
-
-failGetMore($manager);
-
-throws(function() use ($cursor) {
- foreach ($cursor as $i => $document) {
- printf("%d => {_id: %d}\n", $i, $document->_id);
- }
-}, "MongoDB\Driver\Exception\ServerException");
-
-?>
-===DONE===
-<?php destroyTemporaryMongoInstance(); ?>
-<?php exit(0); ?>
---CLEAN--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php destroyTemporaryMongoInstance(); ?>
---EXPECT--
-Inserted: 5
-0 => {_id: 0}
-1 => {_id: 1}
-OK: Got MongoDB\Driver\Exception\ServerException
-===DONE===
diff --git a/mongodb-1.12.0/tests/cursor/cursor-isDead-001.phpt b/mongodb-1.12.0/tests/cursor/cursor-isDead-001.phpt
deleted file mode 100644
index bca82a10..00000000
--- a/mongodb-1.12.0/tests/cursor/cursor-isDead-001.phpt
+++ /dev/null
@@ -1,35 +0,0 @@
---TEST--
-MongoDB\Driver\Cursor::isDead() with basic iteration (find command)
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-
-$bulk = new MongoDB\Driver\BulkWrite();
-$bulk->insert(['_id' => 1]);
-$bulk->insert(['_id' => 2]);
-$bulk->insert(['_id' => 3]);
-$manager->executeBulkWrite(NS, $bulk);
-
-$cursor = $manager->executeQuery(NS, new MongoDB\Driver\Query([], ['batchSize' => 2]));
-
-foreach ($cursor as $_) {
- var_dump($cursor->isDead());
-}
-
-var_dump($cursor->isDead());
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-bool(false)
-bool(false)
-bool(false)
-bool(true)
-===DONE===
diff --git a/mongodb-1.12.0/tests/cursor/cursor-isDead-002.phpt b/mongodb-1.12.0/tests/cursor/cursor-isDead-002.phpt
deleted file mode 100644
index ba31e9af..00000000
--- a/mongodb-1.12.0/tests/cursor/cursor-isDead-002.phpt
+++ /dev/null
@@ -1,39 +0,0 @@
---TEST--
-MongoDB\Driver\Cursor::isDead() with IteratorIterator (find command)
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-
-$bulk = new MongoDB\Driver\BulkWrite();
-$bulk->insert(['_id' => 1]);
-$bulk->insert(['_id' => 2]);
-$bulk->insert(['_id' => 3]);
-$manager->executeBulkWrite(NS, $bulk);
-
-$cursor = $manager->executeQuery(NS, new MongoDB\Driver\Query([], ['batchSize' => 2]));
-
-$iterator = new IteratorIterator($cursor);
-$iterator->rewind();
-
-for ($i = 0; $i < 3; $i++) {
- var_dump($cursor->isDead());
- $iterator->next();
-}
-
-var_dump($cursor->isDead());
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-bool(false)
-bool(false)
-bool(false)
-bool(true)
-===DONE===
diff --git a/mongodb-1.12.0/tests/cursor/cursor-isDead-003.phpt b/mongodb-1.12.0/tests/cursor/cursor-isDead-003.phpt
deleted file mode 100644
index 3fc8f0bd..00000000
--- a/mongodb-1.12.0/tests/cursor/cursor-isDead-003.phpt
+++ /dev/null
@@ -1,36 +0,0 @@
---TEST--
-MongoDB\Driver\Cursor::isDead() with basic iteration (OP_QUERY)
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_server_version('>=', '3.1'); ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-
-$bulk = new MongoDB\Driver\BulkWrite();
-$bulk->insert(['_id' => 1]);
-$bulk->insert(['_id' => 2]);
-$bulk->insert(['_id' => 3]);
-$manager->executeBulkWrite(NS, $bulk);
-
-$cursor = $manager->executeQuery(NS, new MongoDB\Driver\Query([], ['batchSize' => 2]));
-
-foreach ($cursor as $_) {
- var_dump($cursor->isDead());
-}
-
-var_dump($cursor->isDead());
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-bool(false)
-bool(false)
-bool(false)
-bool(true)
-===DONE===
diff --git a/mongodb-1.12.0/tests/cursor/cursor-isDead-004.phpt b/mongodb-1.12.0/tests/cursor/cursor-isDead-004.phpt
deleted file mode 100644
index f9375f4f..00000000
--- a/mongodb-1.12.0/tests/cursor/cursor-isDead-004.phpt
+++ /dev/null
@@ -1,40 +0,0 @@
---TEST--
-MongoDB\Driver\Cursor::isDead() with IteratorIterator (OP_QUERY)
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_server_version('>=', '3.1'); ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-
-$bulk = new MongoDB\Driver\BulkWrite();
-$bulk->insert(['_id' => 1]);
-$bulk->insert(['_id' => 2]);
-$bulk->insert(['_id' => 3]);
-$manager->executeBulkWrite(NS, $bulk);
-
-$cursor = $manager->executeQuery(NS, new MongoDB\Driver\Query([], ['batchSize' => 2]));
-
-$iterator = new IteratorIterator($cursor);
-$iterator->rewind();
-
-for ($i = 0; $i < 3; $i++) {
- var_dump($cursor->isDead());
- $iterator->next();
-}
-
-var_dump($cursor->isDead());
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-bool(false)
-bool(false)
-bool(false)
-bool(true)
-===DONE===
diff --git a/mongodb-1.12.0/tests/cursor/cursor-session-001.phpt b/mongodb-1.12.0/tests/cursor/cursor-session-001.phpt
deleted file mode 100644
index 8776d99c..00000000
--- a/mongodb-1.12.0/tests/cursor/cursor-session-001.phpt
+++ /dev/null
@@ -1,63 +0,0 @@
---TEST--
-MongoDB\Driver\Cursor debug output for query cursor includes explicit session
---SKIPIF--
-<?php require __DIR__ . "/" ."../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-
-$bulk = new MongoDB\Driver\BulkWrite;
-$bulk->insert(['_id' => 1]);
-$bulk->insert(['_id' => 2]);
-$bulk->insert(['_id' => 3]);
-$manager->executeBulkWrite(NS, $bulk);
-
-$query = new MongoDB\Driver\Query([], ['batchSize' => 2]);
-$session = $manager->startSession();
-
-$cursor = $manager->executeQuery(NS, $query, ['session' => $session]);
-
-$iterator = new IteratorIterator($cursor);
-$iterator->rewind();
-$iterator->next();
-
-printf("Cursor ID is zero: %s\n", (string) $cursor->getId() === '0' ? 'yes' : 'no');
-var_dump($cursor);
-
-$iterator->next();
-
-/* Per PHPC-1161, the Cursor will free a reference to the Session as soon as it
- * is exhausted. While this is primarily done to ensure implicit sessions for
- * command cursors are returned to the pool ASAP, it also applies to explicit
- * sessions. */
-printf("\nCursor ID is zero: %s\n", (string) $cursor->getId() === '0' ? 'yes' : 'no');
-var_dump($cursor);
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-Cursor ID is zero: no
-object(MongoDB\Driver\Cursor)#%d (%d) {
- %a
- ["session"]=>
- object(MongoDB\Driver\Session)#%d (%d) {
- %a
- }
- %a
-}
-
-Cursor ID is zero: yes
-object(MongoDB\Driver\Cursor)#%d (%d) {
- %a
- ["session"]=>
- NULL
- %a
-}
-===DONE===
diff --git a/mongodb-1.12.0/tests/cursor/cursor-session-002.phpt b/mongodb-1.12.0/tests/cursor/cursor-session-002.phpt
deleted file mode 100644
index 672b9234..00000000
--- a/mongodb-1.12.0/tests/cursor/cursor-session-002.phpt
+++ /dev/null
@@ -1,59 +0,0 @@
---TEST--
-MongoDB\Driver\Cursor debug output for query cursor omits implicit session
---SKIPIF--
-<?php require __DIR__ . "/" ."../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-
-$bulk = new MongoDB\Driver\BulkWrite;
-$bulk->insert(['_id' => 1]);
-$bulk->insert(['_id' => 2]);
-$bulk->insert(['_id' => 3]);
-$manager->executeBulkWrite(NS, $bulk);
-
-$query = new MongoDB\Driver\Query([], ['batchSize' => 2]);
-
-$cursor = $manager->executeQuery(NS, $query);
-
-$iterator = new IteratorIterator($cursor);
-$iterator->rewind();
-$iterator->next();
-
-/* Implicit sessions for query cursors are never exposed to PHPC, as they are
- * handled internally by libmongoc. Cursor debug ouput should never report such
- * sessions. */
-printf("Cursor ID is zero: %s\n", (string) $cursor->getId() === '0' ? 'yes' : 'no');
-var_dump($cursor);
-
-$iterator->next();
-
-printf("\nCursor ID is zero: %s\n", (string) $cursor->getId() === '0' ? 'yes' : 'no');
-var_dump($cursor);
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-Cursor ID is zero: no
-object(MongoDB\Driver\Cursor)#%d (%d) {
- %a
- ["session"]=>
- NULL
- %a
-}
-
-Cursor ID is zero: yes
-object(MongoDB\Driver\Cursor)#%d (%d) {
- %a
- ["session"]=>
- NULL
- %a
-}
-===DONE===
diff --git a/mongodb-1.12.0/tests/cursor/cursor-session-003.phpt b/mongodb-1.12.0/tests/cursor/cursor-session-003.phpt
deleted file mode 100644
index 7ae8e9cd..00000000
--- a/mongodb-1.12.0/tests/cursor/cursor-session-003.phpt
+++ /dev/null
@@ -1,67 +0,0 @@
---TEST--
-MongoDB\Driver\Cursor debug output for command cursor includes explicit session
---SKIPIF--
-<?php require __DIR__ . "/" ."../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-
-$bulk = new MongoDB\Driver\BulkWrite;
-$bulk->insert(['_id' => 1]);
-$bulk->insert(['_id' => 2]);
-$bulk->insert(['_id' => 3]);
-$manager->executeBulkWrite(NS, $bulk);
-
-$command = new MongoDB\Driver\Command([
- 'aggregate' => COLLECTION_NAME,
- 'pipeline' => [['$match' => new stdClass]],
- 'cursor' => ['batchSize' => 2],
-]);
-$session = $manager->startSession();
-
-$cursor = $manager->executeCommand(DATABASE_NAME, $command, ['session' => $session]);
-
-$iterator = new IteratorIterator($cursor);
-$iterator->rewind();
-$iterator->next();
-
-printf("Cursor ID is zero: %s\n", (string) $cursor->getId() === '0' ? 'yes' : 'no');
-var_dump($cursor);
-
-$iterator->next();
-
-/* Per PHPC-1161, the Cursor will free a reference to the Session as soon as it
- * is exhausted. While this is primarily done to ensure implicit sessions for
- * command cursors are returned to the pool ASAP, it also applies to explicit
- * sessions. */
-printf("\nCursor ID is zero: %s\n", (string) $cursor->getId() === '0' ? 'yes' : 'no');
-var_dump($cursor);
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-Cursor ID is zero: no
-object(MongoDB\Driver\Cursor)#%d (%d) {
- %a
- ["session"]=>
- object(MongoDB\Driver\Session)#%d (%d) {
- %a
- }
- %a
-}
-
-Cursor ID is zero: yes
-object(MongoDB\Driver\Cursor)#%d (%d) {
- %a
- ["session"]=>
- NULL
- %a
-}
-===DONE===
diff --git a/mongodb-1.12.0/tests/cursor/cursor-session-004.phpt b/mongodb-1.12.0/tests/cursor/cursor-session-004.phpt
deleted file mode 100644
index 82afadf4..00000000
--- a/mongodb-1.12.0/tests/cursor/cursor-session-004.phpt
+++ /dev/null
@@ -1,66 +0,0 @@
---TEST--
-MongoDB\Driver\Cursor debug output for command cursor includes implicit session
---SKIPIF--
-<?php require __DIR__ . "/" ."../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-
-$bulk = new MongoDB\Driver\BulkWrite;
-$bulk->insert(['_id' => 1]);
-$bulk->insert(['_id' => 2]);
-$bulk->insert(['_id' => 3]);
-$manager->executeBulkWrite(NS, $bulk);
-
-$command = new MongoDB\Driver\Command([
- 'aggregate' => COLLECTION_NAME,
- 'pipeline' => [['$match' => new stdClass]],
- 'cursor' => ['batchSize' => 2],
-]);
-
-$cursor = $manager->executeCommand(DATABASE_NAME, $command);
-
-$iterator = new IteratorIterator($cursor);
-$iterator->rewind();
-$iterator->next();
-
-printf("Cursor ID is zero: %s\n", (string) $cursor->getId() === '0' ? 'yes' : 'no');
-var_dump($cursor);
-
-$iterator->next();
-
-/* Unlike implicit sessions for query cursors, which are handled internally by
- * libmongoc, PHPC-1152 emulates its own implicit sessions for command cursors
- * in order to ensure that command cursors always share the same session as the
- * originating command. */
-printf("\nCursor ID is zero: %s\n", (string) $cursor->getId() === '0' ? 'yes' : 'no');
-var_dump($cursor);
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-Cursor ID is zero: no
-object(MongoDB\Driver\Cursor)#%d (%d) {
- %a
- ["session"]=>
- object(MongoDB\Driver\Session)#%d (%d) {
- %a
- }
- %a
-}
-
-Cursor ID is zero: yes
-object(MongoDB\Driver\Cursor)#%d (%d) {
- %a
- ["session"]=>
- NULL
- %a
-}
-===DONE===
diff --git a/mongodb-1.12.0/tests/cursor/cursor-tailable-003.phpt b/mongodb-1.12.0/tests/cursor/cursor-tailable-003.phpt
deleted file mode 100644
index 404f525b..00000000
--- a/mongodb-1.12.0/tests/cursor/cursor-tailable-003.phpt
+++ /dev/null
@@ -1,47 +0,0 @@
---TEST--
-MongoDB\Driver\Cursor tailable iteration with awaitData and maxAwaitTimeMS options
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_not_clean(); ?>
-<?php skip_if_server_version('<', '3.2'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-
-$manager->executeCommand(DATABASE_NAME, new MongoDB\Driver\Command([
- 'create' => COLLECTION_NAME,
- 'capped' => true,
- 'size' => 1048576,
-]));
-
-$bulkWrite = new MongoDB\Driver\BulkWrite;
-$bulkWrite->insert(['_id' => 1]);
-$manager->executeBulkWrite(NS, $bulkWrite);
-
-$cursor = $manager->executeQuery(NS, new MongoDB\Driver\Query([], [
- 'tailable' => true,
- 'awaitData' => true,
- 'maxAwaitTimeMS' => 10,
-]));
-$it = new IteratorIterator($cursor);
-
-$it->rewind();
-printf("{_id: %d}\n", $it->current()->_id);
-$it->next();
-
-$startTime = microtime(true);
-echo "Awaiting results...\n";
-$it->next();
-printf("Waited for %.6f seconds\n", microtime(true) - $startTime);
-// Sometimes the cursor will wait for 0.0099 seconds and sometimes it will wait for 0.01.
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-{_id: 1}
-Awaiting results...
-Waited for 0.0%d seconds
-===DONE===
diff --git a/mongodb-1.12.0/tests/cursor/cursor-tailable_error-002.phpt b/mongodb-1.12.0/tests/cursor/cursor-tailable_error-002.phpt
deleted file mode 100644
index 45c98a22..00000000
--- a/mongodb-1.12.0/tests/cursor/cursor-tailable_error-002.phpt
+++ /dev/null
@@ -1,90 +0,0 @@
---TEST--
-MongoDB\Driver\Cursor cursor killed during tailable iteration
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_not_clean(); ?>
-<?php skip_if_server_version('<', '3.2'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-function insert(MongoDB\Driver\Manager $manager, $from, $to = null)
-{
- if ($to === null) {
- $to = $from;
- }
-
- $bulkWrite = new MongoDB\Driver\BulkWrite;
-
- for ($i = $from; $i <= $to; $i++) {
- $bulkWrite->insert(['_id' => $i]);
- }
-
- $writeResult = $manager->executeBulkWrite(NS, $bulkWrite);
-
- printf("Inserted %d document(s): %s\n", $writeResult->getInsertedCount(), implode(', ', range($from, $to)));
-}
-
-$manager = create_test_manager();
-
-$manager->executeCommand(DATABASE_NAME, new MongoDB\Driver\Command([
- 'create' => COLLECTION_NAME,
- 'capped' => true,
- 'size' => 1048576,
-]));
-
-insert($manager, 1, 3);
-
-echo throws(function() use ($manager) {
- $cursor = $manager->executeQuery(NS, new MongoDB\Driver\Query([], ['tailable' => true]));
- $it = new IteratorIterator($cursor);
-
- $numAwaitAttempts = 0;
- $maxAwaitAttempts = 7;
-
- for ($it->rewind(); $numAwaitAttempts < $maxAwaitAttempts; $it->next()) {
- $document = $it->current();
-
- if ($document !== null) {
- printf("{_id: %d}\n", $document->_id);
- continue;
- }
-
- if ($numAwaitAttempts === 2) {
- insert($manager, 4, 6);
- }
-
- if ($numAwaitAttempts === 5) {
- $cursor->getServer()->executeCommand(DATABASE_NAME, new MongoDB\Driver\Command([
- 'killCursors' => COLLECTION_NAME,
- 'cursors' => [ $cursor->getId() ],
- ]));
- }
-
- echo "Awaiting results...\n";
- $numAwaitAttempts += 1;
- }
-}, 'MongoDB\Driver\Exception\RuntimeException'), "\n";
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-Inserted 3 document(s): 1, 2, 3
-{_id: 1}
-{_id: 2}
-{_id: 3}
-Awaiting results...
-Awaiting results...
-Inserted 3 document(s): 4, 5, 6
-Awaiting results...
-{_id: 4}
-{_id: 5}
-{_id: 6}
-Awaiting results...
-Awaiting results...
-Awaiting results...
-OK: Got MongoDB\Driver\Exception\RuntimeException
-%r(Cursor not found, cursor id: \d+|cursor id \d+ not found|Cursor not found \(.*id: \d+\)\.)%r
-===DONE===
diff --git a/mongodb-1.12.0/tests/cursorid/cursorid-002.phpt b/mongodb-1.12.0/tests/cursorid/cursorid-002.phpt
deleted file mode 100644
index 1ca48ad3..00000000
--- a/mongodb-1.12.0/tests/cursorid/cursorid-002.phpt
+++ /dev/null
@@ -1,44 +0,0 @@
---TEST--
-MongoDB\Driver\CursorId BSON serialization for killCursors command
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_not_clean(); ?>
-<?php skip_if_server_version('<', '3.2'); ?>
---FILE--
-<?php
-
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-
-// Select a specific server for future operations to avoid mongos switching in sharded clusters
-$server = $manager->selectServer(new \MongoDB\Driver\ReadPreference('primary'));
-
-$bulk = new MongoDB\Driver\BulkWrite();
-$bulk->insert(['_id' => 1]);
-$bulk->insert(['_id' => 2]);
-$bulk->insert(['_id' => 3]);
-$server->executeBulkWrite(NS, $bulk);
-
-$cursor = $server->executeQuery(NS, new MongoDB\Driver\Query([], ['batchSize' => 2]));
-$cursorId = $cursor->getId();
-
-$command = new MongoDB\Driver\Command([
- 'killCursors' => COLLECTION_NAME,
- 'cursors' => [ $cursorId ],
-]);
-
-/* Since the killCursors command result includes cursor IDs as 64-bit integers,
- * unserializing the result document requires a 64-bit platform. */
-$result = $server->executeCommand(DATABASE_NAME, $command)->toArray()[0];
-printf("Killed %d cursor(s)\n", count($result->cursorsKilled));
-printf("Killed expected cursor: %s\n", (string) $cursorId === (string) $result->cursorsKilled[0] ? 'yes' : 'no');
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-Killed 1 cursor(s)
-Killed expected cursor: yes
-===DONE===
diff --git a/mongodb-1.12.0/tests/manager/bug0572.phpt b/mongodb-1.12.0/tests/manager/bug0572.phpt
deleted file mode 100644
index f22776a3..00000000
--- a/mongodb-1.12.0/tests/manager/bug0572.phpt
+++ /dev/null
@@ -1,34 +0,0 @@
---TEST--
-PHPC-572: Ensure stream context does not go out of scope before socket init
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_ssl(); ?>
-<?php skip_if_not_ssl(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$closure = function() {
- $context = stream_context_create([
- 'ssl' => [
- 'verify_peer' => false,
- 'verify_peer_name' => false,
- 'allow_self_signed' => true,
- ],
- ]);
- return create_test_manager(URI, [], ['context' => $context]);
-};
-
-$manager = $closure();
-$cursor = $manager->executeCommand(DATABASE_NAME, new MongoDB\Driver\Command(['ping' => 1]));
-printf("ping: %d\n", $cursor->toArray()[0]->ok);
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-Deprecated: MongoDB\Driver\Manager::__construct(): The "context" driver option is deprecated.%s
-
-Deprecated: MongoDB\Driver\Manager::__construct(): The "allow_self_signed" context driver option is deprecated. Please use the "tlsAllowInvalidCertificates" URI option instead.%s
-ping: 1
-===DONE===
diff --git a/mongodb-1.12.0/tests/manager/bug1163-001.phpt b/mongodb-1.12.0/tests/manager/bug1163-001.phpt
deleted file mode 100644
index 04b007f5..00000000
--- a/mongodb-1.12.0/tests/manager/bug1163-001.phpt
+++ /dev/null
@@ -1,83 +0,0 @@
---TEST--
-PHPC-1163: Unacknowledged write concern should omit implicit session
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_server_version('<', '3.4'); ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-class Test implements MongoDB\Driver\Monitoring\CommandSubscriber
-{
- public function run()
- {
- $manager = create_test_manager(URI, ['w' => 0]);
-
- MongoDB\Driver\Monitoring\addSubscriber($this);
-
- $bulk = new MongoDB\Driver\BulkWrite;
- $bulk->insert(['x' => 1]);
-
- echo "Testing executeBulkWrite\n";
- $manager->executeBulkWrite(NS, $bulk);
-
- $command = new MongoDB\Driver\Command([
- 'insert' => COLLECTION_NAME,
- 'documents' => [['x' => 1]],
- ]);
-
- /* Note: executeCommand() and executeReadCommand() are not tested
- * because they do not inherit the client-level write concern. */
-
- echo "\nTesting executeWriteCommand\n";
- $manager->executeWriteCommand(DATABASE_NAME, $command);
-
- /* We can safely re-use the insert command with executeReadWriteCommand
- * because there is no readConcern to inherit. */
- echo "\nTesting executeReadWriteCommand\n";
- $manager->executeReadWriteCommand(DATABASE_NAME, $command);
-
- MongoDB\Driver\Monitoring\removeSubscriber($this);
- }
-
- public function commandStarted(MongoDB\Driver\Monitoring\CommandStartedEvent $event)
- {
- if ($event->getCommandName() === 'insert') {
- $command = $event->getCommand();
- $hasSession = isset($command->lsid);
- $writeConcern = isset($command->writeConcern) ? $command->writeConcern: null;
-
- printf("insert command write concern: %s\n", json_encode($writeConcern));
- printf("insert command has session: %s\n", $hasSession ? 'yes' : 'no');
- }
- }
-
- public function commandSucceeded(MongoDB\Driver\Monitoring\CommandSucceededEvent $event)
- {
- }
-
- public function commandFailed(MongoDB\Driver\Monitoring\CommandFailedEvent $event)
- {
- }
-}
-
-(new Test)->run();
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-Testing executeBulkWrite
-insert command write concern: {"w":0}
-insert command has session: no
-
-Testing executeWriteCommand
-insert command write concern: {"w":0}
-insert command has session: no
-
-Testing executeReadWriteCommand
-insert command write concern: {"w":0}
-insert command has session: no
-===DONE===
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-auth_mechanism-error-001.phpt b/mongodb-1.12.0/tests/manager/manager-ctor-auth_mechanism-error-001.phpt
deleted file mode 100644
index a98783e7..00000000
--- a/mongodb-1.12.0/tests/manager/manager-ctor-auth_mechanism-error-001.phpt
+++ /dev/null
@@ -1,61 +0,0 @@
---TEST--
-MongoDB\Driver\Manager::__construct(): authentication options are validated
---FILE--
-<?php
-
-require_once __DIR__ . '/../utils/basic.inc';
-
-echo throws(function() {
- create_test_manager('mongodb://localhost:27017/?authMechanism=GSSAPI&authSource=admin');
-}, "MongoDB\Driver\Exception\InvalidArgumentException"), "\n";
-
-echo throws(function() {
- create_test_manager('mongodb://localhost:27017/', ['authMechanism' => 'GSSAPI', 'authSource' => 'admin']);
-}, "MongoDB\Driver\Exception\InvalidArgumentException"), "\n";
-
-echo throws(function() {
- create_test_manager('mongodb://localhost:27017/?authMechanism=MONGODB-X509&authSource=admin');
-}, "MongoDB\Driver\Exception\InvalidArgumentException"), "\n";
-
-echo throws(function() {
- create_test_manager('mongodb://localhost:27017/', ['authMechanism' => 'MONGODB-X509', 'authSource' => 'admin']);
-}, "MongoDB\Driver\Exception\InvalidArgumentException"), "\n";
-
-echo throws(function() {
- create_test_manager('mongodb://@localhost:27017/?authMechanism=SCRAM-SHA-1');
-}, "MongoDB\Driver\Exception\InvalidArgumentException"), "\n";
-
-echo throws(function() {
- create_test_manager('mongodb://localhost:27017/', ['username' => '', 'authMechanism' => 'SCRAM-SHA-1']);
-}, "MongoDB\Driver\Exception\InvalidArgumentException"), "\n";
-
-echo throws(function() {
- create_test_manager('mongodb://localhost:27017/', ['password' => 'password', 'authMechanism' => 'MONGODB-X509']);
-}, "MongoDB\Driver\Exception\InvalidArgumentException"), "\n";
-
-// TODO: This test case should be removed by PHPC-1950
-echo throws(function() {
- create_test_manager('mongodb://localhost:27017/', ['authSource' => 'foo']);
-}, "MongoDB\Driver\Exception\InvalidArgumentException"), "\n";
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse MongoDB URI: 'mongodb://localhost:27017/?authMechanism=GSSAPI&authSource=admin'. GSSAPI and X509 require "$external" authSource.
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse URI options: GSSAPI and X509 require "$external" authSource.
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse MongoDB URI: 'mongodb://localhost:27017/?authMechanism=MONGODB-X509&authSource=admin'. GSSAPI and X509 require "$external" authSource.
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse URI options: GSSAPI and X509 require "$external" authSource.
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse MongoDB URI: 'mongodb://@localhost:27017/?authMechanism=SCRAM-SHA-1'. 'SCRAM-SHA-1' authentication mechanism requires username.
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse URI options: 'SCRAM-SHA-1' authentication mechanism requires username.
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse URI options: X509 authentication mechanism does not accept a password.
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse URI options: Default authentication mechanism requires username.
-===DONE===
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-directconnection-error-001.phpt b/mongodb-1.12.0/tests/manager/manager-ctor-directconnection-error-001.phpt
deleted file mode 100644
index 9d185938..00000000
--- a/mongodb-1.12.0/tests/manager/manager-ctor-directconnection-error-001.phpt
+++ /dev/null
@@ -1,25 +0,0 @@
---TEST--
-MongoDB\Driver\Manager::__construct(): directConnection=true conflicts with multiple seeds
---FILE--
-<?php
-
-require_once __DIR__ . '/../utils/basic.inc';
-
-echo throws(function() {
- $manager = create_test_manager('mongodb://a.example.com,b.example.com/?directConnection=true');
-}, "MongoDB\Driver\Exception\InvalidArgumentException"), "\n\n";
-
-echo throws(function() {
- $manager = create_test_manager('mongodb://a.example.com,b.example.com', ['directConnection' => true]);
-}, "MongoDB\Driver\Exception\InvalidArgumentException"), "\n";
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse MongoDB URI: 'mongodb://a.example.com,b.example.com/?directConnection=true'. Multiple seeds not allowed with directConnection option.
-
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse URI options: Multiple seeds not allowed with directConnection option.
-===DONE===
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-directconnection-error-002.phpt b/mongodb-1.12.0/tests/manager/manager-ctor-directconnection-error-002.phpt
deleted file mode 100644
index bd5600df..00000000
--- a/mongodb-1.12.0/tests/manager/manager-ctor-directconnection-error-002.phpt
+++ /dev/null
@@ -1,25 +0,0 @@
---TEST--
-MongoDB\Driver\Manager::__construct(): directConnection=true conflicts with SRV
---FILE--
-<?php
-
-require_once __DIR__ . '/../utils/basic.inc';
-
-echo throws(function() {
- $manager = create_test_manager('mongodb+srv://a.example.com/?directConnection=true');
-}, "MongoDB\Driver\Exception\InvalidArgumentException"), "\n\n";
-
-echo throws(function() {
- $manager = create_test_manager('mongodb+srv://a.example.com', ['directConnection' => true]);
-}, "MongoDB\Driver\Exception\InvalidArgumentException"), "\n";
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse MongoDB URI: 'mongodb+srv://a.example.com/?directConnection=true'. SRV URI not allowed with directConnection option.
-
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse URI options: SRV URI not allowed with directConnection option.
-===DONE===
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-disableClientPersistence-003.phpt b/mongodb-1.12.0/tests/manager/manager-ctor-disableClientPersistence-003.phpt
deleted file mode 100644
index e9c9eef7..00000000
--- a/mongodb-1.12.0/tests/manager/manager-ctor-disableClientPersistence-003.phpt
+++ /dev/null
@@ -1,40 +0,0 @@
---TEST--
-MongoDB\Driver\Manager with disableClientPersistence=true referenced by Session
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-ini_set('mongodb.debug', 'stderr');
-$manager = create_test_manager(URI, [], ['disableClientPersistence' => true]);
-ini_set('mongodb.debug', '');
-
-echo "Creating session\n";
-$session = $manager->startSession();
-
-echo "Unsetting manager\n";
-ini_set('mongodb.debug', 'stderr');
-unset($manager);
-ini_set('mongodb.debug', '');
-
-echo "Unsetting session\n";
-ini_set('mongodb.debug', 'stderr');
-unset($session);
-ini_set('mongodb.debug', '');
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-%A
-[%s] PHONGO: DEBUG > Created client with hash: %s
-[%s] PHONGO: DEBUG > Stored non-persistent client
-Creating session
-Unsetting manager
-Unsetting session%A
-[%s] PHONGO: DEBUG > Destroying non-persistent client for Manager%A
-===DONE===
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-tls-error-001.phpt b/mongodb-1.12.0/tests/manager/manager-ctor-tls-error-001.phpt
deleted file mode 100644
index 2a752f90..00000000
--- a/mongodb-1.12.0/tests/manager/manager-ctor-tls-error-001.phpt
+++ /dev/null
@@ -1,152 +0,0 @@
---TEST--
-MongoDB\Driver\Manager::__construct(): Test invalid URI option combinations
---FILE--
-<?php
-
-require_once __DIR__ . '/../utils/basic.inc';
-
-$invalidCombinations = [
- ['tlsInsecure', 'tlsAllowInvalidHostnames'],
- ['tlsInsecure', 'tlsAllowInvalidCertificates'],
- ['tlsInsecure', 'tlsDisableOCSPEndpointCheck'],
- ['tlsInsecure', 'tlsDisableCertificateRevocationCheck'],
- ['tlsAllowInvalidCertificates', 'tlsDisableOCSPEndpointCheck'],
- ['tlsAllowInvalidCertificates', 'tlsDisableCertificateRevocationCheck'],
-];
-
-foreach ($invalidCombinations as list($optionA, $optionB)) {
- foreach ([false, true] as $valueA) {
- foreach ([false, true] as $valueB) {
- echo throws(function() use ($optionA, $valueA, $optionB, $valueB) {
- create_test_manager(sprintf(
- 'mongodb://localhost:27017/?%s=%s&%s=%s',
- $optionA,
- $valueA ? 'true' : 'false',
- $optionB,
- $valueB ? 'true' : 'false'
- ));
- }, "MongoDB\Driver\Exception\InvalidArgumentException"), "\n";
-
- echo throws(function() use ($optionA, $valueA, $optionB, $valueB) {
- create_test_manager(
- sprintf(
- 'mongodb://localhost:27017/?%s=%s',
- $optionA,
- $valueA ? 'true' : 'false'
- ),
- [ $optionB => $valueB ]
- );
- }, "MongoDB\Driver\Exception\InvalidArgumentException"), "\n";
- }
- }
-
- echo "\n";
-}
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse MongoDB URI: 'mongodb://localhost:27017/?tlsInsecure=false&tlsAllowInvalidHostnames=false'. tlsinsecure may not be specified with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck.
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse URI options: tlsinsecure may not be combined with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck.
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse MongoDB URI: 'mongodb://localhost:27017/?tlsInsecure=false&tlsAllowInvalidHostnames=true'. tlsinsecure may not be specified with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck.
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse URI options: tlsinsecure may not be combined with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck.
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse MongoDB URI: 'mongodb://localhost:27017/?tlsInsecure=true&tlsAllowInvalidHostnames=false'. tlsinsecure may not be specified with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck.
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse URI options: tlsinsecure may not be combined with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck.
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse MongoDB URI: 'mongodb://localhost:27017/?tlsInsecure=true&tlsAllowInvalidHostnames=true'. tlsinsecure may not be specified with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck.
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse URI options: tlsinsecure may not be combined with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck.
-
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse MongoDB URI: 'mongodb://localhost:27017/?tlsInsecure=false&tlsAllowInvalidCertificates=false'. tlsinsecure may not be specified with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck.
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse URI options: tlsinsecure may not be combined with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck.
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse MongoDB URI: 'mongodb://localhost:27017/?tlsInsecure=false&tlsAllowInvalidCertificates=true'. tlsinsecure may not be specified with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck.
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse URI options: tlsinsecure may not be combined with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck.
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse MongoDB URI: 'mongodb://localhost:27017/?tlsInsecure=true&tlsAllowInvalidCertificates=false'. tlsinsecure may not be specified with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck.
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse URI options: tlsinsecure may not be combined with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck.
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse MongoDB URI: 'mongodb://localhost:27017/?tlsInsecure=true&tlsAllowInvalidCertificates=true'. tlsinsecure may not be specified with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck.
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse URI options: tlsinsecure may not be combined with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck.
-
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse MongoDB URI: 'mongodb://localhost:27017/?tlsInsecure=false&tlsDisableOCSPEndpointCheck=false'. tlsinsecure may not be specified with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck.
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse URI options: tlsinsecure may not be combined with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck.
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse MongoDB URI: 'mongodb://localhost:27017/?tlsInsecure=false&tlsDisableOCSPEndpointCheck=true'. tlsinsecure may not be specified with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck.
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse URI options: tlsinsecure may not be combined with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck.
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse MongoDB URI: 'mongodb://localhost:27017/?tlsInsecure=true&tlsDisableOCSPEndpointCheck=false'. tlsinsecure may not be specified with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck.
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse URI options: tlsinsecure may not be combined with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck.
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse MongoDB URI: 'mongodb://localhost:27017/?tlsInsecure=true&tlsDisableOCSPEndpointCheck=true'. tlsinsecure may not be specified with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck.
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse URI options: tlsinsecure may not be combined with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck.
-
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse MongoDB URI: 'mongodb://localhost:27017/?tlsInsecure=false&tlsDisableCertificateRevocationCheck=false'. tlsinsecure may not be specified with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck.
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse URI options: tlsinsecure may not be combined with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck.
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse MongoDB URI: 'mongodb://localhost:27017/?tlsInsecure=false&tlsDisableCertificateRevocationCheck=true'. tlsinsecure may not be specified with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck.
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse URI options: tlsinsecure may not be combined with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck.
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse MongoDB URI: 'mongodb://localhost:27017/?tlsInsecure=true&tlsDisableCertificateRevocationCheck=false'. tlsinsecure may not be specified with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck.
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse URI options: tlsinsecure may not be combined with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck.
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse MongoDB URI: 'mongodb://localhost:27017/?tlsInsecure=true&tlsDisableCertificateRevocationCheck=true'. tlsinsecure may not be specified with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck.
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse URI options: tlsinsecure may not be combined with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck.
-
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse MongoDB URI: 'mongodb://localhost:27017/?tlsAllowInvalidCertificates=false&tlsDisableOCSPEndpointCheck=false'. tlsallowinvalidcertificates may not be specified with tlsdisableocspendpointcheck or tlsdisablecertificaterevocationcheck.
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse URI options: tlsallowinvalidcertificates may not be combined with tlsdisableocspendpointcheck or tlsdisablecertificaterevocationcheck.
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse MongoDB URI: 'mongodb://localhost:27017/?tlsAllowInvalidCertificates=false&tlsDisableOCSPEndpointCheck=true'. tlsallowinvalidcertificates may not be specified with tlsdisableocspendpointcheck or tlsdisablecertificaterevocationcheck.
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse URI options: tlsallowinvalidcertificates may not be combined with tlsdisableocspendpointcheck or tlsdisablecertificaterevocationcheck.
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse MongoDB URI: 'mongodb://localhost:27017/?tlsAllowInvalidCertificates=true&tlsDisableOCSPEndpointCheck=false'. tlsallowinvalidcertificates may not be specified with tlsdisableocspendpointcheck or tlsdisablecertificaterevocationcheck.
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse URI options: tlsallowinvalidcertificates may not be combined with tlsdisableocspendpointcheck or tlsdisablecertificaterevocationcheck.
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse MongoDB URI: 'mongodb://localhost:27017/?tlsAllowInvalidCertificates=true&tlsDisableOCSPEndpointCheck=true'. tlsallowinvalidcertificates may not be specified with tlsdisableocspendpointcheck or tlsdisablecertificaterevocationcheck.
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse URI options: tlsallowinvalidcertificates may not be combined with tlsdisableocspendpointcheck or tlsdisablecertificaterevocationcheck.
-
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse MongoDB URI: 'mongodb://localhost:27017/?tlsAllowInvalidCertificates=false&tlsDisableCertificateRevocationCheck=false'. tlsallowinvalidcertificates may not be specified with tlsdisableocspendpointcheck or tlsdisablecertificaterevocationcheck.
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse URI options: tlsallowinvalidcertificates may not be combined with tlsdisableocspendpointcheck or tlsdisablecertificaterevocationcheck.
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse MongoDB URI: 'mongodb://localhost:27017/?tlsAllowInvalidCertificates=false&tlsDisableCertificateRevocationCheck=true'. tlsallowinvalidcertificates may not be specified with tlsdisableocspendpointcheck or tlsdisablecertificaterevocationcheck.
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse URI options: tlsallowinvalidcertificates may not be combined with tlsdisableocspendpointcheck or tlsdisablecertificaterevocationcheck.
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse MongoDB URI: 'mongodb://localhost:27017/?tlsAllowInvalidCertificates=true&tlsDisableCertificateRevocationCheck=false'. tlsallowinvalidcertificates may not be specified with tlsdisableocspendpointcheck or tlsdisablecertificaterevocationcheck.
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse URI options: tlsallowinvalidcertificates may not be combined with tlsdisableocspendpointcheck or tlsdisablecertificaterevocationcheck.
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse MongoDB URI: 'mongodb://localhost:27017/?tlsAllowInvalidCertificates=true&tlsDisableCertificateRevocationCheck=true'. tlsallowinvalidcertificates may not be specified with tlsdisableocspendpointcheck or tlsdisablecertificaterevocationcheck.
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Failed to parse URI options: tlsallowinvalidcertificates may not be combined with tlsdisableocspendpointcheck or tlsdisablecertificaterevocationcheck.
-
-===DONE===
diff --git a/mongodb-1.12.0/tests/manager/manager-executeBulkWrite-011.phpt b/mongodb-1.12.0/tests/manager/manager-executeBulkWrite-011.phpt
deleted file mode 100644
index 21858edd..00000000
--- a/mongodb-1.12.0/tests/manager/manager-executeBulkWrite-011.phpt
+++ /dev/null
@@ -1,85 +0,0 @@
---TEST--
-MongoDB\Driver\BulkWrite: bypassDocumentValidation option
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_not_clean(); ?>
-<?php skip_if_server_version('<', '3.2'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-
-$command = new MongoDB\Driver\Command([
- 'create' => COLLECTION_NAME,
- 'validator' => ['x' => ['$type' => 'number']],
-]);
-$manager->executeCommand(DATABASE_NAME, $command);
-
-$bulk = new MongoDB\Driver\BulkWrite();
-$bulk->insert(['_id' => 1, 'x' => 1]);
-$bulk->insert(['_id' => 2, 'x' => 2]);
-$manager->executeBulkWrite(NS, $bulk);
-
-$bulk = new MongoDB\Driver\BulkWrite(['bypassDocumentValidation' => true]);
-$bulk->update(['_id' => 2], ['$set' => ['x' => 'two']]);
-$manager->executeBulkWrite(NS, $bulk);
-
-$bulk = new MongoDB\Driver\BulkWrite(['bypassDocumentValidation' => true]);
-$bulk->insert(['_id' => 3, 'x' => 'three']);
-$manager->executeBulkWrite(NS, $bulk);
-
-$bulk = new MongoDB\Driver\BulkWrite();
-$bulk->insert(['_id' => 4, 'x' => 'four']);
-
-echo throws(function() use($manager, $bulk) {
- $manager->executeBulkWrite(NS, $bulk);
-}, "MongoDB\Driver\Exception\BulkWriteException"), "\n";
-
-$bulk = new MongoDB\Driver\BulkWrite();
-$bulk->update(['_id' => 1], ['$set' => ['x' => 'one']]);
-
-echo throws(function() use($manager, $bulk) {
- $manager->executeBulkWrite(NS, $bulk);
-}, "MongoDB\Driver\Exception\BulkWriteException"), "\n";
-
-$bulk = new MongoDB\Driver\BulkWrite();
-$bulk->update(['_id' => 2], ['$set' => ['x' => 2]]);
-$manager->executeBulkWrite(NS, $bulk);
-
-$cursor = $manager->executeQuery(NS, new MongoDB\Driver\Query([]));
-var_dump(iterator_to_array($cursor));
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-OK: Got MongoDB\Driver\Exception\BulkWriteException
-Document failed validation
-OK: Got MongoDB\Driver\Exception\BulkWriteException
-Document failed validation
-array(3) {
- [0]=>
- object(stdClass)#%d (2) {
- ["_id"]=>
- int(1)
- ["x"]=>
- int(1)
- }
- [1]=>
- object(stdClass)#%d (2) {
- ["_id"]=>
- int(2)
- ["x"]=>
- int(2)
- }
- [2]=>
- object(stdClass)#%d (2) {
- ["_id"]=>
- int(3)
- ["x"]=>
- string(5) "three"
- }
-}
-===DONE===
diff --git a/mongodb-1.12.0/tests/manager/manager-executeBulkWrite_error-010.phpt b/mongodb-1.12.0/tests/manager/manager-executeBulkWrite_error-010.phpt
deleted file mode 100644
index 4b655006..00000000
--- a/mongodb-1.12.0/tests/manager/manager-executeBulkWrite_error-010.phpt
+++ /dev/null
@@ -1,43 +0,0 @@
---TEST--
-MongoDB\Driver\Manager::executeBulkWrite() cannot combine session with unacknowledged write concern
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-echo throws(function() {
- $manager = create_test_manager();
-
- $bulk = new MongoDB\Driver\BulkWrite;
- $bulk->insert(['x' => 1]);
-
- $manager->executeBulkWrite(NS, $bulk, [
- 'session' => $manager->startSession(),
- 'writeConcern' => new MongoDB\Driver\WriteConcern(0),
- ]);
-}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
-
-echo throws(function() {
- $manager = create_test_manager(URI, ['w' => 0]);
-
- $bulk = new MongoDB\Driver\BulkWrite;
- $bulk->insert(['x' => 1]);
-
- $manager->executeBulkWrite(NS, $bulk, [
- 'session' => $manager->startSession(),
- ]);
-}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Cannot combine "session" option with an unacknowledged write concern
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Cannot combine "session" option with an unacknowledged write concern
-===DONE===
diff --git a/mongodb-1.12.0/tests/manager/manager-executeCommand-004.phpt b/mongodb-1.12.0/tests/manager/manager-executeCommand-004.phpt
deleted file mode 100644
index c3903829..00000000
--- a/mongodb-1.12.0/tests/manager/manager-executeCommand-004.phpt
+++ /dev/null
@@ -1,51 +0,0 @@
---TEST--
-MongoDB\Driver\Manager::executeCommand() options (MONGOC_CMD_RAW)
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_not_replica_set(); ?>
-<?php skip_if_no_secondary(); ?>
-<?php skip_if_not_clean(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-require_once __DIR__ . "/../utils/observer.php";
-
-$manager = create_test_manager();
-
-(new CommandObserver)->observe(
- function() use ($manager) {
- $command = new MongoDB\Driver\Command([
- 'ping' => true,
- ]);
-
- try {
- $manager->executeCommand(
- DATABASE_NAME,
- $command,
- [
- 'readPreference' => new \MongoDB\Driver\ReadPreference(\MongoDB\Driver\ReadPreference::RP_SECONDARY),
- 'readConcern' => new \MongoDB\Driver\ReadConcern(\MongoDB\Driver\ReadConcern::LOCAL),
- 'writeConcern' => new \MongoDB\Driver\WriteConcern(\MongoDB\Driver\WriteConcern::MAJORITY),
- ]
- );
- } catch ( Exception $e ) {
- // Ignore exception that ping doesn't support writeConcern
- }
- },
- function(stdClass $command) {
- echo "Read Preference: ", $command->{'$readPreference'}->mode, "\n";
- echo "Read Concern: ", $command->readConcern->level, "\n";
- echo "Write Concern: ", $command->writeConcern->w, "\n";
- }
-);
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-Read Preference: secondary
-Read Concern: local
-Write Concern: majority
-===DONE===
diff --git a/mongodb-1.12.0/tests/manager/manager-executeCommand-007.phpt b/mongodb-1.12.0/tests/manager/manager-executeCommand-007.phpt
deleted file mode 100644
index 3ec8d754..00000000
--- a/mongodb-1.12.0/tests/manager/manager-executeCommand-007.phpt
+++ /dev/null
@@ -1,47 +0,0 @@
---TEST--
-MongoDB\Driver\Manager::executeCommand() does not inherit read or write concern
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_replica_set(); ?>
-<?php skip_if_not_enough_data_nodes(2); /* w:2 */ ?>
-<?php skip_if_server_version('<', '3.6'); /* readConcernLevel:available */ ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-require_once __DIR__ . "/../utils/observer.php";
-
-$manager = create_test_manager(URI, ['readConcernLevel' => 'local', 'w' => 2, 'wtimeoutms' => 1000]);
-
-$command = new MongoDB\Driver\Command([
- 'aggregate' => COLLECTION_NAME,
- 'pipeline' => [
- ['$group' => ['_id' => 1]],
- ['$out' => COLLECTION_NAME . '.out'],
- ],
- 'cursor' => (object) [],
-]);
-
-(new CommandObserver)->observe(
- function() use ($manager, $command) {
- $manager->executeCommand(DATABASE_NAME, $command);
- $manager->executeCommand(DATABASE_NAME, $command, [
- 'readConcern' => new MongoDB\Driver\ReadConcern(MongoDB\Driver\ReadConcern::AVAILABLE),
- 'writeConcern' => new MongoDB\Driver\WriteConcern(1),
- ]);
- },
- function(stdClass $command) {
- echo json_encode($command->readConcern ?? null), "\n";
- echo json_encode($command->writeConcern ?? null), "\n";
- }
-);
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-null
-null
-{"level":"available"}
-{"w":1}
-===DONE===
diff --git a/mongodb-1.12.0/tests/manager/manager-executeCommand_error-005.phpt b/mongodb-1.12.0/tests/manager/manager-executeCommand_error-005.phpt
deleted file mode 100644
index fb4211ee..00000000
--- a/mongodb-1.12.0/tests/manager/manager-executeCommand_error-005.phpt
+++ /dev/null
@@ -1,28 +0,0 @@
---TEST--
-MongoDB\Driver\Manager::executeCommand() cannot combine session with unacknowledged write concern
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-echo throws(function() {
- $manager = create_test_manager();
- $command = new MongoDB\Driver\Command([
- 'insert' => COLLECTION_NAME,
- 'documents' => [['x' => 1]],
- ]);
- $manager->executeCommand(DATABASE_NAME, $command, [
- 'session' => $manager->startSession(),
- 'writeConcern' => new MongoDB\Driver\WriteConcern(0),
- ]);
-}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Cannot combine "session" option with an unacknowledged write concern
-===DONE===
diff --git a/mongodb-1.12.0/tests/manager/manager-executeQuery-001.phpt b/mongodb-1.12.0/tests/manager/manager-executeQuery-001.phpt
deleted file mode 100644
index 0f7ecfd3..00000000
--- a/mongodb-1.12.0/tests/manager/manager-executeQuery-001.phpt
+++ /dev/null
@@ -1,92 +0,0 @@
---TEST--
-MongoDB\Driver\Manager::executeQuery() one document (OP_QUERY)
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_server_version('>=', '3.1'); ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-
-// load fixtures for test
-$bulk = new MongoDB\Driver\BulkWrite();
-$bulk->insert(array('_id' => 1, 'x' => 2, 'y' => 3));
-$bulk->insert(array('_id' => 2, 'x' => 3, 'y' => 4));
-$bulk->insert(array('_id' => 3, 'x' => 4, 'y' => 5));
-$manager->executeBulkWrite(NS, $bulk);
-
-$query = new MongoDB\Driver\Query(array('x' => 3), array('projection' => array('y' => 1)));
-$qr = $manager->executeQuery(NS, $query);
-
-var_dump($qr instanceof MongoDB\Driver\Cursor);
-var_dump($qr);
-
-$server = $qr->getServer();
-
-var_dump($server instanceof MongoDB\Driver\Server);
-var_dump($server->getHost());
-var_dump($server->getPort());
-
-var_dump(iterator_to_array($qr));
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-bool(true)
-object(MongoDB\Driver\Cursor)#%d (%d) {
- ["database"]=>
- string(6) "phongo"
- ["collection"]=>
- string(32) "manager_manager_executeQuery_001"
- ["query"]=>
- object(MongoDB\Driver\Query)#%d (%d) {
- ["filter"]=>
- object(stdClass)#%d (%d) {
- ["x"]=>
- int(3)
- }
- ["options"]=>
- object(stdClass)#%d (%d) {
- ["projection"]=>
- object(stdClass)#%d (%d) {
- ["y"]=>
- int(1)
- }
- }
- ["readConcern"]=>
- NULL
- }
- ["command"]=>
- NULL
- ["readPreference"]=>
- NULL
- ["session"]=>
- NULL
- ["isDead"]=>
- bool(false)
- ["currentIndex"]=>
- int(0)
- ["currentDocument"]=>
- NULL
- ["server"]=>
- object(MongoDB\Driver\Server)#%d (%d) {
- %a
- }
-}
-bool(true)
-string(%d) "%s"
-int(%d)
-array(1) {
- [0]=>
- object(stdClass)#%d (2) {
- ["_id"]=>
- int(2)
- ["y"]=>
- int(4)
- }
-}
-===DONE===
diff --git a/mongodb-1.12.0/tests/manager/manager-executeQuery-002.phpt b/mongodb-1.12.0/tests/manager/manager-executeQuery-002.phpt
deleted file mode 100644
index 9cd90781..00000000
--- a/mongodb-1.12.0/tests/manager/manager-executeQuery-002.phpt
+++ /dev/null
@@ -1,91 +0,0 @@
---TEST--
-MongoDB\Driver\Manager::executeQuery() one document (find command)
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-
-// load fixtures for test
-$bulk = new MongoDB\Driver\BulkWrite();
-$bulk->insert(array('_id' => 1, 'x' => 2, 'y' => 3));
-$bulk->insert(array('_id' => 2, 'x' => 3, 'y' => 4));
-$bulk->insert(array('_id' => 3, 'x' => 4, 'y' => 5));
-$manager->executeBulkWrite(NS, $bulk);
-
-$query = new MongoDB\Driver\Query(array('x' => 3), array('projection' => array('y' => 1)));
-$qr = $manager->executeQuery(NS, $query);
-
-var_dump($qr instanceof MongoDB\Driver\Cursor);
-var_dump($qr);
-
-$server = $qr->getServer();
-
-var_dump($server instanceof MongoDB\Driver\Server);
-var_dump($server->getHost());
-var_dump($server->getPort());
-
-var_dump(iterator_to_array($qr));
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-bool(true)
-object(MongoDB\Driver\Cursor)#%d (%d) {
- ["database"]=>
- string(6) "phongo"
- ["collection"]=>
- string(32) "manager_manager_executeQuery_002"
- ["query"]=>
- object(MongoDB\Driver\Query)#%d (%d) {
- ["filter"]=>
- object(stdClass)#%d (%d) {
- ["x"]=>
- int(3)
- }
- ["options"]=>
- object(stdClass)#%d (%d) {
- ["projection"]=>
- object(stdClass)#%d (%d) {
- ["y"]=>
- int(1)
- }
- }
- ["readConcern"]=>
- NULL
- }
- ["command"]=>
- NULL
- ["readPreference"]=>
- NULL
- ["session"]=>
- NULL
- ["isDead"]=>
- bool(false)
- ["currentIndex"]=>
- int(0)
- ["currentDocument"]=>
- NULL
- ["server"]=>
- object(MongoDB\Driver\Server)#%d (%d) {
- %a
- }
-}
-bool(true)
-string(%d) "%s"
-int(%d)
-array(1) {
- [0]=>
- object(stdClass)#%d (2) {
- ["_id"]=>
- int(2)
- ["y"]=>
- int(4)
- }
-}
-===DONE===
diff --git a/mongodb-1.12.0/tests/manager/manager-executeQuery-007.phpt b/mongodb-1.12.0/tests/manager/manager-executeQuery-007.phpt
deleted file mode 100644
index cc5f51a4..00000000
--- a/mongodb-1.12.0/tests/manager/manager-executeQuery-007.phpt
+++ /dev/null
@@ -1,33 +0,0 @@
---TEST--
-MongoDB\Driver\Manager::executeQuery() read concern inheritance
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_replica_set(); ?>
-<?php skip_if_server_version('<', '3.6'); /* readConcernLevel:available */ ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-require_once __DIR__ . "/../utils/observer.php";
-
-$manager = create_test_manager(URI, ['readConcernLevel' => 'local']);
-
-(new CommandObserver)->observe(
- function() use ($manager) {
- $manager->executeQuery(NS, new MongoDB\Driver\Query([]));
- $manager->executeQuery(NS, new MongoDB\Driver\Query([], [
- 'readConcern' => new MongoDB\Driver\ReadConcern(MongoDB\Driver\ReadConcern::AVAILABLE),
- ]));
- },
- function(stdClass $command) {
- echo json_encode($command->readConcern), "\n";
- }
-);
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-{"level":"local"}
-{"level":"available"}
-===DONE===
diff --git a/mongodb-1.12.0/tests/manager/manager-executeQuery_error-003.phpt b/mongodb-1.12.0/tests/manager/manager-executeQuery_error-003.phpt
deleted file mode 100644
index 130c7239..00000000
--- a/mongodb-1.12.0/tests/manager/manager-executeQuery_error-003.phpt
+++ /dev/null
@@ -1,30 +0,0 @@
---TEST--
-MongoDB\Driver\Manager::executeQuery() exposes error document via CommandException
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_server_version('<', '3.2'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-$query = new MongoDB\Driver\Query(['field' => ['$unsupportedOperator' => true]]);
-
-try {
- $manager->executeQuery(NS, $query);
-} catch (\MongoDB\Driver\Exception\CommandException $e) {
- printf("%s(%d): %s\n", get_class($e), $e->getCode(), $e->getMessage());
- $doc = $e->getResultDocument();
- var_dump($doc->errmsg === $e->getMessage());
- var_dump($doc->code === $e->getCode());
-}
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-MongoDB\Driver\Exception\CommandException(2): unknown operator: $unsupportedOperator
-bool(true)
-bool(true)
-===DONE===
diff --git a/mongodb-1.12.0/tests/manager/manager-executeReadCommand-001.phpt b/mongodb-1.12.0/tests/manager/manager-executeReadCommand-001.phpt
deleted file mode 100644
index 16ece346..00000000
--- a/mongodb-1.12.0/tests/manager/manager-executeReadCommand-001.phpt
+++ /dev/null
@@ -1,47 +0,0 @@
---TEST--
-MongoDB\Driver\Manager::executeReadCommand()
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_not_replica_set(); ?>
-<?php skip_if_no_secondary(); ?>
-<?php skip_if_not_clean(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
-<?php skip_if_not_server_storage_engine('wiredTiger'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-require_once __DIR__ . "/../utils/observer.php";
-
-$manager = create_test_manager();
-
-(new CommandObserver)->observe(
- function() use ($manager) {
- $command = new MongoDB\Driver\Command( [
- 'aggregate' => NS,
- 'pipeline' => [],
- 'cursor' => new stdClass(),
- ] );
- $manager->executeReadCommand(
- DATABASE_NAME,
- $command,
- [
- 'readPreference' => new \MongoDB\Driver\ReadPreference(\MongoDB\Driver\ReadPreference::RP_SECONDARY),
- 'readConcern' => new \MongoDB\Driver\ReadConcern(\MongoDB\Driver\ReadConcern::MAJORITY),
- ]
- );
- },
- function(stdClass $command) {
- echo "Read Preference: ", $command->{'$readPreference'}->mode, "\n";
- echo "Read Concern: ", $command->readConcern->level, "\n";
- }
-);
-
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-Read Preference: secondary
-Read Concern: majority
-===DONE===
diff --git a/mongodb-1.12.0/tests/manager/manager-executeReadCommand-003.phpt b/mongodb-1.12.0/tests/manager/manager-executeReadCommand-003.phpt
deleted file mode 100644
index 084ba1f6..00000000
--- a/mongodb-1.12.0/tests/manager/manager-executeReadCommand-003.phpt
+++ /dev/null
@@ -1,39 +0,0 @@
---TEST--
-MongoDB\Driver\Manager::executeReadCommand() read concern inheritance
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_replica_set(); ?>
-<?php skip_if_server_version('<', '3.6'); /* readConcernLevel:available */ ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-require_once __DIR__ . "/../utils/observer.php";
-
-$manager = create_test_manager(URI, ['readConcernLevel' => 'local']);
-
-$command = new MongoDB\Driver\Command([
- 'aggregate' => COLLECTION_NAME,
- 'pipeline' => [['$group' => ['_id' => 1]]],
- 'cursor' => (object) [],
-]);
-
-(new CommandObserver)->observe(
- function() use ($manager, $command) {
- $manager->executeReadCommand(DATABASE_NAME, $command);
- $manager->executeReadCommand(DATABASE_NAME, $command, [
- 'readConcern' => new MongoDB\Driver\ReadConcern(MongoDB\Driver\ReadConcern::AVAILABLE),
- ]);
- },
- function(stdClass $command) {
- echo json_encode($command->readConcern), "\n";
- }
-);
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-{"level":"local"}
-{"level":"available"}
-===DONE===
diff --git a/mongodb-1.12.0/tests/manager/manager-executeReadWriteCommand-001.phpt b/mongodb-1.12.0/tests/manager/manager-executeReadWriteCommand-001.phpt
deleted file mode 100644
index 9c0b1b2a..00000000
--- a/mongodb-1.12.0/tests/manager/manager-executeReadWriteCommand-001.phpt
+++ /dev/null
@@ -1,47 +0,0 @@
---TEST--
-MongoDB\Driver\Manager::executeReadWriteCommand()
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_not_clean(); ?>
-<?php skip_if_server_version('<', '3.4'); /* aggregate write concern */ ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-require_once __DIR__ . "/../utils/observer.php";
-
-$manager = create_test_manager();
-
-$command = new MongoDB\Driver\Command([
- 'aggregate' => COLLECTION_NAME,
- 'pipeline' => [
- ['$group' => ['_id' => 1]],
- ['$out' => COLLECTION_NAME . '.out'],
- ],
- 'cursor' => (object) [],
-]);
-
-(new CommandObserver)->observe(
- function() use ($manager, $command) {
- $manager->executeReadWriteCommand(
- DATABASE_NAME,
- $command,
- [
- 'readConcern' => new \MongoDB\Driver\ReadConcern(\MongoDB\Driver\ReadConcern::LOCAL),
- 'writeConcern' => new \MongoDB\Driver\WriteConcern(\MongoDB\Driver\WriteConcern::MAJORITY),
- ]
- );
- },
- function(stdClass $command) {
- echo "Read Concern: ", $command->readConcern->level, "\n";
- echo "Write Concern: ", $command->writeConcern->w, "\n";
- }
-);
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-Read Concern: local
-Write Concern: majority
-===DONE===
diff --git a/mongodb-1.12.0/tests/manager/manager-executeReadWriteCommand-003.phpt b/mongodb-1.12.0/tests/manager/manager-executeReadWriteCommand-003.phpt
deleted file mode 100644
index 17cfb5ce..00000000
--- a/mongodb-1.12.0/tests/manager/manager-executeReadWriteCommand-003.phpt
+++ /dev/null
@@ -1,47 +0,0 @@
---TEST--
-MongoDB\Driver\Manager::executeReadWriteCommand() read and write concern inheritance
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_replica_set(); ?>
-<?php skip_if_not_enough_data_nodes(2); /* w:2 */ ?>
-<?php skip_if_server_version('<', '3.6'); /* readConcernLevel:available */ ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-require_once __DIR__ . "/../utils/observer.php";
-
-$manager = create_test_manager(URI, ['readConcernLevel' => 'local', 'w' => 2, 'wtimeoutms' => 1000]);
-
-$command = new MongoDB\Driver\Command([
- 'aggregate' => COLLECTION_NAME,
- 'pipeline' => [
- ['$group' => ['_id' => 1]],
- ['$out' => COLLECTION_NAME . '.out'],
- ],
- 'cursor' => (object) [],
-]);
-
-(new CommandObserver)->observe(
- function() use ($manager, $command) {
- $manager->executeReadWriteCommand(DATABASE_NAME, $command);
- $manager->executeReadWriteCommand(DATABASE_NAME, $command, [
- 'readConcern' => new MongoDB\Driver\ReadConcern(MongoDB\Driver\ReadConcern::AVAILABLE),
- 'writeConcern' => new MongoDB\Driver\WriteConcern(1),
- ]);
- },
- function(stdClass $command) {
- echo json_encode($command->readConcern), "\n";
- echo json_encode($command->writeConcern), "\n";
- }
-);
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-{"level":"local"}
-{"w":2,"wtimeout":1000}
-{"level":"available"}
-{"w":1}
-===DONE===
diff --git a/mongodb-1.12.0/tests/manager/manager-executeReadWriteCommand_error-002.phpt b/mongodb-1.12.0/tests/manager/manager-executeReadWriteCommand_error-002.phpt
deleted file mode 100644
index d20caa85..00000000
--- a/mongodb-1.12.0/tests/manager/manager-executeReadWriteCommand_error-002.phpt
+++ /dev/null
@@ -1,49 +0,0 @@
---TEST--
-MongoDB\Driver\Manager::executeReadWriteCommand() cannot combine session with unacknowledged write concern
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-/* insert should not normally be used with executeReadWriteCommand(), but we are
- * only testing executeReadWriteCommand()'s option validation. */
-echo throws(function() {
- $manager = create_test_manager();
-
- $command = new MongoDB\Driver\Command([
- 'insert' => COLLECTION_NAME,
- 'documents' => [['x' => 1]],
- ]);
-
- $manager->executeReadWriteCommand(DATABASE_NAME, $command, [
- 'session' => $manager->startSession(),
- 'writeConcern' => new MongoDB\Driver\WriteConcern(0),
- ]);
-}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
-
-echo throws(function() {
- $manager = create_test_manager(URI, ['w' => 0]);
-
- $command = new MongoDB\Driver\Command([
- 'insert' => COLLECTION_NAME,
- 'documents' => [['x' => 1]],
- ]);
-
- $manager->executeReadWriteCommand(DATABASE_NAME, $command, [
- 'session' => $manager->startSession(),
- ]);
-}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Cannot combine "session" option with an unacknowledged write concern
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Cannot combine "session" option with an unacknowledged write concern
-===DONE===
diff --git a/mongodb-1.12.0/tests/manager/manager-executeWriteCommand-001.phpt b/mongodb-1.12.0/tests/manager/manager-executeWriteCommand-001.phpt
deleted file mode 100644
index af3f00bc..00000000
--- a/mongodb-1.12.0/tests/manager/manager-executeWriteCommand-001.phpt
+++ /dev/null
@@ -1,42 +0,0 @@
---TEST--
-MongoDB\Driver\Manager::executeWriteCommand()
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_not_clean(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-require_once __DIR__ . "/../utils/observer.php";
-
-$manager = create_test_manager();
-
-$bw = new MongoDB\Driver\BulkWrite();
-$bw->insert(['a' => 1]);
-$manager->executeBulkWrite(NS, $bw);
-
-(new CommandObserver)->observe(
- function() use ($manager) {
- $command = new MongoDB\Driver\Command([
- 'drop' => COLLECTION_NAME,
- ]);
- $manager->executeWriteCommand(
- DATABASE_NAME,
- $command,
- [
- 'writeConcern' => new \MongoDB\Driver\WriteConcern(\MongoDB\Driver\WriteConcern::MAJORITY),
- ]
- );
- },
- function(stdClass $command) {
- echo "Write Concern: ", $command->writeConcern->w, "\n";
- }
-);
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-Write Concern: majority
-===DONE===
diff --git a/mongodb-1.12.0/tests/manager/manager-executeWriteCommand-003.phpt b/mongodb-1.12.0/tests/manager/manager-executeWriteCommand-003.phpt
deleted file mode 100644
index 19b483c6..00000000
--- a/mongodb-1.12.0/tests/manager/manager-executeWriteCommand-003.phpt
+++ /dev/null
@@ -1,40 +0,0 @@
---TEST--
-MongoDB\Driver\Manager::executeWriteCommand() write concern inheritance
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_replica_set(); ?>
-<?php skip_if_not_enough_data_nodes(2); /* w:2 */ ?>
-<?php skip_if_server_version('<', '3.2'); /* findAndModify writeConcern */ ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-require_once __DIR__ . "/../utils/observer.php";
-
-$manager = create_test_manager(URI, ['w' => 2, 'wtimeoutms' => 1000]);
-
-$command = new MongoDB\Driver\Command([
- 'findAndModify' => COLLECTION_NAME,
- 'query' => ['x' => 1],
- 'upsert' => true,
- 'new' => true,
- 'update' => ['$inc' => ['x' => 1]],
-]);
-
-(new CommandObserver)->observe(
- function() use ($manager, $command) {
- $manager->executeWriteCommand(DATABASE_NAME, $command);
- $manager->executeWriteCommand(DATABASE_NAME, $command, ['writeConcern' => new MongoDB\Driver\WriteConcern(1)]);
- },
- function(stdClass $command) {
- echo json_encode($command->writeConcern), "\n";
- }
-);
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-{"w":2,"wtimeout":1000}
-{"w":1}
-===DONE===
diff --git a/mongodb-1.12.0/tests/manager/manager-executeWriteCommand_error-002.phpt b/mongodb-1.12.0/tests/manager/manager-executeWriteCommand_error-002.phpt
deleted file mode 100644
index 7dff00ab..00000000
--- a/mongodb-1.12.0/tests/manager/manager-executeWriteCommand_error-002.phpt
+++ /dev/null
@@ -1,33 +0,0 @@
---TEST--
-MongoDB\Driver\Manager::executeWriteCommand() throws CommandException for invalid writeConcern
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_replica_set(); ?>
-<?php skip_if_server_version('<', '3.2'); ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-
-$command = new MongoDB\Driver\Command([
- 'findAndModify' => COLLECTION_NAME,
- 'query' => ['_id' => 'foo'],
- 'update' => ['foo' => ['bar']],
- 'upsert' => true,
- 'new' => true,
-]);
-
-try {
- $manager->executeWriteCommand(DATABASE_NAME, $command, ['writeConcern' => new MongoDB\Driver\WriteConcern("undefined")]);
-} catch (MongoDB\Driver\Exception\CommandException $e) {
- printf("%s(%d): %s\n", get_class($e), $e->getCode(), $e->getMessage());
-}
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-MongoDB\Driver\Exception\CommandException(79): Write Concern error: No write concern mode named 'undefined' found in replica set configuration
-===DONE===
diff --git a/mongodb-1.12.0/tests/manager/manager-executeWriteCommand_error-003.phpt b/mongodb-1.12.0/tests/manager/manager-executeWriteCommand_error-003.phpt
deleted file mode 100644
index a215a8a9..00000000
--- a/mongodb-1.12.0/tests/manager/manager-executeWriteCommand_error-003.phpt
+++ /dev/null
@@ -1,31 +0,0 @@
---TEST--
-MongoDB\Driver\Manager::executeWriteCommand() throws CommandException for unsupported update operator
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_server_version('<', '3.4'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-
-$command = new MongoDB\Driver\Command([
- 'findAndModify' => COLLECTION_NAME,
- 'query' => ['_id' => 'foo'],
- 'upsert' => true,
- 'new' => true,
-]);
-
-try {
- $manager->executeWriteCommand(DATABASE_NAME, $command);
-} catch (MongoDB\Driver\Exception\CommandException $e) {
- printf("%s(%d): %s\n", get_class($e), $e->getCode(), $e->getMessage());
-}
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-MongoDB\Driver\Exception\CommandException(9): Either an update or remove=true must be specified
-===DONE===
diff --git a/mongodb-1.12.0/tests/manager/manager-executeWriteCommand_error-004.phpt b/mongodb-1.12.0/tests/manager/manager-executeWriteCommand_error-004.phpt
deleted file mode 100644
index a4449784..00000000
--- a/mongodb-1.12.0/tests/manager/manager-executeWriteCommand_error-004.phpt
+++ /dev/null
@@ -1,47 +0,0 @@
---TEST--
-MongoDB\Driver\Manager::executeWriteCommand() cannot combine session with unacknowledged write concern
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-echo throws(function() {
- $manager = create_test_manager();
-
- $command = new MongoDB\Driver\Command([
- 'insert' => COLLECTION_NAME,
- 'documents' => [['x' => 1]],
- ]);
-
- $manager->executeWriteCommand(DATABASE_NAME, $command, [
- 'session' => $manager->startSession(),
- 'writeConcern' => new MongoDB\Driver\WriteConcern(0),
- ]);
-}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
-
-echo throws(function() {
- $manager = create_test_manager(URI, ['w' => 0]);
-
- $command = new MongoDB\Driver\Command([
- 'insert' => COLLECTION_NAME,
- 'documents' => [['x' => 1]],
- ]);
-
- $manager->executeWriteCommand(DATABASE_NAME, $command, [
- 'session' => $manager->startSession(),
- ]);
-}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Cannot combine "session" option with an unacknowledged write concern
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Cannot combine "session" option with an unacknowledged write concern
-===DONE===
diff --git a/mongodb-1.12.0/tests/manager/manager-getservers-002.phpt b/mongodb-1.12.0/tests/manager/manager-getservers-002.phpt
deleted file mode 100644
index 8be5f5a7..00000000
--- a/mongodb-1.12.0/tests/manager/manager-getservers-002.phpt
+++ /dev/null
@@ -1,57 +0,0 @@
---TEST--
-MongoDB\Driver\Manager::getServers() (replica set)
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_replica_set(); ?>
-<?php skip_if_not_enough_nodes(3); ?>
-<?php skip_if_no_arbiter(); ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-function assertServerType($type) {
- $rsTypes = array(
- MongoDB\Driver\Server::TYPE_RS_PRIMARY,
- MongoDB\Driver\Server::TYPE_RS_SECONDARY,
- MongoDB\Driver\Server::TYPE_RS_ARBITER,
- );
-
- if (in_array($type, $rsTypes, true)) {
- printf("Found replica set server type: %d\n", $type);
- } else {
- printf("Unexpected server type: %d\n", $type);
- }
-}
-
-$manager = create_test_manager();
-
-$servers = $manager->getServers();
-printf("Known servers: %d\n", count($servers));
-
-echo "Pinging\n";
-$command = new MongoDB\Driver\Command(array('ping' => 1));
-$manager->executeCommand(DATABASE_NAME, $command);
-
-$servers = $manager->getServers();
-printf("Known servers: %d\n", count($servers));
-
-foreach ($servers as $server) {
- printf("Found server: %s:%d\n", $server->getHost(), $server->getPort());
- assertServerType($server->getType());
-}
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-Known servers: 0
-Pinging
-Known servers: 3
-Found server: %s:%d
-Found replica set server type: %r(4|5|6)%r
-Found server: %s:%d
-Found replica set server type: %r(4|5|6)%r
-Found server: %s:%d
-Found replica set server type: %r(4|5|6)%r
-===DONE===
diff --git a/mongodb-1.12.0/tests/manager/manager-set-uri-options-002.phpt b/mongodb-1.12.0/tests/manager/manager-set-uri-options-002.phpt
deleted file mode 100644
index 19a86d38..00000000
--- a/mongodb-1.12.0/tests/manager/manager-set-uri-options-002.phpt
+++ /dev/null
@@ -1,57 +0,0 @@
---TEST--
-MongoDB\Driver\Manager: Connecting to MongoDB using "ssl" from $options
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_ssl(); ?>
-<?php skip_if_not_ssl(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$opts = array(
- "ssl" => array(
- "verify_peer" => false,
- "verify_peer_name" => false,
- "allow_self_signed" => true,
- ),
-);
-$context = stream_context_create($opts);
-
-$options = array(
- "ssl" => false,
- "serverselectiontimeoutms" => 100,
-);
-/* The server requires SSL */
-$manager = create_test_manager(URI, $options, array("context" => $context));
-
-$bulk = new MongoDB\Driver\BulkWrite;
-$bulk->insert(array("my" => "value"));
-
-throws(function() use ($manager, $bulk) {
- $inserted = $manager->executeBulkWrite(NS, $bulk)->getInsertedCount();
- printf("Inserted incorrectly: %d\n", $inserted);
-}, MongoDB\Driver\Exception\ConnectionException::class);
-
-$options = array(
- "ssl" => true,
-);
-$manager = create_test_manager(URI, $options, array("context" => $context));
-$bulk = new MongoDB\Driver\BulkWrite;
-
-$bulk->insert(array("my" => "value"));
-$inserted = $manager->executeBulkWrite(NS, $bulk)->getInsertedCount();
-printf("Inserted: %d\n", $inserted);
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-Deprecated: MongoDB\Driver\Manager::__construct(): The "context" driver option is deprecated.%s
-
-Deprecated: MongoDB\Driver\Manager::__construct(): The "allow_self_signed" context driver option is deprecated. Please use the "tlsAllowInvalidCertificates" URI option instead.%s
-OK: Got MongoDB\Driver\Exception\ConnectionException
-
-Deprecated: MongoDB\Driver\Manager::__construct(): The "context" driver option is deprecated.%s
-
-Deprecated: MongoDB\Driver\Manager::__construct(): The "allow_self_signed" context driver option is deprecated. Please use the "tlsAllowInvalidCertificates" URI option instead.%s
-Inserted: 1
-===DONE===
diff --git a/mongodb-1.12.0/tests/manager/manager-startSession_error-001.phpt b/mongodb-1.12.0/tests/manager/manager-startSession_error-001.phpt
deleted file mode 100644
index 1670dc84..00000000
--- a/mongodb-1.12.0/tests/manager/manager-startSession_error-001.phpt
+++ /dev/null
@@ -1,93 +0,0 @@
---TEST--
-MongoDB\Driver\Manager::startSession() with wrong defaultTransactionOptions
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-
-$options = [
- [ 'maxCommitTimeMS' => -1 ],
- [ 'readConcern' => 42 ],
- [ 'readConcern' => new stdClass ],
- [ 'readConcern' => new \MongoDB\Driver\WriteConcern( 2 ) ],
- [ 'readPreference' => 42 ],
- [ 'readPreference' => new stdClass ],
- [ 'readPreference' => new \MongoDB\Driver\ReadConcern( \MongoDB\Driver\ReadConcern::LOCAL ) ],
- [ 'writeConcern' => 42 ],
- [ 'writeConcern' => new stdClass ],
- [ 'writeConcern' => new \MongoDB\Driver\ReadPreference( \MongoDB\Driver\ReadPreference::RP_SECONDARY ) ],
-
- [
- 'readConcern' => new \MongoDB\Driver\ReadConcern( \MongoDB\Driver\ReadConcern::LOCAL ),
- 'readPreference' => new \MongoDB\Driver\ReadConcern( \MongoDB\Driver\ReadConcern::LOCAL ),
- ],
- [
- 'readConcern' => new \MongoDB\Driver\ReadConcern( \MongoDB\Driver\ReadConcern::LOCAL ),
- 'writeConcern' => new \MongoDB\Driver\ReadPreference( \MongoDB\Driver\ReadPreference::RP_SECONDARY ),
- ],
- [
- 'readPreference' => new \MongoDB\Driver\ReadPreference( \MongoDB\Driver\ReadPreference::RP_SECONDARY ),
- 'writeConcern' => new \MongoDB\Driver\ReadPreference( \MongoDB\Driver\ReadPreference::RP_SECONDARY ),
- ],
-
- 42,
- new stdClass,
-];
-
-foreach ($options as $txnOptions) {
- echo throws(function() use ($manager, $txnOptions) {
- $manager->startSession([
- 'defaultTransactionOptions' => $txnOptions
- ]);
- }, MongoDB\Driver\Exception\InvalidArgumentException::class), "\n";
-}
-
-echo raises(function() use ($manager) {
- $manager->startSession([
- 'defaultTransactionOptions' => [ 'maxCommitTimeMS' => new stdClass ]
- ]);
-}, E_NOTICE | E_WARNING), "\n";
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Expected "maxCommitTimeMS" option to be >= 0, -1 given
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Expected "readConcern" option to be MongoDB\Driver\ReadConcern, int%S given
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Expected "readConcern" option to be MongoDB\Driver\ReadConcern, stdClass given
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Expected "readConcern" option to be MongoDB\Driver\ReadConcern, MongoDB\Driver\WriteConcern given
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Expected "readPreference" option to be MongoDB\Driver\ReadPreference, int%S given
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Expected "readPreference" option to be MongoDB\Driver\ReadPreference, stdClass given
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Expected "readPreference" option to be MongoDB\Driver\ReadPreference, MongoDB\Driver\ReadConcern given
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Expected "writeConcern" option to be MongoDB\Driver\WriteConcern, int%S given
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Expected "writeConcern" option to be MongoDB\Driver\WriteConcern, stdClass given
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Expected "writeConcern" option to be MongoDB\Driver\WriteConcern, MongoDB\Driver\ReadPreference given
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Expected "readPreference" option to be MongoDB\Driver\ReadPreference, MongoDB\Driver\ReadConcern given
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Expected "writeConcern" option to be MongoDB\Driver\WriteConcern, MongoDB\Driver\ReadPreference given
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Expected "writeConcern" option to be MongoDB\Driver\WriteConcern, MongoDB\Driver\ReadPreference given
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Expected "defaultTransactionOptions" option to be an array, int%S given
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Expected "defaultTransactionOptions" option to be an array, stdClass given
-OK: Got %r(E_NOTICE|E_WARNING)%r
-Object of class stdClass could not be converted to int
-===DONE===
diff --git a/mongodb-1.12.0/tests/manager/manager-startSession_error-002.phpt b/mongodb-1.12.0/tests/manager/manager-startSession_error-002.phpt
deleted file mode 100644
index 31ed5b97..00000000
--- a/mongodb-1.12.0/tests/manager/manager-startSession_error-002.phpt
+++ /dev/null
@@ -1,30 +0,0 @@
---TEST--
-MongoDB\Driver\Manager::startSession() snapshot and causalConsistency cannot both be true
---DESCRIPTION--
-Session spec prose test #1
-https://github.com/mongodb/specifications/blob/master/source/sessions/tests/README.rst#prose-tests
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-
-echo throws(function() use ($manager) {
- $manager->startSession([
- 'causalConsistency' => true,
- 'snapshot' => true,
- ]);
-}, MongoDB\Driver\Exception\InvalidArgumentException::class), "\n";
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Only one of "causalConsistency" and "snapshot" can be enabled
-===DONE===
diff --git a/mongodb-1.12.0/tests/query/bug0705-001.phpt b/mongodb-1.12.0/tests/query/bug0705-001.phpt
deleted file mode 100644
index 8d53dffc..00000000
--- a/mongodb-1.12.0/tests/query/bug0705-001.phpt
+++ /dev/null
@@ -1,54 +0,0 @@
---TEST--
-PHPC-705: Do not unnecessarily wrap filters in $query (profiled query)
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_server_version('>=', '3.1'); ?>
-<?php skip_if_not_clean(); ?>
-<?php skip_if_not_clean(DATABASE_NAME, 'system.profile'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-
-$command = new MongoDB\Driver\Command(['profile' => 2]);
-$cursor = $manager->executeCommand(DATABASE_NAME, $command);
-$result = current($cursor->toArray());
-
-printf("Set profile level to 2 successfully: %s\n", (empty($result->ok) ? 'no' : 'yes'));
-
-$manager->executeQuery(NS, new MongoDB\Driver\Query(["x" => 1]));
-
-$query = new MongoDB\Driver\Query(
- [
- 'op' => 'query',
- 'ns' => NS,
- ],
- [
- 'sort' => ['ts' => -1],
- 'limit' => 1,
- ]
-);
-$cursor = $manager->executeQuery(DATABASE_NAME . '.system.profile', $query);
-$profileEntry = current($cursor->toArray());
-
-var_dump($profileEntry->query);
-
-$command = new MongoDB\Driver\Command(array('profile' => 0));
-$cursor = $manager->executeCommand(DATABASE_NAME, $command);
-$result = current($cursor->toArray());
-
-printf("Set profile level to 0 successfully: %s\n", (empty($result->ok) ? 'no' : 'yes'));
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-Set profile level to 2 successfully: yes
-object(stdClass)#%d (%d) {
- ["x"]=>
- int(1)
-}
-Set profile level to 0 successfully: yes
-===DONE===
diff --git a/mongodb-1.12.0/tests/query/bug0705-002.phpt b/mongodb-1.12.0/tests/query/bug0705-002.phpt
deleted file mode 100644
index 46640f57..00000000
--- a/mongodb-1.12.0/tests/query/bug0705-002.phpt
+++ /dev/null
@@ -1,29 +0,0 @@
---TEST--
-PHPC-705: Do not unnecessarily wrap filters in $query (currentOp query)
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_not_standalone(); ?>
-<?php skip_if_server_version('>=', '3.1'); ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-$cursor = $manager->executeQuery('admin.$cmd.sys.inprog', new MongoDB\Driver\Query([]));
-var_dump($cursor->toArray());
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-array(1) {
- [0]=>
- object(stdClass)#%d (%d) {
- ["inprog"]=>
- array(0) {
- }
- }
-}
-===DONE===
diff --git a/mongodb-1.12.0/tests/readPreference/bug0146-001.phpt b/mongodb-1.12.0/tests/readPreference/bug0146-001.phpt
deleted file mode 100644
index e1c43923..00000000
--- a/mongodb-1.12.0/tests/readPreference/bug0146-001.phpt
+++ /dev/null
@@ -1,225 +0,0 @@
---TEST--
-PHPC-146: ReadPreference primaryPreferred and secondary swapped (OP_QUERY)
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_server_version('>=', '3.1'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-
-$bulk = new MongoDB\Driver\BulkWrite();
-$bulk->insert(array('my' => 'document'));
-$manager->executeBulkWrite(NS, $bulk);
-
-$rps = array(
- MongoDB\Driver\ReadPreference::RP_PRIMARY,
- MongoDB\Driver\ReadPreference::RP_PRIMARY_PREFERRED,
- MongoDB\Driver\ReadPreference::RP_SECONDARY,
- MongoDB\Driver\ReadPreference::RP_SECONDARY_PREFERRED,
- MongoDB\Driver\ReadPreference::RP_NEAREST,
-);
-
-foreach($rps as $r) {
- $rp = new MongoDB\Driver\ReadPreference($r);
- $cursor = $manager->executeQuery(NS, new MongoDB\Driver\Query(array("my" => "query")), $rp);
- var_dump($cursor);
-}
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-object(MongoDB\Driver\Cursor)#%d (%d) {
- ["database"]=>
- string(6) "phongo"
- ["collection"]=>
- string(26) "readPreference_bug0146_001"
- ["query"]=>
- object(MongoDB\Driver\Query)#%d (%d) {
- ["filter"]=>
- object(stdClass)#%d (%d) {
- ["my"]=>
- string(5) "query"
- }
- ["options"]=>
- object(stdClass)#%d (%d) {
- }
- ["readConcern"]=>
- NULL
- }
- ["command"]=>
- NULL
- ["readPreference"]=>
- object(MongoDB\Driver\ReadPreference)#%d (%d) {
- ["mode"]=>
- string(7) "primary"
- }
- ["session"]=>
- NULL
- ["isDead"]=>
- bool(true)
- ["currentIndex"]=>
- int(0)
- ["currentDocument"]=>
- NULL
- ["server"]=>
- object(MongoDB\Driver\Server)#%d (%d) {
- %a
- }
-}
-object(MongoDB\Driver\Cursor)#%d (%d) {
- ["database"]=>
- string(6) "phongo"
- ["collection"]=>
- string(26) "readPreference_bug0146_001"
- ["query"]=>
- object(MongoDB\Driver\Query)#%d (%d) {
- ["filter"]=>
- object(stdClass)#%d (%d) {
- ["my"]=>
- string(5) "query"
- }
- ["options"]=>
- object(stdClass)#%d (%d) {
- }
- ["readConcern"]=>
- NULL
- }
- ["command"]=>
- NULL
- ["readPreference"]=>
- object(MongoDB\Driver\ReadPreference)#%d (%d) {
- ["mode"]=>
- string(16) "primaryPreferred"
- }
- ["session"]=>
- NULL
- ["isDead"]=>
- bool(true)
- ["currentIndex"]=>
- int(0)
- ["currentDocument"]=>
- NULL
- ["server"]=>
- object(MongoDB\Driver\Server)#%d (%d) {
- %a
- }
-}
-object(MongoDB\Driver\Cursor)#%d (%d) {
- ["database"]=>
- string(6) "phongo"
- ["collection"]=>
- string(26) "readPreference_bug0146_001"
- ["query"]=>
- object(MongoDB\Driver\Query)#%d (%d) {
- ["filter"]=>
- object(stdClass)#%d (%d) {
- ["my"]=>
- string(5) "query"
- }
- ["options"]=>
- object(stdClass)#%d (%d) {
- }
- ["readConcern"]=>
- NULL
- }
- ["command"]=>
- NULL
- ["readPreference"]=>
- object(MongoDB\Driver\ReadPreference)#%d (%d) {
- ["mode"]=>
- string(9) "secondary"
- }
- ["session"]=>
- NULL
- ["isDead"]=>
- bool(true)
- ["currentIndex"]=>
- int(0)
- ["currentDocument"]=>
- NULL
- ["server"]=>
- object(MongoDB\Driver\Server)#%d (%d) {
- %a
- }
-}
-object(MongoDB\Driver\Cursor)#%d (%d) {
- ["database"]=>
- string(6) "phongo"
- ["collection"]=>
- string(26) "readPreference_bug0146_001"
- ["query"]=>
- object(MongoDB\Driver\Query)#%d (%d) {
- ["filter"]=>
- object(stdClass)#%d (%d) {
- ["my"]=>
- string(5) "query"
- }
- ["options"]=>
- object(stdClass)#%d (%d) {
- }
- ["readConcern"]=>
- NULL
- }
- ["command"]=>
- NULL
- ["readPreference"]=>
- object(MongoDB\Driver\ReadPreference)#%d (%d) {
- ["mode"]=>
- string(18) "secondaryPreferred"
- }
- ["session"]=>
- NULL
- ["isDead"]=>
- bool(true)
- ["currentIndex"]=>
- int(0)
- ["currentDocument"]=>
- NULL
- ["server"]=>
- object(MongoDB\Driver\Server)#%d (%d) {
- %a
- }
-}
-object(MongoDB\Driver\Cursor)#%d (%d) {
- ["database"]=>
- string(6) "phongo"
- ["collection"]=>
- string(26) "readPreference_bug0146_001"
- ["query"]=>
- object(MongoDB\Driver\Query)#%d (%d) {
- ["filter"]=>
- object(stdClass)#%d (%d) {
- ["my"]=>
- string(5) "query"
- }
- ["options"]=>
- object(stdClass)#%d (%d) {
- }
- ["readConcern"]=>
- NULL
- }
- ["command"]=>
- NULL
- ["readPreference"]=>
- object(MongoDB\Driver\ReadPreference)#%d (%d) {
- ["mode"]=>
- string(7) "nearest"
- }
- ["session"]=>
- NULL
- ["isDead"]=>
- bool(true)
- ["currentIndex"]=>
- int(0)
- ["currentDocument"]=>
- NULL
- ["server"]=>
- object(MongoDB\Driver\Server)#%d (%d) {
- %a
- }
-}
-===DONE===
diff --git a/mongodb-1.12.0/tests/readPreference/bug0146-002.phpt b/mongodb-1.12.0/tests/readPreference/bug0146-002.phpt
deleted file mode 100644
index 2edfbce8..00000000
--- a/mongodb-1.12.0/tests/readPreference/bug0146-002.phpt
+++ /dev/null
@@ -1,227 +0,0 @@
---TEST--
-PHPC-146: ReadPreference primaryPreferred and secondary swapped (find command)
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_not_replica_set(); ?>
-<?php skip_if_no_secondary(); ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-
-$bulk = new MongoDB\Driver\BulkWrite();
-$bulk->insert(array('my' => 'document'));
-$manager->executeBulkWrite(NS, $bulk);
-
-$rps = array(
- MongoDB\Driver\ReadPreference::RP_PRIMARY,
- MongoDB\Driver\ReadPreference::RP_PRIMARY_PREFERRED,
- MongoDB\Driver\ReadPreference::RP_SECONDARY,
- MongoDB\Driver\ReadPreference::RP_SECONDARY_PREFERRED,
- MongoDB\Driver\ReadPreference::RP_NEAREST,
-);
-
-foreach($rps as $r) {
- $rp = new MongoDB\Driver\ReadPreference($r);
- $cursor = $manager->executeQuery(NS, new MongoDB\Driver\Query(array("my" => "query")), $rp);
- var_dump($cursor);
-}
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-object(MongoDB\Driver\Cursor)#%d (%d) {
- ["database"]=>
- string(6) "phongo"
- ["collection"]=>
- string(26) "readPreference_bug0146_002"
- ["query"]=>
- object(MongoDB\Driver\Query)#%d (%d) {
- ["filter"]=>
- object(stdClass)#%d (%d) {
- ["my"]=>
- string(5) "query"
- }
- ["options"]=>
- object(stdClass)#%d (%d) {
- }
- ["readConcern"]=>
- NULL
- }
- ["command"]=>
- NULL
- ["readPreference"]=>
- object(MongoDB\Driver\ReadPreference)#%d (%d) {
- ["mode"]=>
- string(7) "primary"
- }
- ["session"]=>
- NULL
- ["isDead"]=>
- bool(true)
- ["currentIndex"]=>
- int(0)
- ["currentDocument"]=>
- NULL
- ["server"]=>
- object(MongoDB\Driver\Server)#%d (%d) {
- %a
- }
-}
-object(MongoDB\Driver\Cursor)#%d (%d) {
- ["database"]=>
- string(6) "phongo"
- ["collection"]=>
- string(26) "readPreference_bug0146_002"
- ["query"]=>
- object(MongoDB\Driver\Query)#%d (%d) {
- ["filter"]=>
- object(stdClass)#%d (%d) {
- ["my"]=>
- string(5) "query"
- }
- ["options"]=>
- object(stdClass)#%d (%d) {
- }
- ["readConcern"]=>
- NULL
- }
- ["command"]=>
- NULL
- ["readPreference"]=>
- object(MongoDB\Driver\ReadPreference)#%d (%d) {
- ["mode"]=>
- string(16) "primaryPreferred"
- }
- ["session"]=>
- NULL
- ["isDead"]=>
- bool(true)
- ["currentIndex"]=>
- int(0)
- ["currentDocument"]=>
- NULL
- ["server"]=>
- object(MongoDB\Driver\Server)#%d (%d) {
- %a
- }
-}
-object(MongoDB\Driver\Cursor)#%d (%d) {
- ["database"]=>
- string(6) "phongo"
- ["collection"]=>
- string(26) "readPreference_bug0146_002"
- ["query"]=>
- object(MongoDB\Driver\Query)#%d (%d) {
- ["filter"]=>
- object(stdClass)#%d (%d) {
- ["my"]=>
- string(5) "query"
- }
- ["options"]=>
- object(stdClass)#%d (%d) {
- }
- ["readConcern"]=>
- NULL
- }
- ["command"]=>
- NULL
- ["readPreference"]=>
- object(MongoDB\Driver\ReadPreference)#%d (%d) {
- ["mode"]=>
- string(9) "secondary"
- }
- ["session"]=>
- NULL
- ["isDead"]=>
- bool(true)
- ["currentIndex"]=>
- int(0)
- ["currentDocument"]=>
- NULL
- ["server"]=>
- object(MongoDB\Driver\Server)#%d (%d) {
- %a
- }
-}
-object(MongoDB\Driver\Cursor)#%d (%d) {
- ["database"]=>
- string(6) "phongo"
- ["collection"]=>
- string(26) "readPreference_bug0146_002"
- ["query"]=>
- object(MongoDB\Driver\Query)#%d (%d) {
- ["filter"]=>
- object(stdClass)#%d (%d) {
- ["my"]=>
- string(5) "query"
- }
- ["options"]=>
- object(stdClass)#%d (%d) {
- }
- ["readConcern"]=>
- NULL
- }
- ["command"]=>
- NULL
- ["readPreference"]=>
- object(MongoDB\Driver\ReadPreference)#%d (%d) {
- ["mode"]=>
- string(18) "secondaryPreferred"
- }
- ["session"]=>
- NULL
- ["isDead"]=>
- bool(true)
- ["currentIndex"]=>
- int(0)
- ["currentDocument"]=>
- NULL
- ["server"]=>
- object(MongoDB\Driver\Server)#%d (%d) {
- %a
- }
-}
-object(MongoDB\Driver\Cursor)#%d (%d) {
- ["database"]=>
- string(6) "phongo"
- ["collection"]=>
- string(26) "readPreference_bug0146_002"
- ["query"]=>
- object(MongoDB\Driver\Query)#%d (%d) {
- ["filter"]=>
- object(stdClass)#%d (%d) {
- ["my"]=>
- string(5) "query"
- }
- ["options"]=>
- object(stdClass)#%d (%d) {
- }
- ["readConcern"]=>
- NULL
- }
- ["command"]=>
- NULL
- ["readPreference"]=>
- object(MongoDB\Driver\ReadPreference)#%d (%d) {
- ["mode"]=>
- string(7) "nearest"
- }
- ["session"]=>
- NULL
- ["isDead"]=>
- bool(true)
- ["currentIndex"]=>
- int(0)
- ["currentDocument"]=>
- NULL
- ["server"]=>
- object(MongoDB\Driver\Server)#%d (%d) {
- %a
- }
-}
-===DONE===
diff --git a/mongodb-1.12.0/tests/replicaset/bug0898-001.phpt b/mongodb-1.12.0/tests/replicaset/bug0898-001.phpt
deleted file mode 100644
index dd30cfff..00000000
--- a/mongodb-1.12.0/tests/replicaset/bug0898-001.phpt
+++ /dev/null
@@ -1,46 +0,0 @@
---TEST--
-PHPC-898: readConcern option should not be included in getMore commands (URI option)
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_replica_set(); ?>
-<?php skip_if_server_version('<', '3.2'); ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager(URI, ['readConcernLevel' => 'local']);
-
-$bulk = new MongoDB\Driver\BulkWrite();
-$bulk->insert(['_id' => 1]);
-$bulk->insert(['_id' => 2]);
-$bulk->insert(['_id' => 3]);
-
-$result = $manager->executeBulkWrite(NS, $bulk);
-printf("Inserted %d document(s)\n", $result->getInsertedCount());
-
-$query = new MongoDB\Driver\Query([], ['batchSize' => 2]);
-$cursor = $manager->executeQuery(NS, $query);
-
-foreach ($cursor as $document) {
- var_dump($document);
-}
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-Inserted 3 document(s)
-object(stdClass)#%d (1) {
- ["_id"]=>
- int(1)
-}
-object(stdClass)#%d (1) {
- ["_id"]=>
- int(2)
-}
-object(stdClass)#%d (1) {
- ["_id"]=>
- int(3)
-}
-===DONE===
diff --git a/mongodb-1.12.0/tests/replicaset/bug0898-002.phpt b/mongodb-1.12.0/tests/replicaset/bug0898-002.phpt
deleted file mode 100644
index beabf892..00000000
--- a/mongodb-1.12.0/tests/replicaset/bug0898-002.phpt
+++ /dev/null
@@ -1,47 +0,0 @@
---TEST--
-PHPC-898: readConcern option should not be included in getMore commands (query option)
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_replica_set(); ?>
-<?php skip_if_server_version('<', '3.2'); ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-
-$bulk = new MongoDB\Driver\BulkWrite();
-$bulk->insert(['_id' => 1]);
-$bulk->insert(['_id' => 2]);
-$bulk->insert(['_id' => 3]);
-
-$result = $manager->executeBulkWrite(NS, $bulk);
-printf("Inserted %d document(s)\n", $result->getInsertedCount());
-
-$rc = new MongoDB\Driver\ReadConcern(MongoDB\Driver\ReadConcern::LOCAL);
-$query = new MongoDB\Driver\Query([], ['batchSize' => 2, 'readConcern' => $rc]);
-$cursor = $manager->executeQuery(NS, $query);
-
-foreach ($cursor as $document) {
- var_dump($document);
-}
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-Inserted 3 document(s)
-object(stdClass)#%d (1) {
- ["_id"]=>
- int(1)
-}
-object(stdClass)#%d (1) {
- ["_id"]=>
- int(2)
-}
-object(stdClass)#%d (1) {
- ["_id"]=>
- int(3)
-}
-===DONE===
diff --git a/mongodb-1.12.0/tests/replicaset/manager-getservers-001.phpt b/mongodb-1.12.0/tests/replicaset/manager-getservers-001.phpt
deleted file mode 100644
index 30e1ae56..00000000
--- a/mongodb-1.12.0/tests/replicaset/manager-getservers-001.phpt
+++ /dev/null
@@ -1,110 +0,0 @@
---TEST--
-MongoDB\Driver\Manager::getServers()
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_replica_set(); ?>
-<?php skip_if_no_secondary(); ?>
-<?php skip_if_no_arbiter(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-
-
-$doc = array("example" => "document");
-$bulk = new \MongoDB\Driver\BulkWrite();
-$bulk->insert($doc);
-$wresult = $manager->executeBulkWrite(NS, $bulk);
-
-var_dump($manager->getServers());
-$servers = $manager->getServers();
-
-foreach($servers as $server) {
- printf("%s:%d - primary: %d, secondary: %d, arbiter: %d\n", $server->getHost(), $server->getPort(), $server->isPrimary(), $server->isSecondary(), $server->isArbiter());
-}
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-array(3) {
- [0]=>
- object(MongoDB\Driver\Server)#%d (%d) {
- ["host"]=>
- string(%d) "%s"
- ["port"]=>
- int(%d)
- ["type"]=>
- int(4)
- ["is_primary"]=>
- bool(true)
- ["is_secondary"]=>
- bool(false)
- ["is_arbiter"]=>
- bool(false)
- ["is_hidden"]=>
- bool(false)
- ["is_passive"]=>
- bool(false)%A
- ["last_hello_response"]=>
- array(%d) {
- %a
- }
- ["round_trip_time"]=>
- int(%d)
- }
- [1]=>
- object(MongoDB\Driver\Server)#%d (%d) {
- ["host"]=>
- string(%d) "%s"
- ["port"]=>
- int(%d)
- ["type"]=>
- int(5)
- ["is_primary"]=>
- bool(false)
- ["is_secondary"]=>
- bool(true)
- ["is_arbiter"]=>
- bool(false)
- ["is_hidden"]=>
- bool(false)
- ["is_passive"]=>
- bool(false)%A
- ["last_hello_response"]=>
- array(%d) {
- %a
- }
- ["round_trip_time"]=>
- int(%d)
- }
- [2]=>
- object(MongoDB\Driver\Server)#%d (%d) {
- ["host"]=>
- string(%d) "%s"
- ["port"]=>
- int(%d)
- ["type"]=>
- int(6)
- ["is_primary"]=>
- bool(false)
- ["is_secondary"]=>
- bool(false)
- ["is_arbiter"]=>
- bool(true)
- ["is_hidden"]=>
- bool(false)
- ["is_passive"]=>
- bool(false)
- ["last_hello_response"]=>
- array(%d) {
- %a
- }
- ["round_trip_time"]=>
- int(%d)
- }
-}
-%s:%d - primary: 1, secondary: 0, arbiter: 0
-%s:%d - primary: 0, secondary: 1, arbiter: 0
-%s:%d - primary: 0, secondary: 0, arbiter: 1
-===DONE===
diff --git a/mongodb-1.12.0/tests/replicaset/readconcern-001.phpt b/mongodb-1.12.0/tests/replicaset/readconcern-001.phpt
deleted file mode 100644
index c56059ad..00000000
--- a/mongodb-1.12.0/tests/replicaset/readconcern-001.phpt
+++ /dev/null
@@ -1,55 +0,0 @@
---TEST--
-ReadConcern: MongoDB\Driver\Manager::executeQuery() with readConcern option (find command)
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_replica_set(); ?>
-<?php skip_if_server_version('<', '3.2'); ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-
-$wc = new MongoDB\Driver\WriteConcern(MongoDB\Driver\WriteConcern::MAJORITY);
-
-$bulk = new MongoDB\Driver\BulkWrite();
-$bulk->insert(['_id' => 1, 'x' => 1]);
-$bulk->insert(['_id' => 2, 'x' => 2]);
-$manager->executeBulkWrite(NS, $bulk, $wc);
-
-$rc = new MongoDB\Driver\ReadConcern(MongoDB\Driver\ReadConcern::LOCAL);
-$query = new MongoDB\Driver\Query(['x' => 2], ['readConcern' => $rc]);
-$cursor = $manager->executeQuery(NS, $query);
-
-var_dump(iterator_to_array($cursor));
-
-$rc = new MongoDB\Driver\ReadConcern(MongoDB\Driver\ReadConcern::MAJORITY);
-$query = new MongoDB\Driver\Query(['x' => 2], ['readConcern' => $rc]);
-$cursor = $manager->executeQuery(NS, $query);
-
-var_dump(iterator_to_array($cursor));
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-array(1) {
- [0]=>
- object(stdClass)#%d (%d) {
- ["_id"]=>
- int(2)
- ["x"]=>
- int(2)
- }
-}
-array(1) {
- [0]=>
- object(stdClass)#%d (%d) {
- ["_id"]=>
- int(2)
- ["x"]=>
- int(2)
- }
-}
-===DONE===
diff --git a/mongodb-1.12.0/tests/replicaset/readconcern-002.phpt b/mongodb-1.12.0/tests/replicaset/readconcern-002.phpt
deleted file mode 100644
index 2fb600e4..00000000
--- a/mongodb-1.12.0/tests/replicaset/readconcern-002.phpt
+++ /dev/null
@@ -1,41 +0,0 @@
---TEST--
-ReadConcern: MongoDB\Driver\Manager::executeQuery() with readConcern option (OP_QUERY)
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_replica_set(); ?>
-<?php skip_if_server_version('>=', '3.1'); ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-
-$bulk = new MongoDB\Driver\BulkWrite();
-$bulk->insert(['_id' => 1, 'x' => 1]);
-$bulk->insert(['_id' => 2, 'x' => 2]);
-$manager->executeBulkWrite(NS, $bulk);
-
-$rc = new MongoDB\Driver\ReadConcern(MongoDB\Driver\ReadConcern::LOCAL);
-$query = new MongoDB\Driver\Query(['x' => 2], ['readConcern' => $rc]);
-
-echo throws(function() use ($manager, $query) {
- $manager->executeQuery(NS, $query);
-}, 'MongoDB\Driver\Exception\RuntimeException'), "\n";
-
-$rc = new MongoDB\Driver\ReadConcern(MongoDB\Driver\ReadConcern::MAJORITY);
-$query = new MongoDB\Driver\Query(['x' => 2], ['readConcern' => $rc]);
-
-echo throws(function() use ($manager, $query) {
- $manager->executeQuery(NS, $query);
-}, 'MongoDB\Driver\Exception\RuntimeException'), "\n";
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-OK: Got MongoDB\Driver\Exception\RuntimeException
-The selected server does not support readConcern
-OK: Got MongoDB\Driver\Exception\RuntimeException
-The selected server does not support readConcern
-===DONE===
diff --git a/mongodb-1.12.0/tests/replicaset/server-001.phpt b/mongodb-1.12.0/tests/replicaset/server-001.phpt
deleted file mode 100644
index c03a5814..00000000
--- a/mongodb-1.12.0/tests/replicaset/server-001.phpt
+++ /dev/null
@@ -1,69 +0,0 @@
---TEST--
-MongoDB\Driver\Server: Manager->getServer() returning correct server
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_replica_set(); ?>
-<?php skip_if_not_enough_data_nodes(2, 2); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-
-
-$doc = array("example" => "document");
-$bulk = new \MongoDB\Driver\BulkWrite();
-$bulk->insert($doc);
-$wresult = $manager->executeBulkWrite(NS, $bulk);
-
-$bulk = new \MongoDB\Driver\BulkWrite();
-$bulk->insert($doc);
-
-/* writes go to the primary */
-$server = $wresult->getServer();
-
-var_dump(
- $server->getHost()
-);
-
-$tags = $server->getTags();
-echo "dc: ", array_key_exists('dc', $tags) ? $tags['dc'] : 'not set', "\n";
-echo "ordinal: ", array_key_exists('ordinal', $tags) ? $tags['ordinal'] : 'not set', "\n";
-
-var_dump(
- $server->getLatency(),
- $server->getPort(),
- $server->getType() == MongoDB\Driver\Server::TYPE_RS_PRIMARY,
- $server->isPrimary(),
- $server->isSecondary(),
- $server->isArbiter(),
- $server->isHidden(),
- $server->isPassive()
-);
-$info = $server->getInfo(); // hello response changes between mongod versions
-var_dump($info["setName"], $info["hosts"]);
-var_dump($info["me"] == $server->getHost() . ":" . $server->getPort());
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-string(%d) "%s"
-dc: ny
-ordinal: one
-int(%d)
-int(%d)
-bool(true)
-bool(true)
-bool(false)
-bool(false)
-bool(false)
-bool(false)
-string(%d) "repl0%S"
-array(2) {
- [0]=>
- string(%d) "%s:%d"
- [1]=>
- string(%d) "%s:%d"
-}
-bool(true)
-===DONE===
diff --git a/mongodb-1.12.0/tests/replicaset/server-002.phpt b/mongodb-1.12.0/tests/replicaset/server-002.phpt
deleted file mode 100644
index 029bac81..00000000
--- a/mongodb-1.12.0/tests/replicaset/server-002.phpt
+++ /dev/null
@@ -1,64 +0,0 @@
---TEST--
-MongoDB\Driver\Server: Manager->getServer() returning correct server
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_replica_set(); ?>
-<?php skip_if_not_enough_data_nodes(2, 2); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-
-
-$rp = new MongoDB\Driver\ReadPreference(MongoDB\Driver\ReadPreference::RP_SECONDARY);
-$result = $manager->executeQuery(NS, new MongoDB\Driver\Query(array()), $rp);
-
-/* writes go to the primary */
-$server = $result->getServer();
-
-var_dump(
- $server->getHost()
-);
-
-$tags = $server->getTags();
-echo "dc: ", array_key_exists('dc', $tags) ? $tags['dc'] : 'not set', "\n";
-echo "ordinal: ", array_key_exists('ordinal', $tags) ? $tags['ordinal'] : 'not set', "\n";
-
-var_dump(
- $server->getLatency(),
- $server->getPort(),
- $server->getType() == MongoDB\Driver\Server::TYPE_RS_SECONDARY,
- $server->isPrimary(),
- $server->isSecondary(),
- $server->isArbiter(),
- $server->isHidden(),
- $server->isPassive()
-);
-$info = $server->getInfo(); // hello response changes between mongod versions
-var_dump($info["setName"], $info["hosts"]);
-var_dump($info["me"] == $server->getHost() . ":" . $server->getPort());
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-string(%d) "%s"
-dc: pa
-ordinal: two
-int(%d)
-int(%d)
-bool(true)
-bool(false)
-bool(true)
-bool(false)
-bool(false)
-bool(false)
-string(%s) "repl0%S"
-array(2) {
- [0]=>
- string(%d) "%s:%d"
- [1]=>
- string(%d) "%s:%d"
-}
-bool(true)
-===DONE===
diff --git a/mongodb-1.12.0/tests/replicaset/writeresult-getserver-002.phpt b/mongodb-1.12.0/tests/replicaset/writeresult-getserver-002.phpt
deleted file mode 100644
index ba46e2d8..00000000
--- a/mongodb-1.12.0/tests/replicaset/writeresult-getserver-002.phpt
+++ /dev/null
@@ -1,99 +0,0 @@
---TEST--
-MongoDB\Driver\Server: Manager->getServer() returning correct server
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_auth(); /* TODO: PHPC-2008 */ ?>
-<?php skip_if_not_replica_set(); ?>
-<?php skip_if_no_secondary(); ?>
-<?php skip_if_not_clean(); ?>
-<?php skip_if_not_clean('local', COLLECTION_NAME); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-// Disable retryWrites since the test writes to the unreplicated "local" database
-// Explicitly use w:1 to work around MongoDB 5.0 applying w:majority (SERVER-61790)
-$manager = create_test_manager(URI, ['retryWrites' => false, 'w' => 1]);
-
-$doc = array("example" => "document");
-$bulk = new \MongoDB\Driver\BulkWrite();
-$bulk->insert($doc);
-$wresult = $manager->executeBulkWrite(NS, $bulk);
-
-$bulk = new \MongoDB\Driver\BulkWrite();
-$bulk->insert($doc);
-
-/* writes go to the primary */
-$server = $wresult->getServer();
-/* This is the same server */
-$server2 = $server->executeBulkWrite(NS, $bulk)->getServer();
-
-/* Both are the primary, e.g. the same server */
-var_dump($server == $server2);
-
-
-$rp = new MongoDB\Driver\ReadPreference(MongoDB\Driver\ReadPreference::RP_SECONDARY);
-/* Fetch a secondary */
-$server3 = $manager->executeQuery(NS, new MongoDB\Driver\Query(array()), $rp)->getServer();
-
-var_dump($server == $server3);
-var_dump($server->getPort(), $server3->getPort());
-
-
-$bulk = new \MongoDB\Driver\BulkWrite();
-$bulk->insert($doc);
-
-$result = $server3->executeBulkWrite('local.' . COLLECTION_NAME, $bulk);
-var_dump($result, $result->getServer()->getHost(), $result->getServer()->getPort());
-$result = $server3->executeQuery('local.' . COLLECTION_NAME, new MongoDB\Driver\Query(array()));
-foreach($result as $document) {
- var_dump($document);
-}
-$cmd = new MongoDB\Driver\Command(['drop' => COLLECTION_NAME]);
-$server3->executeCommand("local", $cmd);
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-bool(true)
-bool(false)
-int(%d)
-int(%d)
-object(MongoDB\Driver\WriteResult)#%d (%d) {
- ["nInserted"]=>
- int(1)
- ["nMatched"]=>
- int(0)
- ["nModified"]=>
- int(0)
- ["nRemoved"]=>
- int(0)
- ["nUpserted"]=>
- int(0)
- ["upsertedIds"]=>
- array(0) {
- }
- ["writeErrors"]=>
- array(0) {
- }
- ["writeConcernError"]=>
- NULL
- ["writeConcern"]=>
- object(MongoDB\Driver\WriteConcern)#%d (%d) {
- ["w"]=>
- int(1)
- }
-}
-string(%d) "%s"
-int(%d)
-object(stdClass)#%d (2) {
- ["_id"]=>
- object(%s\ObjectId)#%d (1) {
- ["oid"]=>
- string(24) "%s"
- }
- ["example"]=>
- string(8) "document"
-}
-===DONE===
diff --git a/mongodb-1.12.0/tests/retryable-writes/retryable-writes-001.phpt b/mongodb-1.12.0/tests/retryable-writes/retryable-writes-001.phpt
deleted file mode 100644
index aeac7d3a..00000000
--- a/mongodb-1.12.0/tests/retryable-writes/retryable-writes-001.phpt
+++ /dev/null
@@ -1,85 +0,0 @@
---TEST--
-Retryable writes: supported single-statement operations include transaction IDs
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_not_replica_set_or_sharded_cluster_with_replica_set(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-class TransactionIdObserver implements MongoDB\Driver\Monitoring\CommandSubscriber
-{
- public function commandStarted(MongoDB\Driver\Monitoring\CommandStartedEvent $event)
- {
- $command = $event->getCommand();
- $hasTransactionId = isset($command->lsid) && isset($command->txnNumber);
-
- printf("%s command includes transaction ID: %s\n", $event->getCommandName(), $hasTransactionId ? 'yes' : 'no');
- }
-
- public function commandSucceeded(MongoDB\Driver\Monitoring\CommandSucceededEvent $event)
- {
- }
-
- public function commandFailed(MongoDB\Driver\Monitoring\CommandFailedEvent $event)
- {
- }
-}
-
-$observer = new TransactionIdObserver;
-MongoDB\Driver\Monitoring\addSubscriber($observer);
-
-$manager = create_test_manager();
-
-echo "Testing deleteOne\n";
-$bulk = new MongoDB\Driver\BulkWrite;
-$bulk->delete(['x' => 1], ['limit' => 1]);
-$manager->executeBulkWrite(NS, $bulk);
-
-echo "\nTesting insertOne\n";
-$bulk = new MongoDB\Driver\BulkWrite;
-$bulk->insert(['x' => 1]);
-$manager->executeBulkWrite(NS, $bulk);
-
-echo "\nTesting replaceOne\n";
-$bulk = new MongoDB\Driver\BulkWrite;
-$bulk->update(['x' => 1], ['x' => 2]);
-$manager->executeBulkWrite(NS, $bulk);
-
-echo "\nTesting updateOne\n";
-$bulk = new MongoDB\Driver\BulkWrite;
-$bulk->update(['x' => 1], ['$inc' => ['x' => 1]]);
-$manager->executeBulkWrite(NS, $bulk);
-
-echo "\nTesting findAndModify\n";
-$command = new MongoDB\Driver\Command([
- 'findAndModify' => COLLECTION_NAME,
- 'query' => ['x' => 1],
- 'update' => ['$inc' => ['x' => 1]],
-]);
-$manager->executeReadWriteCommand(DATABASE_NAME, $command);
-
-MongoDB\Driver\Monitoring\removeSubscriber($observer);
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-Testing deleteOne
-delete command includes transaction ID: yes
-
-Testing insertOne
-insert command includes transaction ID: yes
-
-Testing replaceOne
-update command includes transaction ID: yes
-
-Testing updateOne
-update command includes transaction ID: yes
-
-Testing findAndModify
-findAndModify command includes transaction ID: yes
-===DONE===
diff --git a/mongodb-1.12.0/tests/retryable-writes/retryable-writes-002.phpt b/mongodb-1.12.0/tests/retryable-writes/retryable-writes-002.phpt
deleted file mode 100644
index 3786d501..00000000
--- a/mongodb-1.12.0/tests/retryable-writes/retryable-writes-002.phpt
+++ /dev/null
@@ -1,86 +0,0 @@
---TEST--
-Retryable writes: supported multi-statement operations include transaction IDs
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_not_replica_set_or_sharded_cluster_with_replica_set(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-class TransactionIdObserver implements MongoDB\Driver\Monitoring\CommandSubscriber
-{
- public function commandStarted(MongoDB\Driver\Monitoring\CommandStartedEvent $event)
- {
- $command = $event->getCommand();
- $hasTransactionId = isset($command->lsid) && isset($command->txnNumber);
-
- printf("%s command includes transaction ID: %s\n", $event->getCommandName(), $hasTransactionId ? 'yes' : 'no');
- }
-
- public function commandSucceeded(MongoDB\Driver\Monitoring\CommandSucceededEvent $event)
- {
- }
-
- public function commandFailed(MongoDB\Driver\Monitoring\CommandFailedEvent $event)
- {
- }
-}
-
-$observer = new TransactionIdObserver;
-MongoDB\Driver\Monitoring\addSubscriber($observer);
-
-$manager = create_test_manager();
-
-echo "Testing multi-statement bulk write (ordered=true)\n";
-$bulk = new MongoDB\Driver\BulkWrite(['ordered' => true]);
-$bulk->delete(['x' => 1], ['limit' => 1]);
-$bulk->insert(['x' => 1]);
-$bulk->update(['x' => 1], ['$inc' => ['x' => 1]]);
-$bulk->update(['x' => 1], ['x' => 2]);
-$manager->executeBulkWrite(NS, $bulk);
-
-echo "\nTesting multi-statement bulk write (ordered=false)\n";
-$bulk = new MongoDB\Driver\BulkWrite(['ordered' => false]);
-$bulk->delete(['x' => 1], ['limit' => 1]);
-$bulk->insert(['x' => 1]);
-$bulk->update(['x' => 1], ['$inc' => ['x' => 1]]);
-$bulk->update(['x' => 1], ['x' => 2]);
-$manager->executeBulkWrite(NS, $bulk);
-
-echo "\nTesting insertMany (ordered=true)\n";
-$bulk = new MongoDB\Driver\BulkWrite(['ordered' => true]);
-$bulk->insert(['x' => 1]);
-$bulk->insert(['x' => 2]);
-$manager->executeBulkWrite(NS, $bulk);
-
-echo "\nTesting insertMany (ordered=false)\n";
-$bulk = new MongoDB\Driver\BulkWrite(['ordered' => false]);
-$bulk->insert(['x' => 1]);
-$bulk->insert(['x' => 2]);
-$manager->executeBulkWrite(NS, $bulk);
-
-MongoDB\Driver\Monitoring\removeSubscriber($observer);
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-Testing multi-statement bulk write (ordered=true)
-delete command includes transaction ID: yes
-insert command includes transaction ID: yes
-update command includes transaction ID: yes
-
-Testing multi-statement bulk write (ordered=false)
-delete command includes transaction ID: yes
-insert command includes transaction ID: yes
-update command includes transaction ID: yes
-
-Testing insertMany (ordered=true)
-insert command includes transaction ID: yes
-
-Testing insertMany (ordered=false)
-insert command includes transaction ID: yes
-===DONE===
diff --git a/mongodb-1.12.0/tests/retryable-writes/retryable-writes-003.phpt b/mongodb-1.12.0/tests/retryable-writes/retryable-writes-003.phpt
deleted file mode 100644
index 09735c67..00000000
--- a/mongodb-1.12.0/tests/retryable-writes/retryable-writes-003.phpt
+++ /dev/null
@@ -1,100 +0,0 @@
---TEST--
-Retryable writes: unsupported operations do not include transaction IDs
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_not_replica_set_or_sharded_cluster_with_replica_set(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-class TransactionIdObserver implements MongoDB\Driver\Monitoring\CommandSubscriber
-{
- public function commandStarted(MongoDB\Driver\Monitoring\CommandStartedEvent $event)
- {
- $command = $event->getCommand();
- $hasTransactionId = isset($command->lsid) && isset($command->txnNumber);
-
- printf("%s command includes transaction ID: %s\n", $event->getCommandName(), $hasTransactionId ? 'yes' : 'no');
- }
-
- public function commandSucceeded(MongoDB\Driver\Monitoring\CommandSucceededEvent $event)
- {
- }
-
- public function commandFailed(MongoDB\Driver\Monitoring\CommandFailedEvent $event)
- {
- }
-}
-
-$observer = new TransactionIdObserver;
-MongoDB\Driver\Monitoring\addSubscriber($observer);
-
-$manager = create_test_manager();
-
-echo "Testing deleteMany\n";
-$bulk = new MongoDB\Driver\BulkWrite;
-$bulk->delete(['x' => 1], ['limit' => 0]);
-$manager->executeBulkWrite(NS, $bulk);
-
-echo "\nTesting updateMany\n";
-$bulk = new MongoDB\Driver\BulkWrite;
-$bulk->update(['x' => 1], ['$inc' => ['x' => 1]], ['multi' => true]);
-$manager->executeBulkWrite(NS, $bulk);
-
-echo "\nTesting multi-statement bulk write with one unsupported operation (ordered=true)\n";
-$bulk = new MongoDB\Driver\BulkWrite(['ordered' => true]);
-$bulk->delete(['x' => 1], ['limit' => 1]);
-$bulk->insert(['x' => 1]);
-$bulk->update(['x' => 1], ['$inc' => ['x' => 1]]);
-$bulk->update(['x' => 1], ['x' => 2]);
-$bulk->update(['x' => 1], ['$inc' => ['x' => 1]], ['multi' => true]);
-$manager->executeBulkWrite(NS, $bulk);
-
-echo "\nTesting multi-statement bulk write with one unsupported operation (ordered=false)\n";
-$bulk = new MongoDB\Driver\BulkWrite(['ordered' => false]);
-$bulk->delete(['x' => 1], ['limit' => 1]);
-$bulk->insert(['x' => 1]);
-$bulk->update(['x' => 1], ['$inc' => ['x' => 1]]);
-$bulk->update(['x' => 1], ['x' => 2]);
-$bulk->update(['x' => 1], ['$inc' => ['x' => 1]], ['multi' => true]);
-$manager->executeBulkWrite(NS, $bulk);
-
-echo "\nTesting aggregate\n";
-$command = new MongoDB\Driver\Command([
- 'aggregate' => COLLECTION_NAME,
- 'pipeline' => [
- ['$match' => ['x' => 1]],
- ['$out' => COLLECTION_NAME . '.out'],
- ],
- 'cursor' => new stdClass,
-]);
-$manager->executeReadWriteCommand(DATABASE_NAME, $command);
-
-MongoDB\Driver\Monitoring\removeSubscriber($observer);
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-Testing deleteMany
-delete command includes transaction ID: no
-
-Testing updateMany
-update command includes transaction ID: no
-
-Testing multi-statement bulk write with one unsupported operation (ordered=true)
-delete command includes transaction ID: yes
-insert command includes transaction ID: yes
-update command includes transaction ID: no
-
-Testing multi-statement bulk write with one unsupported operation (ordered=false)
-delete command includes transaction ID: yes
-insert command includes transaction ID: yes
-update command includes transaction ID: no
-
-Testing aggregate
-aggregate command includes transaction ID: no
-===DONE===
diff --git a/mongodb-1.12.0/tests/retryable-writes/retryable-writes-004.phpt b/mongodb-1.12.0/tests/retryable-writes/retryable-writes-004.phpt
deleted file mode 100644
index 07da71a2..00000000
--- a/mongodb-1.12.0/tests/retryable-writes/retryable-writes-004.phpt
+++ /dev/null
@@ -1,89 +0,0 @@
---TEST--
-Retryable writes: unacknowledged write operations do not include transaction IDs
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_not_replica_set_or_sharded_cluster_with_replica_set(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-class TransactionIdObserver implements MongoDB\Driver\Monitoring\CommandSubscriber
-{
- public function commandStarted(MongoDB\Driver\Monitoring\CommandStartedEvent $event)
- {
- $command = $event->getCommand();
- $hasTransactionId = isset($command->lsid) && isset($command->txnNumber);
-
- printf("%s command includes transaction ID: %s\n", $event->getCommandName(), $hasTransactionId ? 'yes' : 'no');
- }
-
- public function commandSucceeded(MongoDB\Driver\Monitoring\CommandSucceededEvent $event)
- {
- }
-
- public function commandFailed(MongoDB\Driver\Monitoring\CommandFailedEvent $event)
- {
- }
-}
-
-$observer = new TransactionIdObserver;
-MongoDB\Driver\Monitoring\addSubscriber($observer);
-
-$manager = create_test_manager();
-$writeConcern = new MongoDB\Driver\WriteConcern(0);
-
-echo "Testing unacknowledged deleteOne\n";
-$bulk = new MongoDB\Driver\BulkWrite;
-$bulk->delete(['x' => 1], ['limit' => 1]);
-$manager->executeBulkWrite(NS, $bulk, ['writeConcern' => $writeConcern]);
-
-echo "\nTesting unacknowledged insertOne\n";
-$bulk = new MongoDB\Driver\BulkWrite;
-$bulk->insert(['x' => 1]);
-$manager->executeBulkWrite(NS, $bulk, ['writeConcern' => $writeConcern]);
-
-echo "\nTesting unacknowledged replaceOne\n";
-$bulk = new MongoDB\Driver\BulkWrite;
-$bulk->update(['x' => 1], ['x' => 2]);
-$manager->executeBulkWrite(NS, $bulk, ['writeConcern' => $writeConcern]);
-
-echo "\nTesting unacknowledged updateOne\n";
-$bulk = new MongoDB\Driver\BulkWrite;
-$bulk->update(['x' => 1], ['$inc' => ['x' => 1]]);
-$manager->executeBulkWrite(NS, $bulk, ['writeConcern' => $writeConcern]);
-
-/* Note: the server does not actually support unacknowledged write concerns for
- * findAndModify. This is just testing that mongoc_cmd_parts_set_write_concern()
- * in libmongoc detects w:0 and refrains from adding a transaction ID. */
-echo "\nTesting unacknowledged findAndModify\n";
-$command = new MongoDB\Driver\Command([
- 'findAndModify' => COLLECTION_NAME,
- 'query' => ['x' => 1],
- 'update' => ['$inc' => ['x' => 1]],
-]);
-$manager->executeReadWriteCommand(DATABASE_NAME, $command, ['writeConcern' => $writeConcern]);
-
-MongoDB\Driver\Monitoring\removeSubscriber($observer);
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-Testing unacknowledged deleteOne
-delete command includes transaction ID: no
-
-Testing unacknowledged insertOne
-insert command includes transaction ID: no
-
-Testing unacknowledged replaceOne
-update command includes transaction ID: no
-
-Testing unacknowledged updateOne
-update command includes transaction ID: no
-
-Testing unacknowledged findAndModify
-findAndModify command includes transaction ID: no
-===DONE===
diff --git a/mongodb-1.12.0/tests/retryable-writes/retryable-writes-005.phpt b/mongodb-1.12.0/tests/retryable-writes/retryable-writes-005.phpt
deleted file mode 100644
index 3e5aa977..00000000
--- a/mongodb-1.12.0/tests/retryable-writes/retryable-writes-005.phpt
+++ /dev/null
@@ -1,71 +0,0 @@
---TEST--
-Retryable writes: non-write command methods do not include transaction IDs
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_not_replica_set_or_sharded_cluster_with_replica_set(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-class TransactionIdObserver implements MongoDB\Driver\Monitoring\CommandSubscriber
-{
- public function commandStarted(MongoDB\Driver\Monitoring\CommandStartedEvent $event)
- {
- $command = $event->getCommand();
- $hasTransactionId = isset($command->lsid) && isset($command->txnNumber);
-
- printf("%s command includes transaction ID: %s\n", $event->getCommandName(), $hasTransactionId ? 'yes' : 'no');
- }
-
- public function commandSucceeded(MongoDB\Driver\Monitoring\CommandSucceededEvent $event)
- {
- }
-
- public function commandFailed(MongoDB\Driver\Monitoring\CommandFailedEvent $event)
- {
- }
-}
-
-$observer = new TransactionIdObserver;
-MongoDB\Driver\Monitoring\addSubscriber($observer);
-
-$manager = create_test_manager();
-$command = new MongoDB\Driver\Command([
- 'findAndModify' => COLLECTION_NAME,
- 'query' => ['x' => 1],
- 'update' => ['$inc' => ['x' => 1]],
-]);
-
-echo "Testing Manager::executeCommand()\n";
-$manager->executeCommand(DATABASE_NAME, $command);
-
-echo "\nTesting Manager::executeReadCommand()\n";
-$manager->executeReadCommand(DATABASE_NAME, $command);
-
-echo "\nTesting Manager::executeReadWriteCommand()\n";
-$manager->executeReadWriteCommand(DATABASE_NAME, $command);
-
-echo "\nTesting Manager::executeWriteCommand()\n";
-$manager->executeWriteCommand(DATABASE_NAME, $command);
-
-MongoDB\Driver\Monitoring\removeSubscriber($observer);
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-Testing Manager::executeCommand()
-findAndModify command includes transaction ID: no
-
-Testing Manager::executeReadCommand()
-findAndModify command includes transaction ID: no
-
-Testing Manager::executeReadWriteCommand()
-findAndModify command includes transaction ID: yes
-
-Testing Manager::executeWriteCommand()
-findAndModify command includes transaction ID: yes
-===DONE===
diff --git a/mongodb-1.12.0/tests/retryable-writes/retryable-writes_error-001.phpt b/mongodb-1.12.0/tests/retryable-writes/retryable-writes_error-001.phpt
deleted file mode 100644
index 0b1e43d7..00000000
--- a/mongodb-1.12.0/tests/retryable-writes/retryable-writes_error-001.phpt
+++ /dev/null
@@ -1,36 +0,0 @@
---TEST--
-Retryable writes: actionable error message when using retryable writes on unsupported storage engines
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_not_server_storage_engine('mmapv1'); ?>
-<?php skip_if_not_replica_set_or_sharded_cluster_with_replica_set(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-$session = $manager->startSession();
-
-echo throws(
- function() use ($manager, $session) {
- $command = new MongoDB\Driver\Command([
- 'findAndModify' => COLLECTION_NAME,
- 'query' => ['x' => 1],
- 'update' => ['$inc' => ['x' => 1]],
- ]);
- $manager->executeReadWriteCommand(DATABASE_NAME, $command, ['session' => $session]);
- },
- \MongoDB\Driver\Exception\CommandException::class
-);
-echo "\n";
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-OK: Got MongoDB\Driver\Exception\CommandException
-This MongoDB deployment does not support retryable writes. Please add retryWrites=false to your connection string.
-===DONE===
diff --git a/mongodb-1.12.0/tests/server/server-construct-001.phpt b/mongodb-1.12.0/tests/server/server-construct-001.phpt
deleted file mode 100644
index 32d9e208..00000000
--- a/mongodb-1.12.0/tests/server/server-construct-001.phpt
+++ /dev/null
@@ -1,33 +0,0 @@
---TEST--
-MongoDB\Driver\Server::__construct()
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_not_clean(); ?>
-<?php skip_if_multiple_mongos(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-/* For replica sets we need to do some extra work to get the primary */
-$uri = is_replica_set(URI) ? get_primary_server(URI)->getInfo()['me'] : URI;
-$parsed = parse_url($uri);
-
-$manager = create_test_manager();
-
-$bulk = new \MongoDB\Driver\BulkWrite();
-$bulk->insert(array('foo' => 'bar'));
-$server = $manager->executeBulkWrite(NS, $bulk)->getServer();
-
-$expectedHost = $parsed['host'];
-$expectedPort = (integer) (isset($parsed['port']) ? $parsed['port'] : 27017);
-
-var_dump($server->getHost() == $expectedHost);
-var_dump($server->getPort() == $expectedPort);
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-bool(true)
-bool(true)
-===DONE===
diff --git a/mongodb-1.12.0/tests/server/server-executeCommand-002.phpt b/mongodb-1.12.0/tests/server/server-executeCommand-002.phpt
deleted file mode 100644
index f837d0a9..00000000
--- a/mongodb-1.12.0/tests/server/server-executeCommand-002.phpt
+++ /dev/null
@@ -1,76 +0,0 @@
---TEST--
-MongoDB\Driver\Server::executeCommand() takes a read preference
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_replica_set(); ?>
-<?php skip_if_no_secondary(); ?>
-<?php skip_if_server_version('<', '3.2'); ?>
-<?php skip_if_not_clean(DATABASE_NAME, 'system.profile'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-
-$rp = new MongoDB\Driver\ReadPreference(MongoDB\Driver\ReadPreference::RP_SECONDARY);
-$secondary = $manager->selectServer($rp);
-
-$command = new MongoDB\Driver\Command(array('profile' => 2));
-$cursor = $secondary->executeCommand(DATABASE_NAME, $command);
-$result = current($cursor->toArray());
-
-printf("Set profile level to 2 successfully: %s\n", (empty($result->ok) ? 'no' : 'yes'));
-
-$command = new MongoDB\Driver\Command([
- 'aggregate' => COLLECTION_NAME,
- 'pipeline' => [ [ '$match' => [ 'x' => 1 ] ] ],
- 'cursor' => (object) [],
-]);
-$secondary->executeCommand(DATABASE_NAME, $command, $rp);
-
-$query = new MongoDB\Driver\Query(
- array(
- 'op' => 'command',
- 'ns' => DATABASE_NAME . '.' . COLLECTION_NAME,
- ),
- array(
- 'sort' => array('ts' => -1),
- 'limit' => 1,
- )
-);
-$cursor = $secondary->executeQuery(DATABASE_NAME . '.system.profile', $query, $rp);
-$profileEntry = current($cursor->toArray());
-
-var_dump($profileEntry->command);
-
-$command = new MongoDB\Driver\Command(array('profile' => 0));
-$cursor = $secondary->executeCommand(DATABASE_NAME, $command);
-$result = current($cursor->toArray());
-
-printf("Set profile level to 0 successfully: %s\n", (empty($result->ok) ? 'no' : 'yes'));
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-Set profile level to 2 successfully: yes
-object(stdClass)#%d (%d) {
- ["aggregate"]=>
- string(32) "server_server_executeCommand_002"
- ["pipeline"]=>
- array(1) {
- [0]=>
- object(stdClass)#%d (%d) {
- ["$match"]=>
- object(stdClass)#%d (%d) {
- ["x"]=>
- int(1)
- }
- }
- }
- ["cursor"]=>
- object(stdClass)#%d (%d) {
- }%A
-}
-Set profile level to 0 successfully: yes
-===DONE===
diff --git a/mongodb-1.12.0/tests/server/server-executeCommand-006.phpt b/mongodb-1.12.0/tests/server/server-executeCommand-006.phpt
deleted file mode 100644
index 5fbdba3e..00000000
--- a/mongodb-1.12.0/tests/server/server-executeCommand-006.phpt
+++ /dev/null
@@ -1,51 +0,0 @@
---TEST--
-MongoDB\Driver\Server::executeCommand() options (MONGO_CMD_RAW)
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_standalone(); ?>
-<?php skip_if_not_clean(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-require_once __DIR__ . "/../utils/observer.php";
-
-$manager = create_test_manager();
-$server = $manager->selectServer(new MongoDB\Driver\ReadPreference(MongoDB\Driver\ReadPreference::RP_PRIMARY));
-
-(new CommandObserver)->observe(
- function() use ($server) {
- $command = new MongoDB\Driver\Command([
- 'ping' => true,
- ]);
-
- try {
- $server->executeCommand(
- DATABASE_NAME,
- $command,
- [
- 'readPreference' => new \MongoDB\Driver\ReadPreference(\MongoDB\Driver\ReadPreference::RP_SECONDARY),
- 'readConcern' => new \MongoDB\Driver\ReadConcern(\MongoDB\Driver\ReadConcern::LOCAL),
- 'writeConcern' => new \MongoDB\Driver\WriteConcern(\MongoDB\Driver\WriteConcern::MAJORITY),
- ]
- );
- } catch ( Exception $e ) {
- // Ignore exception that ping doesn't support writeConcern
- }
- },
- function(stdClass $command) {
- echo "Read Preference: ", $command->{'$readPreference'}->mode, "\n";
- echo "Read Concern: ", $command->readConcern->level, "\n";
- echo "Write Concern: ", $command->writeConcern->w, "\n";
- }
-);
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-Read Preference: secondary
-Read Concern: local
-Write Concern: majority
-===DONE===
diff --git a/mongodb-1.12.0/tests/server/server-executeCommand-008.phpt b/mongodb-1.12.0/tests/server/server-executeCommand-008.phpt
deleted file mode 100644
index 13205efb..00000000
--- a/mongodb-1.12.0/tests/server/server-executeCommand-008.phpt
+++ /dev/null
@@ -1,51 +0,0 @@
---TEST--
-MongoDB\Driver\Server::executeCommand() does not send read preference to standalone
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_not_standalone(); ?>
-<?php skip_if_not_clean(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-require_once __DIR__ . "/../utils/observer.php";
-
-$manager = create_test_manager();
-$server = $manager->selectServer(new MongoDB\Driver\ReadPreference(MongoDB\Driver\ReadPreference::RP_PRIMARY));
-
-(new CommandObserver)->observe(
- function() use ($server) {
- $command = new MongoDB\Driver\Command([
- 'ping' => true,
- ]);
-
- try {
- $server->executeCommand(
- DATABASE_NAME,
- $command,
- [
- 'readPreference' => new \MongoDB\Driver\ReadPreference(\MongoDB\Driver\ReadPreference::RP_SECONDARY),
- 'readConcern' => new \MongoDB\Driver\ReadConcern(\MongoDB\Driver\ReadConcern::LOCAL),
- 'writeConcern' => new \MongoDB\Driver\WriteConcern(\MongoDB\Driver\WriteConcern::MAJORITY),
- ]
- );
- } catch ( Exception $e ) {
- // Ignore exception that ping doesn't support writeConcern
- }
- },
- function(stdClass $command) {
- echo isset($command->{'$readPreference'}) ? 'Read preference set' : 'No read preference set', "\n";
- echo "Read Concern: ", $command->readConcern->level, "\n";
- echo "Write Concern: ", $command->writeConcern->w, "\n";
- }
-);
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-No read preference set
-Read Concern: local
-Write Concern: majority
-===DONE===
diff --git a/mongodb-1.12.0/tests/server/server-executeCommand-010.phpt b/mongodb-1.12.0/tests/server/server-executeCommand-010.phpt
deleted file mode 100644
index 514623fc..00000000
--- a/mongodb-1.12.0/tests/server/server-executeCommand-010.phpt
+++ /dev/null
@@ -1,48 +0,0 @@
---TEST--
-MongoDB\Driver\Server::executeCommand() does not inherit read or write concern
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_replica_set(); ?>
-<?php skip_if_not_enough_data_nodes(2); /* w:2 */ ?>
-<?php skip_if_server_version('<', '3.6'); /* readConcernLevel:available */ ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-require_once __DIR__ . "/../utils/observer.php";
-
-$manager = create_test_manager(URI, ['readConcernLevel' => 'local', 'w' => 2, 'wtimeoutms' => 1000]);
-$server = $manager->selectServer(new MongoDB\Driver\ReadPreference('primary'));
-
-$command = new MongoDB\Driver\Command([
- 'aggregate' => COLLECTION_NAME,
- 'pipeline' => [
- ['$group' => ['_id' => 1]],
- ['$out' => COLLECTION_NAME . '.out'],
- ],
- 'cursor' => (object) [],
-]);
-
-(new CommandObserver)->observe(
- function() use ($server, $command) {
- $server->executeCommand(DATABASE_NAME, $command);
- $server->executeCommand(DATABASE_NAME, $command, [
- 'readConcern' => new MongoDB\Driver\ReadConcern(MongoDB\Driver\ReadConcern::AVAILABLE),
- 'writeConcern' => new MongoDB\Driver\WriteConcern(1),
- ]);
- },
- function(stdClass $command) {
- echo json_encode($command->readConcern ?? null), "\n";
- echo json_encode($command->writeConcern ?? null), "\n";
- }
-);
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-null
-null
-{"level":"available"}
-{"w":1}
-===DONE===
diff --git a/mongodb-1.12.0/tests/server/server-executeQuery-005.phpt b/mongodb-1.12.0/tests/server/server-executeQuery-005.phpt
deleted file mode 100644
index 4b4985d3..00000000
--- a/mongodb-1.12.0/tests/server/server-executeQuery-005.phpt
+++ /dev/null
@@ -1,60 +0,0 @@
---TEST--
-MongoDB\Driver\Server::executeQuery() takes a read preference (OP_QUERY)
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_replica_set(); ?>
-<?php skip_if_server_version('>=', '3.1'); ?>
-<?php skip_if_not_clean(DATABASE_NAME, 'system.profile'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-
-$rp = new MongoDB\Driver\ReadPreference(MongoDB\Driver\ReadPreference::RP_SECONDARY);
-$secondary = $manager->selectServer($rp);
-
-$command = new MongoDB\Driver\Command(array('profile' => 2));
-$cursor = $secondary->executeCommand(DATABASE_NAME, $command);
-$result = current($cursor->toArray());
-
-printf("Set profile level to 2 successfully: %s\n", (empty($result->ok) ? 'no' : 'yes'));
-
-if (empty($result->ok)) {
- exit("Could not set profile level\n");
-}
-
-$secondary->executeQuery(NS, new MongoDB\Driver\Query(array("x" => 1)), $rp);
-
-$query = new MongoDB\Driver\Query(
- array(
- 'op' => 'query',
- 'ns' => NS,
- ),
- array(
- 'sort' => array('ts' => -1),
- 'limit' => 1,
- )
-);
-$cursor = $secondary->executeQuery(DATABASE_NAME . '.system.profile', $query, $rp);
-$profileEntry = current($cursor->toArray());
-
-var_dump($profileEntry->query);
-
-$command = new MongoDB\Driver\Command(array('profile' => 0));
-$cursor = $secondary->executeCommand(DATABASE_NAME, $command);
-$result = current($cursor->toArray());
-
-printf("Set profile level to 0 successfully: %s\n", (empty($result->ok) ? 'no' : 'yes'));
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-Set profile level to 2 successfully: yes
-object(stdClass)#%d (%d) {
- ["x"]=>
- int(1)
-}
-Set profile level to 0 successfully: yes
-===DONE===
diff --git a/mongodb-1.12.0/tests/server/server-executeQuery-006.phpt b/mongodb-1.12.0/tests/server/server-executeQuery-006.phpt
deleted file mode 100644
index baf8a5fe..00000000
--- a/mongodb-1.12.0/tests/server/server-executeQuery-006.phpt
+++ /dev/null
@@ -1,66 +0,0 @@
---TEST--
-MongoDB\Driver\Server::executeQuery() takes a read preference (find command)
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_replica_set(); ?>
-<?php skip_if_no_secondary(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
-<?php skip_if_not_clean(DATABASE_NAME, 'system.profile'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-
-$rp = new MongoDB\Driver\ReadPreference(MongoDB\Driver\ReadPreference::RP_SECONDARY);
-$secondary = $manager->selectServer($rp);
-
-$command = new MongoDB\Driver\Command(array('profile' => 2));
-$cursor = $secondary->executeCommand(DATABASE_NAME, $command);
-$result = current($cursor->toArray());
-
-printf("Set profile level to 2 successfully: %s\n", (empty($result->ok) ? 'no' : 'yes'));
-
-if (empty($result->ok)) {
- exit("Could not set profile level\n");
-}
-
-$secondary->executeQuery(NS, new MongoDB\Driver\Query(array("x" => 1)), $rp);
-
-$query = new MongoDB\Driver\Query(
- array(
- 'op' => 'query',
- 'ns' => NS,
- ),
- array(
- 'sort' => array('ts' => -1),
- 'limit' => 1,
- )
-);
-$cursor = $secondary->executeQuery(DATABASE_NAME . '.system.profile', $query, $rp);
-$profileEntry = current($cursor->toArray());
-
-if (! isset( $profileEntry->command )) {
- var_dump($profileEntry);
-}
-var_dump($profileEntry->command->find);
-var_dump($profileEntry->command->filter);
-
-$command = new MongoDB\Driver\Command(array('profile' => 0));
-$cursor = $secondary->executeCommand(DATABASE_NAME, $command);
-$result = current($cursor->toArray());
-
-printf("Set profile level to 0 successfully: %s\n", (empty($result->ok) ? 'no' : 'yes'));
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-Set profile level to 2 successfully: yes
-string(%d) "%s"
-object(stdClass)#%d (1) {
- ["x"]=>
- int(1)
-}
-Set profile level to 0 successfully: yes
-===DONE===
diff --git a/mongodb-1.12.0/tests/server/server-executeQuery-012.phpt b/mongodb-1.12.0/tests/server/server-executeQuery-012.phpt
deleted file mode 100644
index c324f075..00000000
--- a/mongodb-1.12.0/tests/server/server-executeQuery-012.phpt
+++ /dev/null
@@ -1,68 +0,0 @@
---TEST--
-MongoDB\Driver\Server::executeQuery() pins transaction to server
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_mongos(); ?>
-<?php skip_if_no_transactions(); ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-
-/* Create collections as that can't be (automatically) done in a transaction */
-$manager->executeCommand(
- DATABASE_NAME,
- new \MongoDB\Driver\Command([ 'create' => COLLECTION_NAME ]),
- [ 'writeConcern' => new \MongoDB\Driver\WriteConcern( \MongoDB\Driver\WriteConcern::MAJORITY ) ]
-);
-
-$servers = $manager->getServers();
-$selectedServer = array_pop($servers);
-$wrongServer = array_pop($servers);
-var_dump($selectedServer != $wrongServer);
-
-$session = $manager->startSession();
-var_dump($session->getServer() instanceof \MongoDB\Driver\Server);
-
-$session->startTransaction();
-var_dump($session->getServer() instanceof \MongoDB\Driver\Server);
-
-$query = new MongoDB\Driver\Query([]);
-$selectedServer->executeQuery(NS, $query, ['session' => $session]);
-
-var_dump($session->getServer() == $selectedServer);
-
-$bulk = new MongoDB\Driver\BulkWrite();
-$bulk->insert(['x' => 1]);
-$selectedServer->executeBulkWrite(NS, $bulk, ['session' => $session]);
-
-echo throws(function () use ($wrongServer, $session) {
- $query = new MongoDB\Driver\Query([]);
- $wrongServer->executeQuery(NS, $query, ['session' => $session]);
-}, \MongoDB\Driver\Exception\RuntimeException::class), "\n";
-
-$session->commitTransaction();
-
-var_dump($session->getServer() == $selectedServer);
-
-$bulk = new MongoDB\Driver\BulkWrite();
-$bulk->insert(['x' => 1]);
-$selectedServer->executeBulkWrite(NS, $bulk, ['session' => $session]);
-
-var_dump($session->getServer() instanceof \MongoDB\Driver\Server);
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-bool(true)
-bool(false)
-bool(false)
-bool(true)
-OK: Got MongoDB\Driver\Exception\RuntimeException
-Requested server id does not matched pinned server id
-bool(true)
-bool(false)
-===DONE===
diff --git a/mongodb-1.12.0/tests/server/server-executeQuery-013.phpt b/mongodb-1.12.0/tests/server/server-executeQuery-013.phpt
deleted file mode 100644
index d8f3067a..00000000
--- a/mongodb-1.12.0/tests/server/server-executeQuery-013.phpt
+++ /dev/null
@@ -1,34 +0,0 @@
---TEST--
-MongoDB\Driver\Server::executeQuery() read concern inheritance
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_replica_set(); ?>
-<?php skip_if_server_version('<', '3.6'); /* readConcernLevel:available */ ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-require_once __DIR__ . "/../utils/observer.php";
-
-$manager = create_test_manager(URI, ['readConcernLevel' => 'local']);
-$server = $manager->selectServer(new MongoDB\Driver\ReadPreference('primary'));
-
-(new CommandObserver)->observe(
- function() use ($server) {
- $server->executeQuery(NS, new MongoDB\Driver\Query([]));
- $server->executeQuery(NS, new MongoDB\Driver\Query([], [
- 'readConcern' => new MongoDB\Driver\ReadConcern(MongoDB\Driver\ReadConcern::AVAILABLE),
- ]));
- },
- function(stdClass $command) {
- echo json_encode($command->readConcern), "\n";
- }
-);
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-{"level":"local"}
-{"level":"available"}
-===DONE===
diff --git a/mongodb-1.12.0/tests/server/server-executeReadCommand-001.phpt b/mongodb-1.12.0/tests/server/server-executeReadCommand-001.phpt
deleted file mode 100644
index 53ed2b36..00000000
--- a/mongodb-1.12.0/tests/server/server-executeReadCommand-001.phpt
+++ /dev/null
@@ -1,48 +0,0 @@
---TEST--
-MongoDB\Driver\Server::executeReadCommand()
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_not_replica_set(); ?>
-<?php skip_if_no_secondary(); ?>
-<?php skip_if_not_clean(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
-<?php skip_if_not_server_storage_engine('wiredTiger'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-require_once __DIR__ . "/../utils/observer.php";
-
-$manager = create_test_manager();
-$server = $manager->selectServer(new MongoDB\Driver\ReadPreference(MongoDB\Driver\ReadPreference::RP_SECONDARY));
-
-(new CommandObserver)->observe(
- function() use ($server) {
- $command = new MongoDB\Driver\Command( [
- 'aggregate' => NS,
- 'pipeline' => [],
- 'cursor' => new stdClass(),
- ] );
- $server->executeReadCommand(
- DATABASE_NAME,
- $command,
- [
- 'readPreference' => new \MongoDB\Driver\ReadPreference(\MongoDB\Driver\ReadPreference::RP_SECONDARY),
- 'readConcern' => new \MongoDB\Driver\ReadConcern(\MongoDB\Driver\ReadConcern::MAJORITY),
- ]
- );
- },
- function(stdClass $command) {
- echo "Read Preference: ", $command->{'$readPreference'}->mode, "\n";
- echo "Read Concern: ", $command->readConcern->level, "\n";
- }
-);
-
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-Read Preference: secondary
-Read Concern: majority
-===DONE===
diff --git a/mongodb-1.12.0/tests/server/server-executeReadCommand-003.phpt b/mongodb-1.12.0/tests/server/server-executeReadCommand-003.phpt
deleted file mode 100644
index fac41853..00000000
--- a/mongodb-1.12.0/tests/server/server-executeReadCommand-003.phpt
+++ /dev/null
@@ -1,40 +0,0 @@
---TEST--
-MongoDB\Driver\Server::executeReadCommand() read concern inheritance
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_replica_set(); ?>
-<?php skip_if_server_version('<', '3.6'); /* readConcernLevel:available */ ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-require_once __DIR__ . "/../utils/observer.php";
-
-$manager = create_test_manager(URI, ['readConcernLevel' => 'local']);
-$server = $manager->selectServer(new MongoDB\Driver\ReadPreference('primary'));
-
-$command = new MongoDB\Driver\Command([
- 'aggregate' => COLLECTION_NAME,
- 'pipeline' => [['$group' => ['_id' => 1]]],
- 'cursor' => (object) [],
-]);
-
-(new CommandObserver)->observe(
- function() use ($server, $command) {
- $server->executeReadCommand(DATABASE_NAME, $command);
- $server->executeReadCommand(DATABASE_NAME, $command, [
- 'readConcern' => new MongoDB\Driver\ReadConcern(MongoDB\Driver\ReadConcern::AVAILABLE),
- ]);
- },
- function(stdClass $command) {
- echo json_encode($command->readConcern), "\n";
- }
-);
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-{"level":"local"}
-{"level":"available"}
-===DONE===
diff --git a/mongodb-1.12.0/tests/server/server-executeReadWriteCommand-001.phpt b/mongodb-1.12.0/tests/server/server-executeReadWriteCommand-001.phpt
deleted file mode 100644
index 2c553a34..00000000
--- a/mongodb-1.12.0/tests/server/server-executeReadWriteCommand-001.phpt
+++ /dev/null
@@ -1,43 +0,0 @@
---TEST--
-MongoDB\Driver\Server::executeReadWriteCommand()
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_not_clean(); ?>
-<?php skip_if_server_version('<', '3.2'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-require_once __DIR__ . "/../utils/observer.php";
-
-$manager = create_test_manager();
-$server = $manager->selectServer(new MongoDB\Driver\ReadPreference(MongoDB\Driver\ReadPreference::RP_PRIMARY));
-
-(new CommandObserver)->observe(
- function() use ($server) {
- $command = new MongoDB\Driver\Command( [
- 'findAndModify' => NS,
- 'update' => [ '$set' => [ 'foo' => 'bar' ] ],
- ] );
- $server->executeReadWriteCommand(
- DATABASE_NAME,
- $command,
- [
- 'readConcern' => new \MongoDB\Driver\ReadConcern(\MongoDB\Driver\ReadConcern::LOCAL),
- 'writeConcern' => new \MongoDB\Driver\WriteConcern(\MongoDB\Driver\WriteConcern::MAJORITY),
- ]
- );
- },
- function(stdClass $command) {
- echo "Read Concern: ", $command->readConcern->level, "\n";
- echo "Write Concern: ", $command->writeConcern->w, "\n";
- }
-);
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-Read Concern: local
-Write Concern: majority
-===DONE===
diff --git a/mongodb-1.12.0/tests/server/server-executeReadWriteCommand-003.phpt b/mongodb-1.12.0/tests/server/server-executeReadWriteCommand-003.phpt
deleted file mode 100644
index 93041077..00000000
--- a/mongodb-1.12.0/tests/server/server-executeReadWriteCommand-003.phpt
+++ /dev/null
@@ -1,48 +0,0 @@
---TEST--
-MongoDB\Driver\Server::executeReadWriteCommand() read and write concern inheritance
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_replica_set(); ?>
-<?php skip_if_not_enough_data_nodes(2); /* w:2 */ ?>
-<?php skip_if_server_version('<', '3.6'); /* readConcernLevel:available */ ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-require_once __DIR__ . "/../utils/observer.php";
-
-$manager = create_test_manager(URI, ['readConcernLevel' => 'local', 'w' => 2, 'wtimeoutms' => 1000]);
-$server = $manager->selectServer(new MongoDB\Driver\ReadPreference('primary'));
-
-$command = new MongoDB\Driver\Command([
- 'aggregate' => COLLECTION_NAME,
- 'pipeline' => [
- ['$group' => ['_id' => 1]],
- ['$out' => COLLECTION_NAME . '.out'],
- ],
- 'cursor' => (object) [],
-]);
-
-(new CommandObserver)->observe(
- function() use ($server, $command) {
- $server->executeReadWriteCommand(DATABASE_NAME, $command);
- $server->executeReadWriteCommand(DATABASE_NAME, $command, [
- 'readConcern' => new MongoDB\Driver\ReadConcern(MongoDB\Driver\ReadConcern::AVAILABLE),
- 'writeConcern' => new MongoDB\Driver\WriteConcern(1),
- ]);
- },
- function(stdClass $command) {
- echo json_encode($command->readConcern), "\n";
- echo json_encode($command->writeConcern), "\n";
- }
-);
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-{"level":"local"}
-{"w":2,"wtimeout":1000}
-{"level":"available"}
-{"w":1}
-===DONE===
diff --git a/mongodb-1.12.0/tests/server/server-executeWriteCommand-001.phpt b/mongodb-1.12.0/tests/server/server-executeWriteCommand-001.phpt
deleted file mode 100644
index d1d17d4c..00000000
--- a/mongodb-1.12.0/tests/server/server-executeWriteCommand-001.phpt
+++ /dev/null
@@ -1,43 +0,0 @@
---TEST--
-MongoDB\Driver\Server::executeWriteCommand()
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_not_clean(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-require_once __DIR__ . "/../utils/observer.php";
-
-$manager = create_test_manager();
-$server = $manager->selectServer(new MongoDB\Driver\ReadPreference(MongoDB\Driver\ReadPreference::RP_PRIMARY));
-
-$bw = new MongoDB\Driver\BulkWrite();
-$bw->insert(['a' => 1]);
-$manager->executeBulkWrite(NS, $bw);
-
-(new CommandObserver)->observe(
- function() use ($server) {
- $command = new MongoDB\Driver\Command([
- 'drop' => COLLECTION_NAME,
- ]);
- $server->executeWriteCommand(
- DATABASE_NAME,
- $command,
- [
- 'writeConcern' => new \MongoDB\Driver\WriteConcern(\MongoDB\Driver\WriteConcern::MAJORITY),
- ]
- );
- },
- function(stdClass $command) {
- echo "Write Concern: ", $command->writeConcern->w, "\n";
- }
-);
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-Write Concern: majority
-===DONE===
diff --git a/mongodb-1.12.0/tests/server/server-executeWriteCommand-003.phpt b/mongodb-1.12.0/tests/server/server-executeWriteCommand-003.phpt
deleted file mode 100644
index 7b96c010..00000000
--- a/mongodb-1.12.0/tests/server/server-executeWriteCommand-003.phpt
+++ /dev/null
@@ -1,41 +0,0 @@
---TEST--
-MongoDB\Driver\Server::executeWriteCommand() write concern inheritance
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_replica_set(); ?>
-<?php skip_if_not_enough_data_nodes(2); /* w:2 */ ?>
-<?php skip_if_server_version('<', '3.2'); /* findAndModify writeConcern */ ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-require_once __DIR__ . "/../utils/observer.php";
-
-$manager = create_test_manager(URI, ['w' => 2, 'wtimeoutms' => 1000]);
-$server = $manager->selectServer(new MongoDB\Driver\ReadPreference('primary'));
-
-$command = new MongoDB\Driver\Command([
- 'findAndModify' => COLLECTION_NAME,
- 'query' => ['x' => 1],
- 'upsert' => true,
- 'new' => true,
- 'update' => ['$inc' => ['x' => 1]],
-]);
-
-(new CommandObserver)->observe(
- function() use ($server, $command) {
- $server->executeWriteCommand(DATABASE_NAME, $command);
- $server->executeWriteCommand(DATABASE_NAME, $command, ['writeConcern' => new MongoDB\Driver\WriteConcern(1)]);
- },
- function(stdClass $command) {
- echo json_encode($command->writeConcern), "\n";
- }
-);
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-{"w":2,"wtimeout":1000}
-{"w":1}
-===DONE===
diff --git a/mongodb-1.12.0/tests/server/server-getLatency-002.phpt b/mongodb-1.12.0/tests/server/server-getLatency-002.phpt
deleted file mode 100644
index c0118634..00000000
--- a/mongodb-1.12.0/tests/server/server-getLatency-002.phpt
+++ /dev/null
@@ -1,20 +0,0 @@
---TEST--
-MongoDB\Driver\Server::getLatency() returns null when unset (e.g. load balancer)
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_not_load_balanced(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-$server = $manager->selectServer(new MongoDB\Driver\ReadPreference('primary'));
-var_dump($server->getLatency());
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-NULL
-===DONE===
diff --git a/mongodb-1.12.0/tests/session/bug1274-002.phpt b/mongodb-1.12.0/tests/session/bug1274-002.phpt
deleted file mode 100644
index ffbff41c..00000000
--- a/mongodb-1.12.0/tests/session/bug1274-002.phpt
+++ /dev/null
@@ -1,107 +0,0 @@
---TEST--
-PHPC-1274: Session destruct should not end session from parent process
---SKIPIF--
-<?php if (!function_exists('pcntl_fork')) { die('skip pcntl_fork() not available'); } ?>
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_not_replica_set(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-class CommandLogger implements MongoDB\Driver\Monitoring\CommandSubscriber
-{
- private $pid;
-
- public function __construct()
- {
- $this->pid = getmypid();
- }
-
- public function commandStarted(MongoDB\Driver\Monitoring\CommandStartedEvent $event)
- {
- $command = $event->getCommand();
- $commandName = $event->getCommandName();
- $process = $this->pid === getmypid() ? 'Parent' : 'Child';
-
- if ($commandName === 'find' || $commandName === 'getMore') {
- printf("%s executes %s with batchSize: %d\n", $process, $commandName, $command->batchSize);
- return;
- }
-
- printf("%s executes %s\n", $process, $commandName);
- }
-
- public function commandSucceeded(MongoDB\Driver\Monitoring\CommandSucceededEvent $event)
- {
- }
-
- public function commandFailed(MongoDB\Driver\Monitoring\CommandFailedEvent $event)
- {
- }
-}
-
-$manager = create_test_manager();
-$session = $manager->startSession();
-
-$bulk = new MongoDB\Driver\BulkWrite();
-$bulk->insert(['x' => 1]);
-$bulk->insert(['x' => 2]);
-$bulk->insert(['x' => 3]);
-$manager->executeBulkWrite(NS, $bulk, ['session' => $session]);
-
-MongoDB\Driver\Monitoring\addSubscriber(new CommandLogger);
-
-$query = new MongoDB\Driver\Query([], ['batchSize' => 2]);
-$cursor = $manager->executeQuery(NS, $query, ['session' => $session]);
-
-$childPid = pcntl_fork();
-
-if ($childPid === 0) {
- echo "Child exits\n";
- exit;
-}
-
-function isSessionOnServer($manager, $session) {
- /* Note: use $listLocalSessions since sessions are only synced to the config
- * database's system.sessions collection every 30 minutes. Alternatively, we
- * could run the refreshLogicalSessionCacheNow command on the primary. */
- $command = new MongoDB\Driver\Command([
- 'aggregate' => 1,
- 'pipeline' => [
- ['$listLocalSessions' => new stdClass],
- ['$match' => ['_id.id' => $session->getLogicalSessionId()->id]],
- ],
- 'cursor' => new stdClass,
- ]);
- $cursor = $manager->executeReadCommand(DATABASE_NAME, $command);
-
- return iterator_count($cursor) > 0;
-}
-
-if ($childPid > 0) {
- $waitPid = pcntl_waitpid($childPid, $status);
-
- if ($waitPid === $childPid) {
- echo "Parent waited for child to exit\n";
- }
-
- printf("Session is on server: %s\n", isSessionOnServer($manager, $session) ? 'yes' : 'no');
-
- printf("Parent fully iterated cursor for %d documents\n", iterator_count($cursor));
-}
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-Parent executes find with batchSize: 2
-Child exits
-Parent waited for child to exit
-Parent executes aggregate
-Session is on server: yes
-Parent executes getMore with batchSize: 2
-Parent fully iterated cursor for 3 documents
-===DONE===
diff --git a/mongodb-1.12.0/tests/session/bug1274-003.phpt b/mongodb-1.12.0/tests/session/bug1274-003.phpt
deleted file mode 100644
index 2886d0ec..00000000
--- a/mongodb-1.12.0/tests/session/bug1274-003.phpt
+++ /dev/null
@@ -1,121 +0,0 @@
---TEST--
-PHPC-1274: Implicit sessions are not reused from parent process
---SKIPIF--
-<?php if (!function_exists('pcntl_fork')) { die('skip pcntl_fork() not available'); } ?>
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_not_replica_set(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
-<?php skip_if_not_clean(); ?>
-<?php skip_if_not_clean(DATABASE_NAME, COLLECTION_NAME . '_sessions'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-class SessionLogger implements MongoDB\Driver\Monitoring\CommandSubscriber
-{
- private $lsids = [];
- private $logNamespace;
- private $manager;
- private $pid;
-
- public function __construct(MongoDB\Driver\Manager $manager, $logNamespace)
- {
- $this->logNamespace = $logNamespace;
- $this->manager = $manager;
- $this->pid = getmypid();
- }
-
- public function executeAndLogSessions(callable $callable)
- {
- $this->lsids = [];
-
- MongoDB\Driver\Monitoring\addSubscriber($this);
- call_user_func($callable);
- MongoDB\Driver\Monitoring\removeSubscriber($this);
-
- if (empty($this->lsids)) {
- return;
- }
-
- $bulk = new MongoDB\Driver\BulkWrite();
-
- foreach ($this->lsids as $lsid) {
- $bulk->update(['lsid' => $lsid], ['$inc' => ['count' => 1]], ['upsert' => true]);
- }
-
- $this->manager->executeBulkWrite($this->logNamespace, $bulk);
- }
-
- public function commandStarted(MongoDB\Driver\Monitoring\CommandStartedEvent $event)
- {
- $command = $event->getCommand();
-
- if (isset($command->lsid)) {
- $this->lsids[] = $command->lsid;
- }
-
- $commandName = $event->getCommandName();
- $process = $this->pid === getmypid() ? 'Parent' : 'Child';
-
- printf("%s executes %s\n", $process, $commandName);
- }
-
- public function commandSucceeded(MongoDB\Driver\Monitoring\CommandSucceededEvent $event)
- {
- }
-
- public function commandFailed(MongoDB\Driver\Monitoring\CommandFailedEvent $event)
- {
- }
-}
-
-$manager = create_test_manager();
-$logNamespace = NS . '_sessions';
-$sessionLogger = new SessionLogger($manager, $logNamespace);
-
-/* This test uses executeBulkWrite() as it's the only execute method that does
- * not create a cursor. The original patch for PHPC-1274 covered those methods
- * that return a cursor but omitted executeBulkWrite(). */
-$sessionLogger->executeAndLogSessions(function() use ($manager) {
- $bulk = new MongoDB\Driver\BulkWrite();
- $bulk->insert(['x' => 1]);
- $manager->executeBulkWrite(NS, $bulk);
-});
-
-$childPid = pcntl_fork();
-
-if ($childPid === 0) {
- $sessionLogger->executeAndLogSessions(function() use ($manager) {
- $bulk = new MongoDB\Driver\BulkWrite();
- $bulk->insert(['x' => 2]);
- $manager->executeBulkWrite(NS, $bulk);
- });
-
- echo "Child exits\n";
- exit;
-}
-
-if ($childPid > 0) {
- $waitPid = pcntl_waitpid($childPid, $status);
-
- if ($waitPid === $childPid) {
- echo "Parent waited for child to exit\n";
- }
-
- $query = new MongoDB\Driver\Query([]);
- $cursor = $manager->executeQuery($logNamespace, $query);
-
- printf("Sessions used: %d\n", iterator_count($cursor));
-}
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-Parent executes insert
-Child executes insert
-Child exits
-Parent waited for child to exit
-Sessions used: 2
-===DONE===
diff --git a/mongodb-1.12.0/tests/session/bug1274-005.phpt b/mongodb-1.12.0/tests/session/bug1274-005.phpt
deleted file mode 100644
index cbc3d948..00000000
--- a/mongodb-1.12.0/tests/session/bug1274-005.phpt
+++ /dev/null
@@ -1,107 +0,0 @@
---TEST--
-PHPC-1274: Session destruct should not end session from parent process (disableClientPersistence=true)
---SKIPIF--
-<?php if (!function_exists('pcntl_fork')) { die('skip pcntl_fork() not available'); } ?>
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_not_replica_set(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-class CommandLogger implements MongoDB\Driver\Monitoring\CommandSubscriber
-{
- private $pid;
-
- public function __construct()
- {
- $this->pid = getmypid();
- }
-
- public function commandStarted(MongoDB\Driver\Monitoring\CommandStartedEvent $event)
- {
- $command = $event->getCommand();
- $commandName = $event->getCommandName();
- $process = $this->pid === getmypid() ? 'Parent' : 'Child';
-
- if ($commandName === 'find' || $commandName === 'getMore') {
- printf("%s executes %s with batchSize: %d\n", $process, $commandName, $command->batchSize);
- return;
- }
-
- printf("%s executes %s\n", $process, $commandName);
- }
-
- public function commandSucceeded(MongoDB\Driver\Monitoring\CommandSucceededEvent $event)
- {
- }
-
- public function commandFailed(MongoDB\Driver\Monitoring\CommandFailedEvent $event)
- {
- }
-}
-
-$manager = create_test_manager(URI, [], ['disableClientPersistence' => true]);
-$session = $manager->startSession();
-
-$bulk = new MongoDB\Driver\BulkWrite();
-$bulk->insert(['x' => 1]);
-$bulk->insert(['x' => 2]);
-$bulk->insert(['x' => 3]);
-$manager->executeBulkWrite(NS, $bulk, ['session' => $session]);
-
-MongoDB\Driver\Monitoring\addSubscriber(new CommandLogger);
-
-$query = new MongoDB\Driver\Query([], ['batchSize' => 2]);
-$cursor = $manager->executeQuery(NS, $query, ['session' => $session]);
-
-$childPid = pcntl_fork();
-
-if ($childPid === 0) {
- echo "Child exits\n";
- exit;
-}
-
-function isSessionOnServer($manager, $session) {
- /* Note: use $listLocalSessions since sessions are only synced to the config
- * database's system.sessions collection every 30 minutes. Alternatively, we
- * could run the refreshLogicalSessionCacheNow command on the primary. */
- $command = new MongoDB\Driver\Command([
- 'aggregate' => 1,
- 'pipeline' => [
- ['$listLocalSessions' => new stdClass],
- ['$match' => ['_id.id' => $session->getLogicalSessionId()->id]],
- ],
- 'cursor' => new stdClass,
- ]);
- $cursor = $manager->executeReadCommand(DATABASE_NAME, $command);
-
- return iterator_count($cursor) > 0;
-}
-
-if ($childPid > 0) {
- $waitPid = pcntl_waitpid($childPid, $status);
-
- if ($waitPid === $childPid) {
- echo "Parent waited for child to exit\n";
- }
-
- printf("Session is on server: %s\n", isSessionOnServer($manager, $session) ? 'yes' : 'no');
-
- printf("Parent fully iterated cursor for %d documents\n", iterator_count($cursor));
-}
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-Parent executes find with batchSize: 2
-Child exits
-Parent waited for child to exit
-Parent executes aggregate
-Session is on server: yes
-Parent executes getMore with batchSize: 2
-Parent fully iterated cursor for 3 documents
-===DONE===
diff --git a/mongodb-1.12.0/tests/session/bug1274-006.phpt b/mongodb-1.12.0/tests/session/bug1274-006.phpt
deleted file mode 100644
index 7f47795d..00000000
--- a/mongodb-1.12.0/tests/session/bug1274-006.phpt
+++ /dev/null
@@ -1,121 +0,0 @@
---TEST--
-PHPC-1274: Implicit sessions are not reused from parent process (disableClientPersistence=true)
---SKIPIF--
-<?php if (!function_exists('pcntl_fork')) { die('skip pcntl_fork() not available'); } ?>
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_not_replica_set(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
-<?php skip_if_not_clean(); ?>
-<?php skip_if_not_clean(DATABASE_NAME, COLLECTION_NAME . '_sessions'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-class SessionLogger implements MongoDB\Driver\Monitoring\CommandSubscriber
-{
- private $lsids = [];
- private $logNamespace;
- private $manager;
- private $pid;
-
- public function __construct(MongoDB\Driver\Manager $manager, $logNamespace)
- {
- $this->logNamespace = $logNamespace;
- $this->manager = $manager;
- $this->pid = getmypid();
- }
-
- public function executeAndLogSessions(callable $callable)
- {
- $this->lsids = [];
-
- MongoDB\Driver\Monitoring\addSubscriber($this);
- call_user_func($callable);
- MongoDB\Driver\Monitoring\removeSubscriber($this);
-
- if (empty($this->lsids)) {
- return;
- }
-
- $bulk = new MongoDB\Driver\BulkWrite();
-
- foreach ($this->lsids as $lsid) {
- $bulk->update(['lsid' => $lsid], ['$inc' => ['count' => 1]], ['upsert' => true]);
- }
-
- $this->manager->executeBulkWrite($this->logNamespace, $bulk);
- }
-
- public function commandStarted(MongoDB\Driver\Monitoring\CommandStartedEvent $event)
- {
- $command = $event->getCommand();
-
- if (isset($command->lsid)) {
- $this->lsids[] = $command->lsid;
- }
-
- $commandName = $event->getCommandName();
- $process = $this->pid === getmypid() ? 'Parent' : 'Child';
-
- printf("%s executes %s\n", $process, $commandName);
- }
-
- public function commandSucceeded(MongoDB\Driver\Monitoring\CommandSucceededEvent $event)
- {
- }
-
- public function commandFailed(MongoDB\Driver\Monitoring\CommandFailedEvent $event)
- {
- }
-}
-
-$manager = create_test_manager(URI, [], ['disableClientPersistence' => true]);
-$logNamespace = NS . '_sessions';
-$sessionLogger = new SessionLogger($manager, $logNamespace);
-
-/* This test uses executeBulkWrite() as it's the only execute method that does
- * not create a cursor. The original patch for PHPC-1274 covered those methods
- * that return a cursor but omitted executeBulkWrite(). */
-$sessionLogger->executeAndLogSessions(function() use ($manager) {
- $bulk = new MongoDB\Driver\BulkWrite();
- $bulk->insert(['x' => 1]);
- $manager->executeBulkWrite(NS, $bulk);
-});
-
-$childPid = pcntl_fork();
-
-if ($childPid === 0) {
- $sessionLogger->executeAndLogSessions(function() use ($manager) {
- $bulk = new MongoDB\Driver\BulkWrite();
- $bulk->insert(['x' => 2]);
- $manager->executeBulkWrite(NS, $bulk);
- });
-
- echo "Child exits\n";
- exit;
-}
-
-if ($childPid > 0) {
- $waitPid = pcntl_waitpid($childPid, $status);
-
- if ($waitPid === $childPid) {
- echo "Parent waited for child to exit\n";
- }
-
- $query = new MongoDB\Driver\Query([]);
- $cursor = $manager->executeQuery($logNamespace, $query);
-
- printf("Sessions used: %d\n", iterator_count($cursor));
-}
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-Parent executes insert
-Child executes insert
-Child exits
-Parent waited for child to exit
-Sessions used: 2
-===DONE===
diff --git a/mongodb-1.12.0/tests/session/session-001.phpt b/mongodb-1.12.0/tests/session/session-001.phpt
deleted file mode 100644
index 87916e24..00000000
--- a/mongodb-1.12.0/tests/session/session-001.phpt
+++ /dev/null
@@ -1,34 +0,0 @@
---TEST--
-MongoDB\Driver\Session spec test: Pool is LIFO
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-
-$firstSession = $manager->startSession();
-$firstSessionId = $firstSession->getLogicalSessionId();
-
-/* libmongoc does not pool unused sessions (CDRIVER-3322), so we must use this
- * session with a command to ensure it enters the pool. */
-$command = new MongoDB\Driver\Command(['ping' => 1]);
-$manager->executeCommand(DATABASE_NAME, $command, ['session' => $firstSession]);
-
-unset($firstSession);
-
-$secondSession = $manager->startSession();
-$secondSessionId = $secondSession->getLogicalSessionId();
-
-var_dump($firstSessionId == $secondSessionId);
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-bool(true)
-===DONE===
diff --git a/mongodb-1.12.0/tests/session/session-002.phpt b/mongodb-1.12.0/tests/session/session-002.phpt
deleted file mode 100644
index 9f402a1d..00000000
--- a/mongodb-1.12.0/tests/session/session-002.phpt
+++ /dev/null
@@ -1,174 +0,0 @@
---TEST--
-MongoDB\Driver\Session spec test: $clusterTime in commands
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_load_balanced(); /* TODO: CDRIVER-4174 */ ?>
-<?php skip_if_not_replica_set_or_sharded_cluster_with_replica_set(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-class Test implements MongoDB\Driver\Monitoring\CommandSubscriber
-{
- private $lastSeenClusterTime;
-
- public function aggregate()
- {
- $this->lastSeenClusterTime = null;
-
- MongoDB\Driver\Monitoring\addSubscriber($this);
-
- $manager = create_test_manager();
- $session = $manager->startSession();
-
- $command = new MongoDB\Driver\Command([
- 'aggregate' => COLLECTION_NAME,
- 'pipeline' => [],
- 'cursor' => new stdClass(),
- ]);
- $manager->executeReadWriteCommand(DATABASE_NAME, $command, ['session' => $session]);
- $manager->executeReadWriteCommand(DATABASE_NAME, $command, ['session' => $session]);
-
- printf("Session reports last seen \$clusterTime: %s\n", ($session->getClusterTime() == $this->lastSeenClusterTime) ? 'yes' : 'no');
-
- MongoDB\Driver\Monitoring\removeSubscriber($this);
- }
-
- public function find()
- {
- $this->lastSeenClusterTime = null;
-
- MongoDB\Driver\Monitoring\addSubscriber($this);
-
- $manager = create_test_manager();
- $session = $manager->startSession();
-
- $query = new MongoDB\Driver\Query([]);
- $manager->executeQuery(NS, $query, ['session' => $session]);
- $manager->executeQuery(NS, $query, ['session' => $session]);
-
- printf("Session reports last seen \$clusterTime: %s\n", ($session->getClusterTime() == $this->lastSeenClusterTime) ? 'yes' : 'no');
-
- MongoDB\Driver\Monitoring\removeSubscriber($this);
- }
-
- public function insert()
- {
- $this->lastSeenClusterTime = null;
-
- MongoDB\Driver\Monitoring\addSubscriber($this);
-
- $manager = create_test_manager();
- $session = $manager->startSession();
-
- $bulk = new MongoDB\Driver\BulkWrite();
- $bulk->insert(['x' => 1]);
- $manager->executeBulkWrite(NS, $bulk, ['session' => $session]);
-
- $bulk = new MongoDB\Driver\BulkWrite();
- $bulk->insert(['x' => 2]);
- $manager->executeBulkWrite(NS, $bulk, ['session' => $session]);
-
- printf("Session reports last seen \$clusterTime: %s\n", ($session->getClusterTime() == $this->lastSeenClusterTime) ? 'yes' : 'no');
-
- MongoDB\Driver\Monitoring\removeSubscriber($this);
- }
-
- public function ping()
- {
- $this->lastSeenClusterTime = null;
-
- MongoDB\Driver\Monitoring\addSubscriber($this);
-
- $manager = create_test_manager();
- $session = $manager->startSession();
-
- $command = new MongoDB\Driver\Command(['ping' => 1]);
- $manager->executeCommand(DATABASE_NAME, $command, ['session' => $session]);
- $manager->executeCommand(DATABASE_NAME, $command, ['session' => $session]);
-
- printf("Session reports last seen \$clusterTime: %s\n", ($session->getClusterTime() == $this->lastSeenClusterTime) ? 'yes' : 'no');
-
- MongoDB\Driver\Monitoring\removeSubscriber($this);
- }
-
- public function commandStarted(MongoDB\Driver\Monitoring\CommandStartedEvent $event)
- {
- $command = $event->getCommand();
- $hasClusterTime = isset($command->{'$clusterTime'});
-
- printf("%s command includes \$clusterTime: %s\n", $event->getCommandName(), $hasClusterTime ? 'yes' : 'no');
-
- if ($hasClusterTime && $this->lastSeenClusterTime !== null) {
- printf("%s command uses last seen \$clusterTime: %s\n", $event->getCommandName(), ($command->{'$clusterTime'} == $this->lastSeenClusterTime) ? 'yes' : 'no');
- }
- }
-
- public function commandSucceeded(MongoDB\Driver\Monitoring\CommandSucceededEvent $event)
- {
- $reply = $event->getReply();
- $hasClusterTime = isset($reply->{'$clusterTime'});
-
- printf("%s command reply includes \$clusterTime: %s\n", $event->getCommandName(), $hasClusterTime ? 'yes' : 'no');
-
- if ($hasClusterTime) {
- $this->lastSeenClusterTime = $reply->{'$clusterTime'};
- }
- }
-
- public function commandFailed(MongoDB\Driver\Monitoring\CommandFailedEvent $event)
- {
- }
-}
-
-echo "\nTesting aggregate command\n";
-(new Test)->aggregate();
-
-echo "\nTesting find command\n";
-(new Test)->find();
-
-echo "\nTesting insert command\n";
-(new Test)->insert();
-
-echo "\nTesting ping command\n";
-(new Test)->ping();
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-Testing aggregate command
-aggregate command includes $clusterTime: yes
-aggregate command reply includes $clusterTime: yes
-aggregate command includes $clusterTime: yes
-aggregate command uses last seen $clusterTime: yes
-aggregate command reply includes $clusterTime: yes
-Session reports last seen $clusterTime: yes
-
-Testing find command
-find command includes $clusterTime: yes
-find command reply includes $clusterTime: yes
-find command includes $clusterTime: yes
-find command uses last seen $clusterTime: yes
-find command reply includes $clusterTime: yes
-Session reports last seen $clusterTime: yes
-
-Testing insert command
-insert command includes $clusterTime: yes
-insert command reply includes $clusterTime: yes
-insert command includes $clusterTime: yes
-insert command uses last seen $clusterTime: yes
-insert command reply includes $clusterTime: yes
-Session reports last seen $clusterTime: yes
-
-Testing ping command
-ping command includes $clusterTime: yes
-ping command reply includes $clusterTime: yes
-ping command includes $clusterTime: yes
-ping command uses last seen $clusterTime: yes
-ping command reply includes $clusterTime: yes
-Session reports last seen $clusterTime: yes
-===DONE===
diff --git a/mongodb-1.12.0/tests/session/session-003.phpt b/mongodb-1.12.0/tests/session/session-003.phpt
deleted file mode 100644
index 8098bfb6..00000000
--- a/mongodb-1.12.0/tests/session/session-003.phpt
+++ /dev/null
@@ -1,53 +0,0 @@
---TEST--
-MongoDB\Driver\Session spec test: session cannot be used for different clients
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-// Vary heartbeatFrequencyMS to ensure each Manager gets a different client
-$manager = create_test_manager(URI, ['heartbeatFrequencyMS' => 60000]);
-$otherManager = create_test_manager(URI, ['heartbeatFrequencyMS' => 90000]);
-
-// Create a session with the second Manager (associated with different client)
-$session = $otherManager->startSession();
-
-echo "\nTesting executeBulkWrite()\n";
-echo throws(function() use ($manager, $session) {
- $bulk = new MongoDB\Driver\BulkWrite();
- $bulk->insert(['x' => 1]);
- $manager->executeBulkWrite(NS, $bulk, ['session' => $session]);
-}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
-
-echo "\nTesting executeCommand()\n";
-echo throws(function() use ($manager, $session) {
- $command = new MongoDB\Driver\Command(['ping' => 1]);
- $manager->executeCommand(DATABASE_NAME, $command, ['session' => $session]);
-}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
-
-echo "\nTesting executeQuery()\n";
-echo throws(function() use ($manager, $session) {
- $query = new MongoDB\Driver\Query([]);
- $manager->executeQuery(NS, $query, ['session' => $session]);
-}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-Testing executeBulkWrite()
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Cannot use Session started from a different Manager
-
-Testing executeCommand()
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Cannot use Session started from a different Manager
-
-Testing executeQuery()
-OK: Got MongoDB\Driver\Exception\InvalidArgumentException
-Cannot use Session started from a different Manager
-===DONE===
diff --git a/mongodb-1.12.0/tests/session/session-005.phpt b/mongodb-1.12.0/tests/session/session-005.phpt
deleted file mode 100644
index 39052a60..00000000
--- a/mongodb-1.12.0/tests/session/session-005.phpt
+++ /dev/null
@@ -1,54 +0,0 @@
---TEST--
-MongoDB\Driver\Session spec test: snapshot option requires MongoDB 5.0+
---DESCRIPTION--
-PHPC-1876: Raise client error for snapshot sessions on <5.0 servers
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
-<?php skip_if_server_version('>=', '5.0'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-$session = $manager->startSession(['snapshot' => true]);
-
-/* Note: executeBulkWrite() always throws a BulkWriteException. Any previous
- * exception's message will be included in the BulkWriteException message. */
-echo "\nTesting executeBulkWrite()\n";
-echo throws(function() use ($manager, $session) {
- $bulk = new MongoDB\Driver\BulkWrite();
- $bulk->insert(['x' => 1]);
- $manager->executeBulkWrite(NS, $bulk, ['session' => $session]);
-}, MongoDB\Driver\Exception\BulkWriteException::class), "\n";
-
-echo "\nTesting executeCommand()\n";
-echo throws(function() use ($manager, $session) {
- $command = new MongoDB\Driver\Command(['ping' => 1]);
- $manager->executeCommand(DATABASE_NAME, $command, ['session' => $session]);
-}, MongoDB\Driver\Exception\RuntimeException::class), "\n";
-
-echo "\nTesting executeQuery()\n";
-echo throws(function() use ($manager, $session) {
- $query = new MongoDB\Driver\Query([]);
- $manager->executeQuery(NS, $query, ['session' => $session]);
-}, MongoDB\Driver\Exception\RuntimeException::class), "\n";
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-Testing executeBulkWrite()
-OK: Got MongoDB\Driver\Exception\BulkWriteException
-Bulk write failed due to previous MongoDB\Driver\Exception\RuntimeException: Snapshot reads require MongoDB 5.0 or later
-
-Testing executeCommand()
-OK: Got MongoDB\Driver\Exception\RuntimeException
-Snapshot reads require MongoDB 5.0 or later
-
-Testing executeQuery()
-OK: Got MongoDB\Driver\Exception\RuntimeException
-Snapshot reads require MongoDB 5.0 or later
-===DONE===
diff --git a/mongodb-1.12.0/tests/session/session-advanceClusterTime-001.phpt b/mongodb-1.12.0/tests/session/session-advanceClusterTime-001.phpt
deleted file mode 100644
index 0c4cc871..00000000
--- a/mongodb-1.12.0/tests/session/session-advanceClusterTime-001.phpt
+++ /dev/null
@@ -1,52 +0,0 @@
---TEST--
-MongoDB\Driver\Session::advanceClusterTime()
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_not_replica_set_or_sharded_cluster_with_replica_set(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-$sessionA = $manager->startSession();
-$sessionB = $manager->startSession();
-
-$command = new MongoDB\Driver\Command(['ping' => 1]);
-$manager->executeCommand(DATABASE_NAME, $command, ['session' => $sessionA]);
-
-echo "Initial cluster time of session B:\n";
-var_dump($sessionB->getClusterTime());
-
-$sessionB->advanceClusterTime($sessionA->getClusterTime());
-
-echo "\nCluster time after advancing session B:\n";
-var_dump($sessionB->getClusterTime());
-
-echo "\nSessions A and B have equivalent cluster times:\n";
-var_dump($sessionA->getClusterTime() == $sessionB->getClusterTime());
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-Initial cluster time of session B:
-NULL
-
-Cluster time after advancing session B:
-object(stdClass)#%d (%d) {
- ["clusterTime"]=>
- object(MongoDB\BSON\Timestamp)#%d (%d) {
- ["increment"]=>
- string(%d) "%d"
- ["timestamp"]=>
- string(%d) "%d"
- }
- ["signature"]=>
- %a
-}
-
-Sessions A and B have equivalent cluster times:
-bool(true)
-===DONE===
diff --git a/mongodb-1.12.0/tests/session/session-advanceOperationTime-001.phpt b/mongodb-1.12.0/tests/session/session-advanceOperationTime-001.phpt
deleted file mode 100644
index 2e34012a..00000000
--- a/mongodb-1.12.0/tests/session/session-advanceOperationTime-001.phpt
+++ /dev/null
@@ -1,47 +0,0 @@
---TEST--
-MongoDB\Driver\Session::advanceOperationTime()
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_not_replica_set_or_sharded_cluster_with_replica_set(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-$sessionA = $manager->startSession();
-$sessionB = $manager->startSession();
-
-$command = new MongoDB\Driver\Command(['ping' => 1]);
-$manager->executeCommand(DATABASE_NAME, $command, ['session' => $sessionA]);
-
-echo "Initial operation time of session B:\n";
-var_dump($sessionB->getOperationTime());
-
-$sessionB->advanceOperationTime($sessionA->getOperationTime());
-
-echo "\nOperation time after advancing session B:\n";
-var_dump($sessionB->getOperationTime());
-
-echo "\nSessions A and B have equivalent operation times:\n";
-var_dump($sessionA->getOperationTime() == $sessionB->getOperationTime());
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-Initial operation time of session B:
-NULL
-
-Operation time after advancing session B:
-object(MongoDB\BSON\Timestamp)#%d (%d) {
- ["increment"]=>
- string(%d) "%d"
- ["timestamp"]=>
- string(%d) "%d"
-}
-
-Sessions A and B have equivalent operation times:
-bool(true)
-===DONE===
diff --git a/mongodb-1.12.0/tests/session/session-advanceOperationTime-002.phpt b/mongodb-1.12.0/tests/session/session-advanceOperationTime-002.phpt
deleted file mode 100644
index d22bf3aa..00000000
--- a/mongodb-1.12.0/tests/session/session-advanceOperationTime-002.phpt
+++ /dev/null
@@ -1,37 +0,0 @@
---TEST--
-MongoDB\Driver\Session::advanceOperationTime() with Timestamp
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_not_replica_set_or_sharded_cluster_with_replica_set(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-$session = $manager->startSession();
-
-echo "Initial operation time of session:\n";
-var_dump($session->getOperationTime());
-
-$session->advanceOperationTime(new MongoDB\BSON\Timestamp(5678, 1234));
-
-echo "\nOperation time after advancing session:\n";
-var_dump($session->getOperationTime());
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-Initial operation time of session:
-NULL
-
-Operation time after advancing session:
-object(MongoDB\BSON\Timestamp)#%d (%d) {
- ["increment"]=>
- string(4) "5678"
- ["timestamp"]=>
- string(4) "1234"
-}
-===DONE===
diff --git a/mongodb-1.12.0/tests/session/session-advanceOperationTime-003.phpt b/mongodb-1.12.0/tests/session/session-advanceOperationTime-003.phpt
deleted file mode 100644
index d375ac91..00000000
--- a/mongodb-1.12.0/tests/session/session-advanceOperationTime-003.phpt
+++ /dev/null
@@ -1,55 +0,0 @@
---TEST--
-MongoDB\Driver\Session::advanceOperationTime() with TimestampInterface
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_not_replica_set_or_sharded_cluster_with_replica_set(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-class MyTimestamp implements MongoDB\BSON\TimestampInterface
-{
- public function getIncrement()
- {
- return 5678;
- }
-
- public function getTimestamp()
- {
- return 1234;
- }
-
- public function __toString()
- {
- return sprintf('[%d:%d]', $this->getIncrement(), $this->getTimestamp());
- }
-}
-
-$manager = create_test_manager();
-$session = $manager->startSession();
-
-echo "Initial operation time of session:\n";
-var_dump($session->getOperationTime());
-
-$session->advanceOperationTime(new MyTimestamp);
-
-echo "\nOperation time after advancing session:\n";
-var_dump($session->getOperationTime());
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-Initial operation time of session:
-NULL
-
-Operation time after advancing session:
-object(MongoDB\BSON\Timestamp)#%d (%d) {
- ["increment"]=>
- string(4) "5678"
- ["timestamp"]=>
- string(4) "1234"
-}
-===DONE===
diff --git a/mongodb-1.12.0/tests/session/session-advanceOperationTime_error-001.phpt b/mongodb-1.12.0/tests/session/session-advanceOperationTime_error-001.phpt
deleted file mode 100644
index b3dd21d0..00000000
--- a/mongodb-1.12.0/tests/session/session-advanceOperationTime_error-001.phpt
+++ /dev/null
@@ -1,92 +0,0 @@
---TEST--
-MongoDB\Driver\Session::advanceOperationTime() with TimestampInterface exceptions
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_not_replica_set_or_sharded_cluster_with_replica_set(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-class MyTimestamp implements MongoDB\BSON\TimestampInterface
-{
- private $failIncrement;
- private $failTimestamp;
-
- public function __construct($failIncrement, $failTimestamp)
- {
- $this->failIncrement = $failIncrement;
- $this->failTimestamp = $failTimestamp;
- }
-
- public function getIncrement()
- {
- if ($this->failIncrement) {
- throw new Exception('getIncrement() failed');
- }
-
- return 5678;
- }
-
- public function getTimestamp()
- {
- if ($this->failTimestamp) {
- throw new Exception('getTimestamp() failed');
- }
-
- return 1234;
- }
-
- public function __toString()
- {
- return sprintf('[%d:%d]', $this->getIncrement(), $this->getTimestamp());
- }
-}
-
-$manager = create_test_manager();
-$session = $manager->startSession();
-
-echo "Initial operation time of session:\n";
-var_dump($session->getOperationTime());
-
-$timestamps = [
- new MyTimestamp(true, false),
- new MyTimestamp(false, true),
- new MyTimestamp(true, true),
-];
-
-foreach ($timestamps as $timestamp) {
- echo "\n", throws(function() use ($session, $timestamp) {
- $session->advanceOperationTime($timestamp);
- }, 'Exception'), "\n";
-
- echo "\nOperation time after advancing session fails:\n";
- var_dump($session->getOperationTime());
-}
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-Initial operation time of session:
-NULL
-
-OK: Got Exception
-getIncrement() failed
-
-Operation time after advancing session fails:
-NULL
-
-OK: Got Exception
-getTimestamp() failed
-
-Operation time after advancing session fails:
-NULL
-
-OK: Got Exception
-getTimestamp() failed
-
-Operation time after advancing session fails:
-NULL
-===DONE===
diff --git a/mongodb-1.12.0/tests/session/session-debug-001.phpt b/mongodb-1.12.0/tests/session/session-debug-001.phpt
deleted file mode 100644
index 2572b5b7..00000000
--- a/mongodb-1.12.0/tests/session/session-debug-001.phpt
+++ /dev/null
@@ -1,49 +0,0 @@
---TEST--
-MongoDB\Driver\Session debug output (before an operation)
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-$session = $manager->startSession();
-
-var_dump($session);
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-object(MongoDB\Driver\Session)#%d (%d) {
- ["logicalSessionId"]=>
- array(1) {
- ["id"]=>
- object(MongoDB\BSON\Binary)#%d (%d) {
- ["data"]=>
- string(16) "%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c"
- ["type"]=>
- int(4)
- }
- }
- ["clusterTime"]=>
- NULL
- ["causalConsistency"]=>
- bool(true)
- ["snapshot"]=>
- bool(false)
- ["operationTime"]=>
- NULL
- ["server"]=>
- NULL
- ["inTransaction"]=>
- bool(false)
- ["transactionState"]=>
- string(4) "none"
- ["transactionOptions"]=>
- NULL
-}
-===DONE===
diff --git a/mongodb-1.12.0/tests/session/session-debug-002.phpt b/mongodb-1.12.0/tests/session/session-debug-002.phpt
deleted file mode 100644
index decbb99d..00000000
--- a/mongodb-1.12.0/tests/session/session-debug-002.phpt
+++ /dev/null
@@ -1,67 +0,0 @@
---TEST--
-MongoDB\Driver\Session debug output (after an operation)
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_not_replica_set_or_sharded_cluster_with_replica_set(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-$session = $manager->startSession();
-
-$command = new MongoDB\Driver\Command(['ping' => 1]);
-$manager->executeCommand(DATABASE_NAME, $command, ['session' => $session]);
-
-var_dump($session);
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-object(MongoDB\Driver\Session)#%d (%d) {
- ["logicalSessionId"]=>
- array(1) {
- ["id"]=>
- object(MongoDB\BSON\Binary)#%d (%d) {
- ["data"]=>
- string(16) "%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c"
- ["type"]=>
- int(4)
- }
- }
- ["clusterTime"]=>
- array(2) {
- ["clusterTime"]=>
- object(MongoDB\BSON\Timestamp)#%d (%d) {
- ["increment"]=>
- string(%d) "%d"
- ["timestamp"]=>
- string(%d) "%d"
- }
- ["signature"]=>
- %a
- }
- ["causalConsistency"]=>
- bool(true)
- ["snapshot"]=>
- bool(false)
- ["operationTime"]=>
- object(MongoDB\BSON\Timestamp)#%d (%d) {
- ["increment"]=>
- string(%d) "%d"
- ["timestamp"]=>
- string(%d) "%d"
- }
- ["server"]=>
- NULL
- ["inTransaction"]=>
- bool(false)
- ["transactionState"]=>
- string(4) "none"
- ["transactionOptions"]=>
- NULL
-}
-===DONE===
diff --git a/mongodb-1.12.0/tests/session/session-debug-003.phpt b/mongodb-1.12.0/tests/session/session-debug-003.phpt
deleted file mode 100644
index ed2edff6..00000000
--- a/mongodb-1.12.0/tests/session/session-debug-003.phpt
+++ /dev/null
@@ -1,49 +0,0 @@
---TEST--
-MongoDB\Driver\Session debug output (causalConsistency=false)
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-$session = $manager->startSession(['causalConsistency' => false]);
-
-var_dump($session);
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-object(MongoDB\Driver\Session)#%d (%d) {
- ["logicalSessionId"]=>
- array(1) {
- ["id"]=>
- object(MongoDB\BSON\Binary)#%d (%d) {
- ["data"]=>
- string(16) "%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c"
- ["type"]=>
- int(4)
- }
- }
- ["clusterTime"]=>
- NULL
- ["causalConsistency"]=>
- bool(false)
- ["snapshot"]=>
- bool(false)
- ["operationTime"]=>
- NULL
- ["server"]=>
- NULL
- ["inTransaction"]=>
- bool(false)
- ["transactionState"]=>
- string(4) "none"
- ["transactionOptions"]=>
- NULL
-}
-===DONE===
diff --git a/mongodb-1.12.0/tests/session/session-debug-004.phpt b/mongodb-1.12.0/tests/session/session-debug-004.phpt
deleted file mode 100644
index 412517d1..00000000
--- a/mongodb-1.12.0/tests/session/session-debug-004.phpt
+++ /dev/null
@@ -1,46 +0,0 @@
---TEST--
-MongoDB\Driver\Session debug output (after ending session)
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-$session = $manager->startSession();
-
-$command = new MongoDB\Driver\Command(['ping' => 1]);
-$manager->executeCommand(DATABASE_NAME, $command, ['session' => $session]);
-
-$session->endSession();
-
-var_dump($session);
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-object(MongoDB\Driver\Session)#%d (%d) {
- ["logicalSessionId"]=>
- NULL
- ["clusterTime"]=>
- NULL
- ["causalConsistency"]=>
- NULL
- ["snapshot"]=>
- NULL
- ["operationTime"]=>
- NULL
- ["server"]=>
- NULL
- ["inTransaction"]=>
- NULL
- ["transactionState"]=>
- NULL
- ["transactionOptions"]=>
- NULL
-}
-===DONE===
diff --git a/mongodb-1.12.0/tests/session/session-debug-005.phpt b/mongodb-1.12.0/tests/session/session-debug-005.phpt
deleted file mode 100644
index efaa997e..00000000
--- a/mongodb-1.12.0/tests/session/session-debug-005.phpt
+++ /dev/null
@@ -1,82 +0,0 @@
---TEST--
-MongoDB\Driver\Session debug output (during a pinned transaction)
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_not_mongos(); ?>
-<?php skip_if_no_transactions(); ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-$server = $manager->selectServer(new \MongoDB\Driver\ReadPreference('primary'));
-
-$session = $manager->startSession();
-$session->startTransaction();
-
-$query = new MongoDB\Driver\Query([]);
-$server->executeQuery(NS, $query, ['session' => $session]);
-
-var_dump($session);
-
-$session->abortTransaction();
-$session->endSession();
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-object(MongoDB\Driver\Session)#%d (%d) {
- ["logicalSessionId"]=>
- array(1) {
- ["id"]=>
- object(MongoDB\BSON\Binary)#%d (%d) {
- ["data"]=>
- string(16) "%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c"
- ["type"]=>
- int(4)
- }
- }
- ["clusterTime"]=>
- array(2) {
- ["clusterTime"]=>
- object(MongoDB\BSON\Timestamp)#%d (%d) {
- ["increment"]=>
- string(%d) "%d"
- ["timestamp"]=>
- string(%d) "%d"
- }
- ["signature"]=>
- %a
- }
- ["causalConsistency"]=>
- bool(true)
- ["snapshot"]=>
- bool(false)
- ["operationTime"]=>
- object(MongoDB\BSON\Timestamp)#%d (%d) {
- ["increment"]=>
- string(%d) "%d"
- ["timestamp"]=>
- string(%d) "%d"
- }
- ["server"]=>
- object(MongoDB\Driver\Server)#%d (%d) {
- %a
- }
- ["inTransaction"]=>
- bool(true)
- ["transactionState"]=>
- string(11) "in_progress"
- ["transactionOptions"]=>
- array(1) {
- ["readPreference"]=>
- object(MongoDB\Driver\ReadPreference)#%d (%d) {
- ["mode"]=>
- string(7) "primary"
- }
- }
-}
-===DONE===
diff --git a/mongodb-1.12.0/tests/session/session-debug-006.phpt b/mongodb-1.12.0/tests/session/session-debug-006.phpt
deleted file mode 100644
index 007e6f66..00000000
--- a/mongodb-1.12.0/tests/session/session-debug-006.phpt
+++ /dev/null
@@ -1,75 +0,0 @@
---TEST--
-MongoDB\Driver\Session debug output (with transaction options)
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_no_transactions(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-$session = $manager->startSession();
-
-$options = [
- 'maxCommitTimeMS' => 1,
- 'readConcern' => new \MongoDB\Driver\ReadConcern('majority'),
- 'readPreference' => new \MongoDB\Driver\ReadPreference('primaryPreferred'),
- 'writeConcern' => new \MongoDB\Driver\WriteConcern('majority'),
-];
-
-$session->startTransaction($options);
-
-var_dump($session);
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-object(MongoDB\Driver\Session)#%d (%d) {
- ["logicalSessionId"]=>
- array(1) {
- ["id"]=>
- object(MongoDB\BSON\Binary)#%d (%d) {
- ["data"]=>
- string(16) "%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c"
- ["type"]=>
- int(4)
- }
- }
- ["clusterTime"]=>
- NULL
- ["causalConsistency"]=>
- bool(true)
- ["snapshot"]=>
- bool(false)
- ["operationTime"]=>
- NULL
- ["server"]=>
- NULL
- ["inTransaction"]=>
- bool(true)
- ["transactionState"]=>
- string(8) "starting"
- ["transactionOptions"]=>
- array(4) {
- ["maxCommitTimeMS"]=>
- int(1)
- ["readConcern"]=>
- object(MongoDB\Driver\ReadConcern)#%d (%d) {
- ["level"]=>
- string(8) "majority"
- }
- ["readPreference"]=>
- object(MongoDB\Driver\ReadPreference)#%d (%d) {
- ["mode"]=>
- string(16) "primaryPreferred"
- }
- ["writeConcern"]=>
- object(MongoDB\Driver\WriteConcern)#%d (%d) {
- ["w"]=>
- string(8) "majority"
- }
- }
-}
-===DONE===
diff --git a/mongodb-1.12.0/tests/session/session-debug-007.phpt b/mongodb-1.12.0/tests/session/session-debug-007.phpt
deleted file mode 100644
index f83753ac..00000000
--- a/mongodb-1.12.0/tests/session/session-debug-007.phpt
+++ /dev/null
@@ -1,49 +0,0 @@
---TEST--
-MongoDB\Driver\Session debug output (snapshot=true)
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-$session = $manager->startSession(['snapshot' => true]);
-
-var_dump($session);
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-object(MongoDB\Driver\Session)#%d (%d) {
- ["logicalSessionId"]=>
- array(1) {
- ["id"]=>
- object(MongoDB\BSON\Binary)#%d (%d) {
- ["data"]=>
- string(16) "%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c"
- ["type"]=>
- int(4)
- }
- }
- ["clusterTime"]=>
- NULL
- ["causalConsistency"]=>
- bool(false)
- ["snapshot"]=>
- bool(true)
- ["operationTime"]=>
- NULL
- ["server"]=>
- NULL
- ["inTransaction"]=>
- bool(false)
- ["transactionState"]=>
- string(4) "none"
- ["transactionOptions"]=>
- NULL
-}
-===DONE===
diff --git a/mongodb-1.12.0/tests/session/session-endSession-002.phpt b/mongodb-1.12.0/tests/session/session-endSession-002.phpt
deleted file mode 100644
index 2648f8a9..00000000
--- a/mongodb-1.12.0/tests/session/session-endSession-002.phpt
+++ /dev/null
@@ -1,22 +0,0 @@
---TEST--
-MongoDB\Driver\Session::endSession() Calling method multiple times
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-
-$sessionA = $manager->startSession();
-$sessionA->endSession();
-$sessionA->endSession();
-$sessionA->endSession();
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-===DONE===
diff --git a/mongodb-1.12.0/tests/session/session-getClusterTime-001.phpt b/mongodb-1.12.0/tests/session/session-getClusterTime-001.phpt
deleted file mode 100644
index e8c87a20..00000000
--- a/mongodb-1.12.0/tests/session/session-getClusterTime-001.phpt
+++ /dev/null
@@ -1,43 +0,0 @@
---TEST--
-MongoDB\Driver\Session::getClusterTime()
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_not_replica_set_or_sharded_cluster_with_replica_set(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-$session = $manager->startSession();
-
-echo "Initial cluster time:\n";
-var_dump($session->getClusterTime());
-
-$command = new MongoDB\Driver\Command(['ping' => 1]);
-$manager->executeCommand(DATABASE_NAME, $command, ['session' => $session]);
-
-echo "\nCluster time after command:\n";
-var_dump($session->getClusterTime());
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-Initial cluster time:
-NULL
-
-Cluster time after command:
-object(stdClass)#%d (%d) {
- ["clusterTime"]=>
- object(MongoDB\BSON\Timestamp)#%d (%d) {
- ["increment"]=>
- string(%d) "%d"
- ["timestamp"]=>
- string(%d) "%d"
- }
- ["signature"]=>
- %a
-}
-===DONE===
diff --git a/mongodb-1.12.0/tests/session/session-getLogicalSessionId-001.phpt b/mongodb-1.12.0/tests/session/session-getLogicalSessionId-001.phpt
deleted file mode 100644
index 2b79565d..00000000
--- a/mongodb-1.12.0/tests/session/session-getLogicalSessionId-001.phpt
+++ /dev/null
@@ -1,30 +0,0 @@
---TEST--
-MongoDB\Driver\Session::getLogicalSessionId()
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-$session = $manager->startSession();
-
-$lsid = $session->getLogicalSessionId();
-
-/* Note: we avoid dumping the Binary object as it may contain bytes that
- * intefere with the test suite's ability to compare expected output. */
-var_dump($lsid instanceof stdClass);
-var_dump($lsid->id instanceof MongoDB\BSON\Binary);
-var_dump($lsid->id->getType() === MongoDB\BSON\Binary::TYPE_UUID);
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-bool(true)
-bool(true)
-bool(true)
-===DONE===
diff --git a/mongodb-1.12.0/tests/session/session-getOperationTime-001.phpt b/mongodb-1.12.0/tests/session/session-getOperationTime-001.phpt
deleted file mode 100644
index 40d659ab..00000000
--- a/mongodb-1.12.0/tests/session/session-getOperationTime-001.phpt
+++ /dev/null
@@ -1,38 +0,0 @@
---TEST--
-MongoDB\Driver\Session::getOperationTime()
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto(); ?>
-<?php skip_if_not_replica_set_or_sharded_cluster_with_replica_set(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-$session = $manager->startSession();
-
-echo "Initial operation time:\n";
-var_dump($session->getOperationTime());
-
-$command = new MongoDB\Driver\Command(['ping' => 1]);
-$manager->executeCommand(DATABASE_NAME, $command, ['session' => $session]);
-
-echo "\nOperation time after command:\n";
-var_dump($session->getOperationTime());
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-Initial operation time:
-NULL
-
-Operation time after command:
-object(MongoDB\BSON\Timestamp)#%d (%d) {
- ["increment"]=>
- string(%d) "%d"
- ["timestamp"]=>
- string(%d) "%d"
-}
-===DONE===
diff --git a/mongodb-1.12.0/tests/session/session-startTransaction_error-006.phpt b/mongodb-1.12.0/tests/session/session-startTransaction_error-006.phpt
deleted file mode 100644
index 2956e5ba..00000000
--- a/mongodb-1.12.0/tests/session/session-startTransaction_error-006.phpt
+++ /dev/null
@@ -1,26 +0,0 @@
---TEST--
-MongoDB\Driver\Session::startTransaction() throws an error on replicasets < 4.0
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto() ?>
-<?php skip_if_not_replica_set(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
-<?php skip_if_server_version('>=', '4.0'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-$session = $manager->startSession();
-
-echo throws(function () use ($session) {
- $session->startTransaction();
-}, MongoDB\Driver\Exception\RuntimeException::class), "\n";
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-OK: Got MongoDB\Driver\Exception\RuntimeException
-Multi-document transactions are not supported by this server version
-===DONE===
diff --git a/mongodb-1.12.0/tests/session/session-startTransaction_error-007.phpt b/mongodb-1.12.0/tests/session/session-startTransaction_error-007.phpt
deleted file mode 100644
index 61695c70..00000000
--- a/mongodb-1.12.0/tests/session/session-startTransaction_error-007.phpt
+++ /dev/null
@@ -1,26 +0,0 @@
---TEST--
-MongoDB\Driver\Session::startTransaction() throws an error on sharded clusters < 4.2
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_libmongoc_crypto() ?>
-<?php skip_if_not_sharded_cluster_with_replica_set(); ?>
-<?php skip_if_server_version('<', '3.6'); ?>
-<?php skip_if_server_version('>=', '4.2'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-$session = $manager->startSession();
-
-echo throws(function () use ($session) {
- $session->startTransaction();
-}, MongoDB\Driver\Exception\RuntimeException::class), "\n";
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-OK: Got MongoDB\Driver\Exception\RuntimeException
-Multi-document transactions are not supported by this server version
-===DONE===
diff --git a/mongodb-1.12.0/tests/standalone/executiontimeoutexception-001.phpt b/mongodb-1.12.0/tests/standalone/executiontimeoutexception-001.phpt
deleted file mode 100644
index 22f07556..00000000
--- a/mongodb-1.12.0/tests/standalone/executiontimeoutexception-001.phpt
+++ /dev/null
@@ -1,35 +0,0 @@
---TEST--
-ExecutionTimeoutException: exceeding $maxTimeMS (queries)
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_not_clean(); ?>
-<?php skip_if_test_commands_disabled(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-
-// Select a specific server for future operations to avoid mongos switching in sharded clusters
-$server = $manager->selectServer(new \MongoDB\Driver\ReadPreference('primary'));
-
-$query = new MongoDB\Driver\Query(array("company" => "Smith, Carter and Buckridge"), array(
- 'projection' => array('_id' => 0, 'username' => 1),
- 'sort' => array('phoneNumber' => 1),
- 'modifiers' => array(
- '$maxTimeMS' => 1,
- ),
-));
-
-failMaxTimeMS($server);
-throws(function() use ($server, $query) {
- $result = $server->executeQuery(NS, $query);
-}, "MongoDB\Driver\Exception\ExecutionTimeoutException");
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-OK: Got MongoDB\Driver\Exception\ExecutionTimeoutException
-===DONE===
diff --git a/mongodb-1.12.0/tests/standalone/executiontimeoutexception-002.phpt b/mongodb-1.12.0/tests/standalone/executiontimeoutexception-002.phpt
deleted file mode 100644
index ddcb7bfa..00000000
--- a/mongodb-1.12.0/tests/standalone/executiontimeoutexception-002.phpt
+++ /dev/null
@@ -1,34 +0,0 @@
---TEST--
-ExecutionTimeoutException: exceeding maxTimeMS (commands)
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_not_clean(); ?>
-<?php skip_if_test_commands_disabled(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-
-// Select a specific server for future operations to avoid mongos switching in sharded clusters
-$server = $manager->selectServer(new \MongoDB\Driver\ReadPreference('primary'));
-
-$cmd = array(
- "count" => "collection",
- "query" => array("a" => 1),
- "maxTimeMS" => 100,
-);
-$command = new MongoDB\Driver\Command($cmd);
-
-failMaxTimeMS($server);
-throws(function() use ($server, $command) {
- $result = $server->executeCommand(DATABASE_NAME, $command);
-}, "MongoDB\Driver\Exception\ExecutionTimeoutException");
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-OK: Got MongoDB\Driver\Exception\ExecutionTimeoutException
-===DONE===
diff --git a/mongodb-1.12.0/tests/utils/skipif.php b/mongodb-1.12.0/tests/utils/skipif.php
deleted file mode 100644
index 25daccac..00000000
--- a/mongodb-1.12.0/tests/utils/skipif.php
+++ /dev/null
@@ -1,484 +0,0 @@
-<?php
-
-use MongoDB\Driver\Command;
-use MongoDB\Driver\Manager;
-use MongoDB\Driver\ReadPreference;
-use MongoDB\Driver\Server;
-use MongoDB\Driver\Exception\ConnectionException;
-use MongoDB\Driver\Exception\RuntimeException;
-
-require_once __DIR__ . '/basic.inc';
-require_once __DIR__ . '/tools.php';
-
-/**
- * Disables SKIPIF caching (PHP 8.1+).
- */
-function disable_skipif_caching()
-{
- if (PHP_VERSION_ID < 80100) {
- return;
- }
-
- echo "nocache\n";
-}
-
-/**
- * Skips the test if the topology is load balanced.
- */
-function skip_if_load_balanced()
-{
- is_load_balanced(URI) and exit('skip topology is load balanced');
-}
-
-/**
- * Skips the test if the topology is not load balanced.
- */
-function skip_if_not_load_balanced()
-{
- is_load_balanced(URI) or exit('skip topology is not load balanced');
-}
-
-/**
- * Skips the test if the topology is a sharded cluster.
- */
-function skip_if_mongos()
-{
- is_mongos(URI) and exit('skip topology is a sharded cluster');
-}
-
-/**
- * Skips the test if the topology contains multiple mongos nodes.
- *
- * This is particularly useful for tests that rely on configureFailPoint, since
- * randomized server selection can interfere with testing.
- */
-function skip_if_multiple_mongos()
-{
- $manager = create_test_manager();
-
- // Ensure SDAM is initialized before calling Manager::getServers()
- $manager->selectServer(new ReadPreference('nearest'));
-
- $mongosNodes = array_filter($manager->getServers(), function(Server $server) {
- return $server->getType() === Server::TYPE_MONGOS;
- });
-
- if (count($mongosNodes) > 1) {
- exit('skip topology contains multiple mongos nodes');
- }
-}
-
-/**
- * Skips the test if the topology is not a shard cluster.
- */
-function skip_if_not_mongos()
-{
- is_mongos(URI) or exit('skip topology is not a sharded cluster');
-}
-
-function skip_if_not_sharded_cluster_with_replica_set()
-{
- is_sharded_cluster_with_replica_set(URI) or exit('skip topology is not a sharded cluster with replica set');
-}
-
-/**
- * Skips the test if the topology is a replica set.
- */
-function skip_if_replica_set()
-{
- is_replica_set(URI) and exit('skip topology is a replica set');
-}
-
-/**
- * Skips the test if the topology is not a replica set.
- */
-function skip_if_not_replica_set()
-{
- is_replica_set(URI) or exit('skip topology is not a replica set');
-}
-
-/**
- * Skips the test if the topology is not a replica set or sharded cluster backed by replica sets
- */
-function skip_if_not_replica_set_or_sharded_cluster_with_replica_set()
-{
- is_replica_set(URI) or is_sharded_cluster_with_replica_set(URI) or exit('skip topology is not a replica set or sharded cluster with replica set');
-}
-
-function skip_if_no_transactions()
-{
- if (is_sharded_cluster_with_replica_set(URI)) {
- skip_if_server_version('<', '4.2');
- } elseif (is_replica_set(URI)) {
- skip_if_server_version('<', '4.0');
- } else {
- exit('skip topology does not support transactions');
- }
-}
-
-/**
- * Skips the test if the topology has no arbiter.
- */
-function skip_if_no_arbiter()
-{
- try {
- $primary = get_primary_server(URI);
- } catch (ConnectionException $e) {
- exit('skip primary server is not accessible: ' . $e->getMessage());
- }
- $info = $primary->getInfo();
-
- if (!isset($info['arbiters']) || count($info['arbiters']) < 1) {
- exit('skip no arbiters available');
- }
-}
-
-/**
- * Skips the test if the topology has no secondary.
- */
-function skip_if_no_secondary()
-{
- try {
- $primary = get_primary_server(URI);
- } catch (ConnectionException $e) {
- exit('skip primary server is not accessible: ' . $e->getMessage());
- }
- $info = $primary->getInfo();
-
- if (!isset($info['hosts']) || count($info['hosts']) < 2) {
- exit('skip no secondaries available');
- }
-}
-
-/**
- * Skips the test if the topology does not have enough data carrying nodes
- */
-function skip_if_not_enough_data_nodes($requiredNodes, $maxNodeCount = null)
-{
- try {
- $primary = get_primary_server(URI);
- } catch (ConnectionException $e) {
- exit('skip primary server is not accessible: ' . $e->getMessage());
- }
- $info = $primary->getInfo();
-
- $dataNodeCount = isset($info['hosts']) ? count($info['hosts']) : 0;
-
- if ($dataNodeCount < $requiredNodes) {
- exit("skip not enough nodes available (wanted: {$requiredNodes}, available: " . count($info['hosts']) . ')');
- }
- if ($maxNodeCount !== null && $dataNodeCount > $requiredNodes) {
- exit("skip too many nodes available (wanted: {$requiredNodes}, available: " . count($info['hosts']) . ')');
- }
-}
-
-/**
- * Skips the test if the topology does not have enough nodes
- */
-function skip_if_not_enough_nodes($requiredNodes, $maxNodeCount = null)
-{
- try {
- $primary = get_primary_server(URI);
- } catch (ConnectionException $e) {
- exit('skip primary server is not accessible: ' . $e->getMessage());
- }
- $info = $primary->getInfo();
-
- $nodeCount =
- (isset($info['hosts']) ? count($info['hosts']) : 0) +
- (isset($info['arbiters']) ? count($info['arbiters']) : 0);
-
- if ($nodeCount < $requiredNodes) {
- exit("skip not enough nodes available (wanted: {$requiredNodes}, available: " . count($info['hosts']) . ')');
- }
- if ($maxNodeCount !== null && $nodeCount > $requiredNodes) {
- exit("skip too many nodes available (wanted: {$requiredNodes}, available: " . count($info['hosts']) . ')');
- }
-}
-
-/**
- * Skips the test if the topology is a standalone.
- */
-function skip_if_standalone()
-{
- is_standalone(URI) and exit('skip topology is a standalone');
-}
-
-/**
- * Skips the test if the topology is not a standalone.
- */
-function skip_if_not_standalone()
-{
- is_standalone(URI) or exit('skip topology is not a standalone');
-}
-
-/**
- * Skips the test if the connection string uses SSL.
- */
-function skip_if_ssl()
-{
- is_ssl(URI) and exit('skip URI is using SSL');
-}
-
-/**
- * Skips the test if the connection string uses SSL.
- */
-function skip_if_not_ssl()
-{
- is_ssl(URI) or exit('skip URI is not using SSL');
-}
-
-/**
- * Skips the test if no SSL directory has been defined.
- */
-function skip_if_no_ssl_dir()
-{
- $sslDir = getenv('SSL_DIR');
- $sslDir !== false or exit('skip SSL_DIR environment variable not set');
-
- $sslDir = realpath($sslDir);
- ($sslDir !== false && is_dir($sslDir)) or exit('skip SSL_DIR is not a valid directory');
-}
-
-/**
- * Skips the test if the connection string is using auth.
- */
-function skip_if_auth()
-{
- is_auth(URI) and exit('skip URI is using auth');
-}
-
-/**
- * Skips the test if the connection string is not using auth.
- */
-function skip_if_not_auth()
-{
- is_auth(URI) or exit('skip URI is not using auth');
-}
-
-/**
- * Skips the test if the connection string is not using a particular
- * authMechanism.
- *
- * @param string $authMechanism
- */
-function skip_if_not_auth_mechanism($authMechanism)
-{
- $uriAuthMechanism = get_uri_option(URI, 'authMechanism');
-
- if ($uriAuthMechanism === null && $authMechanism !== null) {
- exit('skip URI is not using authMechanism');
- }
-
- if ($uriAuthMechanism !== $authMechanism) {
- exit("skip URI authMechanism is '$uriAuthMechanism' (needed: '$authMechanism')");
- }
-}
-
-/**
- * Skips the test if the server is not accessible.
- */
-function skip_if_not_live()
-{
- try {
- get_primary_server(URI);
- } catch (ConnectionException $e) {
- exit('skip server is not accessible: ' . $e->getMessage());
- }
-}
-
-/**
- * Skips the test if the server version satisfies a comparison.
- *
- * @see http://php.net/version_compare
- * @param string $operator Comparison operator
- * @param string $version Version to compare against
- */
-function skip_if_server_version($operator, $version)
-{
- $serverVersion = get_server_version(URI);
-
- if (version_compare($serverVersion, $version, $operator)) {
- exit("skip Server version '$serverVersion' $operator '$version'");
- }
-}
-
-/**
- * Skips the test if the PHP version satisfies a comparison.
- *
- * @see http://php.net/version_compare
- * @param string $operator Comparison operator
- * @param string $version Version to compare against
- */
-function skip_if_php_version($operator, $version)
-{
- if (version_compare(PHP_VERSION, $version, $operator)) {
- exit("skip PHP version '" . PHP_VERSION . "' $operator '$version'");
- }
-}
-
-/**
- * Skips the test if the server not using a particular storage engine.
- *
- * @param string $storageEngine Storage engine name
- */
-function skip_if_not_server_storage_engine($storageEngine)
-{
- $serverStorageEngine = get_server_storage_engine(URI);
-
- if ($serverStorageEngine !== $storageEngine) {
- exit("skip Server storage engine is '$serverStorageEngine' (needed '$storageEngine')");
- }
-}
-
-/**
- * Skips the test if the server does not support the sleep command.
- */
-function skip_if_sleep_command_unavailable()
-{
- if (!command_works(URI, ['sleep' => 1, 'secs' => 1, 'w' => false])) {
- exit('skip sleep command not available');
- }
-}
-
-/**
- * Skips the test if the server does not support test commands.
- */
-function skip_if_test_commands_disabled()
-{
- if (!get_server_parameter(URI, 'enableTestCommands')) {
- exit('skip test commands are disabled');
- }
-}
-
-/**
- * Skips the test if libmongoc does not support crypto.
- *
- * If one or more libaries are provided, additionally check that the reported
- * library is in that array. Possible values are "libcrypto", "Common Crypto",
- * and "CNG".
- *
- * @param array $libs Optional list of crypto libraries to require
- */
-function skip_if_not_libmongoc_crypto(array $libs = [])
-{
- $lib = get_module_info('libmongoc crypto library');
-
- if ($lib === null) {
- exit('skip libmongoc crypto is not enabled');
- }
-
- if (!empty($libs) && !in_array($lib, $libs)) {
- exit('skip Needs libmongoc crypto library ' . implode(', ', $libs) . ', but found ' . $lib);
- }
-}
-
-/**
- * Skips the test if libmongoc does not support SSL.
- *
- * If one or more libaries are provided, additionally check that the reported
- * library is in that array. Possible values are "OpenSSL", "LibreSSL",
- * "Secure Transport", and "Secure Channel".
- *
- * @param array $libs Optional list of SSL libraries to require
- */
-function skip_if_not_libmongoc_ssl(array $libs = [])
-{
- $lib = get_module_info('libmongoc SSL library');
-
- if ($lib === null) {
- exit('skip libmongoc SSL is not enabled');
- }
-
- if (!empty($libs) && !in_array($lib, $libs)) {
- exit('skip Needs libmongoc SSL library ' . implode(', ', $libs) . ', but found ' . $lib);
- }
-}
-
-/**
- * Skips the test if the driver was not compiled with support for FLE
- */
-function skip_if_not_libmongocrypt()
-{
- $lib = get_module_info('libmongocrypt');
-
- if ($lib === 'disabled') {
- exit('skip libmongocrypt is not enabled');
- }
-}
-
-/**
- * Skips the test if the driver was compiled with support for FLE
- */
-function skip_if_libmongocrypt()
-{
- $lib = get_module_info('libmongocrypt');
-
- if ($lib !== 'disabled') {
- exit('skip libmongocrypt is enabled');
- }
-}
-
-/**
- * Skips the test if the collection cannot be dropped.
- *
- * @param string $databaseName Database name
- * @param string $collectionName Collection name
- */
-function skip_if_not_clean($databaseName = DATABASE_NAME, $collectionName = COLLECTION_NAME)
-{
- try {
- drop_collection(URI, $databaseName, $collectionName);
- } catch (RuntimeException $e) {
- exit("skip Could not drop '$databaseName.$collectionName': " . $e->getMessage());
- }
-
- /* Since this function modifies the state of the database, we need it to run
- * each time before a test. */
- disable_skipif_caching();
-}
-
-function skip_if_no_getmore_failpoint()
-{
- $serverVersion = get_server_version(URI);
-
- if (
- version_compare($serverVersion, '3.2', '>=') &&
- version_compare($serverVersion, '4.0', '<')
- ) {
- exit("skip Server version '$serverVersion' does not support a getMore failpoint'");
- }
-}
-
-function skip_if_no_failcommand_failpoint()
-{
- skip_if_test_commands_disabled();
-
- $serverVersion = get_server_version(URI);
-
- if (is_mongos(URI) && version_compare($serverVersion, '4.1.8', '<')) {
- exit("skip mongos version '$serverVersion' does not support 'failCommand' failpoint'");
- } elseif (version_compare($serverVersion, '4.0', '<')) {
- exit("skip mongod version '$serverVersion' does not support 'failCommand' failpoint'");
- }
-}
-
-function skip_if_no_mongo_orchestration()
-{
- $ctx = stream_context_create(['http' => ['timeout' => 0.5]]);
- $result = @file_get_contents(MONGO_ORCHESTRATION_URI, false, $ctx);
-
- /* Note: file_get_contents emits an E_WARNING on failure, which will be
- * caught by the error handler in basic-skipif.inc. In that case, this may
- * never be reached. */
- if ($result === false) {
- exit("skip mongo-orchestration is not accessible: '" . MONGO_ORCHESTRATION_URI . "'");
- }
-}
-
-function skip_if_appveyor()
-{
- if (getenv('APPVEYOR')) {
- exit('skip Test cannot be run on AppVeyor');
- }
-}
diff --git a/mongodb-1.12.0/tests/utils/tools.php b/mongodb-1.12.0/tests/utils/tools.php
deleted file mode 100644
index bbd4a3ca..00000000
--- a/mongodb-1.12.0/tests/utils/tools.php
+++ /dev/null
@@ -1,852 +0,0 @@
-<?php
-
-use MongoDB\Driver\BulkWrite;
-use MongoDB\Driver\Command;
-use MongoDB\Driver\Manager;
-use MongoDB\Driver\ReadPreference;
-use MongoDB\Driver\Server;
-use MongoDB\Driver\ServerApi;
-use MongoDB\Driver\WriteConcern;
-use MongoDB\Driver\WriteConcernError;
-use MongoDB\Driver\WriteError;
-use MongoDB\Driver\WriteResult;
-use MongoDB\Driver\Exception\ConnectionException;
-use MongoDB\Driver\Exception\RuntimeException;
-
-/**
- * Appends an option to a URI string and returns a new URI.
- *
- * @param string $uri
- * @param string $option
- * @param string $value
- * @return string
- */
-function append_uri_option($uri, $option)
-{
- // Append to existing query string
- if (strpos($uri, '?') !== false) {
- return $uri . '&' . $option;
- }
-
- // Terminate host list and append new query string
- if (parse_url($uri, PHP_URL_PATH) === null) {
- return $uri . '/?' . $option;
- }
-
- // Append query string after terminated host list and possible auth database
- return $uri . '?' . $option;
-}
-
-/**
- * Drops a collection on the primary server.
- *
- * @param string $uri Connection string
- * @param string $databaseName Database name
- * @param string $collectionName Collection name
- * @throws RuntimeException
- */
-function drop_collection($uri, $databaseName, $collectionName)
-{
- $server = get_primary_server($uri);
- $command = new Command(['drop' => $collectionName]);
-
- try {
- /* Unless we are dropping a collection within the "local" database,
- * which does not support a write concern, we need to use w:majority due
- * to the issue explained in SERVER-35613: "drop" uses a two phase
- * commit, and due to that, it is possible that a lock can't be acquired
- * for a transaction that gets quickly started as the "drop" reaper
- * hasn't completed yet. */
- $wc = $databaseName === 'local' ? new WriteConcern(1) : new WriteConcern(WriteConcern::MAJORITY);
-
- $server->executeCommand(
- $databaseName,
- $command,
- ['writeConcern' => $wc]
- );
- } catch (RuntimeException $e) {
- if ($e->getMessage() !== 'ns not found') {
- throw $e;
- }
- }
-}
-
-/**
- * Returns the value of a module row from phpinfo(), or null if it's not found.
- *
- * @param string $row
- * @return string|null
- */
-function get_module_info($row)
-{
- ob_start();
- phpinfo(INFO_MODULES);
- $info = ob_get_clean();
-
- $pattern = sprintf('/^%s([\w ]+)$/m', preg_quote($row . ' => '));
-
- if (preg_match($pattern, $info, $matches) !== 1) {
- return null;
- }
-
- return $matches[1];
-}
-
-function create_test_manager(string $uri = null, array $options = [], array $driverOptions = [])
-{
- if (getenv('API_VERSION') && ! isset($driverOptions['serverApi'])) {
- $driverOptions['serverApi'] = new ServerApi(getenv('API_VERSION'));
- }
-
- return new Manager($uri ?? URI, $options, $driverOptions);
-}
-
-/**
- * Returns the primary server.
- *
- * @param string $uri Connection string
- * @return Server
- * @throws ConnectionException
- */
-function get_primary_server($uri)
-{
- return create_test_manager($uri)->selectServer(new ReadPreference('primary'));
-}
-
-/**
- * Returns a secondary server.
- *
- * @param string $uri Connection string
- * @return Server
- * @throws ConnectionException
- */
-function get_secondary_server($uri)
-{
- return create_test_manager($uri)->selectServer(new ReadPreference('secondary'));
-}
-
-/**
- * Runs a command and returns whether an exception was thrown or not
- *
- * @param string $uri Connection string
- * @param array|object $commandSpec
- * @return bool
- * @throws RuntimeException
- */
-function command_works($uri, $commandSpec)
-{
- $command = new Command($commandSpec);
- $server = get_primary_server($uri);
- try {
- $cursor = $server->executeCommand('admin', $command);
- return true;
- } catch (Exception $e) {
- return false;
- }
-}
-
-/**
- * Returns a parameter of the primary server.
- *
- * @param string $uri Connection string
- * @return mixed
- * @throws RuntimeException
- */
-function get_server_parameter($uri, $parameter)
-{
- $server = get_primary_server($uri);
- $command = new Command(['getParameter' => 1, $parameter => 1]);
- $cursor = $server->executeCommand('admin', $command);
-
- return current($cursor->toArray())->$parameter;
-}
-
-/**
- * Returns the storage engine of the primary server.
- *
- * @param string $uri Connection string
- * @return string
- * @throws RuntimeException
- */
-function get_server_storage_engine($uri)
-{
- $server = get_primary_server($uri);
- $command = new Command(['serverStatus' => 1]);
- $cursor = $server->executeCommand('admin', $command);
-
- return current($cursor->toArray())->storageEngine->name;
-}
-
-/**
- * Helper to return the version of a specific server.
- *
- * @param Server $server
- * @return string
- * @throws RuntimeException
- */
-function get_server_version_from_server(Server $server)
-{
- $command = new Command(['buildInfo' => 1]);
- $cursor = $server->executeCommand('admin', $command);
-
- return current($cursor->toArray())->version;
-}
-
-/**
- * Returns the version of the primary server.
- *
- * @param string $uri Connection string
- * @return string
- * @throws RuntimeException
- */
-function get_server_version($uri)
-{
- $server = get_primary_server($uri);
- return get_server_version_from_server($server);
-}
-
-/**
- * Returns the value of a URI option, or null if it's not found.
- *
- * @param string $uri
- * @return string|null
- */
-function get_uri_option($uri, $option)
-{
- $pattern = sprintf('/[?&]%s=([^&]+)/i', preg_quote($option));
-
- if (preg_match($pattern, $uri, $matches) !== 1) {
- return null;
- }
-
- return $matches[1];
-}
-
-/**
- * Checks that the topology is load balanced.
- *
- * @param string $uri
- * @return boolean
- */
-function is_load_balanced($uri)
-{
- return get_primary_server($uri)->getType() === Server::TYPE_LOAD_BALANCER;
-}
-
-/**
- * Checks that the topology is a sharded cluster.
- *
- * @param string $uri
- * @return boolean
- */
-function is_mongos($uri)
-{
- return get_primary_server($uri)->getType() === Server::TYPE_MONGOS;
-}
-
-/**
- * Checks that the topology is a sharded cluster using a replica set.
- *
- * Note: only the first shard is checked.
- */
-function is_sharded_cluster_with_replica_set($uri)
-{
- $server = get_primary_server($uri);
-
- if ($server->getType() !== Server::TYPE_MONGOS && $server->getType() !== Server::TYPE_LOAD_BALANCER) {
- return false;
- }
-
- $cursor = $server->executeQuery('config.shards', new \MongoDB\Driver\Query([], ['limit' => 1]));
- $cursor->setTypeMap(['root' => 'array', 'document' => 'array']);
- $document = current($cursor->toArray());
-
- if (! $document) {
- return false;
- }
-
- /**
- * Use regular expression to distinguish between standalone or replicaset:
- * Without a replicaset: "host" : "localhost:4100"
- * With a replicaset: "host" : "dec6d8a7-9bc1-4c0e-960c-615f860b956f/localhost:4400,localhost:4401"
- */
- return preg_match('@^.*/.*:\d+@', $document['host']);
-}
-
-/**
- * Checks that the topology is a replica set.
- *
- * @param string $uri
- * @return boolean
- */
-function is_replica_set($uri)
-{
- if (get_primary_server($uri)->getType() !== Server::TYPE_RS_PRIMARY) {
- return false;
- }
-
- /* Note: this may return a false negative if replicaSet is specified through
- * a TXT record for a mongodb+srv connection string. */
- if (get_uri_option($uri, 'replicaSet') === NULL) {
- return false;
- }
-
- return true;
-}
-
-/**
- * Checks if the connection string uses authentication.
- *
- * @param string $uri
- * @return boolean
- */
-function is_auth($uri)
-{
- if (stripos($uri, 'authmechanism=') !== false) {
- return true;
- }
-
- if (strpos($uri, ':') !== false && strpos($uri, '@') !== false) {
- return true;
- }
-
- return false;
-}
-
-/**
- * Checks if the connection string uses SSL.
- *
- * @param string $uri
- * @return boolean
- */
-function is_ssl($uri)
-{
- return stripos($uri, 'ssl=true') !== false || stripos($uri, 'tls=true') !== false;
-}
-
-/**
- * Checks that the topology is a standalone.
- *
- * @param string $uri
- * @return boolean
- */
-function is_standalone($uri)
-{
- return get_primary_server($uri)->getType() === Server::TYPE_STANDALONE;
-}
-
-/**
- * Converts the server type constant to a string.
- *
- * @see http://php.net/manual/en/class.mongodb-driver-server.php
- * @param integer $type
- * @return string
- */
-function server_type_as_string($type)
-{
- switch ($type) {
- case Server::TYPE_STANDALONE:
- return 'Standalone';
- case Server::TYPE_MONGOS:
- return 'Mongos';
- case Server::TYPE_POSSIBLE_PRIMARY:
- return 'PossiblePrimary';
- case Server::TYPE_RS_PRIMARY:
- return 'RSPrimary';
- case Server::TYPE_RS_SECONDARY:
- return 'RSSecondary';
- case Server::TYPE_RS_ARBITER:
- return 'RSArbiter';
- case Server::TYPE_RS_OTHER:
- return 'RSOther';
- case Server::TYPE_RS_GHOST:
- return 'RSGhost';
- default:
- return 'Unknown';
- }
-}
-
-/**
- * Converts an errno number to a string.
- *
- * @see http://php.net/manual/en/errorfunc.constants.php
- * @param integer $errno
- * @param string
- */
-function errno_as_string($errno)
-{
- $errors = [
- 'E_ERROR',
- 'E_WARNING',
- 'E_PARSE',
- 'E_NOTICE',
- 'E_CORE_ERROR',
- 'E_CORE_WARNING',
- 'E_COMPILE_ERROR',
- 'E_COMPILE_WARNING',
- 'E_USER_ERROR',
- 'E_USER_WARNING',
- 'E_USER_NOTICE',
- 'E_STRICT',
- 'E_RECOVERABLE_ERROR',
- 'E_DEPRECATED',
- 'E_USER_DEPRECATED',
- 'E_ALL',
- ];
-
- foreach ($errors as $error) {
- if ($errno === constant($error)) {
- return $error;
- }
- }
-
- return 'Unknown';
-}
-
-/**
- * Prints a traditional hex dump of byte values and printable characters.
- *
- * @see http://stackoverflow.com/a/4225813/162228
- * @param string $data Binary data
- * @param integer $width Bytes displayed per line
- */
-function hex_dump($data, $width = 16)
-{
- static $pad = '.'; // Placeholder for non-printable characters
- static $from = '';
- static $to = '';
-
- if ($from === '') {
- for ($i = 0; $i <= 0xFF; $i++) {
- $from .= chr($i);
- $to .= ($i >= 0x20 && $i <= 0x7E) ? chr($i) : $pad;
- }
- }
-
- $hex = str_split(bin2hex($data), $width * 2);
- $chars = str_split(strtr($data, $from, $to), $width);
-
- $offset = 0;
- $length = $width * 3;
-
- foreach ($hex as $i => $line) {
- printf("%6X : %-{$length}s [%s]\n", $offset, implode(' ', str_split($line, 2)), $chars[$i]);
- $offset += $width;
- }
-}
-
-/**
- * Canonicalizes a JSON string.
- *
- * @param string $json
- * @return string
- */
-function json_canonicalize($json)
-{
- $json = json_encode(json_decode($json));
-
- /* Versions of PHP before 7.1 replace empty JSON keys with "_empty_" when
- * decoding to a stdClass (see: https://bugs.php.net/bug.php?id=46600). Work
- * around this by replacing "_empty_" keys before returning.
- */
- $json = str_replace('"_empty_":', '"":', $json);
-
- /* Canonicalize string values for $numberDouble to ensure they are converted
- * the same as number literals in legacy and relaxed output. This is needed
- * because the printf format in _bson_as_json_visit_double uses a high level
- * of precision and may not produce the exponent notation expected by the
- * BSON corpus tests. */
- $json = preg_replace_callback(
- '/{"\$numberDouble":"(-?\d+(\.\d+([eE]\+\d+)?)?)"}/',
- function ($matches) {
- return '{"$numberDouble":"' . json_encode(json_decode($matches[1])) . '"}';
- },
- $json
- );
-
- return $json;
-}
-
-/**
- * Return a collection name to use for the test file.
- *
- * The filename will be stripped of the base path to the test suite (prefix) as
- * well as the PHP file extension (suffix). Special characters (including hyphen
- * for shell compatibility) will be replaced with underscores.
- *
- * @param string $filename
- * @return string
- */
-function makeCollectionNameFromFilename($filename)
-{
- $filename = realpath($filename);
- $prefix = realpath(dirname(__FILE__) . '/..') . DIRECTORY_SEPARATOR;
-
- $replacements = array(
- // Strip test path prefix
- sprintf('/^%s/', preg_quote($prefix, '/')) => '',
- // Strip file extension suffix
- '/\.php$/' => '',
- // SKIPIFs add ".skip" between base name and extension
- '/\.skip$/' => '',
- // Replace special characters with underscores
- sprintf('/[%s]/', preg_quote('-$/\\', '/')) => '_',
- );
-
- return preg_replace(array_keys($replacements), array_values($replacements), $filename);
-}
-
-function NEEDS($configuration) {
- if (!constant($configuration)) {
- exit("skip -- need '$configuration' defined");
- }
-}
-function SLOW() {
- if (getenv("SKIP_SLOW_TESTS")) {
- exit("skip SKIP_SLOW_TESTS");
- }
-}
-
-function loadFixtures(Manager $manager, $dbname = DATABASE_NAME, $collname = COLLECTION_NAME, $filename = null)
-{
- if (!$filename) {
- $filename = "compress.zlib://" . __DIR__ . "/" . "PHONGO-FIXTURES.json.gz";
- }
-
- $bulk = new BulkWrite(['ordered' => false]);
-
- $server = $manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY));
-
- $data = file_get_contents($filename);
- $array = json_decode($data);
-
- foreach($array as $document) {
- $bulk->insert($document);
- }
-
- $retval = $server->executeBulkWrite("$dbname.$collname", $bulk);
-
- if ($retval->getInsertedCount() !== count($array)) {
- exit(sprintf('skip Fixtures were not loaded (expected: %d, actual: %d)', $total, $retval->getInsertedCount()));
- }
-}
-
-function createTemporaryMongoInstance(array $options = [])
-{
- $id = 'mo_' . COLLECTION_NAME;
- $options += [
- "name" => "mongod",
- "id" => $id,
- 'procParams' => [
- 'logpath' => "/tmp/MO/phongo/{$id}.log",
- 'ipv6' => true,
- 'setParameter' => [ 'enableTestCommands' => 1 ],
- ],
- ];
- $opts = array(
- "http" => array(
- "timeout" => 60,
- "method" => "PUT",
- "header" => "Accept: application/json\r\n" .
- "Content-type: application/x-www-form-urlencoded",
- "content" => json_encode($options),
- "ignore_errors" => true,
- ),
- );
- $ctx = stream_context_create($opts);
- $json = file_get_contents(MONGO_ORCHESTRATION_URI . "/servers/$id", false, $ctx);
- $result = json_decode($json, true);
-
- /* Failed -- or was already started */
- if (!isset($result["mongodb_uri"])) {
- destroyTemporaryMongoInstance($id);
- throw new Exception("Could not start temporary server instance\n");
- } else {
- return $result['mongodb_uri'];
- }
-}
-
-function destroyTemporaryMongoInstance($id = NULL)
-{
- if ($id == NULL) {
- $id = 'mo_' . COLLECTION_NAME;
- }
-
- $opts = array(
- "http" => array(
- "timeout" => 60,
- "method" => "DELETE",
- "header" => "Accept: application/json\r\n",
- "ignore_errors" => true,
- ),
- );
- $ctx = stream_context_create($opts);
- $json = file_get_contents(MONGO_ORCHESTRATION_URI . "/servers/$id", false, $ctx);
-}
-
-/**
- * Converts an error level (constant or bitmask) to a string description.
- */
-function severityToString(int $severity): string {
- static $constants = [
- 'E_ERROR' => E_ERROR,
- 'E_WARNING' => E_WARNING,
- 'E_PARSE' => E_PARSE,
- 'E_NOTICE' => E_NOTICE,
- 'E_CORE_ERROR' => E_CORE_ERROR,
- 'E_CORE_WARNING' => E_CORE_WARNING,
- 'E_COMPILE_ERROR' => E_COMPILE_ERROR,
- 'E_COMPILE_WARNING' => E_COMPILE_WARNING,
- 'E_USER_ERROR' => E_USER_ERROR,
- 'E_USER_WARNING' => E_USER_WARNING,
- 'E_USER_NOTICE' => E_USER_NOTICE,
- 'E_STRICT' => E_STRICT,
- 'E_RECOVERABLE_ERROR' => E_RECOVERABLE_ERROR,
- 'E_DEPRECATED' => E_DEPRECATED,
- 'E_USER_DEPRECATED' => E_USER_DEPRECATED,
- // E_ALL is handled separately
- ];
-
- if ($severity === E_ALL) {
- return 'E_ALL';
- }
-
- foreach ($constants as $constant => $value) {
- if ($severity & $value) {
- $matches[] = $constant;
- }
- }
-
- return empty($matches) ? 'UNKNOWN' : implode('|', $matches);
-}
-
-/**
- * Expects the callable to raise an error matching the expected severity, which
- * may be a constant or bitmask. May optionally expect the error to be raised
- * from a particular function. Returns the message from the raised error or
- * exception, or an empty string if neither was thrown.
- */
-function raises(callable $callable, int $expectedSeverity, string $expectedFromFunction = null): string
-{
- set_error_handler(function(int $severity, string $message, string $file, int $line) {
- throw new ErrorException($message, 0, $severity, $file, $line);
- });
-
- try {
- call_user_func($callable);
- } catch (ErrorException $e) {
- if (!($e->getSeverity() & $expectedSeverity)) {
- printf("ALMOST: Got %s - expected %s\n", severityToString($e->getSeverity()), severityToString($expectedSeverity));
- return $e->getMessage();
- }
-
- if ($expectedFromFunction === null) {
- printf("OK: Got %s\n", severityToString($e->getSeverity()));
- return $e->getMessage();
- }
-
- $fromFunction = $e->getTrace()[0]['function'];
-
- if (strcasecmp($fromFunction, $expectedFromFunction) !== 0) {
- printf("ALMOST: Got %s - but was raised from %s, not %s\n", errorLevelToString($e->getSeverity()), $fromFunction, $expectedFromFunction);
- return $e->getMessage();
- }
-
- printf("OK: Got %s raised from %s\n", severityToString($e->getSeverity()), $fromFunction);
- return $e->getMessage();
- } catch (Throwable $e) {
- printf("ALMOST: Got %s - expected %s\n", get_class($e), ErrorException::class);
- return $e->getMessage();
- } finally {
- restore_error_handler();
- }
-
- printf("FAILED: Expected %s, but no error raised!\n", ErrorException::class);
- return '';
-}
-
-/**
- * Expects the callable to throw an expected exception. May optionally expect
- * the exception to be thrown from a particular function. Returns the message
- * from the thrown exception, or an empty string if one was not thrown.
- */
-function throws(callable $callable, string $expectedException, string $expectedFromFunction = null): string
-{
- try {
- call_user_func($callable);
- } catch (Throwable $e) {
- if (!($e instanceof $expectedException)) {
- printf("ALMOST: Got %s - expected %s\n", get_class($e), $expectedException);
- return $e->getMessage();
- }
-
- if ($expectedFromFunction === null) {
- printf("OK: Got %s\n", $expectedException);
- return $e->getMessage();
- }
-
- $fromFunction = $e->getTrace()[0]['function'];
-
- if (strcasecmp($fromFunction, $expectedFromFunction) !== 0) {
- printf("ALMOST: Got %s - but was thrown from %s, not %s\n", $expectedException, $fromFunction, $expectedFromFunction);
- return $e->getMessage();
- }
-
- printf("OK: Got %s thrown from %s\n", $expectedException, $fromFunction);
- return $e->getMessage();
- }
-
- printf("FAILED: Expected %s, but no exception thrown!\n", $expectedException);
- return '';
-}
-
-function printServer(Server $server)
-{
- printf("server: %s:%d\n", $server->getHost(), $server->getPort());
-}
-
-function printWriteResult(WriteResult $result, $details = true)
-{
- printServer($result->getServer());
-
- printf("insertedCount: %d\n", $result->getInsertedCount());
- printf("matchedCount: %d\n", $result->getMatchedCount());
- printf("modifiedCount: %d\n", $result->getModifiedCount());
- printf("upsertedCount: %d\n", $result->getUpsertedCount());
- printf("deletedCount: %d\n", $result->getDeletedCount());
-
- foreach ($result->getUpsertedIds() as $index => $id) {
- printf("upsertedId[%d]: ", $index);
- var_dump($id);
- }
-
- $writeConcernError = $result->getWriteConcernError();
- printWriteConcernError($writeConcernError ? $writeConcernError : null, $details);
-
- foreach ($result->getWriteErrors() as $writeError) {
- printWriteError($writeError);
- }
-}
-
-function printWriteConcernError(WriteConcernError $error = null, $details)
-{
- if ($error) {
- /* This stuff is generated by the server, no need for us to test it */
- if (!$details) {
- printf("writeConcernError: %s (%d)\n", $error->getMessage(), $error->getCode());
- return;
- }
- var_dump($error);
- printf("writeConcernError.message: %s\n", $error->getMessage());
- printf("writeConcernError.code: %d\n", $error->getCode());
- printf("writeConcernError.info: ");
- var_dump($error->getInfo());
- }
-}
-
-function printWriteError(WriteError $error)
-{
- var_dump($error);
- printf("writeError[%d].message: %s\n", $error->getIndex(), $error->getMessage());
- printf("writeError[%d].code: %d\n", $error->getIndex(), $error->getCode());
-}
-
-function getInsertCount($retval) {
- return $retval->getInsertedCount();
-}
-function getModifiedCount($retval) {
- return $retval->getModifiedCount();
-}
-function getDeletedCount($retval) {
- return $retval->getDeletedCount();
-}
-function getUpsertedCount($retval) {
- return $retval->getUpsertedCount();
-}
-function getWriteErrors($retval) {
- return (array)$retval->getWriteErrors();
-}
-
-function def($arr) {
- foreach($arr as $const => $value) {
- define($const, getenv("PHONGO_TEST_$const") ?: $value);
- }
-}
-
-function configureFailPoint(Manager $manager, $failPoint, $mode, array $data = [])
-{
- $doc = [
- 'configureFailPoint' => $failPoint,
- 'mode' => $mode,
- ];
- if ($data) {
- $doc['data'] = $data;
- }
-
- $cmd = new Command($doc);
- $manager->executeCommand('admin', $cmd);
-}
-
-function configureTargetedFailPoint(Server $server, $failPoint, $mode, array $data = [])
-{
- $doc = array(
- 'configureFailPoint' => $failPoint,
- 'mode' => $mode,
- );
- if ($data) {
- $doc['data'] = $data;
- }
-
- $cmd = new Command($doc);
- $server->executeCommand('admin', $cmd);
-}
-
-function failMaxTimeMS(Server $server)
-{
- configureTargetedFailPoint($server, 'maxTimeAlwaysTimeOut', [ 'times' => 1 ]);
-}
-
-function toPHP($var, $typemap = array()) {
- return MongoDB\BSON\toPHP($var, $typemap);
-}
-function fromPHP($var) {
- return MongoDB\BSON\fromPHP($var);
-}
-function toJSON($var) {
- return MongoDB\BSON\toJSON($var);
-}
-function toCanonicalExtendedJSON($var) {
- return MongoDB\BSON\toCanonicalExtendedJSON($var);
-}
-function toRelaxedExtendedJSON($var) {
- return MongoDB\BSON\toRelaxedExtendedJSON($var);
-}
-function fromJSON($var) {
- return MongoDB\BSON\fromJSON($var);
-}
-
-/* Note: this fail point may terminate the mongod process, so you may want to
- * use this in conjunction with a throwaway server. */
-function failGetMore(Manager $manager)
-{
- /* We need to do version detection here */
- $primary = $manager->selectServer(new ReadPreference('primary'));
- $version = get_server_version_from_server($primary);
-
- if (version_compare($version, "3.2", "<")) {
- configureFailPoint($manager, 'failReceivedGetmore', 'alwaysOn');
- return;
- }
-
- if (version_compare($version, "4.0", ">=")) {
- /* We use 237 here, as that's the same original code that MongoD would
- * throw if a cursor had already gone by the time we call getMore. This
- * allows us to make things consistent with the getMore OP behaviour
- * from previous mongod versions. An errorCode is required here for the
- * failPoint to work. */
- configureFailPoint($manager, 'failCommand', 'alwaysOn', [ 'errorCode' => 237, 'failCommands' => ['getMore'] ]);
- return;
- }
-
- throw new Exception("Trying to configure a getMore fail point for a server version ($version) that doesn't support it");
-}
diff --git a/mongodb-1.12.0/tests/writeConcernError/writeconcernerror-debug-001.phpt b/mongodb-1.12.0/tests/writeConcernError/writeconcernerror-debug-001.phpt
deleted file mode 100644
index ed60f2be..00000000
--- a/mongodb-1.12.0/tests/writeConcernError/writeconcernerror-debug-001.phpt
+++ /dev/null
@@ -1,36 +0,0 @@
---TEST--
-MongoDB\Driver\WriteConcernError debug output
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_replica_set(); ?>
-<?php skip_if_server_version('>=', '3.1'); ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-
-$bulk = new MongoDB\Driver\BulkWrite;
-$bulk->insert(['x' => 1]);
-
-try {
- /* We assume that the replica set does not have 12 nodes */
- $manager->executeBulkWrite(NS, $bulk, new MongoDB\Driver\WriteConcern(12));
-} catch(MongoDB\Driver\Exception\BulkWriteException $e) {
- var_dump($e->getWriteResult()->getWriteConcernError());
-}
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-object(MongoDB\Driver\WriteConcernError)#%d (%d) {
- ["message"]=>
- string(29) "Not enough data-bearing nodes"
- ["code"]=>
- int(100)
- ["info"]=>
- NULL
-}
-===DONE===
diff --git a/mongodb-1.12.0/tests/writeConcernError/writeconcernerror-debug-002.phpt b/mongodb-1.12.0/tests/writeConcernError/writeconcernerror-debug-002.phpt
deleted file mode 100644
index 4616b182..00000000
--- a/mongodb-1.12.0/tests/writeConcernError/writeconcernerror-debug-002.phpt
+++ /dev/null
@@ -1,41 +0,0 @@
---TEST--
-MongoDB\Driver\WriteConcernError debug output
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php SLOW(); ?>
-<?php skip_if_not_replica_set(); ?>
-<?php skip_if_server_version('>=', '3.1'); ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-
-$bulk = new MongoDB\Driver\BulkWrite;
-for ($i = 0; $i < 6; $i++) {
- $bulk->insert(['x' => $i, 'y' => str_repeat('a', 4194304)]);
-}
-
-try {
- $manager->executeBulkWrite(NS, $bulk, new MongoDB\Driver\WriteConcern(2, 1));
-} catch(MongoDB\Driver\Exception\BulkWriteException $e) {
- var_dump($e->getWriteResult()->getWriteConcernError());
-}
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-object(MongoDB\Driver\WriteConcernError)#%d (%d) {
- ["message"]=>
- string(33) "waiting for replication timed out"
- ["code"]=>
- int(64)
- ["info"]=>
- object(stdClass)#%d (%d) {
- ["wtimeout"]=>
- bool(true)
- }
-}
-===DONE===
diff --git a/mongodb-1.12.0/tests/writeConcernError/writeconcernerror-getcode-001.phpt b/mongodb-1.12.0/tests/writeConcernError/writeconcernerror-getcode-001.phpt
deleted file mode 100644
index f8cc93c3..00000000
--- a/mongodb-1.12.0/tests/writeConcernError/writeconcernerror-getcode-001.phpt
+++ /dev/null
@@ -1,29 +0,0 @@
---TEST--
-MongoDB\Driver\WriteConcernError::getCode()
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_replica_set(); ?>
-<?php skip_if_server_version('>=', '3.1'); ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-
-$bulk = new MongoDB\Driver\BulkWrite;
-$bulk->insert(['x' => 1]);
-
-try {
- /* We assume that the replica set does not have 12 nodes */
- $manager->executeBulkWrite(NS, $bulk, new MongoDB\Driver\WriteConcern(12));
-} catch(MongoDB\Driver\Exception\BulkWriteException $e) {
- var_dump($e->getWriteResult()->getWriteConcernError()->getCode());
-}
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-int(100)
-===DONE===
diff --git a/mongodb-1.12.0/tests/writeConcernError/writeconcernerror-getinfo-001.phpt b/mongodb-1.12.0/tests/writeConcernError/writeconcernerror-getinfo-001.phpt
deleted file mode 100644
index 2e148b75..00000000
--- a/mongodb-1.12.0/tests/writeConcernError/writeconcernerror-getinfo-001.phpt
+++ /dev/null
@@ -1,29 +0,0 @@
---TEST--
-MongoDB\Driver\WriteConcernError::getInfo()
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_replica_set(); ?>
-<?php skip_if_server_version('>=', '3.1'); ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-
-$bulk = new MongoDB\Driver\BulkWrite;
-$bulk->insert(['x' => 1]);
-
-try {
- /* We assume that the replica set does not have 12 nodes */
- $manager->executeBulkWrite(NS, $bulk, new MongoDB\Driver\WriteConcern(12));
-} catch(MongoDB\Driver\Exception\BulkWriteException $e) {
- var_dump($e->getWriteResult()->getWriteConcernError()->getInfo());
-}
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-NULL
-===DONE===
diff --git a/mongodb-1.12.0/tests/writeConcernError/writeconcernerror-getinfo-002.phpt b/mongodb-1.12.0/tests/writeConcernError/writeconcernerror-getinfo-002.phpt
deleted file mode 100644
index 56e67ea5..00000000
--- a/mongodb-1.12.0/tests/writeConcernError/writeconcernerror-getinfo-002.phpt
+++ /dev/null
@@ -1,34 +0,0 @@
---TEST--
-MongoDB\Driver\WriteConcernError::getInfo()
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php SLOW(); ?>
-<?php skip_if_not_replica_set(); ?>
-<?php skip_if_server_version('>=', '3.1'); ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-
-$bulk = new MongoDB\Driver\BulkWrite;
-for ($i = 0; $i < 6; $i++) {
- $bulk->insert(['x' => $i, 'y' => str_repeat('a', 4194304)]);
-}
-
-try {
- $manager->executeBulkWrite(NS, $bulk, new MongoDB\Driver\WriteConcern(2, 1));
-} catch(MongoDB\Driver\Exception\BulkWriteException $e) {
- var_dump($e->getWriteResult()->getWriteConcernError()->getInfo());
-}
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-object(stdClass)#%d (%d) {
- ["wtimeout"]=>
- bool(true)
-}
-===DONE===
diff --git a/mongodb-1.12.0/tests/writeConcernError/writeconcernerror-getinfo-003.phpt b/mongodb-1.12.0/tests/writeConcernError/writeconcernerror-getinfo-003.phpt
deleted file mode 100644
index 9650abd5..00000000
--- a/mongodb-1.12.0/tests/writeConcernError/writeconcernerror-getinfo-003.phpt
+++ /dev/null
@@ -1,63 +0,0 @@
---TEST--
-MongoDB\Driver\WriteConcernError::getInfo() exposes writeConcernError.errInfo
---DESCRIPTION--
-CRUD spec prose test #1
-https://github.com/mongodb/specifications/blob/master/source/crud/tests/README.rst#writeconcernerror-details-exposes-writeconcernerror-errinfo
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_no_failcommand_failpoint(); ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-
-// Select a specific server for future operations to avoid mongos switching in sharded clusters
-$server = $manager->selectServer(new MongoDB\Driver\ReadPreference('primary'));
-
-configureTargetedFailPoint(
- $server,
- 'failCommand',
- [ 'times' => 1],
- [
- 'failCommands' => ['insert'],
- 'writeConcernError' => [
- 'code' => 100,
- 'codeName' => 'UnsatisfiableWriteConcern',
- 'errmsg' => 'Not enough data-bearing nodes',
- 'errInfo' => [
- 'writeConcern' => [
- 'w' => 2,
- 'wtimeout' => 0,
- 'provenance' => 'clientSupplied',
- ],
- ],
- ],
- ]
-);
-
-$bulk = new MongoDB\Driver\BulkWrite;
-$bulk->insert(['_id' => 1]);
-
-try {
- $server->executeBulkWrite(NS, $bulk);
-} catch (MongoDB\Driver\Exception\BulkWriteException $e) {
- var_dump($e->getWriteResult()->getWriteConcernError()->getInfo());
-}
-
-?>
-===DONE===
---EXPECTF--
-object(stdClass)#%d (%d) {
- ["writeConcern"]=>
- object(stdClass)#%d (%d) {
- ["w"]=>
- int(2)
- ["wtimeout"]=>
- int(0)
- ["provenance"]=>
- string(14) "clientSupplied"
- }
-}
-===DONE===
\ No newline at end of file
diff --git a/mongodb-1.12.0/tests/writeConcernError/writeconcernerror-getmessage-001.phpt b/mongodb-1.12.0/tests/writeConcernError/writeconcernerror-getmessage-001.phpt
deleted file mode 100644
index c2de53f5..00000000
--- a/mongodb-1.12.0/tests/writeConcernError/writeconcernerror-getmessage-001.phpt
+++ /dev/null
@@ -1,29 +0,0 @@
---TEST--
-MongoDB\Driver\WriteConcernError::getMessage()
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_replica_set(); ?>
-<?php skip_if_server_version('>=', '3.1'); ?>
-<?php skip_if_not_clean(); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-$manager = create_test_manager();
-
-$bulk = new MongoDB\Driver\BulkWrite;
-$bulk->insert(['x' => 1]);
-
-try {
- /* We assume that the replica set does not have 12 nodes */
- $manager->executeBulkWrite(NS, $bulk, new MongoDB\Driver\WriteConcern(12));
-} catch(MongoDB\Driver\Exception\BulkWriteException $e) {
- var_dump($e->getWriteResult()->getWriteConcernError()->getMessage());
-}
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECT--
-string(29) "Not enough data-bearing nodes"
-===DONE===
diff --git a/mongodb-1.12.0/tests/writeResult/writeresult-getupsertedids-002.phpt b/mongodb-1.12.0/tests/writeResult/writeresult-getupsertedids-002.phpt
deleted file mode 100644
index c814202e..00000000
--- a/mongodb-1.12.0/tests/writeResult/writeresult-getupsertedids-002.phpt
+++ /dev/null
@@ -1,101 +0,0 @@
---TEST--
-MongoDB\Driver\WriteResult::getUpsertedIds() with client-generated values
---SKIPIF--
-<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
-<?php skip_if_not_live(); ?>
-<?php skip_if_not_clean(); ?>
-<?php skip_if_server_version('<', '3.0'); ?>
---FILE--
-<?php
-require_once __DIR__ . "/../utils/basic.inc";
-
-/* Do not test Decimal128, since it is only supported by MongoDB 3.4+.
- *
- * Do not test array or Regex types, which are not permitted to be used as an
- * ID. If a regular expression is used in upsert criteria and does not match an
- * existing document, the server generates a new ObjectId. */
-$tests = [
- null,
- true,
- 1,
- 4.125,
- 'foo',
- (object) [],
- new MongoDB\BSON\Binary('foo', MongoDB\BSON\Binary::TYPE_GENERIC),
- new MongoDB\BSON\Javascript('function(){}'),
- new MongoDB\BSON\MaxKey,
- new MongoDB\BSON\MinKey,
- new MongoDB\BSON\ObjectId('586c18d86118fd6c9012dec1'),
- new MongoDB\BSON\Timestamp(1234, 5678),
- new MongoDB\BSON\UTCDateTime('1483479256924'),
-];
-
-$manager = create_test_manager();
-
-$bulk = new MongoDB\Driver\BulkWrite;
-
-foreach ($tests as $value) {
- $bulk->update(['_id' => $value], ['$set' => ['x' => 1]], ['upsert' => true]);
-}
-
-$result = $manager->executeBulkWrite(NS, $bulk);
-
-var_dump($result->getUpsertedIds());
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-array(13) {
- [0]=>
- NULL
- [1]=>
- bool(true)
- [2]=>
- int(1)
- [3]=>
- float(4.125)
- [4]=>
- string(3) "foo"
- [5]=>
- object(stdClass)#%d (%d) {
- }
- [6]=>
- object(MongoDB\BSON\Binary)#%d (%d) {
- ["data"]=>
- string(3) "foo"
- ["type"]=>
- int(0)
- }
- [7]=>
- object(MongoDB\BSON\Javascript)#%d (%d) {
- ["code"]=>
- string(12) "function(){}"
- ["scope"]=>
- NULL
- }
- [8]=>
- object(MongoDB\BSON\MaxKey)#%d (%d) {
- }
- [9]=>
- object(MongoDB\BSON\MinKey)#%d (%d) {
- }
- [10]=>
- object(MongoDB\BSON\ObjectId)#%d (%d) {
- ["oid"]=>
- string(24) "586c18d86118fd6c9012dec1"
- }
- [11]=>
- object(MongoDB\BSON\Timestamp)#%d (%d) {
- ["increment"]=>
- string(4) "1234"
- ["timestamp"]=>
- string(4) "5678"
- }
- [12]=>
- object(MongoDB\BSON\UTCDateTime)#%d (%d) {
- ["milliseconds"]=>
- string(13) "1483479256924"
- }
-}
-===DONE===
diff --git a/mongodb-1.13.0/CONTRIBUTING.md b/mongodb-1.13.0/CONTRIBUTING.md
new file mode 100644
index 00000000..9063a665
--- /dev/null
+++ b/mongodb-1.13.0/CONTRIBUTING.md
@@ -0,0 +1,467 @@
+# Contributing to the PHP Driver for MongoDB
+
+## Building from Source
+
+Developers who would like to contribute to the driver will need to build it from
+source. The repository may be initialized with:
+
+```
+$ git clone https://github.com/mongodb/mongo-php-driver.git
+$ cd mongo-php-driver
+$ git submodule update --init
+```
+
+The following script may be used to build the driver:
+
+```
+#!/bin/sh
+
+phpize > /dev/null && \
+./configure --enable-mongodb-developer-flags > /dev/null && \
+make clean > /dev/null && make all > /dev/null && make install
+```
+
+## Testing
+
+The extension's test use the PHPT format from PHP internals. This format is
+documented in the following links:
+
+ * [Introduction to PHPT Files](https://qa.php.net/write-test.php)
+ * [PHPT - Test File Layout](https://qa.php.net/phpt_details.php)
+
+Generally, most tests will be based on the following template:
+
+```
+--TEST--
+Description of API or JIRA issue being tested
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php /* One or more skip functions */ ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+// Test code
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+===DONE===
+```
+
+The `basic-skipif.inc` and `basic.inc` files contain utility functions for the
+`SKIPIF` and `FILE` sections, respectively. If those functions are not needed
+(e.g. skip logic only depends on checking the `PHP_INT_SIZE` constant), the test
+should not include the file. When it doubt, keep it simple.
+
+### Best Practices for `SKIPIF`
+
+The [`skipif.php`](tests/utils/skipif.php) file defines various helper functions
+for use within a test's [`SKIPIF`](https://qa.php.net/phpt_details.php#skipif_section)
+section. When multiple functions are used in a single `SKIPIF` section, they
+should be logically ordered:
+
+ * Any PHP environment requirements should be checked first. For example, if a
+ test requires a 64-bit architecture, start by checking `PHP_INT_SIZE` before
+ anything else.
+ * Any extension build requirements (e.g. `skip_if_not_libmongoc_crypto()`) or
+ test environment requirements (e.g. `skip_if_auth()`) should then be checked.
+ These functions only examine local information, such as `phpinfo()` output or
+ the structure of the `URI` constant, and do not interact with a remote
+ MongoDB server.
+ * Any remote server requirements should then be checked. A general integration
+ test that requires any type of remote server to be accessible might use
+ `skip_if_not_live()` while a test requiring a replica set would prefer
+ `skip_if_not_replica_set()`.
+ * After requiring a remote server to be accessible (optionally with a specific
+ type), you can enforce requirements about that server. This includes checking
+ its server version, storage engine, availability of test commands, etc.
+ * Finally, use `skip_if_not_clean()` if needed to ensure that the collection(s)
+ under test are dropped before the test runs.
+
+As a rule of thumb, your `SKIPIF` logic should be written to allow the test to
+run in as many environments as possible. To paraphrase the
+[robustness principal](https://en.wikipedia.org/wiki/Robustness_principle):
+
+> Be conservative in what/how you test, and liberal in what environment you require
+
+Consider that a well-crafted `EXPECTF` section may allow a `SKIPIF` section to
+be less restrictive.
+
+### Environment Variables
+
+The test suite references the following environment variables:
+
+ * `MONGODB_URI`: Connection string. Defaults to `mongodb://127.0.0.1/`, which
+ assumes a MongoDB server is listening localhost port 27017.
+ * `MONGO_ORCHESTRATION_URI`: API endpoint for Mongo Orchestration. Defaults to
+ `http://localhost:8889/v1`. This is only used by a few tests that start
+ temporary servers, and those tests will be skipped if Mongo Orchestration is
+ inaccessible.
+ * `MONGODB_DATABASE`: Default database to use in tests. Defaults to `phongo`.
+ * `SSL_DIR`: Path to directory containing certificate files. On Evergreen, this
+ will be set to the
+ [.evergreen/x509gen](https://github.com/mongodb-labs/drivers-evergreen-tools/tree/master/.evergreen/x509gen)
+ directory within
+ [drivers-evergreen-tools](https://github.com/mongodb-labs/drivers-evergreen-tools).
+ If undefined or inaccessible, tests requiring certificates will be skipped.
+ * `API_VERSION`: If defined, this value will be used to construct a
+ [`MongoDB\Driver\ServerApi`](https://www.php.net/manual/en/mongodb-driver-serverapi.construct.php),
+ which will then be specified as the `serverApi` driver option for
+ [`MongoDB\Driver\Manager`](https://www.php.net/manual/en/class.mongodb-driver-manager.php)
+ objects created by the test suite.
+
+### Mongo Orchestration
+
+[Mongo Orchestration](https://github.com/10gen/mongo-orchestration) is an HTTP
+server that provides a REST API for managing MongoDB servers and clusters.
+Evergreen CI and GitHub Actions use configurations provided by the
+[drivers-evergreen-tools](https://github.com/mongodb-labs/drivers-evergreen-tools)
+repository. These configurations are loaded by Mongo Orchestration, which then
+provides a connection string to assign to `MONGODB_URI` and run the test suite.
+Additionally, some tests start temporary servers and interact directly with
+Mongo Orchestration (via `MONGO_ORCHESTRATION_URI`).
+
+For local development, running Mongo Orchestration is not required and it is
+generally sufficient to test against a single-node replica set.
+
+## Updating libmongoc, libbson, and libmongocrypt
+
+The PHP driver can use either system libraries or bundled versions of
+libmongoc, libbson, and libmongocrypt. If a new version of either library is
+available, the submodule and build configuration will need to be updated to
+reflect the new sources and/or package version.
+
+### Updating libmongoc and libbson
+
+#### Update libmongoc submodule
+
+```
+$ cd src/libmongoc
+$ git fetch
+$ git checkout 1.20.0
+```
+
+During development, it may be necessary to temporarily point the libmongoc
+submodule to a commit on the developer's fork of libmongoc. For instance, the
+developer may be working on a PHP driver feature that depends on an unmerged
+pull request to libmongoc. In this case, `git remote add` can be used to add
+the fork before fetching and checking out the target commit. Additionally, the
+submodule path in
+[`.gitmodules`](https://github.com/mongodb/mongo-php-driver/blob/master/.gitmodules)
+must also be updated to refer to the fork.
+
+#### Ensure libmongoc version information is correct
+
+The build process for Autotools and Windows rely on
+`src/LIBMONGOC_VERSION_CURRENT` to infer version information for libmongoc and
+libbson. This file can be regenerated using the following Makefile target:
+
+```
+$ make libmongoc-version-current
+```
+
+Alternatively, the `build/calc_release_version.py` script in libmongoc can be
+executed directly.
+
+Note: If the libmongoc submodule points to a non-release, non-master branch, the
+script may fail to correctly detect the version. This issue is being tracked in
+[CDRIVER-3315](https://jira.mongodb.org/browse/CDRIVER-3315) and can be safely
+ignored since this should only happen during development (any PHP driver release
+should point to a tagged libmongoc release).
+
+#### Update sources in build configurations
+
+The Autotools and Windows build configurations (`config.m4` and `config.w32`,
+respectively) define several variables (e.g. `PHP_MONGODB_MONGOC_SOURCES`) that
+collectively enumerate all of the the sources within the libmongoc submodule to
+include in a bundled build.
+
+These variables should each have a shell command in a preceding comment, which
+should be run to regenerate that particular list of source files. Each command
+may be run manually or `scripts/update-submodule-sources.php` may be used to
+update all variables. In the event that either libmongoc or libbson introduce a
+new source directory, that will need to be manually added (follow prior art).
+
+#### Update package dependencies
+
+The Autotools configuration additionally includes some `pkg-config` commands for
+using libmongoc and libbson as system libraries (in lieu of a bundled build).
+When bumping the libmongoc version, be sure to update the version check _and_
+error message in the `pkg-config` blocks for both libmongoc and libbson.
+
+For example, the following lines might be updated for libmongoc:
+
+```
+if $PKG_CONFIG libmongoc-1.0 --atleast-version 1.20.0; then
+
+...
+
+AC_MSG_ERROR(system libmongoc must be upgraded to version >= 1.20.0)
+```
+
+#### Update tested versions in Evergreen configuration
+
+Evergreen tests against multiple versions of libmongoc. When updating to a newer
+libmongoc version, make sure to update the `libmongoc-version` build axis in
+`.evergreen/config.yml`. In general, we test against two additional versions of
+libmongoc:
+
+- The upcoming patch release of the current libmongoc minor version (e.g. the
+ `r1.x` branch)
+- The upcoming minor release of libmongoc (e.g. the `master` branch)
+
+#### Update sources in PECL package generation script
+
+If either libmongoc or libbson introduce a new source directory, that may also
+require updating the glob patterns in the `bin/prep-release.php` script to
+ensure new source files will be included in any generated PECL package.
+
+#### Test and commit your changes
+
+Verify that the upgrade was successful by ensuring that the driver can compile
+using both the bundled sources and system libraries for libmongoc and libbson,
+and by ensuring that the test suite passes. Once done, commit the changes to all
+of the above files/paths. For example:
+
+```
+$ git commit -m "Bump libmongoc to 1.20.0" config.m4 config.w32 src/libmongoc src/LIBMONGOC_VERSION_CURRENT
+```
+
+### Updating libmongocrypt
+
+To update libmongocrypt, the steps are similar to the above:
+
+```
+$ cd src/libmongocrypt
+$ git fetch
+$ git checkout 1.3.0
+$ make libmongocrypt-version-current
+```
+
+Package dependencies in `config.m4` must also be updated (either manually or
+with `scripts/update-submodule-sources.php`), as do the sources in the PECL
+generation script.
+
+## Releasing
+
+The follow steps outline the release process for a maintenance branch (e.g.
+releasing the `vX.Y` branch as X.Y.Z).
+
+### Ensure PHP version compatibility
+
+Ensure that the library test suite completes on supported versions of PHP.
+
+### Ensure Windows compatibility
+
+PECL will create Windows DLLs for new releases; however, you must ensure that
+the extension successfully builds on Windows before releasing. Windows builds
+are tested by [AppVeyor](.appveyor.yml).
+
+See the [internals wiki](https://wiki.php.net/internals/windows/stepbystepbuild)
+for more information.
+
+### Transition JIRA issues and version
+
+All issues associated with the release version should be in the "Closed" state
+and have a resolution of "Fixed". Issues with other resolutions (e.g.
+"Duplicate", "Works as Designed") should be removed from the release version so
+that they do not appear in the release notes.
+
+Check the corresponding ".x" fix version to see if it contains any issues that
+are resolved as "Fixed" and should be included in this release version.
+
+Update the version's release date and status from the
+[Manage Versions](https://jira.mongodb.org/plugins/servlet/project-config/PHPC/versions)
+page.
+
+### Update version info
+
+The PHP driver uses [semantic versioning](http://semver.org/). Do not break
+backwards compatibility in a non-major release or your users will kill you.
+
+Before proceeding, ensure that the `master` branch is up-to-date with all code
+changes in this maintenance branch. This is important because we will later
+merge the ensuing release commits up to master with `--strategy=ours`, which
+will ignore changes from the merged commits.
+
+Update the version and stability constants in `phongo_version.h`. This should
+entail removing the version's "-dev" suffix, changing the stability to
+"stable", and increasing the last digit for `PHP_MONGO_VERSION_DESC`:
+
+```
+#define PHP_MONGODB_VERSION "1.1.8-dev"
+#define PHP_MONGODB_STABILITY "devel"
+#define PHP_MONGODB_VERSION_DESC 1,1,8,0
+```
+
+The above would be changed to:
+
+```
+#define PHP_MONGODB_VERSION "1.1.8"
+#define PHP_MONGODB_STABILITY "stable"
+#define PHP_MONGODB_VERSION_DESC 1,1,8,1
+```
+
+The Makefile targets for creating the PECL package depend on these constants, so
+you must rebuild the extension after updating `phongo_version.h`.
+
+> **Note:** If this is an alpha or beta release, the version string should
+> include the X.Y.Z version followed by the stability and an increment. For
+> instance, the first beta release in the 1.4.0 series would be "1.4.0beta1".
+> Alpha and beta releases use "alpha" and "beta" stability strings,
+> respectively. Release candidates (e.g. "1.4.0RC1") also use "beta" stability.
+> See [Documenting release stability and API stability](https://pear.php.net/manual/en/guide.developers.package2.stability.php)
+> for more information. For each change to the suffixes of
+> `PHP_MONGODB_VERSION`, increment the last digit of
+> `PHP_MONGODB_VERSION_DESC`.
+
+### Build PECL package
+
+Create the PECL package description file with `make package.xml`. This creates
+a `package.xml` file from a template. Version, author, and file information will
+be filled in, but release notes must be copied manually from JIRA.
+
+After copying release notes, use `make package` to create the package file (e.g.
+`mongodb-X.Y.Z.tgz`) and ensure that it can be successfully installed:
+
+```
+$ pecl install -f mongodb-X.Y.Z.tgz
+```
+
+### Commit version update and release notes
+
+Commit the modified `phongo_version.h` file as "Package X.Y.Z"
+
+```
+$ git add phongo_version.h
+$ git commit -m "Package X.Y.Z"
+```
+
+### Tag release
+
+The previous commit will be the target for our release tag:
+
+```
+$ git tag -a -m "Release X.Y.Z" X.Y.Z
+```
+
+### Update version info back to dev
+
+After tagging, the version and stability constants in `phongo_version.h` should be
+updated back to development status.
+
+```
+#define PHP_MONGODB_VERSION "1.1.8"
+#define PHP_MONGODB_STABILITY "stable"
+#define PHP_MONGODB_VERSION_DESC 1,1,8,1
+```
+
+The above would be changed to:
+
+```
+#define PHP_MONGODB_VERSION "1.1.9-dev"
+#define PHP_MONGODB_STABILITY "devel"
+#define PHP_MONGODB_VERSION_DESC 1,1,9,0
+```
+
+Commit this change:
+
+```
+$ git commit -m "Back to -dev" phongo_version.h
+```
+
+> **Note:** If this is an alpha, beta, or RC release, the version string should
+> increment the stability sequence instead of the patch version. For example,
+> if the constants were originally "1.4.0-dev" and "devel" and then changed to
+> "1.4.0beta1" and "beta" for the first beta release, this step would see them
+> ultimately changed to "1.4.0beta2-dev" and "devel".
+
+### Push commits and tags
+
+```
+$ git push
+$ git push --tags
+```
+
+### Release PECL package
+
+The PECL package may be published via the
+[Release Upload](https://pecl.php.net/release-upload.php) form. You will have
+one chance to confirm the package information after uploading.
+
+### Merge the maintenance branch up to master
+
+```
+$ git checkout master
+$ git merge vX.Y --strategy=ours
+$ git push
+```
+
+The `--strategy=ours` option ensures that all changes from the merged commits
+will be ignored.
+
+### Publish release notes
+
+The following template should be used for creating GitHub release notes via
+[this form](https://github.com/mongodb/mongo-php-driver/releases/new). The PECL
+package may also be attached to the release notes.
+
+```
+The PHP team is happy to announce that version X.Y.Z of the [mongodb](https://pecl.php.net/package/mongodb) PHP extension is now available on PECL.
+
+**Release Highlights**
+
+<one or more paragraphs describing important changes in this release>
+
+A complete list of resolved issues in this release may be found at:
+$JIRA_URL
+
+**Documentation**
+
+Documentation is available on PHP.net:
+https://www.php.net/set.mongodb
+
+**Installation**
+
+You can either download and install the source manually, or you can install the extension with:
+
+ pecl install mongodb-X.Y.Z
+
+or update with:
+
+ pecl upgrade mongodb-X.Y.Z
+
+Windows binaries are available on PECL:
+https://pecl.php.net/package/mongodb
+```
+
+> **Note:** If this is an alpha or beta release, the installation examples
+> should refer to the exact version (e.g. "mongodb-1.8.0beta2"). This is necessary
+> because PECL prioritizes recent, stable releases over any stability preferences
+> (e.g. "mongodb-beta").
+
+The URL for the list of resolved JIRA issues will need to be updated with each
+release. You may obtain the list from
+[this form](https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=12484).
+
+If commits from community contributors were included in this release, append the
+following section:
+
+```
+**Thanks**
+
+Thanks for our community contributors for X.Y.Z:
+
+ * [$CONTRIBUTOR_NAME](https://github.com/$GITHUB_USERNAME)
+```
+
+Release announcements should also be posted in the [MongoDB Product & Driver Announcements: Driver Releases](https://www.mongodb.com/community/forums/tags/c/announcements/driver-releases/110/php) forum and shared on Twitter.
+
+### Update compatibility tables in MongoDB docs
+
+For minor releases, create a DOCSP ticket indicating whether there are changes to MongoDB Server or PHP version
+compatibility. The [compatibility tables](https://docs.mongodb.com/drivers/driver-compatibility-reference#php-driver-compatibility)
+in the MongoDB documentation must be updated to account for new releases. Make sure to update both MongoDB and Language
+compatibility tables, as shown in [this pull request](https://github.com/mongodb/docs-ecosystem/pull/642).
diff --git a/mongodb-1.12.0/CREDITS b/mongodb-1.13.0/CREDITS
similarity index 100%
rename from mongodb-1.12.0/CREDITS
rename to mongodb-1.13.0/CREDITS
diff --git a/mongodb-1.12.0/LICENSE b/mongodb-1.13.0/LICENSE
similarity index 100%
rename from mongodb-1.12.0/LICENSE
rename to mongodb-1.13.0/LICENSE
diff --git a/mongodb-1.12.0/Makefile.frag b/mongodb-1.13.0/Makefile.frag
similarity index 100%
rename from mongodb-1.12.0/Makefile.frag
rename to mongodb-1.13.0/Makefile.frag
diff --git a/mongodb-1.12.0/README.md b/mongodb-1.13.0/README.md
similarity index 100%
rename from mongodb-1.12.0/README.md
rename to mongodb-1.13.0/README.md
diff --git a/mongodb-1.12.0/THIRD_PARTY_NOTICES b/mongodb-1.13.0/THIRD_PARTY_NOTICES
similarity index 100%
rename from mongodb-1.12.0/THIRD_PARTY_NOTICES
rename to mongodb-1.13.0/THIRD_PARTY_NOTICES
diff --git a/mongodb-1.12.0/Vagrantfile b/mongodb-1.13.0/Vagrantfile
similarity index 100%
rename from mongodb-1.12.0/Vagrantfile
rename to mongodb-1.13.0/Vagrantfile
diff --git a/mongodb-1.13.0/config.m4 b/mongodb-1.13.0/config.m4
new file mode 100644
index 00000000..2a0e97a5
--- /dev/null
+++ b/mongodb-1.13.0/config.m4
@@ -0,0 +1,560 @@
+dnl config.m4 for extension mongodb
+PHP_ARG_ENABLE([mongodb],
+ [whether to enable MongoDB support],
+ [AS_HELP_STRING([--enable-mongodb],
+ [Enable MongoDB support])])
+
+if test "$PHP_MONGODB" != "no"; then
+ dnl Check PHP version is compatible with this extension
+ AC_MSG_CHECKING([PHP version])
+
+ PHP_MONGODB_PHP_VERSION=$PHP_VERSION
+ PHP_MONGODB_PHP_VERSION_ID=$PHP_VERSION_ID
+
+ if test -z "$PHP_MONGODB_PHP_VERSION"; then
+ if test -z "$PHP_CONFIG"; then
+ AC_MSG_ERROR([php-config not found])
+ fi
+ PHP_MONGODB_PHP_VERSION=`${PHP_CONFIG} --version`
+ PHP_MONGODB_PHP_VERSION_ID=`echo "${PHP_MONGODB_PHP_VERSION}" | $AWK 'BEGIN { FS = "."; } { printf "%d", ([$]1 * 100 + [$]2) * 100 + [$]3;}'`
+ fi
+
+ AC_MSG_RESULT($PHP_MONGODB_PHP_VERSION)
+ if test "$PHP_MONGODB_PHP_VERSION_ID" -lt "70200"; then
+ AC_MSG_ERROR([not supported. Need a PHP version >= 7.2.0 (found $PHP_MONGODB_PHP_VERSION)])
+ fi
+
+ PHP_ARG_ENABLE([mongodb-developer-flags],
+ [whether to enable developer build flags],
+ [AS_HELP_STRING([--enable-mongodb-developer-flags],
+ [MongoDB: Enable developer flags [default=no]])],
+ [no],
+ [no])
+
+ if test "$PHP_MONGODB_DEVELOPER_FLAGS" = "yes"; then
+ dnl Warn about functions which might be candidates for format attributes
+ AX_CHECK_COMPILE_FLAG(-Wmissing-format-attribute, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wmissing-format-attribute" ,, -Werror)
+ dnl Avoid duplicating values for an enum
+ AX_CHECK_COMPILE_FLAG(-Wduplicate-enum, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wduplicate-enum" ,, -Werror)
+ dnl Warns on mismatches between #ifndef and #define header guards
+ AX_CHECK_COMPILE_FLAG(-Wheader-guard, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wheader-guard" ,, -Werror)
+ dnl logical not of a non-boolean expression
+ AX_CHECK_COMPILE_FLAG(-Wlogical-not-parentheses, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wlogical-not-parentheses" ,, -Werror)
+ dnl Warn about suspicious uses of logical operators in expressions
+ AX_CHECK_COMPILE_FLAG(-Wlogical-op, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wlogical-op" ,, -Werror)
+ dnl memory error detector.
+ dnl FIXME: -fsanitize=address,undefined for clang. The AX_CHECK_COMPILE_FLAG macro isn't happy about that string :(
+ AX_CHECK_COMPILE_FLAG(-fsanitize-address, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -fsanitize-address" ,, -Werror)
+ dnl Enable frame debugging
+ AX_CHECK_COMPILE_FLAG(-fno-omit-frame-pointer, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -fno-omit-frame-pointer" ,, -Werror)
+ dnl Make sure we don't optimize calls
+ AX_CHECK_COMPILE_FLAG(-fno-optimize-sibling-calls, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -fno-optimize-sibling-calls" ,, -Werror)
+ AX_CHECK_COMPILE_FLAG(-Wlogical-op-parentheses, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wlogical-op-parentheses" ,, -Werror)
+ AX_CHECK_COMPILE_FLAG(-Wpointer-bool-conversion, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wpointer-bool-conversion" ,, -Werror)
+ AX_CHECK_COMPILE_FLAG(-Wbool-conversion, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wbool-conversion" ,, -Werror)
+ AX_CHECK_COMPILE_FLAG(-Wloop-analysis, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wloop-analysis" ,, -Werror)
+ AX_CHECK_COMPILE_FLAG(-Wsizeof-array-argument, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wsizeof-array-argument" ,, -Werror)
+ AX_CHECK_COMPILE_FLAG(-Wstring-conversion, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wstring-conversion" ,, -Werror)
+ AX_CHECK_COMPILE_FLAG(-Wno-variadic-macros, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wno-variadic-macros" ,, -Werror)
+ AX_CHECK_COMPILE_FLAG(-Wno-sign-compare, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wno-sign-compare" ,, -Werror)
+ AX_CHECK_COMPILE_FLAG(-fstack-protector, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -fstack-protector" ,, -Werror)
+ AX_CHECK_COMPILE_FLAG(-fno-exceptions, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -fno-exceptions" ,, -Werror)
+ AX_CHECK_COMPILE_FLAG(-Wformat-security, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wformat-security" ,, -Werror)
+ AX_CHECK_COMPILE_FLAG(-Wformat-nonliteral, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wformat-nonliteral" ,, -Werror)
+ AX_CHECK_COMPILE_FLAG(-Winit-self, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Winit-self" ,, -Werror)
+ AX_CHECK_COMPILE_FLAG(-Wwrite-strings, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wwrite-strings" ,, -Werror)
+ AX_CHECK_COMPILE_FLAG(-Wenum-compare, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wenum-compare" ,, -Werror)
+ AX_CHECK_COMPILE_FLAG(-Wempty-body, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wempty-body" ,, -Werror)
+ AX_CHECK_COMPILE_FLAG(-Wparentheses, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wparentheses" ,, -Werror)
+ AX_CHECK_COMPILE_FLAG(-Wdeclaration-after-statement, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wdeclaration-after-statement" ,, -Werror)
+ AX_CHECK_COMPILE_FLAG(-Wmaybe-uninitialized, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wmaybe-uninitialized" ,, -Werror)
+ AX_CHECK_COMPILE_FLAG(-Wimplicit-fallthrough, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wimplicit-fallthrough" ,, -Werror)
+ AX_CHECK_COMPILE_FLAG(-Werror, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Werror" ,, -Werror)
+ AX_CHECK_COMPILE_FLAG(-Wextra, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wextra" ,, -Werror)
+ AX_CHECK_COMPILE_FLAG(-Wno-unused-parameter, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wno-unused-parameter" ,, -Werror)
+ AX_CHECK_COMPILE_FLAG(-Wno-unused-but-set-variable, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wno-unused-but-set-variable" ,, -Werror)
+ AX_CHECK_COMPILE_FLAG(-Wno-missing-field-initializers, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wno-missing-field-initializers",, -Werror)
+
+ MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS"
+ STD_CFLAGS="-g -O0 -Wall"
+ fi
+
+
+ PHP_ARG_ENABLE([mongodb-coverage],
+ [whether to enable code coverage],
+ [AS_HELP_STRING([--enable-mongodb-coverage],
+ [MongoDB: Enable developer code coverage information [default=no]])],
+ [no],
+ [no])
+
+ if test "$PHP_MONGODB_COVERAGE" = "yes"; then
+ if test "$ext_shared" != "yes"; then
+ AC_MSG_ERROR(code coverage is not supported for static builds)
+ fi
+
+ COVERAGE_CFLAGS="--coverage -g"
+ COVERAGE_LDFLAGS="--coverage"
+
+ MONGODB_SHARED_LIBADD="$MONGODB_SHARED_LIBADD $COVERAGE_LDFLAGS"
+ fi
+
+ PHP_MONGODB_CFLAGS="$STD_CFLAGS $MAINTAINER_CFLAGS $COVERAGE_CFLAGS"
+
+ PHP_MONGODB_SOURCES="\
+ php_phongo.c \
+ src/phongo_apm.c \
+ src/phongo_bson.c \
+ src/phongo_bson_encode.c \
+ src/phongo_client.c \
+ src/phongo_compat.c \
+ src/phongo_error.c \
+ src/phongo_execute.c \
+ src/phongo_ini.c \
+ src/phongo_util.c \
+ src/BSON/Binary.c \
+ src/BSON/BinaryInterface.c \
+ src/BSON/DBPointer.c \
+ src/BSON/Decimal128.c \
+ src/BSON/Decimal128Interface.c \
+ src/BSON/Int64.c \
+ src/BSON/Javascript.c \
+ src/BSON/JavascriptInterface.c \
+ src/BSON/MaxKey.c \
+ src/BSON/MaxKeyInterface.c \
+ src/BSON/MinKey.c \
+ src/BSON/MinKeyInterface.c \
+ src/BSON/ObjectId.c \
+ src/BSON/ObjectIdInterface.c \
+ src/BSON/Persistable.c \
+ src/BSON/Regex.c \
+ src/BSON/RegexInterface.c \
+ src/BSON/Serializable.c \
+ src/BSON/Symbol.c \
+ src/BSON/Timestamp.c \
+ src/BSON/TimestampInterface.c \
+ src/BSON/Type.c \
+ src/BSON/Undefined.c \
+ src/BSON/Unserializable.c \
+ src/BSON/UTCDateTime.c \
+ src/BSON/UTCDateTimeInterface.c \
+ src/BSON/functions.c \
+ src/MongoDB/BulkWrite.c \
+ src/MongoDB/ClientEncryption.c \
+ src/MongoDB/Command.c \
+ src/MongoDB/Cursor.c \
+ src/MongoDB/CursorId.c \
+ src/MongoDB/CursorInterface.c \
+ src/MongoDB/Manager.c \
+ src/MongoDB/Query.c \
+ src/MongoDB/ReadConcern.c \
+ src/MongoDB/ReadPreference.c \
+ src/MongoDB/Server.c \
+ src/MongoDB/ServerApi.c \
+ src/MongoDB/ServerDescription.c \
+ src/MongoDB/Session.c \
+ src/MongoDB/TopologyDescription.c \
+ src/MongoDB/WriteConcern.c \
+ src/MongoDB/WriteConcernError.c \
+ src/MongoDB/WriteError.c \
+ src/MongoDB/WriteResult.c \
+ src/MongoDB/Exception/AuthenticationException.c \
+ src/MongoDB/Exception/BulkWriteException.c \
+ src/MongoDB/Exception/CommandException.c \
+ src/MongoDB/Exception/ConnectionException.c \
+ src/MongoDB/Exception/ConnectionTimeoutException.c \
+ src/MongoDB/Exception/EncryptionException.c \
+ src/MongoDB/Exception/Exception.c \
+ src/MongoDB/Exception/ExecutionTimeoutException.c \
+ src/MongoDB/Exception/InvalidArgumentException.c \
+ src/MongoDB/Exception/LogicException.c \
+ src/MongoDB/Exception/RuntimeException.c \
+ src/MongoDB/Exception/ServerException.c \
+ src/MongoDB/Exception/SSLConnectionException.c \
+ src/MongoDB/Exception/UnexpectedValueException.c \
+ src/MongoDB/Exception/WriteException.c \
+ src/MongoDB/Monitoring/CommandFailedEvent.c \
+ src/MongoDB/Monitoring/CommandStartedEvent.c \
+ src/MongoDB/Monitoring/CommandSubscriber.c \
+ src/MongoDB/Monitoring/CommandSucceededEvent.c \
+ src/MongoDB/Monitoring/SDAMSubscriber.c \
+ src/MongoDB/Monitoring/Subscriber.c \
+ src/MongoDB/Monitoring/ServerChangedEvent.c \
+ src/MongoDB/Monitoring/ServerClosedEvent.c \
+ src/MongoDB/Monitoring/ServerHeartbeatFailedEvent.c \
+ src/MongoDB/Monitoring/ServerHeartbeatStartedEvent.c \
+ src/MongoDB/Monitoring/ServerHeartbeatSucceededEvent.c \
+ src/MongoDB/Monitoring/ServerOpeningEvent.c \
+ src/MongoDB/Monitoring/TopologyChangedEvent.c \
+ src/MongoDB/Monitoring/TopologyClosedEvent.c \
+ src/MongoDB/Monitoring/TopologyOpeningEvent.c \
+ src/MongoDB/Monitoring/functions.c \
+ "
+
+ PHP_ARG_WITH([mongodb-system-libs],
+ [whether to compile against system libraries instead of bundled],
+ [AS_HELP_STRING([--with-mongodb-system-libs=@<:@yes/no@:>@],
+ [MongoDB: Use system libraries for libbson, libmongoc, and libmongocrypt [default=no]])],
+ [no],
+ [no])
+ PHP_ARG_WITH([libbson],
+ [whether to use system libbson],
+ [AS_HELP_STRING([--with-libbson=@<:@yes/no@:>@],
+ [MongoDB: Use system libbson [default=no]])],
+ [no],
+ [no])
+ PHP_ARG_WITH([libmongoc],
+ [whether to use system libmongoc],
+ [AS_HELP_STRING([--with-libmongoc=@<:@yes/no@:>@],
+ [MongoDB: Use system libmongoc [default=no]])],
+ [no],
+ [no])
+ PHP_ARG_WITH([mongodb-client-side-encryption],
+ [whether to enable client-side encryption],
+ [AS_HELP_STRING([--with-mongodb-client-side-encryption=@<:@auto/yes/no@:>@],
+ [MongoDB: Enable client-side encryption [default=auto]])],
+ [auto],
+ [no])
+
+ if test "$PHP_LIBBSON" != "no"; then
+ AC_MSG_WARN(Using --with-libbson is deprecated and will be removed in a future version. Please use --with-system-libs instead)
+
+ if test "$PHP_LIBMONGOC" = "no"; then
+ AC_MSG_ERROR(Cannot use system libbson and bundled libmongoc)
+ fi
+
+ PHP_MONGODB_SYSTEM_LIBS="yes"
+ fi
+
+ if test "$PHP_LIBMONGOC" != "no"; then
+ AC_MSG_WARN(Using --with-libmongoc is deprecated and will be removed in a future version. Please use --with-system-libs instead)
+
+ if test "$PHP_LIBBSON" = "no"; then
+ AC_MSG_ERROR(Cannot use system libmongoc and bundled libbson)
+ fi
+
+ PHP_MONGODB_SYSTEM_LIBS="yes"
+ fi
+
+ PHP_MONGODB_BSON_VERSION_STRING="None"
+ PHP_MONGODB_MONGOC_VERSION_STRING="None"
+ PHP_MONGODB_MONGOCRYPT_VERSION_STRING="None"
+
+ if test "$PHP_MONGODB_SYSTEM_LIBS" != "no"; then
+ AC_PATH_PROG(PKG_CONFIG, pkg-config, no)
+ AC_MSG_CHECKING(for libbson)
+ if test -x "$PKG_CONFIG" && $PKG_CONFIG --exists libbson-1.0; then
+ if $PKG_CONFIG libbson-1.0 --atleast-version 1.21.1; then
+ PHP_MONGODB_BSON_CFLAGS=`$PKG_CONFIG libbson-1.0 --cflags`
+ PHP_MONGODB_BSON_LIBS=`$PKG_CONFIG libbson-1.0 --libs`
+ PHP_MONGODB_BSON_VERSION=`$PKG_CONFIG libbson-1.0 --modversion`
+ PHP_MONGODB_BSON_VERSION_STRING="System ($PHP_MONGODB_BSON_VERSION)"
+ AC_MSG_RESULT(version $PHP_MONGODB_BSON_VERSION found)
+ else
+ AC_MSG_ERROR(system libbson must be upgraded to version >= 1.21.1)
+ fi
+ else
+ AC_MSG_ERROR(pkgconfig and libbson must be installed)
+ fi
+ PHP_MONGODB_CFLAGS="$PHP_MONGODB_CFLAGS $PHP_MONGODB_BSON_CFLAGS"
+ PHP_EVAL_LIBLINE($PHP_MONGODB_BSON_LIBS, MONGODB_SHARED_LIBADD)
+ AC_DEFINE(HAVE_SYSTEM_LIBBSON, 1, [Use system libbson])
+
+ AC_MSG_CHECKING(for libmongoc)
+ if test -x "$PKG_CONFIG" && $PKG_CONFIG --exists libmongoc-1.0; then
+ if $PKG_CONFIG libmongoc-1.0 --atleast-version 1.21.1; then
+ PHP_MONGODB_MONGOC_CFLAGS=`$PKG_CONFIG libmongoc-1.0 --cflags`
+ PHP_MONGODB_MONGOC_LIBS=`$PKG_CONFIG libmongoc-1.0 --libs`
+ PHP_MONGODB_MONGOC_VERSION=`$PKG_CONFIG libmongoc-1.0 --modversion`
+ PHP_MONGODB_MONGOC_VERSION_STRING="System ($PHP_MONGODB_MONGOC_VERSION)"
+ AC_MSG_RESULT(version $PHP_MONGODB_MONGOC_VERSION found)
+ else
+ AC_MSG_ERROR(system libmongoc must be upgraded to version >= 1.21.1)
+ fi
+ else
+ AC_MSG_ERROR(pkgconfig and libmongoc must be installed)
+ fi
+ PHP_MONGODB_CFLAGS="$PHP_MONGODB_CFLAGS $PHP_MONGODB_MONGOC_CFLAGS"
+ PHP_EVAL_LIBLINE($PHP_MONGODB_MONGOC_LIBS, MONGODB_SHARED_LIBADD)
+ AC_DEFINE(HAVE_SYSTEM_LIBMONGOC, 1, [Use system libmongoc])
+
+ if test "$PHP_MONGODB_CLIENT_SIDE_ENCRYPTION" != "no"; then
+ AC_MSG_CHECKING(for libmongocrypt)
+
+ if test -x "$PKG_CONFIG" && $PKG_CONFIG --exists libmongocrypt; then
+ if $PKG_CONFIG libmongocrypt --atleast-version 1.3.2; then
+ PHP_MONGODB_MONGOCRYPT_CFLAGS=`$PKG_CONFIG libmongocrypt --cflags`
+ PHP_MONGODB_MONGOCRYPT_LIBS=`$PKG_CONFIG libmongocrypt --libs`
+ PHP_MONGODB_MONGOCRYPT_VERSION=`$PKG_CONFIG libmongocrypt --modversion`
+ PHP_MONGODB_MONGOCRYPT_VERSION_STRING="System ($PHP_MONGODB_MONGOCRYPT_VERSION)"
+ AC_MSG_RESULT(version $PHP_MONGODB_MONGOCRYPT_VERSION found)
+
+ PHP_MONGODB_CFLAGS="$PHP_MONGODB_CFLAGS $PHP_MONGODB_MONGOCRYPT_CFLAGS"
+ PHP_EVAL_LIBLINE($PHP_MONGODB_MONGOCRYPT_LIBS, MONGODB_SHARED_LIBADD)
+ AC_DEFINE(HAVE_SYSTEM_LIBMONGOCRYPT, 1, [Use system libmongocrypt])
+ elif test "$PHP_MONGODB_CLIENT_SIDE_ENCRYPTION" = "yes"; then
+ AC_MSG_ERROR(system libmongocrypt must be upgraded to version >= 1.3.2)
+ else
+ AC_MSG_RESULT(found an older version, compiling without client-side encryption)
+ fi
+ else
+ if test "$PHP_MONGODB_CLIENT_SIDE_ENCRYPTION" = "yes"; then
+ AC_MSG_ERROR(pkgconfig and libmongocrypt must be installed)
+ else
+ AC_MSG_RESULT(not found, compiling without client-side encryption)
+ fi
+ fi
+ fi
+ fi
+
+ if test "$PHP_MONGODB_SYSTEM_LIBS" = "no"; then
+ PHP_MONGODB_BUNDLED_CFLAGS="$STD_CFLAGS -DBSON_COMPILATION -DMONGOC_COMPILATION"
+ dnl TODO: MONGOCRYPT-219 makes the -std argument obsolete
+ PHP_MONGODB_LIBMONGOCRYPT_CFLAGS="-DKMS_MSG_STATIC -DMLIB_USER -std=gnu99"
+ PHP_MONGODB_ZLIB_CFLAGS=""
+
+ dnl M4 doesn't know if we're building statically or as a shared module, so
+ dnl attempt to include both paths while ignoring errors. If neither path
+ dnl exists, report an error during configure (this is later than M4 parsing
+ dnl during phpize but better than nothing).
+ m4_pushdef([_include],[
+ dnl TODO: Fix this for PECL install (PHPC-1218)
+ dnl if test ! \( -f "$1" -o -f "ext/mongodb/$1" \); then
+ dnl AC_MSG_ERROR([m4 could not include $1: No such file or directory])
+ dnl fi
+ m4_builtin([sinclude],[$1])
+ m4_builtin([sinclude],[ext/mongodb/][$1])
+ ])
+
+ dnl Avoid using AC_CONFIG_MACRO_DIR, which might conflict with PHP
+ _include([scripts/autotools/m4/as_var_copy.m4])
+ _include([scripts/autotools/m4/ax_check_compile_flag.m4])
+ _include([scripts/autotools/m4/ax_prototype.m4])
+ _include([scripts/autotools/m4/ax_pthread.m4])
+ _include([scripts/autotools/m4/php_mongodb.m4])
+ _include([scripts/autotools/m4/pkg.m4])
+
+ _include([scripts/autotools/CheckCompiler.m4])
+ _include([scripts/autotools/CheckHost.m4])
+
+ _include([scripts/autotools/libbson/CheckAtomics.m4])
+ _include([scripts/autotools/libbson/CheckHeaders.m4])
+ _include([scripts/autotools/libbson/Endian.m4])
+ _include([scripts/autotools/libbson/FindDependencies.m4])
+ _include([scripts/autotools/libbson/Versions.m4])
+
+ _include([scripts/autotools/libmongoc/CheckCompression.m4])
+ _include([scripts/autotools/libmongoc/CheckResolv.m4])
+ _include([scripts/autotools/libmongoc/CheckSasl.m4])
+ _include([scripts/autotools/libmongoc/CheckSSL.m4])
+ _include([scripts/autotools/libmongoc/CheckICU.m4])
+ _include([scripts/autotools/libmongoc/FindDependencies.m4])
+ _include([scripts/autotools/libmongoc/PlatformFlags.m4])
+ _include([scripts/autotools/libmongoc/Versions.m4])
+ _include([scripts/autotools/libmongoc/WeakSymbols.m4])
+
+ dnl This include modifies the value of $PHP_MONGODB_CLIENT_SIDE_ENCRYPTION to "yes"
+ dnl or "no" depending on whether dependencies for libmongocrypt are fulfilled
+ _include([scripts/autotools/libmongocrypt/CheckSSL.m4])
+ _include([scripts/autotools/libmongocrypt/Endian.m4])
+ _include([scripts/autotools/libmongocrypt/Version.m4])
+
+ PHP_MONGODB_BSON_VERSION_STRING="Bundled ($BSON_VERSION)"
+ PHP_MONGODB_MONGOC_VERSION_STRING="Bundled ($MONGOC_VERSION)"
+ PHP_MONGODB_MONGOCRYPT_VERSION_STRING="Bundled ($MONGOCRYPT_BUILD_VERSION)"
+
+ m4_popdef([_include])
+
+ AC_SUBST(BSON_EXTRA_ALIGN, 0)
+ AC_SUBST(BSON_OS, 1)
+
+ AC_SUBST(MONGOC_NO_AUTOMATIC_GLOBALS, 1)
+ AC_SUBST(MONGOC_ENABLE_MONGODB_AWS_AUTH, 0)
+ AC_SUBST(MONGOC_ENABLE_RDTSCP, 0)
+ AC_SUBST(MONGOC_ENABLE_SHM_COUNTERS, 0)
+ AC_SUBST(MONGOC_TRACE, 1)
+
+ dnl Assignments for metadata handshake. Leave CFLAGS/LDFLAGS empty as they
+ dnl would likely cause platform info (PHP version) to be truncated. We can
+ dnl consider restoring CFLAGS/LDFLAGS once CDRIVER-3134 is resolved.
+ AC_SUBST(MONGOC_CC, [$CC])
+ AC_SUBST(MONGOC_USER_SET_CFLAGS, [])
+ AC_SUBST(MONGOC_USER_SET_LDFLAGS, [])
+
+ if test "$PHP_MONGODB_CLIENT_SIDE_ENCRYPTION" = "yes"; then
+ AC_SUBST(MONGOC_ENABLE_CLIENT_SIDE_ENCRYPTION, 1)
+ else
+ AC_SUBST(MONGOC_ENABLE_CLIENT_SIDE_ENCRYPTION, 0)
+ fi
+
+ if test "$PHP_MONGODB_DEVELOPER_FLAGS" = "yes"; then
+ AC_SUBST(MONGOC_ENABLE_DEBUG_ASSERTIONS, 1)
+ else
+ AC_SUBST(MONGOC_ENABLE_DEBUG_ASSERTIONS, 0)
+ fi
+
+ dnl On MacOS, use gcut from the coreutils brew package instead of cut
+ dnl Generated with: find src/libmongoc/src/common -name '*.c' -print0 | cut -sz -d / -f 5- | sort -dz | tr '\000' ' '
+ PHP_MONGODB_COMMON_SOURCES="common-b64.c common-md5.c common-thread.c"
+
+ dnl Generated with: find src/libmongoc/src/kms-message/src -maxdepth 1 -name '*.c' -print0 | cut -sz -d / -f 6- | sort -dz | tr '\000' ' '
+ PHP_MONGODB_KMS_MESSAGE_SOURCES="hexlify.c kms_b64.c kms_caller_identity_request.c kms_crypto_apple.c kms_crypto_libcrypto.c kms_crypto_none.c kms_crypto_windows.c kms_decrypt_request.c kms_encrypt_request.c kms_kv_list.c kms_message.c kms_port.c kms_request.c kms_request_opt.c kms_request_str.c kms_response.c kms_response_parser.c sort.c"
+
+ dnl Generated with: find src/libmongoc/src/libbson/src/bson -name '*.c' -print0 | cut -sz -d / -f 7- | sort -dz | tr '\000' ' '
+ PHP_MONGODB_BSON_SOURCES="bcon.c bson-atomic.c bson.c bson-clock.c bson-context.c bson-decimal128.c bson-error.c bson-iso8601.c bson-iter.c bson-json.c bson-keys.c bson-md5.c bson-memory.c bson-oid.c bson-reader.c bson-string.c bson-timegm.c bson-utf8.c bson-value.c bson-version-functions.c bson-writer.c"
+
+ dnl Generated with: find src/libmongoc/src/libbson/src/jsonsl -name '*.c' -print0 | cut -sz -d / -f 7- | sort -dz | tr '\000' ' '
+ PHP_MONGODB_JSONSL_SOURCES="jsonsl.c"
+
+ dnl Generated with: find src/libmongoc/src/libmongoc/src/mongoc -name '*.c' -print0 | cut -sz -d / -f 7- | sort -dz | tr '\000' ' '
+ PHP_MONGODB_MONGOC_SOURCES="mongoc-aggregate.c mongoc-apm.c mongoc-array.c mongoc-async.c mongoc-async-cmd.c mongoc-buffer.c mongoc-bulk-operation.c mongoc-change-stream.c mongoc-client.c mongoc-client-pool.c mongoc-client-session.c mongoc-client-side-encryption.c mongoc-cluster-aws.c mongoc-cluster.c mongoc-cluster-cyrus.c mongoc-cluster-sasl.c mongoc-cluster-sspi.c mongoc-cmd.c mongoc-collection.c mongoc-compression.c mongoc-counters.c mongoc-crypt.c mongoc-crypto.c mongoc-crypto-cng.c mongoc-crypto-common-crypto.c mongoc-crypto-openssl.c mongoc-cursor-array.c mongoc-cursor.c mongoc-cursor-change-stream.c mongoc-cursor-cmd.c mongoc-cursor-cmd-deprecated.c mongoc-cursor-find.c mongoc-cursor-find-cmd.c mongoc-cursor-find-opquery.c mongoc-cursor-legacy.c mongoc-cyrus.c mongoc-database.c mongoc-error.c mongoc-find-and-modify.c mongoc-generation-map.c mongoc-gridfs-bucket.c mongoc-gridfs-bucket-file.c mongoc-gridfs.c mongoc-gridfs-file.c mongoc-gridfs-file-list.c mongoc-gridfs-file-page.c mongoc-handshake.c mongoc-host-list.c mongoc-http.c mongoc-index.c mongoc-init.c mongoc-interrupt.c mongoc-libressl.c mongoc-linux-distro-scanner.c mongoc-list.c mongoc-log.c mongoc-matcher.c mongoc-matcher-op.c mongoc-memcmp.c mongoc-ocsp-cache.c mongoc-openssl.c mongoc-optional.c mongoc-opts.c mongoc-opts-helpers.c mongoc-queue.c mongoc-rand-cng.c mongoc-rand-common-crypto.c mongoc-rand-openssl.c mongoc-read-concern.c mongoc-read-prefs.c mongoc-rpc.c mongoc-sasl.c mongoc-scram.c mongoc-secure-channel.c mongoc-secure-transport.c mongoc-server-api.c mongoc-server-description.c mongoc-server-monitor.c mongoc-server-stream.c mongoc-set.c mongoc-shared.c mongoc-socket.c mongoc-ssl.c mongoc-sspi.c mongoc-stream-buffered.c mongoc-stream.c mongoc-stream-file.c mongoc-stream-gridfs.c mongoc-stream-gridfs-download.c mongoc-stream-gridfs-upload.c mongoc-stream-socket.c mongoc-stream-tls.c mongoc-stream-tls-libressl.c mongoc-stream-tls-openssl-bio.c mongoc-stream-tls-openssl.c mongoc-stream-tls-secure-channel.c mongoc-stream-tls-secure-transport.c mongoc-timeout.c mongoc-topology-background-monitoring.c mongoc-topology.c mongoc-topology-description-apm.c mongoc-topology-description.c mongoc-topology-scanner.c mongoc-ts-pool.c mongoc-uri.c mongoc-util.c mongoc-version-functions.c mongoc-write-command.c mongoc-write-command-legacy.c mongoc-write-concern.c"
+
+ dnl Generated with: find src/libmongoc/src/zlib-1.2.11 -maxdepth 1 -name '*.c' -print0 | cut -sz -d / -f 5- | sort -dz | tr '\000' ' '
+ PHP_MONGODB_ZLIB_SOURCES="adler32.c compress.c crc32.c deflate.c gzclose.c gzlib.c gzread.c gzwrite.c infback.c inffast.c inflate.c inftrees.c trees.c uncompr.c zutil.c"
+
+ PHP_MONGODB_ADD_SOURCES([src/libmongoc/src/common/], $PHP_MONGODB_COMMON_SOURCES, $PHP_MONGODB_BUNDLED_CFLAGS)
+ PHP_MONGODB_ADD_SOURCES([src/libmongoc/src/libbson/src/bson/], $PHP_MONGODB_BSON_SOURCES, $PHP_MONGODB_BUNDLED_CFLAGS)
+ PHP_MONGODB_ADD_SOURCES([src/libmongoc/src/libbson/src/jsonsl/], $PHP_MONGODB_JSONSL_SOURCES, $PHP_MONGODB_BUNDLED_CFLAGS)
+ PHP_MONGODB_ADD_SOURCES([src/libmongoc/src/libmongoc/src/mongoc/], $PHP_MONGODB_MONGOC_SOURCES, $PHP_MONGODB_BUNDLED_CFLAGS)
+
+ PHP_MONGODB_ADD_INCLUDE([src/libmongoc/src/common/])
+ PHP_MONGODB_ADD_INCLUDE([src/libmongoc/src/libbson/src/])
+ PHP_MONGODB_ADD_INCLUDE([src/libmongoc/src/libbson/src/jsonsl/])
+ PHP_MONGODB_ADD_INCLUDE([src/libmongoc/src/libmongoc/src/])
+
+ PHP_MONGODB_ADD_BUILD_DIR([src/libmongoc/src/common/])
+ PHP_MONGODB_ADD_BUILD_DIR([src/libmongoc/src/libbson/src/bson/])
+ PHP_MONGODB_ADD_BUILD_DIR([src/libmongoc/src/libbson/src/jsonsl/])
+ PHP_MONGODB_ADD_BUILD_DIR([src/libmongoc/src/libmongoc/src/mongoc/])
+
+ dnl If compiling without libmongocrypt, use kms_message sources bundled with libmongoc.
+ dnl If compiling with libmongocrypt, kms_message bundled with libmongocrypt is used as it is most likely newer.
+ if test "$PHP_MONGODB_CLIENT_SIDE_ENCRYPTION" != "yes" && test "$PHP_MONGODB_SSL" != "no"; then
+ AC_SUBST(MONGOC_ENABLE_MONGODB_AWS_AUTH, 1)
+ PHP_MONGODB_ADD_SOURCES([src/libmongoc/src/kms-message/src/], $PHP_MONGODB_KMS_MESSAGE_SOURCES, $PHP_MONGODB_BUNDLED_CFLAGS)
+ PHP_MONGODB_ADD_INCLUDE([src/libmongoc/src/kms-message/src/])
+ PHP_MONGODB_ADD_BUILD_DIR([src/libmongoc/src/kms-message/src/])
+ fi
+
+ dnl TODO: Use $ext_srcdir if we can move this after PHP_NEW_EXTENSION
+ ac_config_dir=PHP_EXT_SRCDIR(mongodb)
+
+ AC_CONFIG_FILES([
+ ${ac_config_dir}/src/libmongoc/src/common/common-config.h
+ ${ac_config_dir}/src/libmongoc/src/libbson/src/bson/bson-config.h
+ ${ac_config_dir}/src/libmongoc/src/libbson/src/bson/bson-version.h
+ ${ac_config_dir}/src/libmongoc/src/libmongoc/src/mongoc/mongoc-config.h
+ ${ac_config_dir}/src/libmongoc/src/libmongoc/src/mongoc/mongoc-version.h
+ ])
+
+ if test "x$bundled_zlib" = "xyes"; then
+ PHP_MONGODB_ZLIB_CFLAGS="$PHP_MONGODB_BUNDLED_CFLAGS $PHP_MONGODB_ZLIB_CFLAGS"
+ PHP_MONGODB_ADD_SOURCES([src/libmongoc/src/zlib-1.2.11/], $PHP_MONGODB_ZLIB_SOURCES, $PHP_MONGODB_ZLIB_CFLAGS)
+ PHP_MONGODB_ADD_INCLUDE([src/libmongoc/src/zlib-1.2.11/])
+ PHP_MONGODB_ADD_BUILD_DIR([src/libmongoc/src/zlib-1.2.11/])
+ AC_CONFIG_FILES([${ac_config_dir}/src/libmongoc/src/zlib-1.2.11/zconf.h])
+ fi
+
+ if test "$PHP_MONGODB_CLIENT_SIDE_ENCRYPTION" = "yes"; then
+ dnl Since libmongocrypt adds kms-message, we can enable AWS auth in this case
+ AC_SUBST(MONGOC_ENABLE_MONGODB_AWS_AUTH, 1)
+ AC_SUBST(MONGOCRYPT_ENABLE_TRACE, 1)
+
+ dnl Generated with: find src/libmongocrypt/src -maxdepth 1 -name '*.c' -print0 | cut -sz -d / -f 4- | sort -dz | tr '\000' ' '
+ PHP_MONGODB_MONGOCRYPT_SOURCES="mongocrypt-binary.c mongocrypt-buffer.c mongocrypt.c mongocrypt-cache.c mongocrypt-cache-collinfo.c mongocrypt-cache-key.c mongocrypt-cache-oauth.c mongocrypt-ciphertext.c mongocrypt-crypto.c mongocrypt-ctx.c mongocrypt-ctx-datakey.c mongocrypt-ctx-decrypt.c mongocrypt-ctx-encrypt.c mongocrypt-endpoint.c mongocrypt-kek.c mongocrypt-key-broker.c mongocrypt-key.c mongocrypt-kms-ctx.c mongocrypt-log.c mongocrypt-marking.c mongocrypt-opts.c mongocrypt-status.c mongocrypt-traverse-util.c mongocrypt-util.c"
+
+ dnl Generated with: find src/libmongocrypt/src/crypto -name '*.c' -print0 | cut -sz -d / -f 5- | sort -dz | tr '\000' ' '
+ PHP_MONGODB_MONGOCRYPT_CRYPTO_SOURCES="cng.c commoncrypto.c libcrypto.c none.c"
+
+ dnl Note: src/libmongocrypt/src/mlib/ does not contain source files (as of libmongocrypt 1.3.2)
+
+ dnl Generated with: find src/libmongocrypt/src/os_posix -name '*.c' -print0 | cut -sz -d / -f 5- | sort -dz | tr '\000' ' '
+ PHP_MONGODB_MONGOCRYPT_OS_POSIX_SOURCES="os_dll.c os_mutex.c"
+
+ dnl Generated with: find src/libmongocrypt/src/os_win -name '*.c' -print0 | cut -sz -d / -f 5- | sort -dz | tr '\000' ' '
+ PHP_MONGODB_MONGOCRYPT_OS_WIN_SOURCES="os_dll.c os_mutex.c"
+
+ dnl Generated with: find src/libmongocrypt/kms-message/src -maxdepth 1 -name '*.c' -print0 | cut -sz -d / -f 5- | sort -dz | tr '\000' ' '
+ PHP_MONGODB_MONGOCRYPT_KMS_MESSAGE_SOURCES="hexlify.c kms_azure_request.c kms_b64.c kms_caller_identity_request.c kms_crypto_apple.c kms_crypto_libcrypto.c kms_crypto_none.c kms_crypto_windows.c kms_decrypt_request.c kms_encrypt_request.c kms_gcp_request.c kms_kmip_reader_writer.c kms_kmip_request.c kms_kmip_response.c kms_kmip_response_parser.c kms_kv_list.c kms_message.c kms_port.c kms_request.c kms_request_opt.c kms_request_str.c kms_response.c kms_response_parser.c sort.c"
+
+ PHP_MONGODB_LIBMONGOCRYPT_CFLAGS="$PHP_MONGODB_BUNDLED_CFLAGS $PHP_MONGODB_LIBMONGOCRYPT_CFLAGS"
+ PHP_MONGODB_ADD_SOURCES([src/libmongocrypt/src/], $PHP_MONGODB_MONGOCRYPT_SOURCES, $PHP_MONGODB_LIBMONGOCRYPT_CFLAGS)
+ PHP_MONGODB_ADD_SOURCES([src/libmongocrypt/src/crypto/], $PHP_MONGODB_MONGOCRYPT_CRYPTO_SOURCES, $PHP_MONGODB_LIBMONGOCRYPT_CFLAGS)
+ PHP_MONGODB_ADD_SOURCES([src/libmongocrypt/src/os_posix/], $PHP_MONGODB_MONGOCRYPT_OS_POSIX_SOURCES, $PHP_MONGODB_LIBMONGOCRYPT_CFLAGS)
+ PHP_MONGODB_ADD_SOURCES([src/libmongocrypt/src/os_win/], $PHP_MONGODB_MONGOCRYPT_OS_WIN_SOURCES, $PHP_MONGODB_LIBMONGOCRYPT_CFLAGS)
+ PHP_MONGODB_ADD_SOURCES([src/libmongocrypt/kms-message/src/], $PHP_MONGODB_MONGOCRYPT_KMS_MESSAGE_SOURCES, $PHP_MONGODB_LIBMONGOCRYPT_CFLAGS)
+
+ PHP_MONGODB_ADD_INCLUDE([src/libmongocrypt/src/])
+ PHP_MONGODB_ADD_INCLUDE([src/libmongocrypt/kms-message/src/])
+ PHP_MONGODB_ADD_INCLUDE([src/libmongocrypt-compat/])
+
+ PHP_MONGODB_ADD_BUILD_DIR([src/libmongocrypt/src/])
+ PHP_MONGODB_ADD_BUILD_DIR([src/libmongocrypt/src/crypto/])
+ PHP_MONGODB_ADD_BUILD_DIR([src/libmongocrypt/src/os_posix/])
+ PHP_MONGODB_ADD_BUILD_DIR([src/libmongocrypt/src/os_win/])
+ PHP_MONGODB_ADD_BUILD_DIR([src/libmongocrypt/kms-message/src/])
+
+ AC_CONFIG_FILES([
+ ${ac_config_dir}/src/libmongocrypt/src/mongocrypt-config.h
+ ${ac_config_dir}/src/libmongocrypt/src/mongocrypt.h
+ ])
+ fi
+ fi
+
+ PHP_NEW_EXTENSION(mongodb, $PHP_MONGODB_SOURCES, $ext_shared,, $PHP_MONGODB_CFLAGS)
+
+ PHP_SUBST(MONGODB_SHARED_LIBADD)
+
+ PHP_ADD_EXTENSION_DEP(mongodb, date)
+ PHP_ADD_EXTENSION_DEP(mongodb, json)
+ PHP_ADD_EXTENSION_DEP(mongodb, spl)
+ PHP_ADD_EXTENSION_DEP(mongodb, standard)
+
+ PHP_ADD_INCLUDE(PHP_EXT_SRCDIR(mongodb)[/src/])
+ PHP_ADD_INCLUDE(PHP_EXT_SRCDIR(mongodb)[/src/BSON/])
+ PHP_ADD_INCLUDE(PHP_EXT_SRCDIR(mongodb)[/src/MongoDB/])
+ PHP_ADD_INCLUDE(PHP_EXT_SRCDIR(mongodb)[/src/MongoDB/Exception/])
+ PHP_ADD_INCLUDE(PHP_EXT_SRCDIR(mongodb)[/src/MongoDB/Monitoring/])
+ PHP_ADD_INCLUDE(PHP_EXT_SRCDIR(mongodb)[/src/contrib/])
+
+ PHP_ADD_BUILD_DIR(PHP_EXT_BUILDDIR(mongodb)[/src/])
+ PHP_ADD_BUILD_DIR(PHP_EXT_BUILDDIR(mongodb)[/src/BSON/])
+ PHP_ADD_BUILD_DIR(PHP_EXT_BUILDDIR(mongodb)[/src/MongoDB/])
+ PHP_ADD_BUILD_DIR(PHP_EXT_BUILDDIR(mongodb)[/src/MongoDB/Exception/])
+ PHP_ADD_BUILD_DIR(PHP_EXT_BUILDDIR(mongodb)[/src/MongoDB/Monitoring/])
+ PHP_ADD_BUILD_DIR(PHP_EXT_BUILDDIR(mongodb)[/src/contrib/])
+
+ dnl Necessary to ensure that static builds include "-pthread" when linking
+ if test "$ext_shared" != "yes"; then
+ EXTRA_LDFLAGS_PROGRAM="$EXTRA_LDFLAGS_PROGRAM $EXTRA_LDFLAGS"
+ fi
+
+ dnl This must come after PHP_NEW_EXTENSION, otherwise the srcdir won't be set
+ PHP_ADD_MAKEFILE_FRAGMENT
+
+ dnl The libmongocrypt line intentionally uses the PHP_LIBBSON flag as that decides whether to build against bundled or system libraries.
+ AC_CONFIG_COMMANDS_POST([
+ if test "$enable_static" = "no"; then
+ echo "
+mongodb was configured with the following options:
+
+Build configuration:
+ CFLAGS : $CFLAGS
+ Extra CFLAGS : $STD_CFLAGS $EXTRA_CFLAGS
+ Developers flags (slow) : $MAINTAINER_CFLAGS
+ Code Coverage flags (extra slow) : $COVERAGE_CFLAGS
+ libmongoc : $PHP_MONGODB_BSON_VERSION_STRING
+ libbson : $PHP_MONGODB_MONGOC_VERSION_STRING
+ libmongocrypt : $PHP_MONGODB_MONGOCRYPT_VERSION_STRING
+ LDFLAGS : $LDFLAGS
+ EXTRA_LDFLAGS : $EXTRA_LDFLAGS
+ MONGODB_SHARED_LIBADD : $MONGODB_SHARED_LIBADD
+
+Please submit bugreports at:
+ https://jira.mongodb.org/browse/PHPC
+
+"
+ fi
+ ])
+fi
+
+dnl: vim: et sw=2
diff --git a/mongodb-1.13.0/config.w32 b/mongodb-1.13.0/config.w32
new file mode 100644
index 00000000..ba0d68b0
--- /dev/null
+++ b/mongodb-1.13.0/config.w32
@@ -0,0 +1,383 @@
+// vim:ft=javascript
+
+function mongodb_generate_header(inpath, outpath, replacements)
+{
+ STDOUT.WriteLine("Generating " + outpath);
+
+ var infile = FSO.OpenTextFile(inpath, 1);
+ var outdata = infile.ReadAll();
+ infile.Close();
+
+ for (var key in replacements) {
+ var replacement = replacements[key];
+
+ if (typeof replacement === 'string') {
+ replacement = replacement.replace(/"/g, '\\"');
+ }
+
+ outdata = outdata.replace(new RegExp('@' + key + '@', 'g'), replacement);
+ }
+
+ var outfile = FSO.CreateTextFile(outpath, true);
+ outfile.Write(outdata);
+ outfile.Close();
+}
+
+function mongodb_parse_version_file(inpath, prefix)
+{
+ var infile = FSO.OpenTextFile(inpath, 1);
+ var version = infile.ReadLine();
+ infile.Close();
+
+ var xyz_pre = version.split("-");
+ var xyz = xyz_pre[0].split(".");
+ var pre = xyz_pre.length > 1 ? xyz_pre[1] : "";
+
+ var replacements = {};
+ replacements[prefix + "VERSION"] = version;
+ replacements[prefix + "MAJOR_VERSION"] = xyz[0];
+ replacements[prefix + "MINOR_VERSION"] = xyz[1];
+ replacements[prefix + "MICRO_VERSION"] = xyz[2];
+ replacements[prefix + "PRERELEASE_VERSION"] = pre;
+
+ return replacements;
+}
+
+function create_folder_recursive(path)
+{
+ if (FSO.FolderExists(path)) {
+ return;
+ }
+
+ create_folder_recursive(FSO.GetParentFolderName(path));
+ FSO.CreateFolder(path);
+}
+
+function MONGODB_ADD_SOURCES(dir, file_list)
+{
+ // Ensure obj_dir and all parent directories exist
+ create_folder_recursive(FSO.BuildPath(get_define('BUILD_DIR'), dir));
+ ADD_SOURCES(configure_module_dirname + dir, file_list, "mongodb", dir);
+}
+
+ARG_ENABLE("mongodb", "MongoDB support", "no");
+ARG_WITH("mongodb-sasl", "MongoDB: Build against Cyrus-SASL", "yes");
+ARG_WITH("mongodb-client-side-encryption", "MongoDB: Enable client-side encryption", "yes");
+
+if (PHP_MONGODB != "no") {
+ /* Note: ADD_EXTENSION_DEP() only reports the date and standard extensions as
+ * installed in PHP 7.3.25+, 7.4.13+, and 8.0.0+). On other versions, assume
+ * that they're always enabled. */
+ if (
+ PHP_VERSION >= 8 ||
+ (PHP_VERSION == 7 && PHP_MINOR_VERSION == 3 && PHP_RELEASE_VERSION >= 25) ||
+ (PHP_VERSION == 7 && PHP_MINOR_VERSION == 4 && PHP_RELEASE_VERSION >= 13)
+ ) {
+ ADD_EXTENSION_DEP("mongodb", "date", false);
+ ADD_EXTENSION_DEP("mongodb", "standard", false);
+ }
+
+ ADD_EXTENSION_DEP("mongodb", "json", false);
+ ADD_EXTENSION_DEP("mongodb", "spl", false);
+
+ /* MongoDB does not actually depend on PHP's OpenSSL extension, but this is in
+ * place to ensure that later SSL library checks succeed. This can be removed
+ * once we support building with Secure Channel. */
+ ADD_EXTENSION_DEP("mongodb", "openssl", false);
+
+ var PHP_MONGODB_CFLAGS="\
+ /D BSON_COMPILATION /D MONGOC_COMPILATION \
+ /I" + configure_module_dirname + " \
+ /I" + configure_module_dirname + "/src \
+ /I" + configure_module_dirname + "/src/BSON \
+ /I" + configure_module_dirname + "/src/MongoDB \
+ /I" + configure_module_dirname + "/src/MongoDB/Exception \
+ /I" + configure_module_dirname + "/src/MongoDB/Monitoring \
+ /I" + configure_module_dirname + "/src/contrib \
+ /I" + configure_module_dirname + "/src/libmongoc/src/common \
+ /I" + configure_module_dirname + "/src/libmongoc/src/libbson/src \
+ /I" + configure_module_dirname + "/src/libmongoc/src/libbson/src/jsonsl \
+ /I" + configure_module_dirname + "/src/libmongoc/src/libmongoc/src \
+ ";
+
+ // Condense whitespace in CFLAGS
+ PHP_MONGODB_CFLAGS = PHP_MONGODB_CFLAGS.replace(/\s+/g, ' ');
+
+ // On MacOS, use gcut from the coreutils brew package instead of cut
+ // Generated with: find src/libmongoc/src/common -name '*.c' -print0 | cut -sz -d / -f 5- | sort -dz | tr '\000' ' '
+ var PHP_MONGODB_COMMON_SOURCES="common-b64.c common-md5.c common-thread.c"
+
+ // Generated with: find src/libmongoc/src/kms-message/src -maxdepth 1 -name '*.c' -print0 | cut -sz -d / -f 6- | sort -dz | tr '\000' ' '
+ var PHP_MONGODB_KMS_MESSAGE_SOURCES="hexlify.c kms_b64.c kms_caller_identity_request.c kms_crypto_apple.c kms_crypto_libcrypto.c kms_crypto_none.c kms_crypto_windows.c kms_decrypt_request.c kms_encrypt_request.c kms_kv_list.c kms_message.c kms_port.c kms_request.c kms_request_opt.c kms_request_str.c kms_response.c kms_response_parser.c sort.c";
+
+ // Generated with: find src/libmongoc/src/libbson/src/bson -name '*.c' -print0 | cut -sz -d / -f 7- | sort -dz | tr '\000' ' '
+ var PHP_MONGODB_BSON_SOURCES="bcon.c bson-atomic.c bson.c bson-clock.c bson-context.c bson-decimal128.c bson-error.c bson-iso8601.c bson-iter.c bson-json.c bson-keys.c bson-md5.c bson-memory.c bson-oid.c bson-reader.c bson-string.c bson-timegm.c bson-utf8.c bson-value.c bson-version-functions.c bson-writer.c";
+
+ // Generated with: find src/libmongoc/src/libbson/src/jsonsl -name '*.c' -print0 | cut -sz -d / -f 7- | sort -dz | tr '\000' ' '
+ var PHP_MONGODB_JSONSL_SOURCES="jsonsl.c";
+
+ // Generated with: find src/libmongoc/src/libmongoc/src/mongoc -name '*.c' -print0 | cut -sz -d / -f 7- | sort -dz | tr '\000' ' '
+ var PHP_MONGODB_MONGOC_SOURCES="mongoc-aggregate.c mongoc-apm.c mongoc-array.c mongoc-async.c mongoc-async-cmd.c mongoc-buffer.c mongoc-bulk-operation.c mongoc-change-stream.c mongoc-client.c mongoc-client-pool.c mongoc-client-session.c mongoc-client-side-encryption.c mongoc-cluster-aws.c mongoc-cluster.c mongoc-cluster-cyrus.c mongoc-cluster-sasl.c mongoc-cluster-sspi.c mongoc-cmd.c mongoc-collection.c mongoc-compression.c mongoc-counters.c mongoc-crypt.c mongoc-crypto.c mongoc-crypto-cng.c mongoc-crypto-common-crypto.c mongoc-crypto-openssl.c mongoc-cursor-array.c mongoc-cursor.c mongoc-cursor-change-stream.c mongoc-cursor-cmd.c mongoc-cursor-cmd-deprecated.c mongoc-cursor-find.c mongoc-cursor-find-cmd.c mongoc-cursor-find-opquery.c mongoc-cursor-legacy.c mongoc-cyrus.c mongoc-database.c mongoc-error.c mongoc-find-and-modify.c mongoc-generation-map.c mongoc-gridfs-bucket.c mongoc-gridfs-bucket-file.c mongoc-gridfs.c mongoc-gridfs-file.c mongoc-gridfs-file-list.c mongoc-gridfs-file-page.c mongoc-handshake.c mongoc-host-list.c mongoc-http.c mongoc-index.c mongoc-init.c mongoc-interrupt.c mongoc-libressl.c mongoc-linux-distro-scanner.c mongoc-list.c mongoc-log.c mongoc-matcher.c mongoc-matcher-op.c mongoc-memcmp.c mongoc-ocsp-cache.c mongoc-openssl.c mongoc-optional.c mongoc-opts.c mongoc-opts-helpers.c mongoc-queue.c mongoc-rand-cng.c mongoc-rand-common-crypto.c mongoc-rand-openssl.c mongoc-read-concern.c mongoc-read-prefs.c mongoc-rpc.c mongoc-sasl.c mongoc-scram.c mongoc-secure-channel.c mongoc-secure-transport.c mongoc-server-api.c mongoc-server-description.c mongoc-server-monitor.c mongoc-server-stream.c mongoc-set.c mongoc-shared.c mongoc-socket.c mongoc-ssl.c mongoc-sspi.c mongoc-stream-buffered.c mongoc-stream.c mongoc-stream-file.c mongoc-stream-gridfs.c mongoc-stream-gridfs-download.c mongoc-stream-gridfs-upload.c mongoc-stream-socket.c mongoc-stream-tls.c mongoc-stream-tls-libressl.c mongoc-stream-tls-openssl-bio.c mongoc-stream-tls-openssl.c mongoc-stream-tls-secure-channel.c mongoc-stream-tls-secure-transport.c mongoc-timeout.c mongoc-topology-background-monitoring.c mongoc-topology.c mongoc-topology-description-apm.c mongoc-topology-description.c mongoc-topology-scanner.c mongoc-ts-pool.c mongoc-uri.c mongoc-util.c mongoc-version-functions.c mongoc-write-command.c mongoc-write-command-legacy.c mongoc-write-concern.c";
+
+ EXTENSION("mongodb", "php_phongo.c", null, PHP_MONGODB_CFLAGS);
+ MONGODB_ADD_SOURCES("/src", "phongo_apm.c phongo_bson.c phongo_bson_encode.c phongo_client.c phongo_compat.c phongo_error.c phongo_execute.c phongo_ini.c phongo_util.c");
+ MONGODB_ADD_SOURCES("/src/BSON", "Binary.c BinaryInterface.c DBPointer.c Decimal128.c Decimal128Interface.c Int64.c Javascript.c JavascriptInterface.c MaxKey.c MaxKeyInterface.c MinKey.c MinKeyInterface.c ObjectId.c ObjectIdInterface.c Persistable.c Regex.c RegexInterface.c Serializable.c Symbol.c Timestamp.c TimestampInterface.c Type.c Undefined.c Unserializable.c UTCDateTime.c UTCDateTimeInterface.c functions.c");
+ MONGODB_ADD_SOURCES("/src/MongoDB", "BulkWrite.c ClientEncryption.c Command.c Cursor.c CursorId.c CursorInterface.c Manager.c Query.c ReadConcern.c ReadPreference.c Server.c ServerApi.c ServerDescription.c Session.c TopologyDescription.c WriteConcern.c WriteConcernError.c WriteError.c WriteResult.c");
+ MONGODB_ADD_SOURCES("/src/MongoDB/Exception", "AuthenticationException.c BulkWriteException.c CommandException.c ConnectionException.c ConnectionTimeoutException.c EncryptionException.c Exception.c ExecutionTimeoutException.c InvalidArgumentException.c LogicException.c RuntimeException.c ServerException.c SSLConnectionException.c UnexpectedValueException.c WriteException.c");
+ MONGODB_ADD_SOURCES("/src/MongoDB/Monitoring", "CommandFailedEvent.c CommandStartedEvent.c CommandSubscriber.c CommandSucceededEvent.c SDAMSubscriber.c Subscriber.c ServerChangedEvent.c ServerClosedEvent.c ServerHeartbeatFailedEvent.c ServerHeartbeatStartedEvent.c ServerHeartbeatSucceededEvent.c ServerOpeningEvent.c TopologyChangedEvent.c TopologyClosedEvent.c TopologyOpeningEvent.c functions.c");
+ MONGODB_ADD_SOURCES("/src/libmongoc/src/common", PHP_MONGODB_COMMON_SOURCES);
+ MONGODB_ADD_SOURCES("/src/libmongoc/src/libbson/src/bson", PHP_MONGODB_BSON_SOURCES);
+ MONGODB_ADD_SOURCES("/src/libmongoc/src/libbson/src/jsonsl", PHP_MONGODB_JSONSL_SOURCES);
+ MONGODB_ADD_SOURCES("/src/libmongoc/src/libmongoc/src/mongoc", PHP_MONGODB_MONGOC_SOURCES);
+
+ var bson_opts = {
+ BSON_BYTE_ORDER: 1234,
+ BSON_OS: 2,
+ BSON_HAVE_STDBOOL_H: 0,
+ BSON_HAVE_STRINGS_H: 0,
+ BSON_HAVE_ATOMIC_32_ADD_AND_FETCH: 0,
+ BSON_HAVE_ATOMIC_64_ADD_AND_FETCH: 0,
+ BSON_PTHREAD_ONCE_INIT_NEEDS_BRACES: 0,
+ BSON_HAVE_CLOCK_GETTIME: 0,
+ BSON_HAVE_STRNLEN: 0,
+ BSON_HAVE_SNPRINTF: 0,
+ BSON_HAVE_STRLCPY: 0,
+ BSON_HAVE_REALLOCF: 0,
+ BSON_NEEDS_SET_OUTPUT_FORMAT: 0,
+ BSON_HAVE_TIMESPEC: 0,
+ BSON_EXTRA_ALIGN: 0,
+ BSON_HAVE_SYSCALL_TID: 0,
+ BSON_HAVE_DECIMAL128: 0,
+ BSON_HAVE_GMTIME_R: 0,
+ BSON_HAVE_RAND_R: 0,
+ BSON_HAVE_ARC4RANDOM_BUF: 0
+ };
+
+ if (CHECK_FUNC_IN_HEADER("stdio.h", "_set_output_format")) {
+ bson_opts.BSON_NEEDS_SET_OUTPUT_FORMAT = 1;
+ }
+
+ mongodb_generate_header(
+ configure_module_dirname + "/src/libmongoc/src/libbson/src/bson/bson-config.h.in",
+ configure_module_dirname + "/src/libmongoc/src/libbson/src/bson/bson-config.h",
+ bson_opts
+ );
+
+ mongodb_generate_header(
+ configure_module_dirname + "/src/libmongoc/src/libbson/src/bson/bson-version.h.in",
+ configure_module_dirname + "/src/libmongoc/src/libbson/src/bson/bson-version.h",
+ mongodb_parse_version_file(configure_module_dirname + "/src/LIBMONGOC_VERSION_CURRENT", "BSON_")
+ );
+
+ var mongoc_opts = {
+ // TODO: Support building with Secure Channel on Windows
+ MONGOC_ENABLE_SSL_SECURE_CHANNEL: 0,
+ MONGOC_ENABLE_CRYPTO_CNG: 0,
+ // Secure Transport does not apply to Windows
+ MONGOC_ENABLE_SSL_SECURE_TRANSPORT: 0,
+ MONGOC_ENABLE_CRYPTO_COMMON_CRYPTO: 0,
+ MONGOC_ENABLE_SSL_LIBRESSL: 0,
+ MONGOC_ENABLE_SSL_OPENSSL: 0,
+ MONGOC_ENABLE_CRYPTO_LIBCRYPTO: 0,
+ MONGOC_ENABLE_SSL: 0,
+ MONGOC_ENABLE_CRYPTO: 0,
+ MONGOC_ENABLE_CRYPTO_SYSTEM_PROFILE: 0,
+ MONGOC_ENABLE_CLIENT_SIDE_ENCRYPTION: 0,
+ MONGOC_ENABLE_COMPRESSION_SNAPPY: 0,
+ MONGOC_ENABLE_COMPRESSION_ZLIB: 0,
+ MONGOC_ENABLE_COMPRESSION_ZSTD: 0,
+ MONGOC_ENABLE_COMPRESSION: 0,
+ MONGOC_ENABLE_DEBUG_ASSERTIONS: 0,
+ MONGOC_ENABLE_MONGODB_AWS_AUTH: 0,
+ MONGOC_ENABLE_SASL: 0,
+ MONGOC_ENABLE_SASL_CYRUS: 0,
+ MONGOC_ENABLE_SASL_GSSAPI: 0,
+ MONGOC_ENABLE_SASL_SSPI: 0,
+ MONGOC_ENABLE_ICU: 0,
+ MONGOC_ENABLE_RDTSCP: 0,
+ MONGOC_ENABLE_SHM_COUNTERS: 0,
+ MONGOC_HAVE_ASN1_STRING_GET0_DATA: 0,
+ MONGOC_HAVE_SASL_CLIENT_DONE: 0,
+ MONGOC_HAVE_SCHED_GETCPU: 0,
+ MONGOC_HAVE_SOCKLEN: 1,
+ MONGOC_HAVE_WEAK_SYMBOLS: 0,
+ MONGOC_NO_AUTOMATIC_GLOBALS: 1,
+ MONGOC_SOCKET_ARG2: "struct sockaddr",
+ MONGOC_SOCKET_ARG3: "socklen_t",
+ MONGOC_TRACE: 1,
+ MONGOC_HAVE_DNSAPI: 0,
+ MONGOC_HAVE_RES_NSEARCH: 0,
+ MONGOC_HAVE_RES_NDESTROY: 0,
+ MONGOC_HAVE_RES_NCLOSE: 0,
+ MONGOC_HAVE_RES_SEARCH: 0,
+ MONGOC_HAVE_SS_FAMILY: 0,
+ MONGOC_CC: "",
+ MONGOC_USER_SET_CFLAGS: "",
+ MONGOC_USER_SET_LDFLAGS: ""
+ };
+
+ var mongoc_ssl_path_to_check = PHP_MONGODB;
+
+ if (typeof PHP_OPENSSL === 'string') {
+ mongoc_ssl_path_to_check += ";" + PHP_OPENSSL;
+ }
+
+ var mongoc_ssl_found = false;
+
+ /* PHP 7.1.2 introduced SETUP_OPENSSL(), which supports OpenSSL 1.1.x. Earlier
+ * versions will use the legacy check for OpenSSL 1.0.x and lower. */
+ if (typeof SETUP_OPENSSL === 'function') {
+ openssl_type = SETUP_OPENSSL("mongodb", mongoc_ssl_path_to_check);
+ mongoc_ssl_found = openssl_type > 0;
+ if (openssl_type >= 2) {
+ mongoc_opts.MONGOC_HAVE_ASN1_STRING_GET0_DATA = 1;
+ }
+ } else if (CHECK_LIB("ssleay32.lib", "mongodb", mongoc_ssl_path_to_check) &&
+ CHECK_LIB("libeay32.lib", "mongodb", mongoc_ssl_path_to_check) &&
+ CHECK_LIB("crypt32.lib", "mongodb", mongoc_ssl_path_to_check) &&
+ CHECK_HEADER_ADD_INCLUDE("openssl/ssl.h", "CFLAGS_MONGODB")) {
+ mongoc_ssl_found = true;
+ }
+
+ if (mongoc_ssl_found) {
+ mongoc_opts.MONGOC_ENABLE_SSL_OPENSSL = 1;
+ mongoc_opts.MONGOC_ENABLE_CRYPTO_LIBCRYPTO = 1;
+ mongoc_opts.MONGOC_ENABLE_SSL = 1;
+ mongoc_opts.MONGOC_ENABLE_CRYPTO = 1;
+ mongoc_opts.MONGOC_ENABLE_MONGODB_AWS_AUTH = 1;
+
+ ADD_FLAG("CFLAGS_MONGODB", "/D KMS_MSG_STATIC=1 /D KMS_MESSAGE_ENABLE_CRYPTO=1 /D KMS_MESSAGE_ENABLE_CRYPTO_LIBCRYPTO=1");
+ } else {
+ WARNING("mongodb libopenssl support not enabled, libs not found");
+ }
+
+ // TODO: Support building with native GSSAPI (SSPI) on Windows
+ if (PHP_MONGODB_SASL != "no" &&
+ CHECK_LIB("libsasl.lib", "mongodb", PHP_MONGODB) &&
+ CHECK_HEADER_ADD_INCLUDE("sasl/sasl.h", "CFLAGS_MONGODB")) {
+ mongoc_opts.MONGOC_ENABLE_SASL = 1;
+ mongoc_opts.MONGOC_ENABLE_SASL_CYRUS = 1;
+ if (CHECK_FUNC_IN_HEADER("sasl/sasl.h", "sasl_client_done")) {
+ mongoc_opts.MONGOC_HAVE_SASL_CLIENT_DONE = 1;
+ }
+ } else if (PHP_MONGODB_SASL != "no") {
+ WARNING("mongodb libsasl support not enabled, libs not found");
+ }
+
+ if (PHP_MONGODB_CLIENT_SIDE_ENCRYPTION != "no" && mongoc_ssl_found) {
+ mongoc_opts.MONGOC_ENABLE_CLIENT_SIDE_ENCRYPTION = 1;
+
+ ADD_FLAG("CFLAGS_MONGODB", "/D KMS_MESSAGE_LITTLE_ENDIAN=1 /D MLIB_USER=1");
+ ADD_FLAG("CFLAGS_MONGODB", "/I" + configure_module_dirname + "/src/libmongocrypt/src");
+ ADD_FLAG("CFLAGS_MONGODB", "/I" + configure_module_dirname + "/src/libmongocrypt/kms-message/src");
+ ADD_FLAG("CFLAGS_MONGODB", "/I" + configure_module_dirname + "/src/libmongocrypt-compat");
+
+ var mongocrypt_opts = {
+ MONGOCRYPT_ENABLE_TRACE: 1,
+ MONGOCRYPT_ENABLE_CRYPTO: 1,
+ MONGOCRYPT_ENABLE_CRYPTO_LIBCRYPTO: 1,
+ // TODO: Support building with Secure Channel on Windows
+ MONGOCRYPT_ENABLE_CRYPTO_CNG: 0,
+ // Secure Transport does not apply to Windows
+ MONGOCRYPT_ENABLE_CRYPTO_COMMON_CRYPTO: 0
+ };
+
+ // Generated with: find src/libmongocrypt/src -maxdepth 1 -name '*.c' -print0 | cut -sz -d / -f 4- | sort -dz | tr '\000' ' '
+ var PHP_MONGODB_MONGOCRYPT_SOURCES="mongocrypt-binary.c mongocrypt-buffer.c mongocrypt.c mongocrypt-cache.c mongocrypt-cache-collinfo.c mongocrypt-cache-key.c mongocrypt-cache-oauth.c mongocrypt-ciphertext.c mongocrypt-crypto.c mongocrypt-ctx.c mongocrypt-ctx-datakey.c mongocrypt-ctx-decrypt.c mongocrypt-ctx-encrypt.c mongocrypt-endpoint.c mongocrypt-kek.c mongocrypt-key-broker.c mongocrypt-key.c mongocrypt-kms-ctx.c mongocrypt-log.c mongocrypt-marking.c mongocrypt-opts.c mongocrypt-status.c mongocrypt-traverse-util.c mongocrypt-util.c";
+
+ // Generated with: find src/libmongocrypt/src/crypto -name '*.c' -print0 | cut -sz -d / -f 5- | sort -dz | tr '\000' ' '
+ var PHP_MONGODB_MONGOCRYPT_CRYPTO_SOURCES="cng.c commoncrypto.c libcrypto.c none.c";
+
+ // Note: src/libmongocrypt/src/mlib/ does not contain source files (as of libmongocrypt 1.3.2)
+
+ // Generated with: find src/libmongocrypt/src/os_posix -name '*.c' -print0 | cut -sz -d / -f 5- | sort -dz | tr '\000' ' '
+ var PHP_MONGODB_MONGOCRYPT_OS_POSIX_SOURCES="os_dll.c os_mutex.c";
+
+ // Generated with: find src/libmongocrypt/src/os_win -name '*.c' -print0 | cut -sz -d / -f 5- | sort -dz | tr '\000' ' '
+ var PHP_MONGODB_MONGOCRYPT_OS_WIN_SOURCES="os_dll.c os_mutex.c";
+
+ // Generated with: find src/libmongocrypt/kms-message/src -maxdepth 1 -name '*.c' -print0 | cut -sz -d / -f 5- | sort -dz | tr '\000' ' '
+ var PHP_MONGODB_MONGOCRYPT_KMS_MESSAGE_SOURCES="hexlify.c kms_azure_request.c kms_b64.c kms_caller_identity_request.c kms_crypto_apple.c kms_crypto_libcrypto.c kms_crypto_none.c kms_crypto_windows.c kms_decrypt_request.c kms_encrypt_request.c kms_gcp_request.c kms_kmip_reader_writer.c kms_kmip_request.c kms_kmip_response.c kms_kmip_response_parser.c kms_kv_list.c kms_message.c kms_port.c kms_request.c kms_request_opt.c kms_request_str.c kms_response.c kms_response_parser.c sort.c";
+
+ MONGODB_ADD_SOURCES("/src/libmongocrypt/src", PHP_MONGODB_MONGOCRYPT_SOURCES);
+ MONGODB_ADD_SOURCES("/src/libmongocrypt/src/crypto", PHP_MONGODB_MONGOCRYPT_CRYPTO_SOURCES);
+ MONGODB_ADD_SOURCES("/src/libmongocrypt/src/os_posix", PHP_MONGODB_MONGOCRYPT_OS_POSIX_SOURCES);
+ MONGODB_ADD_SOURCES("/src/libmongocrypt/src/os_win", PHP_MONGODB_MONGOCRYPT_OS_WIN_SOURCES);
+ MONGODB_ADD_SOURCES("/src/libmongocrypt/kms-message/src", PHP_MONGODB_MONGOCRYPT_KMS_MESSAGE_SOURCES);
+
+ var mongocrypt_version = mongodb_parse_version_file(configure_module_dirname + "/src/LIBMONGOCRYPT_VERSION_CURRENT", "")
+ mongocrypt_opts.MONGOCRYPT_BUILD_VERSION = mongocrypt_version.VERSION;
+
+ mongodb_generate_header(
+ configure_module_dirname + "/src/libmongocrypt/src/mongocrypt-config.h.in",
+ configure_module_dirname + "/src/libmongocrypt/src/mongocrypt-config.h",
+ mongocrypt_opts
+ );
+
+ mongodb_generate_header(
+ configure_module_dirname + "/src/libmongocrypt/src/mongocrypt.h.in",
+ configure_module_dirname + "/src/libmongocrypt/src/mongocrypt.h",
+ mongocrypt_opts
+ );
+ } else if (PHP_MONGODB_CLIENT_SIDE_ENCRYPTION != "no") {
+ // No SSL library found, we can't enable libmongocrypt
+ WARNING("mongodb libmongocrypt support not enabled, crypto libs not found");
+ }
+
+ if (PHP_MONGODB_CLIENT_SIDE_ENCRYPTION == "no" && mongoc_ssl_found) {
+ // Add kms-message sources bundled with libmongoc
+ MONGODB_ADD_SOURCES("/src/libmongoc/src/kms-message/src", PHP_MONGODB_KMS_MESSAGE_SOURCES);
+ ADD_FLAG("CFLAGS_MONGODB", "/I" + configure_module_dirname + "/src/libmongoc/src/kms-message/src");
+ }
+
+ if (CHECK_LIB("dnsapi.lib", "mongodb", PHP_MONGODB) &&
+ CHECK_HEADER_ADD_INCLUDE("windns.h", "CFLAGS_MONGODB")) {
+ mongoc_opts.MONGOC_HAVE_DNSAPI = 1;
+ }
+
+ if (CHECK_LIB("icuuc.lib", "mongodb", PHP_MONGODB) &&
+ CHECK_HEADER_ADD_INCLUDE("unicode/utf.h", "CFLAGS_MONGODB")) {
+ mongoc_opts.MONGODB_ENABLE_ICU = 1;
+
+ ADD_FLAG("LIBS_MONGODB", "icudt.lib icuin.lib icuio.lib");
+
+ /* Compat for ICU before 58.1.*/
+ if (CHECK_LIB("icule.lib", "mongodb", PHP_MONGODB)) {
+ ADD_FLAG("LIBS_MONGODB", "icule.lib");
+ }
+ if (CHECK_LIB("iculx.lib", "mongodb", PHP_MONGODB)) {
+ ADD_FLAG("LIBS_MONGODB", "iculx.lib");
+ }
+
+ ADD_FLAG("CFLAGS_MONGODB", "/EHsc /D U_USING_ICU_NAMESPACE=1");
+ }
+
+ if (typeof COMPILER_NAME === 'string') {
+ mongoc_opts.MONGOC_CC = COMPILER_NAME;
+ } else if (typeof VC_VERSIONS === 'array' && typeof VC_VERSIONS[VCVERS] === 'string') {
+ mongoc_opts.MONGOC_CC = VC_VERSIONS[VCVERS];
+ } else if (typeof COMPILER_NAME_LONG === 'string') {
+ mongoc_opts.MONGOC_CC = COMPILER_NAME_LONG;
+ }
+
+ /* MONGOC_USER_SET_CFLAGS and MONGOC_USER_SET_LDFLAGS can be left blank, as we
+ * do not expect CFLAGS or LDFLAGS to be customized at build time. */
+
+ mongodb_generate_header(
+ configure_module_dirname + "/src/libmongoc/src/libmongoc/src/mongoc/mongoc-config.h.in",
+ configure_module_dirname + "/src/libmongoc/src/libmongoc/src/mongoc/mongoc-config.h",
+ mongoc_opts
+ );
+
+ mongodb_generate_header(
+ configure_module_dirname + "/src/libmongoc/src/common/common-config.h.in",
+ configure_module_dirname + "/src/libmongoc/src/common/common-config.h",
+ mongoc_opts
+ );
+
+ mongodb_generate_header(
+ configure_module_dirname + "/src/libmongoc/src/libmongoc/src/mongoc/mongoc-version.h.in",
+ configure_module_dirname + "/src/libmongoc/src/libmongoc/src/mongoc/mongoc-version.h",
+ mongodb_parse_version_file(configure_module_dirname + "/src/LIBMONGOC_VERSION_CURRENT", "MONGOC_")
+ );
+}
diff --git a/mongodb-1.13.0/php_phongo.c b/mongodb-1.13.0/php_phongo.c
new file mode 100644
index 00000000..f46e8fcd
--- /dev/null
+++ b/mongodb-1.13.0/php_phongo.c
@@ -0,0 +1,566 @@
+/*
+ * Copyright 2014-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bson/bson.h"
+#include "mongoc/mongoc.h"
+
+#ifdef MONGOC_ENABLE_CLIENT_SIDE_ENCRYPTION
+#include <mongocrypt/mongocrypt.h>
+#endif
+
+#include <php.h>
+#include <ext/standard/info.h>
+
+#include "php_phongo.h"
+#include "src/phongo_client.h"
+#include "src/phongo_error.h"
+#include "src/phongo_ini.h"
+#include "src/BSON/functions.h"
+#include "src/MongoDB/Monitoring/functions.h"
+
+ZEND_DECLARE_MODULE_GLOBALS(mongodb)
+#if defined(ZTS) && defined(COMPILE_DL_MONGODB)
+ZEND_TSRMLS_CACHE_DEFINE();
+#endif
+
+/* Initialize a thread counter, which will be atomically incremented in GINIT.
+ * In turn, GSHUTDOWN will decrement the counter and call mongoc_cleanup() when
+ * it reaches zero (i.e. last thread is shutdown). This is necessary because
+ * mongoc_cleanup() must be called after all persistent clients have been
+ * destroyed. */
+static int32_t phongo_num_threads = 0;
+
+/* Declare zend_class_entry dependencies, which are initialized in MINIT */
+zend_class_entry* php_phongo_date_immutable_ce;
+zend_class_entry* php_phongo_json_serializable_ce;
+
+/* {{{ phongo_std_object_handlers */
+zend_object_handlers phongo_std_object_handlers;
+
+zend_object_handlers* phongo_get_std_object_handlers(void)
+{
+ return &phongo_std_object_handlers;
+}
+/* }}} */
+
+/* {{{ Memory allocation wrappers */
+static void* php_phongo_malloc(size_t num_bytes) /* {{{ */
+{
+ return pemalloc(num_bytes, 1);
+} /* }}} */
+
+static void* php_phongo_calloc(size_t num_members, size_t num_bytes) /* {{{ */
+{
+ return pecalloc(num_members, num_bytes, 1);
+} /* }}} */
+
+static void* php_phongo_realloc(void* mem, size_t num_bytes) /* {{{ */
+{
+ return perealloc(mem, num_bytes, 1);
+} /* }}} */
+
+static void php_phongo_free(void* mem) /* {{{ */
+{
+ if (mem) {
+ pefree(mem, 1);
+ }
+} /* }}} */
+
+PHP_RINIT_FUNCTION(mongodb) /* {{{ */
+{
+ /* Initialize HashTable for non-persistent clients, which is initialized to
+ * NULL in GINIT and destroyed and reset to NULL in RSHUTDOWN. Although we
+ * specify an element destructor here, all request clients should be freed
+ * naturally via garbage collection (i.e. the HashTable should be empty at
+ * the time it is destroyed in RSHUTDOWN). */
+ if (MONGODB_G(request_clients) == NULL) {
+ ALLOC_HASHTABLE(MONGODB_G(request_clients));
+ zend_hash_init(MONGODB_G(request_clients), 0, NULL, php_phongo_pclient_destroy_ptr, 0);
+ }
+
+ /* Initialize HashTable for APM subscribers, which is initialized to NULL in
+ * GINIT and destroyed and reset to NULL in RSHUTDOWN. Since this HashTable
+ * will store subscriber object zvals, we specify ZVAL_PTR_DTOR as its
+ * element destructor so that any still-registered subscribers can be freed
+ * in RSHUTDOWN. */
+ if (MONGODB_G(subscribers) == NULL) {
+ ALLOC_HASHTABLE(MONGODB_G(subscribers));
+ zend_hash_init(MONGODB_G(subscribers), 0, NULL, ZVAL_PTR_DTOR, 0);
+ }
+
+ /* Initialize HashTable for registering Manager objects. This is initialized
+ * to NULL in GINIT and destroyed and reset to NULL in RSHUTDOWN. Since this
+ * HashTable stores pointers to existing php_phongo_manager_t objects (not
+ * counted references), the element destructor is intentionally NULL. */
+ if (MONGODB_G(managers) == NULL) {
+ ALLOC_HASHTABLE(MONGODB_G(managers));
+ zend_hash_init(MONGODB_G(managers), 0, NULL, NULL, 0);
+ }
+
+ return SUCCESS;
+} /* }}} */
+
+PHP_GINIT_FUNCTION(mongodb) /* {{{ */
+{
+#if defined(COMPILE_DL_MONGODB) && defined(ZTS)
+ ZEND_TSRMLS_CACHE_UPDATE();
+#endif
+
+ /* Increment the thread counter. */
+ bson_atomic_int32_fetch_add(&phongo_num_threads, 1, bson_memory_order_seq_cst);
+
+ /* Clear extension globals */
+ memset(mongodb_globals, 0, sizeof(zend_mongodb_globals));
+
+ /* Initialize HashTable for persistent clients, which will be destroyed in
+ * GSHUTDOWN. We specify an element destructor so that persistent clients
+ * can be destroyed along with the HashTable. The HashTable's struct is
+ * nested within globals, so no allocation is needed (unlike the HashTables
+ * allocated in RINIT). */
+ zend_hash_init(&mongodb_globals->persistent_clients, 0, NULL, php_phongo_pclient_destroy_ptr, 1);
+} /* }}} */
+
+static zend_class_entry* php_phongo_fetch_internal_class(const char* class_name, size_t class_name_len)
+{
+ zend_class_entry* pce;
+
+ if ((pce = zend_hash_str_find_ptr(CG(class_table), class_name, class_name_len))) {
+ return pce;
+ }
+
+ return NULL;
+}
+
+static HashTable* php_phongo_std_get_gc(phongo_compat_object_handler_type* object, zval** table, int* n) /* {{{ */
+{
+ *table = NULL;
+ *n = 0;
+ return zend_std_get_properties(object);
+} /* }}} */
+
+PHP_MINIT_FUNCTION(mongodb) /* {{{ */
+{
+ bson_mem_vtable_t bson_mem_vtable = {
+ php_phongo_malloc,
+ php_phongo_calloc,
+ php_phongo_realloc,
+ php_phongo_free,
+ };
+
+ (void) type; /* We don't care if we are loaded via dl() or extension= */
+
+ phongo_register_ini_entries(INIT_FUNC_ARGS_PASSTHRU);
+
+ /* Assign our custom vtable to libbson, so all memory allocation in libbson
+ * (and libmongoc) will use PHP's persistent memory API. After doing so,
+ * initialize libmongoc. Later, we will shutdown libmongoc and restore
+ * libbson's vtable in the final GSHUTDOWN. */
+ bson_mem_set_vtable(&bson_mem_vtable);
+ mongoc_init();
+
+ /* Prep default object handlers to be used when we register the classes */
+ memcpy(&phongo_std_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
+ /* Disable cloning by default. Individual classes can opt in if they need to
+ * support this (e.g. BSON objects). */
+ phongo_std_object_handlers.clone_obj = NULL;
+ /* Ensure that get_gc delegates to zend_std_get_properties directly in case
+ * our class defines a get_properties handler for debugging purposes. */
+ phongo_std_object_handlers.get_gc = php_phongo_std_get_gc;
+
+ /* Initialize zend_class_entry dependencies.
+ *
+ * Although DateTimeImmutable was introduced in PHP 5.5.0,
+ * php_date_get_immutable_ce() is not available in PHP versions before
+ * 5.5.24 and 5.6.8.
+ *
+ * Although JsonSerializable was introduced in PHP 5.4.0,
+ * php_json_serializable_ce is not exported in PHP versions before 5.4.26
+ * and 5.5.10. For later PHP versions, looking up the class manually also
+ * helps with distros that disable LTDL_LAZY for dlopen() (e.g. Fedora).
+ */
+ php_phongo_date_immutable_ce = php_phongo_fetch_internal_class(ZEND_STRL("datetimeimmutable"));
+ php_phongo_json_serializable_ce = php_phongo_fetch_internal_class(ZEND_STRL("jsonserializable"));
+
+ if (php_phongo_json_serializable_ce == NULL) {
+ zend_error(E_ERROR, "JsonSerializable class is not defined. Please ensure that the 'json' module is loaded before the 'mongodb' module.");
+ return FAILURE;
+ }
+
+ /* Register base BSON classes first */
+ php_phongo_type_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_serializable_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_unserializable_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+
+ php_phongo_binary_interface_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_decimal128_interface_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_javascript_interface_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_maxkey_interface_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_minkey_interface_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_objectid_interface_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_regex_interface_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_timestamp_interface_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_utcdatetime_interface_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+
+ php_phongo_binary_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_dbpointer_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_decimal128_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_int64_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_javascript_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_maxkey_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_minkey_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_objectid_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_persistable_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_regex_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_symbol_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_timestamp_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_undefined_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_utcdatetime_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+
+ php_phongo_cursor_interface_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+
+ php_phongo_bulkwrite_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_clientencryption_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_command_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_cursor_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_cursorid_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_manager_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_query_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_readconcern_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_readpreference_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_server_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_serverapi_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_serverdescription_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_topologydescription_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_session_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_writeconcern_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_writeconcernerror_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_writeerror_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_writeresult_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+
+ /* Register base exception classes first */
+ php_phongo_exception_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_runtimeexception_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_serverexception_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_connectionexception_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_writeexception_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+
+ php_phongo_authenticationexception_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_bulkwriteexception_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_commandexception_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_connectiontimeoutexception_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_encryptionexception_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_executiontimeoutexception_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_invalidargumentexception_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_logicexception_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_sslconnectionexception_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_unexpectedvalueexception_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+
+ /* Register base APM classes first */
+ php_phongo_subscriber_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_commandsubscriber_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_commandfailedevent_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_commandstartedevent_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_commandsucceededevent_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_sdamsubscriber_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_serverchangedevent_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_serverclosedevent_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_serverheartbeatfailedevent_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_serverheartbeatstartedevent_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_serverheartbeatsucceededevent_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_serveropeningevent_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_topologychangedevent_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_topologyclosedevent_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+ php_phongo_topologyopeningevent_init_ce(INIT_FUNC_ARGS_PASSTHRU);
+
+ REGISTER_STRING_CONSTANT("MONGODB_VERSION", (char*) PHP_MONGODB_VERSION, CONST_CS | CONST_PERSISTENT);
+ REGISTER_STRING_CONSTANT("MONGODB_STABILITY", (char*) PHP_MONGODB_STABILITY, CONST_CS | CONST_PERSISTENT);
+
+ return SUCCESS;
+} /* }}} */
+
+PHP_MSHUTDOWN_FUNCTION(mongodb) /* {{{ */
+{
+ phongo_unregister_ini_entries(SHUTDOWN_FUNC_ARGS_PASSTHRU);
+
+ return SUCCESS;
+} /* }}} */
+
+PHP_RSHUTDOWN_FUNCTION(mongodb) /* {{{ */
+{
+ /* Destroy HashTable for APM subscribers, which was initialized in RINIT. */
+ if (MONGODB_G(subscribers)) {
+ zend_hash_destroy(MONGODB_G(subscribers));
+ FREE_HASHTABLE(MONGODB_G(subscribers));
+ MONGODB_G(subscribers) = NULL;
+ }
+
+ /* Destroy HashTable for non-persistent clients, which was initialized in
+ * RINIT. This is intentionally done after the APM subscribers to allow any
+ * non-persistent clients still referenced by a subscriber (not freed prior
+ * to RSHUTDOWN) to be naturally garbage collected and freed by the Manager
+ * free_object handler rather than the HashTable's element destructor. There
+ * is no need to use zend_hash_graceful_reverse_destroy here like we do for
+ * persistent clients; moreover, the HashTable should already be empty. */
+ if (MONGODB_G(request_clients)) {
+ zend_hash_destroy(MONGODB_G(request_clients));
+ FREE_HASHTABLE(MONGODB_G(request_clients));
+ MONGODB_G(request_clients) = NULL;
+ }
+
+ /* Destroy HashTable for Managers, which was initialized in RINIT. */
+ if (MONGODB_G(managers)) {
+ zend_hash_destroy(MONGODB_G(managers));
+ FREE_HASHTABLE(MONGODB_G(managers));
+ MONGODB_G(managers) = NULL;
+ }
+
+ return SUCCESS;
+} /* }}} */
+
+PHP_GSHUTDOWN_FUNCTION(mongodb) /* {{{ */
+{
+ /* Destroy persistent client HashTable in reverse order. This is necessary
+ * to prevent segmentation faults as clients may reference other clients in
+ * encryption settings. */
+ zend_hash_graceful_reverse_destroy(&mongodb_globals->persistent_clients);
+
+ phongo_log_disable(mongodb_globals->debug_fd);
+ mongodb_globals->debug_fd = NULL;
+
+ /* Decrement the thread counter. If it reaches zero, we can infer that this
+ * is the last thread, MSHUTDOWN has been called, persistent clients from
+ * all threads have been destroyed, and it is now safe to shutdown libmongoc
+ * and restore libbson's original vtable. */
+ if (bson_atomic_int32_fetch_sub(&phongo_num_threads, 1, bson_memory_order_seq_cst) - 1 == 0) {
+ mongoc_cleanup();
+ bson_mem_restore_vtable();
+ }
+} /* }}} */
+
+PHP_MINFO_FUNCTION(mongodb) /* {{{ */
+{
+ php_info_print_table_start();
+ php_info_print_table_header(2, "MongoDB support", "enabled");
+ php_info_print_table_row(2, "MongoDB extension version", PHP_MONGODB_VERSION);
+ php_info_print_table_row(2, "MongoDB extension stability", PHP_MONGODB_STABILITY);
+
+#ifdef HAVE_SYSTEM_LIBBSON
+ php_info_print_table_row(2, "libbson headers version", BSON_VERSION_S);
+ php_info_print_table_row(2, "libbson library version", bson_get_version());
+#else
+ php_info_print_table_row(2, "libbson bundled version", BSON_VERSION_S);
+#endif
+
+#ifdef HAVE_SYSTEM_LIBMONGOC
+ php_info_print_table_row(2, "libmongoc headers version", MONGOC_VERSION_S);
+ php_info_print_table_row(2, "libmongoc library version", mongoc_get_version());
+#else
+ /* Bundled libraries, buildtime = runtime */
+ php_info_print_table_row(2, "libmongoc bundled version", MONGOC_VERSION_S);
+#endif
+
+#ifdef MONGOC_ENABLE_SSL
+ php_info_print_table_row(2, "libmongoc SSL", "enabled");
+#if defined(MONGOC_ENABLE_SSL_OPENSSL)
+ php_info_print_table_row(2, "libmongoc SSL library", "OpenSSL");
+#elif defined(MONGOC_ENABLE_SSL_LIBRESSL)
+ php_info_print_table_row(2, "libmongoc SSL library", "LibreSSL");
+#elif defined(MONGOC_ENABLE_SSL_SECURE_TRANSPORT)
+ php_info_print_table_row(2, "libmongoc SSL library", "Secure Transport");
+#elif defined(MONGOC_ENABLE_SSL_SECURE_CHANNEL)
+ php_info_print_table_row(2, "libmongoc SSL library", "Secure Channel");
+#else
+ php_info_print_table_row(2, "libmongoc SSL library", "unknown");
+#endif
+#else /* MONGOC_ENABLE_SSL */
+ php_info_print_table_row(2, "libmongoc SSL", "disabled");
+#endif
+
+#ifdef MONGOC_ENABLE_CRYPTO
+ php_info_print_table_row(2, "libmongoc crypto", "enabled");
+#if defined(MONGOC_ENABLE_CRYPTO_LIBCRYPTO)
+ php_info_print_table_row(2, "libmongoc crypto library", "libcrypto");
+#elif defined(MONGOC_ENABLE_CRYPTO_COMMON_CRYPTO)
+ php_info_print_table_row(2, "libmongoc crypto library", "Common Crypto");
+#elif defined(MONGOC_ENABLE_CRYPTO_CNG)
+ php_info_print_table_row(2, "libmongoc crypto library", "CNG");
+#else
+ php_info_print_table_row(2, "libmongoc crypto library", "unknown");
+#endif
+#ifdef MONGOC_ENABLE_CRYPTO_SYSTEM_PROFILE
+ php_info_print_table_row(2, "libmongoc crypto system profile", "enabled");
+#else
+ php_info_print_table_row(2, "libmongoc crypto system profile", "disabled");
+#endif
+#else /* MONGOC_ENABLE_CRYPTO */
+ php_info_print_table_row(2, "libmongoc crypto", "disabled");
+#endif
+
+#ifdef MONGOC_ENABLE_SASL
+ php_info_print_table_row(2, "libmongoc SASL", "enabled");
+#else
+ php_info_print_table_row(2, "libmongoc SASL", "disabled");
+#endif
+
+#ifdef MONGOC_ENABLE_ICU
+ php_info_print_table_row(2, "libmongoc ICU", "enabled");
+#else
+ php_info_print_table_row(2, "libmongoc ICU", "disabled");
+#endif
+
+#ifdef MONGOC_ENABLE_COMPRESSION
+ php_info_print_table_row(2, "libmongoc compression", "enabled");
+#ifdef MONGOC_ENABLE_COMPRESSION_SNAPPY
+ php_info_print_table_row(2, "libmongoc compression snappy", "enabled");
+#else
+ php_info_print_table_row(2, "libmongoc compression snappy", "disabled");
+#endif
+#ifdef MONGOC_ENABLE_COMPRESSION_ZLIB
+ php_info_print_table_row(2, "libmongoc compression zlib", "enabled");
+#else
+ php_info_print_table_row(2, "libmongoc compression zlib", "disabled");
+#endif
+#ifdef MONGOC_ENABLE_COMPRESSION_ZSTD
+ php_info_print_table_row(2, "libmongoc compression zstd", "enabled");
+#else
+ php_info_print_table_row(2, "libmongoc compression zstd", "disabled");
+#endif
+#else /* MONGOC_ENABLE_COMPRESSION */
+ php_info_print_table_row(2, "libmongoc compression", "disabled");
+#endif
+
+#ifdef MONGOC_ENABLE_CLIENT_SIDE_ENCRYPTION
+#ifdef HAVE_SYSTEM_LIBMONGOCRYPT
+ php_info_print_table_row(2, "libmongocrypt headers version", MONGOCRYPT_VERSION);
+ php_info_print_table_row(2, "libmongocrypt library version", mongocrypt_version(NULL));
+#else
+ php_info_print_table_row(2, "libmongocrypt bundled version", MONGOCRYPT_VERSION);
+#endif
+
+#ifdef MONGOCRYPT_ENABLE_CRYPTO
+ php_info_print_table_row(2, "libmongocrypt crypto", "enabled");
+
+#if defined(MONGOCRYPT_ENABLE_CRYPTO_LIBCRYPTO)
+ php_info_print_table_row(2, "libmongocrypt crypto library", "libcrypto");
+#elif defined(MONGOCRYPT_ENABLE_CRYPTO_COMMON_CRYPTO)
+ php_info_print_table_row(2, "libmongocrypt crypto library", "Common Crypto");
+#elif defined(MONGOCRYPT_ENABLE_CRYPTO_CNG)
+ php_info_print_table_row(2, "libmongocrypt crypto library", "CNG");
+#else
+ php_info_print_table_row(2, "libmongocrypt crypto library", "unknown");
+#endif
+#else /* MONGOCRYPT_ENABLE_CRYPTO */
+ php_info_print_table_row(2, "libmongocrypt crypto", "disabled");
+#endif
+#else /* MONGOC_ENABLE_CLIENT_SIDE_ENCRYPTION */
+ php_info_print_table_row(2, "libmongocrypt", "disabled");
+#endif
+
+ php_info_print_table_end();
+
+ phongo_display_ini_entries(ZEND_MODULE_INFO_FUNC_ARGS_PASSTHRU);
+} /* }}} */
+
+/* {{{ Shared function entries for disabling constructors and unserialize() */
+PHP_FUNCTION(MongoDB_disabled___construct) /* {{{ */
+{
+ phongo_throw_exception(PHONGO_ERROR_RUNTIME, "Accessing private constructor");
+} /* }}} */
+
+PHP_FUNCTION(MongoDB_disabled___wakeup) /* {{{ */
+{
+ zend_error_handling error_handling;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ phongo_throw_exception(PHONGO_ERROR_RUNTIME, "%s", "MongoDB\\Driver objects cannot be serialized");
+} /* }}} */
+/* }}} */
+
+/* {{{ Extension functions, module dependencies, and module entry */
+ZEND_BEGIN_ARG_INFO_EX(ai_bson_fromPHP, 0, 0, 1)
+ ZEND_ARG_INFO(0, value)
+ZEND_END_ARG_INFO();
+
+ZEND_BEGIN_ARG_INFO_EX(ai_bson_toPHP, 0, 0, 1)
+ ZEND_ARG_INFO(0, bson)
+ ZEND_ARG_ARRAY_INFO(0, typemap, 0)
+ZEND_END_ARG_INFO();
+
+ZEND_BEGIN_ARG_INFO_EX(ai_bson_toJSON, 0, 0, 1)
+ ZEND_ARG_INFO(0, bson)
+ZEND_END_ARG_INFO();
+
+ZEND_BEGIN_ARG_INFO_EX(ai_bson_fromJSON, 0, 0, 1)
+ ZEND_ARG_INFO(0, json)
+ZEND_END_ARG_INFO();
+
+ZEND_BEGIN_ARG_INFO_EX(ai_mongodb_driver_monitoring_subscriber, 0, 0, 1)
+ ZEND_ARG_OBJ_INFO(0, subscriber, MongoDB\\Driver\\Monitoring\\Subscriber, 0)
+ZEND_END_ARG_INFO();
+
+static const zend_function_entry mongodb_functions[] = {
+ /* clang-format off */
+ ZEND_NS_NAMED_FE("MongoDB\\BSON", fromPHP, PHP_FN(MongoDB_BSON_fromPHP), ai_bson_fromPHP)
+ ZEND_NS_NAMED_FE("MongoDB\\BSON", toPHP, PHP_FN(MongoDB_BSON_toPHP), ai_bson_toPHP)
+ ZEND_NS_NAMED_FE("MongoDB\\BSON", toJSON, PHP_FN(MongoDB_BSON_toJSON), ai_bson_toJSON)
+ ZEND_NS_NAMED_FE("MongoDB\\BSON", toCanonicalExtendedJSON, PHP_FN(MongoDB_BSON_toCanonicalExtendedJSON), ai_bson_toJSON)
+ ZEND_NS_NAMED_FE("MongoDB\\BSON", toRelaxedExtendedJSON, PHP_FN(MongoDB_BSON_toRelaxedExtendedJSON), ai_bson_toJSON)
+ ZEND_NS_NAMED_FE("MongoDB\\BSON", fromJSON, PHP_FN(MongoDB_BSON_fromJSON), ai_bson_fromJSON)
+ ZEND_NS_NAMED_FE("MongoDB\\Driver\\Monitoring", addSubscriber, PHP_FN(MongoDB_Driver_Monitoring_addSubscriber), ai_mongodb_driver_monitoring_subscriber)
+ ZEND_NS_NAMED_FE("MongoDB\\Driver\\Monitoring", removeSubscriber, PHP_FN(MongoDB_Driver_Monitoring_removeSubscriber), ai_mongodb_driver_monitoring_subscriber)
+ PHP_FE_END
+ /* clang-format on */
+};
+
+static const zend_module_dep mongodb_deps[] = {
+ /* clang-format off */
+ ZEND_MOD_REQUIRED("date")
+ ZEND_MOD_REQUIRED("json")
+ ZEND_MOD_REQUIRED("spl")
+ ZEND_MOD_REQUIRED("standard")
+ ZEND_MOD_END
+ /* clang-format on */
+};
+
+zend_module_entry mongodb_module_entry = {
+ STANDARD_MODULE_HEADER_EX,
+ NULL,
+ mongodb_deps,
+ "mongodb",
+ mongodb_functions,
+ PHP_MINIT(mongodb),
+ PHP_MSHUTDOWN(mongodb),
+ PHP_RINIT(mongodb),
+ PHP_RSHUTDOWN(mongodb),
+ PHP_MINFO(mongodb),
+ PHP_MONGODB_VERSION,
+ PHP_MODULE_GLOBALS(mongodb),
+ PHP_GINIT(mongodb),
+ PHP_GSHUTDOWN(mongodb),
+ NULL,
+ STANDARD_MODULE_PROPERTIES_EX
+};
+/* }}} */
+
+#ifdef COMPILE_DL_MONGODB
+ZEND_GET_MODULE(mongodb)
+#endif
diff --git a/mongodb-1.13.0/php_phongo.h b/mongodb-1.13.0/php_phongo.h
new file mode 100644
index 00000000..ca54b4c2
--- /dev/null
+++ b/mongodb-1.13.0/php_phongo.h
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2014-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PHONGO_H
+#define PHONGO_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/* Include headers for getpid(), which is used by PHONGO_SET_CREATED_BY_PID.
+ * This is based on PHP's ext/standard/pageinfo.c includes for getmypid. */
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef PHP_WIN32
+#include <process.h>
+#endif
+
+#include "phongo_version.h"
+#include "phongo_compat.h"
+#include "phongo_classes.h"
+#include "phongo_structs.h"
+
+/* Define a common logging domain for the extension. Individual files may
+ * override the domain after including this header (e.g. phongo_bson.c). */
+#undef MONGOC_LOG_DOMAIN
+#define MONGOC_LOG_DOMAIN "PHONGO"
+
+#define phpext_mongodb_ptr &mongodb_module_entry
+extern zend_module_entry mongodb_module_entry;
+
+ZEND_BEGIN_MODULE_GLOBALS(mongodb)
+ char* debug;
+ FILE* debug_fd;
+ bool mock_service_id;
+ HashTable persistent_clients;
+ HashTable* request_clients;
+ HashTable* subscribers;
+ HashTable* managers;
+ZEND_END_MODULE_GLOBALS(mongodb)
+
+#define MONGODB_G(v) ZEND_MODULE_GLOBALS_ACCESSOR(mongodb, v)
+#if defined(ZTS) && defined(COMPILE_DL_MONGODB)
+ZEND_TSRMLS_CACHE_EXTERN()
+#endif
+
+zend_object_handlers* phongo_get_std_object_handlers(void);
+
+#define PHONGO_CE_FINAL(ce) \
+ do { \
+ ce->ce_flags |= ZEND_ACC_FINAL; \
+ } while (0)
+
+#if PHP_VERSION_ID < 80100
+#define PHONGO_CE_DISABLE_SERIALIZATION(ce) \
+ do { \
+ ce->serialize = zend_class_serialize_deny; \
+ ce->unserialize = zend_class_unserialize_deny; \
+ } while (0)
+#else
+#define PHONGO_CE_DISABLE_SERIALIZATION(ce) \
+ do { \
+ ce->ce_flags |= ZEND_ACC_NOT_SERIALIZABLE; \
+ } while (0)
+#endif
+
+#define PHONGO_GET_PROPERTY_HASH_INIT_PROPS(is_temp, intern, props, size) \
+ do { \
+ if (is_temp) { \
+ ALLOC_HASHTABLE(props); \
+ zend_hash_init((props), (size), NULL, ZVAL_PTR_DTOR, 0); \
+ } else if ((intern)->properties) { \
+ (props) = (intern)->properties; \
+ } else { \
+ ALLOC_HASHTABLE(props); \
+ zend_hash_init((props), (size), NULL, ZVAL_PTR_DTOR, 0); \
+ (intern)->properties = (props); \
+ } \
+ } while (0)
+
+#define PHONGO_GET_PROPERTY_HASH_FREE_PROPS(is_temp, props) \
+ do { \
+ if (is_temp) { \
+ zend_hash_destroy((props)); \
+ FREE_HASHTABLE(props); \
+ } \
+ } while (0)
+
+#define PHONGO_ZVAL_CLASS_OR_TYPE_NAME(zv) (Z_TYPE(zv) == IS_OBJECT ? ZSTR_VAL(Z_OBJCE(zv)->name) : zend_get_type_by_const(Z_TYPE(zv)))
+#define PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(zvp) PHONGO_ZVAL_CLASS_OR_TYPE_NAME(*(zvp))
+
+#define PHONGO_ZVAL_EXCEPTION_NAME(e) (ZSTR_VAL(e->ce->name))
+
+#define PHONGO_SET_CREATED_BY_PID(intern) \
+ do { \
+ (intern)->created_by_pid = (int) getpid(); \
+ } while (0)
+
+/* Shared function entries for disabling constructors and unserialize() */
+PHP_FUNCTION(MongoDB_disabled___construct);
+PHP_FUNCTION(MongoDB_disabled___wakeup);
+
+#endif /* PHONGO_H */
diff --git a/mongodb-1.12.0/scripts/autotools/CheckCompiler.m4 b/mongodb-1.13.0/scripts/autotools/CheckCompiler.m4
similarity index 100%
rename from mongodb-1.12.0/scripts/autotools/CheckCompiler.m4
rename to mongodb-1.13.0/scripts/autotools/CheckCompiler.m4
diff --git a/mongodb-1.12.0/scripts/autotools/CheckHost.m4 b/mongodb-1.13.0/scripts/autotools/CheckHost.m4
similarity index 100%
rename from mongodb-1.12.0/scripts/autotools/CheckHost.m4
rename to mongodb-1.13.0/scripts/autotools/CheckHost.m4
diff --git a/mongodb-1.12.0/scripts/autotools/libbson/CheckAtomics.m4 b/mongodb-1.13.0/scripts/autotools/libbson/CheckAtomics.m4
similarity index 100%
rename from mongodb-1.12.0/scripts/autotools/libbson/CheckAtomics.m4
rename to mongodb-1.13.0/scripts/autotools/libbson/CheckAtomics.m4
diff --git a/mongodb-1.12.0/scripts/autotools/libbson/CheckHeaders.m4 b/mongodb-1.13.0/scripts/autotools/libbson/CheckHeaders.m4
similarity index 100%
rename from mongodb-1.12.0/scripts/autotools/libbson/CheckHeaders.m4
rename to mongodb-1.13.0/scripts/autotools/libbson/CheckHeaders.m4
diff --git a/mongodb-1.12.0/scripts/autotools/libbson/Endian.m4 b/mongodb-1.13.0/scripts/autotools/libbson/Endian.m4
similarity index 100%
rename from mongodb-1.12.0/scripts/autotools/libbson/Endian.m4
rename to mongodb-1.13.0/scripts/autotools/libbson/Endian.m4
diff --git a/mongodb-1.13.0/scripts/autotools/libbson/FindDependencies.m4 b/mongodb-1.13.0/scripts/autotools/libbson/FindDependencies.m4
new file mode 100644
index 00000000..8950c5ee
--- /dev/null
+++ b/mongodb-1.13.0/scripts/autotools/libbson/FindDependencies.m4
@@ -0,0 +1,125 @@
+if test "$os_win32" != "yes"; then
+ PHP_MONGODB_BUNDLED_CFLAGS="$PHP_MONGODB_BUNDLED_CFLAGS -D_DEFAULT_SOURCE"
+fi
+
+# Check for strnlen()
+dnl AC_CHECK_FUNC isn't properly respecting _XOPEN_SOURCE for strnlen for unknown reason
+AC_SUBST(BSON_HAVE_STRNLEN, 0)
+AC_CACHE_CHECK([for strnlen],
+ bson_cv_have_strnlen,
+ [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <string.h>
+int strnlen () { return 0; }
+]])],
+ [bson_cv_have_strnlen=no],
+ [bson_cv_have_strnlen=yes])])
+if test "$bson_cv_have_strnlen" = yes; then
+ AC_SUBST(BSON_HAVE_STRNLEN, 1)
+fi
+
+# Check for reallocf() (BSD/Darwin)
+AC_SUBST(BSON_HAVE_REALLOCF, 0)
+AC_CACHE_CHECK([for reallocf],
+ bson_cv_have_reallocf,
+ [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <stdlib.h>
+int reallocf () { return 0; }
+]])],
+ [bson_cv_have_reallocf=no],
+ [bson_cv_have_reallocf=yes])])
+if test "$bson_cv_have_reallocf" = yes; then
+ AC_SUBST(BSON_HAVE_REALLOCF, 1)
+fi
+
+# Check for syscall()
+AC_SUBST(BSON_HAVE_SYSCALL_TID, 0)
+AC_CACHE_CHECK([for syscall],
+ bson_cv_have_syscall_tid,
+ [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <unistd.h>
+#include <sys/syscall.h>
+int syscall () { return 0; }
+]])],
+ [bson_cv_have_syscall_tid=no],
+ [bson_cv_have_syscall_tid=yes])])
+if test "$bson_cv_have_syscall_tid" = yes -a "$os_darwin" != "yes"; then
+ AC_CACHE_CHECK([for SYS_gettid],
+ bson_cv_have_sys_gettid_tid,
+ [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <unistd.h>
+#include <sys/syscall.h>
+int gettid () { return SYS_gettid; }
+ ]])],
+ [bson_cv_have_sys_gettid_tid=yes],
+ [bson_cv_have_sys_gettid_tid=no])])
+ if test "$bson_cv_have_sys_gettid_tid" = yes; then
+ AC_SUBST(BSON_HAVE_SYSCALL_TID, 1)
+ fi
+fi
+
+# Check for snprintf()
+AC_SUBST(BSON_HAVE_SNPRINTF, 0)
+AC_CHECK_FUNC(snprintf, [AC_SUBST(BSON_HAVE_SNPRINTF, 1)])
+
+# Check for strlcpy()
+AC_SUBST(BSON_HAVE_STRLCPY, 0)
+AC_CHECK_FUNC(strlcpy, [AC_SUBST(BSON_HAVE_STRLCPY, 1)])
+
+# Check for struct timespec
+AC_SUBST(BSON_HAVE_TIMESPEC, 0)
+AC_CHECK_TYPE([struct timespec], [AC_SUBST(BSON_HAVE_TIMESPEC, 1)], [], [#include <time.h>])
+
+# Check for clock_gettime and if it needs -lrt
+AC_SUBST(BSON_HAVE_CLOCK_GETTIME, 0)
+AC_SEARCH_LIBS([clock_gettime], [rt], [AC_SUBST(BSON_HAVE_CLOCK_GETTIME, 1)])
+# Check if math functions need -lm
+AC_SEARCH_LIBS([floor], [m])
+
+# Check for gmtime_r()
+AC_SUBST(BSON_HAVE_GMTIME_R, 0)
+AC_CHECK_FUNC(gmtime_r, [AC_SUBST(BSON_HAVE_GMTIME_R, 1)])
+
+# Check for rand_r()
+AC_SUBST(BSON_HAVE_RAND_R, 0)
+AC_CHECK_FUNC(rand_r, [AC_SUBST(BSON_HAVE_RAND_R, 1)])
+
+# Check for arc4random_buf()
+AC_SUBST(BSON_HAVE_ARC4RANDOM_BUF, 0)
+AC_CHECK_FUNC(arc4random_buf, [AC_SUBST(BSON_HAVE_ARC4RANDOM_BUF, 1)])
+
+# Check for pthreads. We might need to make this better to handle mingw,
+# but I actually think it is okay to just check for it even though we will
+# use win32 primatives.
+AX_PTHREAD([
+ PHP_MONGODB_BUNDLED_CFLAGS="$PHP_MONGODB_BUNDLED_CFLAGS $PTHREAD_CFLAGS"
+ PHP_EVAL_LIBLINE([$PTHREAD_LIBS],[MONGODB_SHARED_LIBADD])
+
+ # PTHREAD_CFLAGS may come back as "-pthread", which should also be used when
+ # linking. We can trust PHP_EVAL_LIBLINE to ignore other values.
+ PHP_EVAL_LIBLINE([$PTHREAD_CFLAGS],[MONGODB_SHARED_LIBADD])
+],[
+ AC_MSG_ERROR([libbson requires pthreads on non-Windows platforms.])
+])
+
+
+# The following is borrowed from the guile configure script.
+#
+# On past versions of Solaris, believe 8 through 10 at least, you
+# had to write "pthread_once_t foo = { PTHREAD_ONCE_INIT };".
+# This is contrary to POSIX:
+# http://www.opengroup.org/onlinepubs/000095399/functions/pthread_once.html
+# Check here if this style is required.
+#
+# glibc (2.3.6 at least) works both with or without braces, so the
+# test checks whether it works without.
+#
+AC_SUBST(BSON_PTHREAD_ONCE_INIT_NEEDS_BRACES, 0)
+AC_CACHE_CHECK([whether PTHREAD_ONCE_INIT needs braces],
+ bson_cv_need_braces_on_pthread_once_init,
+ [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <pthread.h>
+ pthread_once_t foo = PTHREAD_ONCE_INIT;]])],
+ [bson_cv_need_braces_on_pthread_once_init=no],
+ [bson_cv_need_braces_on_pthread_once_init=yes])])
+if test "$bson_cv_need_braces_on_pthread_once_init" = yes; then
+ AC_SUBST(BSON_PTHREAD_ONCE_INIT_NEEDS_BRACES, 1)
+fi
diff --git a/mongodb-1.12.0/scripts/autotools/libbson/Versions.m4 b/mongodb-1.13.0/scripts/autotools/libbson/Versions.m4
similarity index 100%
rename from mongodb-1.12.0/scripts/autotools/libbson/Versions.m4
rename to mongodb-1.13.0/scripts/autotools/libbson/Versions.m4
diff --git a/mongodb-1.13.0/scripts/autotools/libmongoc/CheckCompression.m4 b/mongodb-1.13.0/scripts/autotools/libmongoc/CheckCompression.m4
new file mode 100644
index 00000000..d17ebd20
--- /dev/null
+++ b/mongodb-1.13.0/scripts/autotools/libmongoc/CheckCompression.m4
@@ -0,0 +1,95 @@
+found_snappy="no"
+found_zlib="no"
+bundled_zlib="no"
+found_zstd="no"
+
+PKG_CHECK_MODULES([PHP_MONGODB_SNAPPY],[snappy],[
+ PHP_MONGODB_BUNDLED_CFLAGS="$PHP_MONGODB_BUNDLED_CFLAGS $PHP_MONGODB_SNAPPY_CFLAGS"
+ PHP_EVAL_LIBLINE([$PHP_MONGODB_SNAPPY_LIBS],[MONGODB_SHARED_LIBADD])
+ found_snappy="yes"
+],[
+ PHP_CHECK_LIBRARY([snappy],
+ [snappy_uncompress],
+ [have_snappy_lib="yes"],
+ [have_snappy_lib="no"])
+
+ AC_CHECK_HEADER([snappy-c.h],
+ [have_snappy_headers=yes],
+ [have_snappy_headers=no])
+
+ if test "$have_snappy_lib" = "yes" -a "$have_snappy_headers" = "yes"; then
+ PHP_ADD_LIBRARY([snappy],,[MONGODB_SHARED_LIBADD])
+ found_snappy="yes"
+ fi
+])
+
+PKG_CHECK_MODULES([PHP_MONGODB_ZLIB],[zlib],[
+ PHP_MONGODB_BUNDLED_CFLAGS="$PHP_MONGODB_BUNDLED_CFLAGS $PHP_MONGODB_ZLIB_CFLAGS"
+ PHP_EVAL_LIBLINE([$PHP_MONGODB_ZLIB_LIBS],[MONGODB_SHARED_LIBADD])
+ found_zlib="yes"
+],[
+ PHP_CHECK_LIBRARY([zlib],
+ [compress2],
+ [have_zlib_lib="yes"],
+ [have_zlib_lib="no"])
+
+ AC_CHECK_HEADER([zlib.h],
+ [have_zlib_headers=yes],
+ [have_zlib_headers=no])
+
+ if test "$have_zlib_lib" = "yes" -a "$have_zlib_headers" = "yes"; then
+ PHP_ADD_LIBRARY([z],,[MONGODB_SHARED_LIBADD])
+ found_zlib="yes"
+ fi
+])
+
+dnl If zlib was not found, use libmongoc's bundled version
+AS_IF([test "$found_zlib" != "yes"],[
+ AC_CHECK_HEADER([unistd.h],[PHP_MONGODB_ZLIB_CFLAGS="$PHP_MONGODB_ZLIB_CFLAGS -DHAVE_UNISTD_H"])
+ AC_CHECK_HEADER([stdarg.h],[PHP_MONGODB_ZLIB_CFLAGS="$PHP_MONGODB_ZLIB_CFLAGS -DHAVE_STDARG_H"])
+ bundled_zlib="yes"
+])
+
+PKG_CHECK_MODULES([PHP_MONGODB_ZSTD],[libzstd],[
+ PHP_MONGODB_BUNDLED_CFLAGS="$PHP_MONGODB_BUNDLED_CFLAGS $PHP_MONGODB_ZSTD_CFLAGS"
+ PHP_EVAL_LIBLINE([$PHP_MONGODB_ZSTD_LIBS],[MONGODB_SHARED_LIBADD])
+ found_zstd="yes"
+],[
+ PHP_CHECK_LIBRARY([zstd],
+ [ZSTD_compress],
+ [have_zstd_lib="yes"],
+ [have_zstd_lib="no"])
+
+ AC_CHECK_HEADER([zstd.h],
+ [have_zstd_headers=yes],
+ [have_zstd_headers=no])
+
+ if test "$have_zstd_lib" = "yes" -a "$have_zstd_headers" = "yes"; then
+ PHP_ADD_LIBRARY([zstd],,[MONGODB_SHARED_LIBADD])
+ found_zstd="yes"
+ fi
+])
+
+if test "$found_snappy" = "yes" -o "$found_zlib" = "yes" -o "$bundled_zlib" = "yes" -o "$found_zstd" = "yes"; then
+ AC_SUBST(MONGOC_ENABLE_COMPRESSION, 1)
+ if test "$found_snappy" = "yes"; then
+ AC_SUBST(MONGOC_ENABLE_COMPRESSION_SNAPPY, 1)
+ else
+ AC_SUBST(MONGOC_ENABLE_COMPRESSION_SNAPPY, 0)
+ fi
+ if test "$found_zlib" = "yes" -o "$bundled_zlib" = "yes"; then
+ AC_SUBST(MONGOC_ENABLE_COMPRESSION_ZLIB, 1)
+ else
+ AC_SUBST(MONGOC_ENABLE_COMPRESSION_ZLIB, 0)
+ fi
+ if test "$found_zstd" = "yes"; then
+ AC_SUBST(MONGOC_ENABLE_COMPRESSION_ZSTD, 1)
+ else
+ AC_SUBST(MONGOC_ENABLE_COMPRESSION_ZSTD, 0)
+ fi
+else
+ AC_SUBST(MONGOC_ENABLE_COMPRESSION, 0)
+ AC_SUBST(MONGOC_ENABLE_COMPRESSION_SNAPPY, 0)
+ AC_SUBST(MONGOC_ENABLE_COMPRESSION_ZLIB, 0)
+ AC_SUBST(MONGOC_ENABLE_COMPRESSION_ZSTD, 0)
+fi
diff --git a/mongodb-1.12.0/scripts/autotools/libmongoc/CheckICU.m4 b/mongodb-1.13.0/scripts/autotools/libmongoc/CheckICU.m4
similarity index 100%
rename from mongodb-1.12.0/scripts/autotools/libmongoc/CheckICU.m4
rename to mongodb-1.13.0/scripts/autotools/libmongoc/CheckICU.m4
diff --git a/mongodb-1.12.0/scripts/autotools/libmongoc/CheckResolv.m4 b/mongodb-1.13.0/scripts/autotools/libmongoc/CheckResolv.m4
similarity index 100%
rename from mongodb-1.12.0/scripts/autotools/libmongoc/CheckResolv.m4
rename to mongodb-1.13.0/scripts/autotools/libmongoc/CheckResolv.m4
diff --git a/mongodb-1.12.0/scripts/autotools/libmongoc/CheckSSL.m4 b/mongodb-1.13.0/scripts/autotools/libmongoc/CheckSSL.m4
similarity index 100%
rename from mongodb-1.12.0/scripts/autotools/libmongoc/CheckSSL.m4
rename to mongodb-1.13.0/scripts/autotools/libmongoc/CheckSSL.m4
diff --git a/mongodb-1.12.0/scripts/autotools/libmongoc/CheckSasl.m4 b/mongodb-1.13.0/scripts/autotools/libmongoc/CheckSasl.m4
similarity index 100%
rename from mongodb-1.12.0/scripts/autotools/libmongoc/CheckSasl.m4
rename to mongodb-1.13.0/scripts/autotools/libmongoc/CheckSasl.m4
diff --git a/mongodb-1.13.0/scripts/autotools/libmongoc/FindDependencies.m4 b/mongodb-1.13.0/scripts/autotools/libmongoc/FindDependencies.m4
new file mode 100644
index 00000000..e39d5167
--- /dev/null
+++ b/mongodb-1.13.0/scripts/autotools/libmongoc/FindDependencies.m4
@@ -0,0 +1,36 @@
+# Check for shm functions
+AC_CHECK_FUNCS([shm_open],[],[
+ AC_CHECK_LIB([rt],
+ [shm_open],
+ [PHP_ADD_LIBRARY([rt],,[MONGODB_SHARED_LIBADD])],
+ [])
+])
+
+# Check for sched_getcpu
+AC_CHECK_FUNC([sched_getcpu],
+ [AC_SUBST(MONGOC_HAVE_SCHED_GETCPU, 1)],
+ [AC_SUBST(MONGOC_HAVE_SCHED_GETCPU, 0)])
+
+AC_CHECK_TYPE([socklen_t],
+ [AC_SUBST(MONGOC_HAVE_SOCKLEN, 1)],
+ [AC_SUBST(MONGOC_HAVE_SOCKLEN, 0)],
+ [#include <sys/socket.h>])
+
+AC_CHECK_MEMBER([struct sockaddr_storage.ss_family],
+ [AC_SUBST(MONGOC_HAVE_SS_FAMILY, 1)],
+ [AC_SUBST(MONGOC_HAVE_SS_FAMILY, 0)],
+ [#include <sys/socket.h>])
+
+# Check for pthreads. libmongoc's original FindDependencies.m4 script did not
+# require pthreads, but it does appear to be necessary on non-Windows platforms
+# based on mongoc-openssl.c and mongoc-thread-private.h.
+AX_PTHREAD([
+ PHP_MONGODB_BUNDLED_CFLAGS="$PHP_MONGODB_BUNDLED_CFLAGS $PTHREAD_CFLAGS"
+ PHP_EVAL_LIBLINE([$PTHREAD_LIBS],[MONGODB_SHARED_LIBADD])
+
+ # PTHREAD_CFLAGS may come back as "-pthread", which should also be used when
+ # linking. We can trust PHP_EVAL_LIBLINE to ignore other values.
+ PHP_EVAL_LIBLINE([$PTHREAD_CFLAGS],[MONGODB_SHARED_LIBADD])
+],[
+ AC_MSG_ERROR([libmongoc requires pthreads on non-Windows platforms.])
+])
diff --git a/mongodb-1.13.0/scripts/autotools/libmongoc/PlatformFlags.m4 b/mongodb-1.13.0/scripts/autotools/libmongoc/PlatformFlags.m4
new file mode 100644
index 00000000..72677c02
--- /dev/null
+++ b/mongodb-1.13.0/scripts/autotools/libmongoc/PlatformFlags.m4
@@ -0,0 +1,10 @@
+dnl Ignore OpenSSL deprecation warnings on OSX
+AS_IF([test "$os_darwin" = "yes"],
+ [AX_CHECK_COMPILE_FLAG([-Wno-deprecated-declarations], [STD_CFLAGS="$STD_CFLAGS -Wno-deprecated-declarations"])])
+dnl We know there are some cast-align issues on OSX
+AS_IF([test "$os_darwin" = "yes"],
+ [AX_CHECK_COMPILE_FLAG([-Wno-cast-align], [STD_CFLAGS="$STD_CFLAGS -Wno-cast-align"])])
+AS_IF([test "$os_darwin" = "yes"],
+ [AX_CHECK_COMPILE_FLAG([-Wno-unneeded-internal-declaration], [STD_CFLAGS="$STD_CFLAGS -Wno-unneeded-internal-declaration"])])
+AS_IF([test "$os_darwin" = "yes"],
+ [AX_CHECK_COMPILE_FLAG([-Wno-error=unused-command-line-argument], [STD_CFLAGS="$STD_CFLAGS -Wno-error=unused-command-line-argument"])])
diff --git a/mongodb-1.12.0/scripts/autotools/libmongoc/Versions.m4 b/mongodb-1.13.0/scripts/autotools/libmongoc/Versions.m4
similarity index 100%
rename from mongodb-1.12.0/scripts/autotools/libmongoc/Versions.m4
rename to mongodb-1.13.0/scripts/autotools/libmongoc/Versions.m4
diff --git a/mongodb-1.12.0/scripts/autotools/libmongoc/WeakSymbols.m4 b/mongodb-1.13.0/scripts/autotools/libmongoc/WeakSymbols.m4
similarity index 100%
rename from mongodb-1.12.0/scripts/autotools/libmongoc/WeakSymbols.m4
rename to mongodb-1.13.0/scripts/autotools/libmongoc/WeakSymbols.m4
diff --git a/mongodb-1.12.0/scripts/autotools/libmongocrypt/CheckSSL.m4 b/mongodb-1.13.0/scripts/autotools/libmongocrypt/CheckSSL.m4
similarity index 100%
rename from mongodb-1.12.0/scripts/autotools/libmongocrypt/CheckSSL.m4
rename to mongodb-1.13.0/scripts/autotools/libmongocrypt/CheckSSL.m4
diff --git a/mongodb-1.12.0/scripts/autotools/libmongocrypt/Endian.m4 b/mongodb-1.13.0/scripts/autotools/libmongocrypt/Endian.m4
similarity index 100%
rename from mongodb-1.12.0/scripts/autotools/libmongocrypt/Endian.m4
rename to mongodb-1.13.0/scripts/autotools/libmongocrypt/Endian.m4
diff --git a/mongodb-1.12.0/scripts/autotools/libmongocrypt/Version.m4 b/mongodb-1.13.0/scripts/autotools/libmongocrypt/Version.m4
similarity index 100%
rename from mongodb-1.12.0/scripts/autotools/libmongocrypt/Version.m4
rename to mongodb-1.13.0/scripts/autotools/libmongocrypt/Version.m4
diff --git a/mongodb-1.12.0/scripts/autotools/m4/as_var_copy.m4 b/mongodb-1.13.0/scripts/autotools/m4/as_var_copy.m4
similarity index 100%
rename from mongodb-1.12.0/scripts/autotools/m4/as_var_copy.m4
rename to mongodb-1.13.0/scripts/autotools/m4/as_var_copy.m4
diff --git a/mongodb-1.12.0/scripts/autotools/m4/ax_check_compile_flag.m4 b/mongodb-1.13.0/scripts/autotools/m4/ax_check_compile_flag.m4
similarity index 100%
rename from mongodb-1.12.0/scripts/autotools/m4/ax_check_compile_flag.m4
rename to mongodb-1.13.0/scripts/autotools/m4/ax_check_compile_flag.m4
diff --git a/mongodb-1.12.0/scripts/autotools/m4/ax_prototype.m4 b/mongodb-1.13.0/scripts/autotools/m4/ax_prototype.m4
similarity index 100%
rename from mongodb-1.12.0/scripts/autotools/m4/ax_prototype.m4
rename to mongodb-1.13.0/scripts/autotools/m4/ax_prototype.m4
diff --git a/mongodb-1.12.0/scripts/autotools/m4/ax_pthread.m4 b/mongodb-1.13.0/scripts/autotools/m4/ax_pthread.m4
similarity index 100%
rename from mongodb-1.12.0/scripts/autotools/m4/ax_pthread.m4
rename to mongodb-1.13.0/scripts/autotools/m4/ax_pthread.m4
diff --git a/mongodb-1.12.0/scripts/autotools/m4/php_mongodb.m4 b/mongodb-1.13.0/scripts/autotools/m4/php_mongodb.m4
similarity index 100%
rename from mongodb-1.12.0/scripts/autotools/m4/php_mongodb.m4
rename to mongodb-1.13.0/scripts/autotools/m4/php_mongodb.m4
diff --git a/mongodb-1.12.0/scripts/autotools/m4/pkg.m4 b/mongodb-1.13.0/scripts/autotools/m4/pkg.m4
similarity index 100%
rename from mongodb-1.12.0/scripts/autotools/m4/pkg.m4
rename to mongodb-1.13.0/scripts/autotools/m4/pkg.m4
diff --git a/mongodb-1.12.0/scripts/clang-format.sh b/mongodb-1.13.0/scripts/clang-format.sh
similarity index 100%
rename from mongodb-1.12.0/scripts/clang-format.sh
rename to mongodb-1.13.0/scripts/clang-format.sh
diff --git a/mongodb-1.12.0/scripts/convert-bson-corpus-tests.php b/mongodb-1.13.0/scripts/convert-bson-corpus-tests.php
similarity index 100%
rename from mongodb-1.12.0/scripts/convert-bson-corpus-tests.php
rename to mongodb-1.13.0/scripts/convert-bson-corpus-tests.php
diff --git a/mongodb-1.13.0/scripts/mongo-orchestration.php b/mongodb-1.13.0/scripts/mongo-orchestration.php
new file mode 100644
index 00000000..5fa0f295
--- /dev/null
+++ b/mongodb-1.13.0/scripts/mongo-orchestration.php
@@ -0,0 +1,138 @@
+<?php
+
+declare(strict_types=1);
+
+set_error_handler(function($errno, $errstr, $errfile, $errline) {
+ fprintf(STDERR, "%s\n", $errstr);
+ exit(1);
+});
+
+set_exception_handler(function($e) {
+ fprintf(STDERR, "%s: %s\n", get_class($e), $e->getMessage());
+ exit(1);
+});
+
+function getId(string $config): string {
+ $config = json_decode($config, null, 512, JSON_THROW_ON_ERROR);
+
+ if (!isset($config->id) || !is_string($config->id)) {
+ throw new UnexpectedValueException('Could not determine id');
+ }
+
+ return $config->id;
+}
+
+function getTopology(string $file): string {
+ $topology = basename(dirname($file));
+
+ if (!in_array($topology, ['servers', 'replica_sets', 'sharded_clusters'])) {
+ throw new UnexpectedValueException('Unsupported topology: ' . $topology);
+ }
+
+ return $topology;
+}
+
+function request(string $uri, array $options = []): stdClass {
+ $options += [
+ 'method' => 'GET',
+ 'header' => 'Accept: application/json',
+ 'ignore_errors' => true,
+ ];
+ $response = file_get_contents($uri, false, stream_context_create(['http' => $options]));
+
+ if (preg_match('#HTTP/1.[01] ([0-9]+)#', $http_response_header[0], $matches) !== 1) {
+ throw new UnexpectedValueException('Could not determine HTTP response code');
+ }
+
+ $code = (int) $matches[1];
+
+ if ($code !== 200) {
+ throw new UnexpectedValueException(sprintf("%s %s returned HTTP response code: %d\n\n%s", $options['method'] ?? 'GET', $uri, $code, $response));
+ }
+
+ return json_decode($response, null, 512, JSON_THROW_ON_ERROR);
+}
+
+function start(string $uri, string $config): void {
+ $options = [
+ 'method' => 'POST',
+ 'header' => "Accept: application/json\r\n" .
+ "Content-type: application/x-www-form-urlencoded",
+ 'content' => $config,
+ 'timeout' => 120,
+ ];
+
+ printf("%s\n", json_encode(request($uri, $options), JSON_PRETTY_PRINT));
+}
+
+function status(string $uri): void {
+ printf("%s\n", json_encode(request($uri), JSON_PRETTY_PRINT));
+}
+
+function stop(string $uri): void {
+ $options = [
+ 'method' => 'DELETE',
+ 'header' => "Accept: application/json\r\n" .
+ "Content-type: application/x-www-form-urlencoded",
+ 'content' => $config,
+ 'timeout' => 120,
+ ];
+
+ printf("%s\n", json_encode(request($uri, $options), JSON_PRETTY_PRINT));
+}
+
+function usage(): void {
+ global $argv;
+
+ fprintf(STDERR, "usage: %s <action> <id>|<path/to/config.json>\n", $argv[0]);
+ fprintf(STDERR, "action: start|status|stop\n");
+ exit(1);
+}
+
+$tools = getenv('DRIVER_TOOLS') ?: '/home/jmikola/workspace/mongodb/drivers-evergreen-tools';
+$server = getenv('MONGO_ORCHESTRATION_URI') ?: 'http://localhost:8889';
+
+if ($argc < 2) {
+ usage();
+}
+
+$action = $argv[1] ?? null;
+
+switch ($action) {
+ case 'start':
+ $file = $argv[2];
+
+ if (!is_readable($file)) {
+ throw new UnexpectedValueException('Cannot read input file');
+ }
+
+ $topology = getTopology($file);
+
+ $config = file_get_contents($file);
+ $config = str_replace('ABSOLUTE_PATH_REPLACEMENT_TOKEN', $tools, $config);
+ start(sprintf('%s/v1/%s', $server, $topology), $config);
+ break;
+
+ case 'status':
+ $topology = $argv[2];
+ $id = $argv[3];
+ status(sprintf('%s/v1/%s/%s', $server, $topology, $id));
+ break;
+
+ case 'stop':
+ $topology = $argv[2];
+ $id = $argv[3];
+ stop(sprintf('%s/v1/%s/%s', $server, $topology, $id));
+ break;
+
+ case 'list':
+ foreach (['servers', 'replica_sets', 'sharded_clusters'] as $topology) {
+ $response = request(sprintf('%s/v1/%s', $server, $topology));
+ printf("%s:\n", $topology);
+ printf("%s\n\n", json_encode($response->$topology, JSON_PRETTY_PRINT));
+ }
+ break;
+
+ default:
+ usage();
+}
diff --git a/mongodb-1.12.0/scripts/update-submodule-sources.php b/mongodb-1.13.0/scripts/update-submodule-sources.php
similarity index 100%
rename from mongodb-1.12.0/scripts/update-submodule-sources.php
rename to mongodb-1.13.0/scripts/update-submodule-sources.php
diff --git a/mongodb-1.13.0/src/BSON/Binary.c b/mongodb-1.13.0/src/BSON/Binary.c
new file mode 100644
index 00000000..27922981
--- /dev/null
+++ b/mongodb-1.13.0/src/BSON/Binary.c
@@ -0,0 +1,477 @@
+/*
+ * Copyright 2014-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <php.h>
+#include <zend_smart_str.h>
+#include <ext/standard/base64.h>
+#include <ext/standard/php_var.h>
+#include <Zend/zend_interfaces.h>
+
+#include "php_phongo.h"
+#include "phongo_error.h"
+
+#define PHONGO_BINARY_UUID_SIZE 16
+
+zend_class_entry* php_phongo_binary_ce;
+
+/* Initialize the object and return whether it was successful. An exception will
+ * be thrown on error. */
+static bool php_phongo_binary_init(php_phongo_binary_t* intern, const char* data, size_t data_len, zend_long type) /* {{{ */
+{
+ if (type < 0 || type > UINT8_MAX) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected type to be an unsigned 8-bit integer, %" PHONGO_LONG_FORMAT " given", type);
+ return false;
+ }
+
+ if ((type == BSON_SUBTYPE_UUID_DEPRECATED || type == BSON_SUBTYPE_UUID) && data_len != PHONGO_BINARY_UUID_SIZE) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected UUID length to be %d bytes, %d given", PHONGO_BINARY_UUID_SIZE, data_len);
+ return false;
+ }
+
+ intern->data = estrndup(data, data_len);
+ intern->data_len = data_len;
+ intern->type = (uint8_t) type;
+
+ return true;
+} /* }}} */
+
+/* Initialize the object from a HashTable and return whether it was successful.
+ * An exception will be thrown on error. */
+static bool php_phongo_binary_init_from_hash(php_phongo_binary_t* intern, HashTable* props) /* {{{ */
+{
+ zval *data, *type;
+
+ if ((data = zend_hash_str_find(props, "data", sizeof("data") - 1)) && Z_TYPE_P(data) == IS_STRING &&
+ (type = zend_hash_str_find(props, "type", sizeof("type") - 1)) && Z_TYPE_P(type) == IS_LONG) {
+
+ return php_phongo_binary_init(intern, Z_STRVAL_P(data), Z_STRLEN_P(data), Z_LVAL_P(type));
+ }
+
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"data\" string and \"type\" integer fields", ZSTR_VAL(php_phongo_binary_ce->name));
+ return false;
+} /* }}} */
+
+static HashTable* php_phongo_binary_get_properties_hash(phongo_compat_object_handler_type* object, bool is_temp) /* {{{ */
+{
+ php_phongo_binary_t* intern;
+ HashTable* props;
+
+ intern = Z_OBJ_BINARY(PHONGO_COMPAT_GET_OBJ(object));
+
+ PHONGO_GET_PROPERTY_HASH_INIT_PROPS(is_temp, intern, props, 2);
+
+ if (!intern->data) {
+ return props;
+ }
+
+ {
+ zval data, type;
+
+ ZVAL_STRINGL(&data, intern->data, intern->data_len);
+ zend_hash_str_update(props, "data", sizeof("data") - 1, &data);
+
+ ZVAL_LONG(&type, intern->type);
+ zend_hash_str_update(props, "type", sizeof("type") - 1, &type);
+ }
+
+ return props;
+} /* }}} */
+
+/* {{{ proto void MongoDB\BSON\Binary::__construct(string $data, int $type)
+ Construct a new BSON binary type */
+static PHP_METHOD(Binary, __construct)
+{
+ zend_error_handling error_handling;
+ php_phongo_binary_t* intern;
+ char* data;
+ size_t data_len;
+ zend_long type;
+
+ intern = Z_BINARY_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "sl", &data, &data_len, &type) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ php_phongo_binary_init(intern, data, data_len, type);
+} /* }}} */
+
+/* {{{ proto MongoDB\BSON\Binary MongoDB\BSON\Binary::__set_state(array $properties)
+*/
+static PHP_METHOD(Binary, __set_state)
+{
+ zend_error_handling error_handling;
+ php_phongo_binary_t* intern;
+ HashTable* props;
+ zval* array;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &array) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ object_init_ex(return_value, php_phongo_binary_ce);
+
+ intern = Z_BINARY_OBJ_P(return_value);
+ props = Z_ARRVAL_P(array);
+
+ php_phongo_binary_init_from_hash(intern, props);
+} /* }}} */
+
+/* {{{ proto string MongoDB\BSON\Binary::__toString()
+ Return the Binary's data string. */
+static PHP_METHOD(Binary, __toString)
+{
+ zend_error_handling error_handling;
+ php_phongo_binary_t* intern;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ intern = Z_BINARY_OBJ_P(getThis());
+
+ RETURN_STRINGL(intern->data, intern->data_len);
+} /* }}} */
+
+/* {{{ proto string MongoDB\BSON\Binary::getData()
+*/
+static PHP_METHOD(Binary, getData)
+{
+ zend_error_handling error_handling;
+ php_phongo_binary_t* intern;
+
+ intern = Z_BINARY_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ RETURN_STRINGL(intern->data, intern->data_len);
+} /* }}} */
+
+/* {{{ proto integer MongoDB\BSON\Binary::getType()
+*/
+static PHP_METHOD(Binary, getType)
+{
+ zend_error_handling error_handling;
+ php_phongo_binary_t* intern;
+
+ intern = Z_BINARY_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ RETURN_LONG(intern->type);
+} /* }}} */
+
+/* {{{ proto array MongoDB\BSON\Binary::jsonSerialize()
+*/
+static PHP_METHOD(Binary, jsonSerialize)
+{
+ zend_error_handling error_handling;
+ php_phongo_binary_t* intern;
+ char type[3];
+ int type_len;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ intern = Z_BINARY_OBJ_P(getThis());
+
+ array_init_size(return_value, 2);
+
+ {
+ zend_string* data = php_base64_encode((unsigned char*) intern->data, intern->data_len);
+ ADD_ASSOC_STRINGL(return_value, "$binary", ZSTR_VAL(data), ZSTR_LEN(data));
+ zend_string_free(data);
+ }
+
+ type_len = snprintf(type, sizeof(type), "%02x", intern->type);
+ ADD_ASSOC_STRINGL(return_value, "$type", type, type_len);
+} /* }}} */
+
+/* {{{ proto string MongoDB\BSON\Binary::serialize()
+*/
+static PHP_METHOD(Binary, serialize)
+{
+ zend_error_handling error_handling;
+ php_phongo_binary_t* intern;
+ zval retval;
+ php_serialize_data_t var_hash;
+ smart_str buf = { 0 };
+
+ intern = Z_BINARY_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ array_init_size(&retval, 2);
+ ADD_ASSOC_STRINGL(&retval, "data", intern->data, intern->data_len);
+ ADD_ASSOC_LONG_EX(&retval, "type", intern->type);
+
+ PHP_VAR_SERIALIZE_INIT(var_hash);
+ php_var_serialize(&buf, &retval, &var_hash);
+ smart_str_0(&buf);
+ PHP_VAR_SERIALIZE_DESTROY(var_hash);
+
+ PHONGO_RETVAL_SMART_STR(buf);
+
+ smart_str_free(&buf);
+ zval_ptr_dtor(&retval);
+} /* }}} */
+
+/* {{{ proto void MongoDB\BSON\Binary::unserialize(string $serialized)
+*/
+static PHP_METHOD(Binary, unserialize)
+{
+ zend_error_handling error_handling;
+ php_phongo_binary_t* intern;
+ char* serialized;
+ size_t serialized_len;
+ zval props;
+ php_unserialize_data_t var_hash;
+
+ intern = Z_BINARY_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &serialized, &serialized_len) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ PHP_VAR_UNSERIALIZE_INIT(var_hash);
+ if (!php_var_unserialize(&props, (const unsigned char**) &serialized, (unsigned char*) serialized + serialized_len, &var_hash)) {
+ zval_ptr_dtor(&props);
+ phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "%s unserialization failed", ZSTR_VAL(php_phongo_binary_ce->name));
+
+ PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+ return;
+ }
+ PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+
+ php_phongo_binary_init_from_hash(intern, HASH_OF(&props));
+ zval_ptr_dtor(&props);
+} /* }}} */
+
+/* {{{ proto array MongoDB\Driver\Binary::__serialize()
+*/
+static PHP_METHOD(Binary, __serialize)
+{
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ RETURN_ARR(php_phongo_binary_get_properties_hash(PHONGO_COMPAT_OBJ_P(getThis()), true));
+} /* }}} */
+
+/* {{{ proto void MongoDB\Driver\Binary::__unserialize(array $data)
+*/
+static PHP_METHOD(Binary, __unserialize)
+{
+ zval* data;
+
+ PHONGO_PARSE_PARAMETERS_START(1, 1)
+ Z_PARAM_ARRAY(data)
+ PHONGO_PARSE_PARAMETERS_END();
+
+ php_phongo_binary_init_from_hash(Z_BINARY_OBJ_P(getThis()), Z_ARRVAL_P(data));
+} /* }}} */
+
+/* {{{ MongoDB\BSON\Binary function entries */
+/* clang-format off */
+ZEND_BEGIN_ARG_INFO_EX(ai_Binary___construct, 0, 0, 2)
+ ZEND_ARG_INFO(0, data)
+ ZEND_ARG_INFO(0, type)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_Binary___set_state, 0, 0, 1)
+ ZEND_ARG_ARRAY_INFO(0, properties, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(ai_Binary___toString, 0, 0, IS_STRING, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_Binary___unserialize, 0, 0, 1)
+ ZEND_ARG_ARRAY_INFO(0, data, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(ai_Binary_jsonSerialize, 0, 0, IS_ARRAY, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_Binary_unserialize, 0, 0, 1)
+ ZEND_ARG_INFO(0, serialized)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_Binary_void, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry php_phongo_binary_me[] = {
+ PHP_ME(Binary, __construct, ai_Binary___construct, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Binary, __serialize, ai_Binary_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Binary, __set_state, ai_Binary___set_state, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+ PHP_ME(Binary, __toString, ai_Binary___toString, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Binary, __unserialize, ai_Binary___unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Binary, jsonSerialize, ai_Binary_jsonSerialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Binary, serialize, ai_Binary_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Binary, unserialize, ai_Binary_unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Binary, getData, ai_Binary_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Binary, getType, ai_Binary_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_FE_END
+};
+/* clang-format on */
+/* }}} */
+
+/* {{{ MongoDB\BSON\Binary object handlers */
+static zend_object_handlers php_phongo_handler_binary;
+
+static void php_phongo_binary_free_object(zend_object* object) /* {{{ */
+{
+ php_phongo_binary_t* intern = Z_OBJ_BINARY(object);
+
+ zend_object_std_dtor(&intern->std);
+
+ if (intern->data) {
+ efree(intern->data);
+ }
+
+ if (intern->properties) {
+ zend_hash_destroy(intern->properties);
+ FREE_HASHTABLE(intern->properties);
+ }
+} /* }}} */
+
+static zend_object* php_phongo_binary_create_object(zend_class_entry* class_type) /* {{{ */
+{
+ php_phongo_binary_t* intern = zend_object_alloc(sizeof(php_phongo_binary_t), class_type);
+
+ zend_object_std_init(&intern->std, class_type);
+ object_properties_init(&intern->std, class_type);
+
+ intern->std.handlers = &php_phongo_handler_binary;
+
+ return &intern->std;
+} /* }}} */
+
+static zend_object* php_phongo_binary_clone_object(phongo_compat_object_handler_type* object) /* {{{ */
+{
+ php_phongo_binary_t* intern;
+ php_phongo_binary_t* new_intern;
+ zend_object* new_object;
+
+ intern = Z_OBJ_BINARY(PHONGO_COMPAT_GET_OBJ(object));
+ new_object = php_phongo_binary_create_object(PHONGO_COMPAT_GET_OBJ(object)->ce);
+
+ new_intern = Z_OBJ_BINARY(new_object);
+ zend_objects_clone_members(&new_intern->std, &intern->std);
+
+ php_phongo_binary_init(new_intern, intern->data, intern->data_len, intern->type);
+
+ return new_object;
+} /* }}} */
+
+static int php_phongo_binary_compare_objects(zval* o1, zval* o2) /* {{{ */
+{
+ php_phongo_binary_t *intern1, *intern2;
+
+ ZEND_COMPARE_OBJECTS_FALLBACK(o1, o2);
+
+ intern1 = Z_BINARY_OBJ_P(o1);
+ intern2 = Z_BINARY_OBJ_P(o2);
+
+ /* MongoDB compares binary types first by the data length, then by the type
+ * byte, and finally by the binary data itself. */
+ if (intern1->data_len != intern2->data_len) {
+ return intern1->data_len < intern2->data_len ? -1 : 1;
+ }
+
+ if (intern1->type != intern2->type) {
+ return intern1->type < intern2->type ? -1 : 1;
+ }
+
+ return zend_binary_strcmp(intern1->data, intern1->data_len, intern2->data, intern2->data_len);
+} /* }}} */
+
+static HashTable* php_phongo_binary_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
+{
+ *is_temp = 1;
+ return php_phongo_binary_get_properties_hash(object, true);
+} /* }}} */
+
+static HashTable* php_phongo_binary_get_properties(phongo_compat_object_handler_type* object) /* {{{ */
+{
+ return php_phongo_binary_get_properties_hash(object, false);
+} /* }}} */
+/* }}} */
+
+void php_phongo_binary_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\BSON", "Binary", php_phongo_binary_me);
+ php_phongo_binary_ce = zend_register_internal_class(&ce);
+ php_phongo_binary_ce->create_object = php_phongo_binary_create_object;
+ PHONGO_CE_FINAL(php_phongo_binary_ce);
+
+ zend_class_implements(php_phongo_binary_ce, 1, php_phongo_binary_interface_ce);
+ zend_class_implements(php_phongo_binary_ce, 1, php_phongo_json_serializable_ce);
+ zend_class_implements(php_phongo_binary_ce, 1, php_phongo_type_ce);
+ zend_class_implements(php_phongo_binary_ce, 1, zend_ce_serializable);
+
+#if PHP_VERSION_ID >= 80000
+ zend_class_implements(php_phongo_binary_ce, 1, zend_ce_stringable);
+#endif
+
+ memcpy(&php_phongo_handler_binary, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
+ PHONGO_COMPAT_SET_COMPARE_OBJECTS_HANDLER(binary);
+ php_phongo_handler_binary.clone_obj = php_phongo_binary_clone_object;
+ php_phongo_handler_binary.get_debug_info = php_phongo_binary_get_debug_info;
+ php_phongo_handler_binary.get_properties = php_phongo_binary_get_properties;
+ php_phongo_handler_binary.free_obj = php_phongo_binary_free_object;
+ php_phongo_handler_binary.offset = XtOffsetOf(php_phongo_binary_t, std);
+
+ zend_declare_class_constant_long(php_phongo_binary_ce, ZEND_STRL("TYPE_GENERIC"), BSON_SUBTYPE_BINARY);
+ zend_declare_class_constant_long(php_phongo_binary_ce, ZEND_STRL("TYPE_FUNCTION"), BSON_SUBTYPE_FUNCTION);
+ zend_declare_class_constant_long(php_phongo_binary_ce, ZEND_STRL("TYPE_OLD_BINARY"), BSON_SUBTYPE_BINARY_DEPRECATED);
+ zend_declare_class_constant_long(php_phongo_binary_ce, ZEND_STRL("TYPE_OLD_UUID"), BSON_SUBTYPE_UUID_DEPRECATED);
+ zend_declare_class_constant_long(php_phongo_binary_ce, ZEND_STRL("TYPE_UUID"), BSON_SUBTYPE_UUID);
+ zend_declare_class_constant_long(php_phongo_binary_ce, ZEND_STRL("TYPE_MD5"), BSON_SUBTYPE_MD5);
+ zend_declare_class_constant_long(php_phongo_binary_ce, ZEND_STRL("TYPE_ENCRYPTED"), BSON_SUBTYPE_ENCRYPTED);
+ zend_declare_class_constant_long(php_phongo_binary_ce, ZEND_STRL("TYPE_COLUMN"), BSON_SUBTYPE_COLUMN);
+ zend_declare_class_constant_long(php_phongo_binary_ce, ZEND_STRL("TYPE_USER_DEFINED"), BSON_SUBTYPE_USER);
+} /* }}} */
diff --git a/mongodb-1.13.0/src/BSON/BinaryInterface.c b/mongodb-1.13.0/src/BSON/BinaryInterface.c
new file mode 100644
index 00000000..2d02e7d9
--- /dev/null
+++ b/mongodb-1.13.0/src/BSON/BinaryInterface.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2017-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <php.h>
+
+#include "php_phongo.h"
+
+zend_class_entry* php_phongo_binary_interface_ce;
+
+/* {{{ MongoDB\BSON\BinaryInterface function entries */
+/* clang-format off */
+ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(ai_BinaryInterface___toString, 0, 0, IS_STRING, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_BinaryInterface_void, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry php_phongo_binary_interface_me[] = {
+ ZEND_ABSTRACT_ME(BinaryInterface, getData, ai_BinaryInterface_void)
+ ZEND_ABSTRACT_ME(BinaryInterface, getType, ai_BinaryInterface_void)
+ ZEND_ABSTRACT_ME(BinaryInterface, __toString, ai_BinaryInterface___toString)
+ PHP_FE_END
+};
+/* clang-format on */
+/* }}} */
+
+void php_phongo_binary_interface_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\BSON", "BinaryInterface", php_phongo_binary_interface_me);
+ php_phongo_binary_interface_ce = zend_register_internal_interface(&ce);
+} /* }}} */
diff --git a/mongodb-1.13.0/src/BSON/DBPointer.c b/mongodb-1.13.0/src/BSON/DBPointer.c
new file mode 100644
index 00000000..9c11f717
--- /dev/null
+++ b/mongodb-1.13.0/src/BSON/DBPointer.c
@@ -0,0 +1,370 @@
+/*
+ * Copyright 2014-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bson/bson.h"
+
+#include <php.h>
+#include <zend_smart_str.h>
+#include <ext/standard/php_var.h>
+#include <Zend/zend_interfaces.h>
+
+#include "php_phongo.h"
+#include "phongo_error.h"
+
+zend_class_entry* php_phongo_dbpointer_ce;
+
+/* Initialize the object and return whether it was successful. An exception will
+ * be thrown on error. */
+static bool php_phongo_dbpointer_init(php_phongo_dbpointer_t* intern, const char* ref, size_t ref_len, const char* id, size_t id_len) /* {{{ */
+{
+ if (strlen(ref) != (size_t) ref_len) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Ref cannot contain null bytes");
+ return false;
+ }
+
+ if (!bson_oid_is_valid(id, id_len)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Error parsing ObjectId string: %s", id);
+ return false;
+ }
+
+ intern->ref = estrndup(ref, ref_len);
+ intern->ref_len = ref_len;
+
+ memset(intern->id, 0, sizeof(intern->id));
+ strncpy(intern->id, id, sizeof(intern->id) - 1);
+
+ return true;
+} /* }}} */
+
+/* Initialize the object from a HashTable and return whether it was successful.
+ * An exception will be thrown on error. */
+static bool php_phongo_dbpointer_init_from_hash(php_phongo_dbpointer_t* intern, HashTable* props) /* {{{ */
+{
+ zval *ref, *id;
+
+ if ((ref = zend_hash_str_find(props, "ref", sizeof("ref") - 1)) && Z_TYPE_P(ref) == IS_STRING &&
+ (id = zend_hash_str_find(props, "id", sizeof("id") - 1)) && Z_TYPE_P(id) == IS_STRING) {
+
+ return php_phongo_dbpointer_init(intern, Z_STRVAL_P(ref), Z_STRLEN_P(ref), Z_STRVAL_P(id), Z_STRLEN_P(id));
+ }
+
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"ref\" and \"id\" string fields", ZSTR_VAL(php_phongo_dbpointer_ce->name));
+ return false;
+} /* }}} */
+
+HashTable* php_phongo_dbpointer_get_properties_hash(phongo_compat_object_handler_type* object, bool is_temp) /* {{{ */
+{
+ php_phongo_dbpointer_t* intern;
+ HashTable* props;
+
+ intern = Z_OBJ_DBPOINTER(PHONGO_COMPAT_GET_OBJ(object));
+
+ PHONGO_GET_PROPERTY_HASH_INIT_PROPS(is_temp, intern, props, 2);
+
+ if (!intern->ref) {
+ return props;
+ }
+
+ {
+ zval ref, id;
+
+ ZVAL_STRING(&ref, intern->ref);
+ ZVAL_STRING(&id, intern->id);
+ zend_hash_str_update(props, "ref", sizeof("ref") - 1, &ref);
+ zend_hash_str_update(props, "id", sizeof("id") - 1, &id);
+ }
+
+ return props;
+} /* }}} */
+
+/* {{{ proto string MongoDB\BSON\DBPointer::__toString()
+ Return the DBPointer's namespace string and ObjectId. */
+static PHP_METHOD(DBPointer, __toString)
+{
+ zend_error_handling error_handling;
+ php_phongo_dbpointer_t* intern;
+ char* retval;
+ int retval_len;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ intern = Z_DBPOINTER_OBJ_P(getThis());
+
+ retval_len = spprintf(&retval, 0, "[%s/%s]", intern->ref, intern->id);
+ RETVAL_STRINGL(retval, retval_len);
+ efree(retval);
+} /* }}} */
+
+/* {{{ proto array MongoDB\BSON\Symbol::jsonSerialize()
+*/
+static PHP_METHOD(DBPointer, jsonSerialize)
+{
+ zend_error_handling error_handling;
+ php_phongo_dbpointer_t* intern;
+ zval zdb_pointer;
+ zval zoid;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ intern = Z_DBPOINTER_OBJ_P(getThis());
+
+ array_init_size(&zdb_pointer, 2);
+ array_init_size(&zoid, 1);
+ ADD_ASSOC_STRINGL(&zdb_pointer, "$ref", intern->ref, intern->ref_len);
+ ADD_ASSOC_STRING(&zoid, "$oid", intern->id);
+ ADD_ASSOC_ZVAL(&zdb_pointer, "$id", &zoid);
+
+ array_init_size(return_value, 1);
+ ADD_ASSOC_ZVAL(return_value, "$dbPointer", &zdb_pointer);
+} /* }}} */
+
+/* {{{ proto string MongoDB\BSON\DBPointer::serialize()
+*/
+static PHP_METHOD(DBPointer, serialize)
+{
+ zend_error_handling error_handling;
+ php_phongo_dbpointer_t* intern;
+ zval retval;
+ php_serialize_data_t var_hash;
+ smart_str buf = { 0 };
+
+ intern = Z_DBPOINTER_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ array_init_size(&retval, 2);
+ ADD_ASSOC_STRINGL(&retval, "ref", intern->ref, intern->ref_len);
+ ADD_ASSOC_STRING(&retval, "id", intern->id);
+
+ PHP_VAR_SERIALIZE_INIT(var_hash);
+ php_var_serialize(&buf, &retval, &var_hash);
+ smart_str_0(&buf);
+ PHP_VAR_SERIALIZE_DESTROY(var_hash);
+
+ PHONGO_RETVAL_SMART_STR(buf);
+
+ smart_str_free(&buf);
+ zval_ptr_dtor(&retval);
+} /* }}} */
+
+/* {{{ proto void MongoDB\BSON\DBPointer::unserialize(string $serialized)
+*/
+static PHP_METHOD(DBPointer, unserialize)
+{
+ zend_error_handling error_handling;
+ php_phongo_dbpointer_t* intern;
+ char* serialized;
+ size_t serialized_len;
+ zval props;
+ php_unserialize_data_t var_hash;
+
+ intern = Z_DBPOINTER_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &serialized, &serialized_len) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ PHP_VAR_UNSERIALIZE_INIT(var_hash);
+ if (!php_var_unserialize(&props, (const unsigned char**) &serialized, (unsigned char*) serialized + serialized_len, &var_hash)) {
+ zval_ptr_dtor(&props);
+ phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "%s unserialization failed", ZSTR_VAL(php_phongo_dbpointer_ce->name));
+
+ PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+ return;
+ }
+ PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+
+ php_phongo_dbpointer_init_from_hash(intern, HASH_OF(&props));
+ zval_ptr_dtor(&props);
+} /* }}} */
+
+/* {{{ proto array MongoDB\Driver\DBPointer::__serialize()
+*/
+static PHP_METHOD(DBPointer, __serialize)
+{
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ RETURN_ARR(php_phongo_dbpointer_get_properties_hash(PHONGO_COMPAT_OBJ_P(getThis()), true));
+} /* }}} */
+
+/* {{{ proto void MongoDB\Driver\DBPointer::__unserialize(array $data)
+*/
+static PHP_METHOD(DBPointer, __unserialize)
+{
+ zval* data;
+
+ PHONGO_PARSE_PARAMETERS_START(1, 1)
+ Z_PARAM_ARRAY(data)
+ PHONGO_PARSE_PARAMETERS_END();
+
+ php_phongo_dbpointer_init_from_hash(Z_DBPOINTER_OBJ_P(getThis()), Z_ARRVAL_P(data));
+} /* }}} */
+
+/* {{{ MongoDB\BSON\DBPointer function entries */
+/* clang-format off */
+ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(ai_DBPointer___toString, 0, 0, IS_STRING, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_DBPointer___unserialize, 0, 0, 1)
+ ZEND_ARG_ARRAY_INFO(0, data, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(ai_DBPointer_jsonSerialize, 0, 0, IS_ARRAY, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_DBPointer_unserialize, 0, 0, 1)
+ ZEND_ARG_INFO(0, serialized)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_DBPointer_void, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry php_phongo_dbpointer_me[] = {
+ /* __set_state intentionally missing */
+ PHP_ME(DBPointer, __serialize, ai_DBPointer_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(DBPointer, __toString, ai_DBPointer___toString, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(DBPointer, __unserialize, ai_DBPointer___unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(DBPointer, jsonSerialize, ai_DBPointer_jsonSerialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(DBPointer, serialize, ai_DBPointer_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(DBPointer, unserialize, ai_DBPointer_unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ ZEND_NAMED_ME(__construct, PHP_FN(MongoDB_disabled___construct), ai_DBPointer_void, ZEND_ACC_PRIVATE | ZEND_ACC_FINAL)
+ PHP_FE_END
+};
+/* clang-format on */
+/* }}} */
+
+/* {{{ MongoDB\BSON\DBPointer object handlers */
+static zend_object_handlers php_phongo_handler_dbpointer;
+
+static void php_phongo_dbpointer_free_object(zend_object* object) /* {{{ */
+{
+ php_phongo_dbpointer_t* intern = Z_OBJ_DBPOINTER(object);
+
+ zend_object_std_dtor(&intern->std);
+
+ if (intern->ref) {
+ efree(intern->ref);
+ }
+
+ if (intern->properties) {
+ zend_hash_destroy(intern->properties);
+ FREE_HASHTABLE(intern->properties);
+ }
+} /* }}} */
+
+zend_object* php_phongo_dbpointer_create_object(zend_class_entry* class_type) /* {{{ */
+{
+ php_phongo_dbpointer_t* intern = zend_object_alloc(sizeof(php_phongo_dbpointer_t), class_type);
+
+ zend_object_std_init(&intern->std, class_type);
+ object_properties_init(&intern->std, class_type);
+
+ intern->std.handlers = &php_phongo_handler_dbpointer;
+
+ return &intern->std;
+} /* }}} */
+
+static zend_object* php_phongo_dbpointer_clone_object(phongo_compat_object_handler_type* object) /* {{{ */
+{
+ php_phongo_dbpointer_t* intern;
+ php_phongo_dbpointer_t* new_intern;
+ zend_object* new_object;
+
+ intern = Z_OBJ_DBPOINTER(PHONGO_COMPAT_GET_OBJ(object));
+ new_object = php_phongo_dbpointer_create_object(PHONGO_COMPAT_GET_OBJ(object)->ce);
+
+ new_intern = Z_OBJ_DBPOINTER(new_object);
+ zend_objects_clone_members(&new_intern->std, &intern->std);
+
+ php_phongo_dbpointer_init(new_intern, intern->ref, intern->ref_len, intern->id, 24);
+
+ return new_object;
+} /* }}} */
+
+static int php_phongo_dbpointer_compare_objects(zval* o1, zval* o2) /* {{{ */
+{
+ php_phongo_dbpointer_t *intern1, *intern2;
+ int retval;
+
+ ZEND_COMPARE_OBJECTS_FALLBACK(o1, o2);
+
+ intern1 = Z_DBPOINTER_OBJ_P(o1);
+ intern2 = Z_DBPOINTER_OBJ_P(o2);
+
+ retval = strcmp(intern1->ref, intern2->ref);
+
+ if (retval != 0) {
+ return retval;
+ }
+
+ return strcmp(intern1->id, intern2->id);
+} /* }}} */
+
+static HashTable* php_phongo_dbpointer_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
+{
+ *is_temp = 1;
+ return php_phongo_dbpointer_get_properties_hash(object, true);
+} /* }}} */
+
+static HashTable* php_phongo_dbpointer_get_properties(phongo_compat_object_handler_type* object) /* {{{ */
+{
+ return php_phongo_dbpointer_get_properties_hash(object, false);
+} /* }}} */
+/* }}} */
+
+void php_phongo_dbpointer_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\BSON", "DBPointer", php_phongo_dbpointer_me);
+ php_phongo_dbpointer_ce = zend_register_internal_class(&ce);
+ php_phongo_dbpointer_ce->create_object = php_phongo_dbpointer_create_object;
+ PHONGO_CE_FINAL(php_phongo_dbpointer_ce);
+
+ zend_class_implements(php_phongo_dbpointer_ce, 1, php_phongo_json_serializable_ce);
+ zend_class_implements(php_phongo_dbpointer_ce, 1, php_phongo_type_ce);
+ zend_class_implements(php_phongo_dbpointer_ce, 1, zend_ce_serializable);
+
+#if PHP_VERSION_ID >= 80000
+ zend_class_implements(php_phongo_dbpointer_ce, 1, zend_ce_stringable);
+#endif
+
+ memcpy(&php_phongo_handler_dbpointer, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
+ PHONGO_COMPAT_SET_COMPARE_OBJECTS_HANDLER(dbpointer);
+ php_phongo_handler_dbpointer.clone_obj = php_phongo_dbpointer_clone_object;
+ php_phongo_handler_dbpointer.get_debug_info = php_phongo_dbpointer_get_debug_info;
+ php_phongo_handler_dbpointer.get_properties = php_phongo_dbpointer_get_properties;
+ php_phongo_handler_dbpointer.free_obj = php_phongo_dbpointer_free_object;
+ php_phongo_handler_dbpointer.offset = XtOffsetOf(php_phongo_dbpointer_t, std);
+} /* }}} */
diff --git a/mongodb-1.13.0/src/BSON/Decimal128.c b/mongodb-1.13.0/src/BSON/Decimal128.c
new file mode 100644
index 00000000..64b6283c
--- /dev/null
+++ b/mongodb-1.13.0/src/BSON/Decimal128.c
@@ -0,0 +1,386 @@
+/*
+ * Copyright 2015-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bson/bson.h"
+
+#include <php.h>
+#include <zend_smart_str.h>
+#include <ext/standard/php_var.h>
+#include <Zend/zend_interfaces.h>
+
+#include "php_phongo.h"
+#include "phongo_error.h"
+
+zend_class_entry* php_phongo_decimal128_ce;
+
+/* Initialize the object and return whether it was successful. An exception will
+ * be thrown on error. */
+static bool php_phongo_decimal128_init(php_phongo_decimal128_t* intern, const char* value) /* {{{ */
+{
+ if (!bson_decimal128_from_string(value, &intern->decimal)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Error parsing Decimal128 string: %s", value);
+ return false;
+ }
+
+ intern->initialized = true;
+
+ return true;
+} /* }}} */
+
+/* Initialize the object from a HashTable and return whether it was successful.
+ * An exception will be thrown on error. */
+static bool php_phongo_decimal128_init_from_hash(php_phongo_decimal128_t* intern, HashTable* props) /* {{{ */
+{
+ zval* dec;
+
+ if ((dec = zend_hash_str_find(props, "dec", sizeof("dec") - 1)) && Z_TYPE_P(dec) == IS_STRING) {
+ return php_phongo_decimal128_init(intern, Z_STRVAL_P(dec));
+ }
+
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"dec\" string field", ZSTR_VAL(php_phongo_decimal128_ce->name));
+ return false;
+} /* }}} */
+
+static HashTable* php_phongo_decimal128_get_properties_hash(phongo_compat_object_handler_type* object, bool is_temp) /* {{{ */
+{
+ php_phongo_decimal128_t* intern;
+ HashTable* props;
+ char outbuf[BSON_DECIMAL128_STRING] = "";
+
+ intern = Z_OBJ_DECIMAL128(PHONGO_COMPAT_GET_OBJ(object));
+
+ PHONGO_GET_PROPERTY_HASH_INIT_PROPS(is_temp, intern, props, 1);
+
+ if (!intern->initialized) {
+ return props;
+ }
+
+ bson_decimal128_to_string(&intern->decimal, outbuf);
+
+ {
+ zval dec;
+
+ ZVAL_STRING(&dec, outbuf);
+ zend_hash_str_update(props, "dec", sizeof("dec") - 1, &dec);
+ }
+
+ return props;
+} /* }}} */
+
+/* {{{ proto void MongoDB\BSON\Decimal128::__construct(string $value)
+ Construct a new BSON Decimal128 type */
+static PHP_METHOD(Decimal128, __construct)
+{
+ zend_error_handling error_handling;
+ php_phongo_decimal128_t* intern;
+ char* value;
+ size_t value_len;
+
+ intern = Z_DECIMAL128_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &value, &value_len) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ php_phongo_decimal128_init(intern, value);
+} /* }}} */
+
+/* {{{ proto MongoDB\BSON\Decimal128 MongoDB\BSON\Decimal128::__set_state(array $properties)
+*/
+static PHP_METHOD(Decimal128, __set_state)
+{
+ zend_error_handling error_handling;
+ php_phongo_decimal128_t* intern;
+ HashTable* props;
+ zval* array;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &array) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ object_init_ex(return_value, php_phongo_decimal128_ce);
+
+ intern = Z_DECIMAL128_OBJ_P(return_value);
+ props = Z_ARRVAL_P(array);
+
+ php_phongo_decimal128_init_from_hash(intern, props);
+} /* }}} */
+
+/* {{{ proto string MongoDB\BSON\Decimal128::__toString()
+*/
+static PHP_METHOD(Decimal128, __toString)
+{
+ zend_error_handling error_handling;
+ php_phongo_decimal128_t* intern;
+ char outbuf[BSON_DECIMAL128_STRING];
+
+ intern = Z_DECIMAL128_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ bson_decimal128_to_string(&intern->decimal, outbuf);
+
+ RETURN_STRING(outbuf);
+} /* }}} */
+
+/* {{{ proto array MongoDB\BSON\Decimal128::jsonSerialize()
+*/
+static PHP_METHOD(Decimal128, jsonSerialize)
+{
+ zend_error_handling error_handling;
+ php_phongo_decimal128_t* intern;
+ char outbuf[BSON_DECIMAL128_STRING] = "";
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ intern = Z_DECIMAL128_OBJ_P(getThis());
+
+ array_init_size(return_value, 1);
+ bson_decimal128_to_string(&intern->decimal, outbuf);
+ ADD_ASSOC_STRING(return_value, "$numberDecimal", outbuf);
+} /* }}} */
+
+/* {{{ proto string MongoDB\BSON\Decimal128::serialize()
+*/
+static PHP_METHOD(Decimal128, serialize)
+{
+ zend_error_handling error_handling;
+ php_phongo_decimal128_t* intern;
+ zval retval;
+ php_serialize_data_t var_hash;
+ smart_str buf = { 0 };
+ char outbuf[BSON_DECIMAL128_STRING];
+
+ intern = Z_DECIMAL128_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ bson_decimal128_to_string(&intern->decimal, outbuf);
+ array_init_size(&retval, 1);
+ ADD_ASSOC_STRING(&retval, "dec", outbuf);
+
+ PHP_VAR_SERIALIZE_INIT(var_hash);
+ php_var_serialize(&buf, &retval, &var_hash);
+ smart_str_0(&buf);
+ PHP_VAR_SERIALIZE_DESTROY(var_hash);
+
+ PHONGO_RETVAL_SMART_STR(buf);
+
+ smart_str_free(&buf);
+ zval_ptr_dtor(&retval);
+} /* }}} */
+
+/* {{{ proto void MongoDB\BSON\Decimal128::unserialize(string $serialized)
+*/
+static PHP_METHOD(Decimal128, unserialize)
+{
+ zend_error_handling error_handling;
+ php_phongo_decimal128_t* intern;
+ char* serialized;
+ size_t serialized_len;
+ zval props;
+ php_unserialize_data_t var_hash;
+
+ intern = Z_DECIMAL128_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &serialized, &serialized_len) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ PHP_VAR_UNSERIALIZE_INIT(var_hash);
+ if (!php_var_unserialize(&props, (const unsigned char**) &serialized, (unsigned char*) serialized + serialized_len, &var_hash)) {
+ zval_ptr_dtor(&props);
+ phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "%s unserialization failed", ZSTR_VAL(php_phongo_decimal128_ce->name));
+
+ PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+ return;
+ }
+ PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+
+ php_phongo_decimal128_init_from_hash(intern, HASH_OF(&props));
+ zval_ptr_dtor(&props);
+} /* }}} */
+
+/* {{{ proto array MongoDB\Driver\Decimal128::__serialize()
+*/
+static PHP_METHOD(Decimal128, __serialize)
+{
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ RETURN_ARR(php_phongo_decimal128_get_properties_hash(PHONGO_COMPAT_OBJ_P(getThis()), true));
+} /* }}} */
+
+/* {{{ proto void MongoDB\Driver\Decimal128::__unserialize(array $data)
+*/
+static PHP_METHOD(Decimal128, __unserialize)
+{
+ zval* data;
+
+ PHONGO_PARSE_PARAMETERS_START(1, 1)
+ Z_PARAM_ARRAY(data)
+ PHONGO_PARSE_PARAMETERS_END();
+
+ php_phongo_decimal128_init_from_hash(Z_DECIMAL128_OBJ_P(getThis()), Z_ARRVAL_P(data));
+} /* }}} */
+
+/* {{{ MongoDB\BSON\Decimal128 function entries */
+/* clang-format off */
+ZEND_BEGIN_ARG_INFO_EX(ai_Decimal128___construct, 0, 0, 1)
+ ZEND_ARG_INFO(0, value)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_Decimal128___set_state, 0, 0, 1)
+ ZEND_ARG_ARRAY_INFO(0, properties, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(ai_Decimal128___toString, 0, 0, IS_STRING, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_Decimal128___unserialize, 0, 0, 1)
+ ZEND_ARG_ARRAY_INFO(0, data, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(ai_Decimal128_jsonSerialize, 0, 0, IS_ARRAY, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_Decimal128_unserialize, 0, 0, 1)
+ ZEND_ARG_INFO(0, serialized)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_Decimal128_void, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry php_phongo_decimal128_me[] = {
+ PHP_ME(Decimal128, __construct, ai_Decimal128___construct, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Decimal128, __serialize, ai_Decimal128_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Decimal128, __set_state, ai_Decimal128___set_state, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+ PHP_ME(Decimal128, __toString, ai_Decimal128___toString, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Decimal128, __unserialize, ai_Decimal128___unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Decimal128, jsonSerialize, ai_Decimal128_jsonSerialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Decimal128, serialize, ai_Decimal128_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Decimal128, unserialize, ai_Decimal128_unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_FE_END
+};
+/* clang-format on */
+/* }}} */
+
+/* {{{ MongoDB\BSON\Decimal128 object handlers */
+static zend_object_handlers php_phongo_handler_decimal128;
+
+static void php_phongo_decimal128_free_object(zend_object* object) /* {{{ */
+{
+ php_phongo_decimal128_t* intern = Z_OBJ_DECIMAL128(object);
+
+ zend_object_std_dtor(&intern->std);
+
+ if (intern->properties) {
+ zend_hash_destroy(intern->properties);
+ FREE_HASHTABLE(intern->properties);
+ }
+} /* }}} */
+
+static zend_object* php_phongo_decimal128_create_object(zend_class_entry* class_type) /* {{{ */
+{
+ php_phongo_decimal128_t* intern = zend_object_alloc(sizeof(php_phongo_decimal128_t), class_type);
+
+ zend_object_std_init(&intern->std, class_type);
+ object_properties_init(&intern->std, class_type);
+
+ intern->std.handlers = &php_phongo_handler_decimal128;
+
+ return &intern->std;
+} /* }}} */
+
+static zend_object* php_phongo_decimal128_clone_object(phongo_compat_object_handler_type* object) /* {{{ */
+{
+ php_phongo_decimal128_t* intern;
+ php_phongo_decimal128_t* new_intern;
+ zend_object* new_object;
+
+ intern = Z_OBJ_DECIMAL128(PHONGO_COMPAT_GET_OBJ(object));
+ new_object = php_phongo_decimal128_create_object(PHONGO_COMPAT_GET_OBJ(object)->ce);
+
+ new_intern = Z_OBJ_DECIMAL128(new_object);
+ zend_objects_clone_members(&new_intern->std, &intern->std);
+
+ // Use memcpy to copy bson value to avoid converting to string and back
+ memcpy(&new_intern->decimal, &intern->decimal, sizeof(bson_decimal128_t));
+ new_intern->initialized = true;
+
+ return new_object;
+} /* }}} */
+
+static HashTable* php_phongo_decimal128_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
+{
+ *is_temp = 1;
+ return php_phongo_decimal128_get_properties_hash(object, true);
+} /* }}} */
+
+static HashTable* php_phongo_decimal128_get_properties(phongo_compat_object_handler_type* object) /* {{{ */
+{
+ return php_phongo_decimal128_get_properties_hash(object, false);
+} /* }}} */
+/* }}} */
+
+void php_phongo_decimal128_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\BSON", "Decimal128", php_phongo_decimal128_me);
+ php_phongo_decimal128_ce = zend_register_internal_class(&ce);
+ php_phongo_decimal128_ce->create_object = php_phongo_decimal128_create_object;
+ PHONGO_CE_FINAL(php_phongo_decimal128_ce);
+
+ zend_class_implements(php_phongo_decimal128_ce, 1, php_phongo_decimal128_interface_ce);
+ zend_class_implements(php_phongo_decimal128_ce, 1, php_phongo_json_serializable_ce);
+ zend_class_implements(php_phongo_decimal128_ce, 1, php_phongo_type_ce);
+ zend_class_implements(php_phongo_decimal128_ce, 1, zend_ce_serializable);
+
+#if PHP_VERSION_ID >= 80000
+ zend_class_implements(php_phongo_decimal128_ce, 1, zend_ce_stringable);
+#endif
+
+ memcpy(&php_phongo_handler_decimal128, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
+ php_phongo_handler_decimal128.clone_obj = php_phongo_decimal128_clone_object;
+ php_phongo_handler_decimal128.get_debug_info = php_phongo_decimal128_get_debug_info;
+ php_phongo_handler_decimal128.get_properties = php_phongo_decimal128_get_properties;
+ php_phongo_handler_decimal128.free_obj = php_phongo_decimal128_free_object;
+ php_phongo_handler_decimal128.offset = XtOffsetOf(php_phongo_decimal128_t, std);
+} /* }}} */
diff --git a/mongodb-1.13.0/src/BSON/Decimal128Interface.c b/mongodb-1.13.0/src/BSON/Decimal128Interface.c
new file mode 100644
index 00000000..f4d55961
--- /dev/null
+++ b/mongodb-1.13.0/src/BSON/Decimal128Interface.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2017-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <php.h>
+
+#include "php_phongo.h"
+
+zend_class_entry* php_phongo_decimal128_interface_ce;
+
+/* {{{ MongoDB\BSON\Decimal128Interface function entries */
+/* clang-format off */
+ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(ai_Decimal128Interface___toString, 0, 0, IS_STRING, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry php_phongo_decimal128_interface_me[] = {
+ ZEND_ABSTRACT_ME(Decimal128Interface, __toString, ai_Decimal128Interface___toString)
+ PHP_FE_END
+};
+/* clang-format on */
+/* }}} */
+
+void php_phongo_decimal128_interface_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\BSON", "Decimal128Interface", php_phongo_decimal128_interface_me);
+ php_phongo_decimal128_interface_ce = zend_register_internal_interface(&ce);
+} /* }}} */
diff --git a/mongodb-1.13.0/src/BSON/Int64.c b/mongodb-1.13.0/src/BSON/Int64.c
new file mode 100644
index 00000000..4bb52ab4
--- /dev/null
+++ b/mongodb-1.13.0/src/BSON/Int64.c
@@ -0,0 +1,346 @@
+/*
+ * Copyright 2018-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <php.h>
+#include <zend_smart_str.h>
+#include <ext/standard/php_var.h>
+#include <Zend/zend_interfaces.h>
+
+#include "php_phongo.h"
+#include "phongo_error.h"
+#include "phongo_util.h"
+
+zend_class_entry* php_phongo_int64_ce;
+
+/* Initialize the object and return whether it was successful. */
+static bool php_phongo_int64_init(php_phongo_int64_t* intern, int64_t integer) /* {{{ */
+{
+ intern->integer = integer;
+ intern->initialized = true;
+
+ return true;
+} /* }}} */
+
+/* Initialize the object from a numeric string and return whether it was
+ * successful. An exception will be thrown on error. */
+static bool php_phongo_int64_init_from_string(php_phongo_int64_t* intern, const char* s_integer, size_t s_integer_len) /* {{{ */
+{
+ int64_t integer;
+
+ if (!php_phongo_parse_int64(&integer, s_integer, s_integer_len)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Error parsing \"%s\" as 64-bit integer for %s initialization", s_integer, ZSTR_VAL(php_phongo_int64_ce->name));
+ return false;
+ }
+
+ return php_phongo_int64_init(intern, integer);
+} /* }}} */
+
+/* Initialize the object from a HashTable and return whether it was successful.
+ * An exception will be thrown on error. */
+static bool php_phongo_int64_init_from_hash(php_phongo_int64_t* intern, HashTable* props) /* {{{ */
+{
+ zval* value;
+
+ if ((value = zend_hash_str_find(props, "integer", sizeof("integer") - 1)) && Z_TYPE_P(value) == IS_STRING) {
+ return php_phongo_int64_init_from_string(intern, Z_STRVAL_P(value), Z_STRLEN_P(value));
+ }
+
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"integer\" string field", ZSTR_VAL(php_phongo_int64_ce->name));
+ return false;
+} /* }}} */
+
+HashTable* php_phongo_int64_get_properties_hash(phongo_compat_object_handler_type* object, bool is_temp) /* {{{ */
+{
+ php_phongo_int64_t* intern;
+ HashTable* props;
+
+ intern = Z_OBJ_INT64(PHONGO_COMPAT_GET_OBJ(object));
+
+ PHONGO_GET_PROPERTY_HASH_INIT_PROPS(is_temp, intern, props, 2);
+
+ if (!intern->initialized) {
+ return props;
+ }
+
+ {
+ zval value;
+
+ ZVAL_INT64_STRING(&value, intern->integer);
+ zend_hash_str_update(props, "integer", sizeof("integer") - 1, &value);
+ }
+
+ return props;
+} /* }}} */
+
+/* {{{ proto string MongoDB\BSON\Int64::__toString()
+ Return the Int64's value as a string. */
+static PHP_METHOD(Int64, __toString)
+{
+ zend_error_handling error_handling;
+ php_phongo_int64_t* intern;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ intern = Z_INT64_OBJ_P(getThis());
+
+ ZVAL_INT64_STRING(return_value, intern->integer);
+} /* }}} */
+
+/* {{{ proto array MongoDB\BSON\Int64::jsonSerialize()
+*/
+static PHP_METHOD(Int64, jsonSerialize)
+{
+ zend_error_handling error_handling;
+ php_phongo_int64_t* intern;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ intern = Z_INT64_OBJ_P(getThis());
+
+ array_init_size(return_value, 1);
+
+ ADD_ASSOC_INT64_AS_STRING(return_value, "$numberLong", intern->integer);
+} /* }}} */
+
+/* {{{ proto string MongoDB\BSON\Int64::serialize()
+*/
+static PHP_METHOD(Int64, serialize)
+{
+ zend_error_handling error_handling;
+ php_phongo_int64_t* intern;
+ zval retval;
+ php_serialize_data_t var_hash;
+ smart_str buf = { 0 };
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ intern = Z_INT64_OBJ_P(getThis());
+
+ array_init_size(&retval, 1);
+ ADD_ASSOC_INT64_AS_STRING(&retval, "integer", intern->integer);
+
+ PHP_VAR_SERIALIZE_INIT(var_hash);
+ php_var_serialize(&buf, &retval, &var_hash);
+ smart_str_0(&buf);
+ PHP_VAR_SERIALIZE_DESTROY(var_hash);
+
+ PHONGO_RETVAL_SMART_STR(buf);
+
+ smart_str_free(&buf);
+ zval_ptr_dtor(&retval);
+} /* }}} */
+
+/* {{{ proto void MongoDB\BSON\Int64::unserialize(string $serialized)
+*/
+static PHP_METHOD(Int64, unserialize)
+{
+ zend_error_handling error_handling;
+ php_phongo_int64_t* intern;
+ char* serialized;
+ size_t serialized_len;
+ zval props;
+ php_unserialize_data_t var_hash;
+
+ intern = Z_INT64_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &serialized, &serialized_len) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ PHP_VAR_UNSERIALIZE_INIT(var_hash);
+ if (!php_var_unserialize(&props, (const unsigned char**) &serialized, (unsigned char*) serialized + serialized_len, &var_hash)) {
+ zval_ptr_dtor(&props);
+ phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "%s unserialization failed", ZSTR_VAL(php_phongo_int64_ce->name));
+
+ PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+ return;
+ }
+ PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+
+ php_phongo_int64_init_from_hash(intern, HASH_OF(&props));
+ zval_ptr_dtor(&props);
+} /* }}} */
+
+/* {{{ proto array MongoDB\Driver\Int64::__serialize()
+*/
+static PHP_METHOD(Int64, __serialize)
+{
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ RETURN_ARR(php_phongo_int64_get_properties_hash(PHONGO_COMPAT_OBJ_P(getThis()), true));
+} /* }}} */
+
+/* {{{ proto void MongoDB\Driver\Int64::__unserialize(array $data)
+*/
+static PHP_METHOD(Int64, __unserialize)
+{
+ zval* data;
+
+ PHONGO_PARSE_PARAMETERS_START(1, 1)
+ Z_PARAM_ARRAY(data)
+ PHONGO_PARSE_PARAMETERS_END();
+
+ php_phongo_int64_init_from_hash(Z_INT64_OBJ_P(getThis()), Z_ARRVAL_P(data));
+} /* }}} */
+
+/* {{{ MongoDB\BSON\Int64 function entries */
+/* clang-format off */
+ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(ai_Int64___toString, 0, 0, IS_STRING, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_Int64___unserialize, 0, 0, 1)
+ ZEND_ARG_ARRAY_INFO(0, data, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(ai_Int64_jsonSerialize, 0, 0, IS_ARRAY, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_Int64_unserialize, 0, 0, 1)
+ ZEND_ARG_INFO(0, serialized)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_Int64_void, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry php_phongo_int64_me[] = {
+ /* __set_state intentionally missing */
+ PHP_ME(Int64, __serialize, ai_Int64_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Int64, __toString, ai_Int64___toString, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Int64, __unserialize, ai_Int64___unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Int64, jsonSerialize, ai_Int64_jsonSerialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Int64, serialize, ai_Int64_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Int64, unserialize, ai_Int64_unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ ZEND_NAMED_ME(__construct, PHP_FN(MongoDB_disabled___construct), ai_Int64_void, ZEND_ACC_PRIVATE | ZEND_ACC_FINAL)
+ PHP_FE_END
+};
+/* clang-format on */
+/* }}} */
+
+/* {{{ MongoDB\BSON\Int64 object handlers */
+static zend_object_handlers php_phongo_handler_int64;
+
+static void php_phongo_int64_free_object(zend_object* object) /* {{{ */
+{
+ php_phongo_int64_t* intern = Z_OBJ_INT64(object);
+
+ zend_object_std_dtor(&intern->std);
+
+ if (intern->properties) {
+ zend_hash_destroy(intern->properties);
+ FREE_HASHTABLE(intern->properties);
+ }
+} /* }}} */
+
+zend_object* php_phongo_int64_create_object(zend_class_entry* class_type) /* {{{ */
+{
+ php_phongo_int64_t* intern = zend_object_alloc(sizeof(php_phongo_int64_t), class_type);
+
+ zend_object_std_init(&intern->std, class_type);
+ object_properties_init(&intern->std, class_type);
+
+ intern->std.handlers = &php_phongo_handler_int64;
+
+ return &intern->std;
+} /* }}} */
+
+static zend_object* php_phongo_int64_clone_object(phongo_compat_object_handler_type* object) /* {{{ */
+{
+ php_phongo_int64_t* intern;
+ php_phongo_int64_t* new_intern;
+ zend_object* new_object;
+
+ intern = Z_OBJ_INT64(PHONGO_COMPAT_GET_OBJ(object));
+ new_object = php_phongo_int64_create_object(PHONGO_COMPAT_GET_OBJ(object)->ce);
+
+ new_intern = Z_OBJ_INT64(new_object);
+ zend_objects_clone_members(&new_intern->std, &intern->std);
+
+ php_phongo_int64_init(new_intern, intern->integer);
+
+ return new_object;
+} /* }}} */
+
+static int php_phongo_int64_compare_objects(zval* o1, zval* o2) /* {{{ */
+{
+ php_phongo_int64_t *intern1, *intern2;
+
+ ZEND_COMPARE_OBJECTS_FALLBACK(o1, o2);
+
+ intern1 = Z_INT64_OBJ_P(o1);
+ intern2 = Z_INT64_OBJ_P(o2);
+
+ if (intern1->integer != intern2->integer) {
+ return intern1->integer < intern2->integer ? -1 : 1;
+ }
+
+ return 0;
+} /* }}} */
+
+static HashTable* php_phongo_int64_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
+{
+ *is_temp = 1;
+ return php_phongo_int64_get_properties_hash(object, true);
+} /* }}} */
+
+static HashTable* php_phongo_int64_get_properties(phongo_compat_object_handler_type* object) /* {{{ */
+{
+ return php_phongo_int64_get_properties_hash(object, false);
+} /* }}} */
+/* }}} */
+
+void php_phongo_int64_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\BSON", "Int64", php_phongo_int64_me);
+ php_phongo_int64_ce = zend_register_internal_class(&ce);
+ php_phongo_int64_ce->create_object = php_phongo_int64_create_object;
+ PHONGO_CE_FINAL(php_phongo_int64_ce);
+
+ zend_class_implements(php_phongo_int64_ce, 1, php_phongo_json_serializable_ce);
+ zend_class_implements(php_phongo_int64_ce, 1, php_phongo_type_ce);
+ zend_class_implements(php_phongo_int64_ce, 1, zend_ce_serializable);
+
+#if PHP_VERSION_ID >= 80000
+ zend_class_implements(php_phongo_int64_ce, 1, zend_ce_stringable);
+#endif
+
+ memcpy(&php_phongo_handler_int64, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
+ PHONGO_COMPAT_SET_COMPARE_OBJECTS_HANDLER(int64);
+ php_phongo_handler_int64.clone_obj = php_phongo_int64_clone_object;
+ php_phongo_handler_int64.get_debug_info = php_phongo_int64_get_debug_info;
+ php_phongo_handler_int64.get_properties = php_phongo_int64_get_properties;
+ php_phongo_handler_int64.free_obj = php_phongo_int64_free_object;
+ php_phongo_handler_int64.offset = XtOffsetOf(php_phongo_int64_t, std);
+} /* }}} */
diff --git a/mongodb-1.13.0/src/BSON/Javascript.c b/mongodb-1.13.0/src/BSON/Javascript.c
new file mode 100644
index 00000000..a0432ac2
--- /dev/null
+++ b/mongodb-1.13.0/src/BSON/Javascript.c
@@ -0,0 +1,520 @@
+/*
+ * Copyright 2014-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bson/bson.h"
+
+#include <php.h>
+#include <zend_smart_str.h>
+#include <ext/standard/php_var.h>
+#include <Zend/zend_interfaces.h>
+
+#include "php_phongo.h"
+#include "phongo_bson_encode.h"
+#include "phongo_error.h"
+
+zend_class_entry* php_phongo_javascript_ce;
+
+/* Initialize the object and return whether it was successful. An exception will
+ * be thrown on error. */
+static bool php_phongo_javascript_init(php_phongo_javascript_t* intern, const char* code, size_t code_len, zval* scope) /* {{{ */
+{
+ if (scope && Z_TYPE_P(scope) != IS_OBJECT && Z_TYPE_P(scope) != IS_ARRAY && Z_TYPE_P(scope) != IS_NULL) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected scope to be array or object, %s given", zend_get_type_by_const(Z_TYPE_P(scope)));
+ return false;
+ }
+
+ if (strlen(code) != (size_t) code_len) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Code cannot contain null bytes");
+ return false;
+ }
+
+ intern->code = estrndup(code, code_len);
+ intern->code_len = code_len;
+
+ if (scope && (Z_TYPE_P(scope) == IS_OBJECT || Z_TYPE_P(scope) == IS_ARRAY)) {
+ intern->scope = bson_new();
+ php_phongo_zval_to_bson(scope, PHONGO_BSON_NONE, intern->scope, NULL);
+ } else {
+ intern->scope = NULL;
+ }
+
+ return true;
+} /* }}} */
+
+/* Initialize the object from a HashTable and return whether it was successful.
+ * An exception will be thrown on error. */
+static bool php_phongo_javascript_init_from_hash(php_phongo_javascript_t* intern, HashTable* props) /* {{{ */
+{
+ zval *code, *scope;
+
+ if ((code = zend_hash_str_find(props, "code", sizeof("code") - 1)) && Z_TYPE_P(code) == IS_STRING) {
+ scope = zend_hash_str_find(props, "scope", sizeof("scope") - 1);
+
+ return php_phongo_javascript_init(intern, Z_STRVAL_P(code), Z_STRLEN_P(code), scope);
+ }
+
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"code\" string field", ZSTR_VAL(php_phongo_javascript_ce->name));
+ return false;
+} /* }}} */
+
+HashTable* php_phongo_javascript_get_properties_hash(phongo_compat_object_handler_type* object, bool is_temp) /* {{{ */
+{
+ php_phongo_javascript_t* intern;
+ HashTable* props;
+
+ intern = Z_OBJ_JAVASCRIPT(PHONGO_COMPAT_GET_OBJ(object));
+
+ PHONGO_GET_PROPERTY_HASH_INIT_PROPS(is_temp, intern, props, 2);
+
+ if (!intern->code) {
+ return props;
+ }
+
+ {
+ zval code;
+
+ ZVAL_STRING(&code, intern->code);
+ zend_hash_str_update(props, "code", sizeof("code") - 1, &code);
+
+ if (intern->scope) {
+ php_phongo_bson_state state;
+
+ PHONGO_BSON_INIT_STATE(state);
+ if (!php_phongo_bson_to_zval_ex(bson_get_data(intern->scope), intern->scope->len, &state)) {
+ zval_ptr_dtor(&state.zchild);
+ goto failure;
+ }
+
+ zend_hash_str_update(props, "scope", sizeof("scope") - 1, &state.zchild);
+ } else {
+ zval scope;
+
+ ZVAL_NULL(&scope);
+ zend_hash_str_update(props, "scope", sizeof("scope") - 1, &scope);
+ }
+ }
+
+ return props;
+
+failure:
+ PHONGO_GET_PROPERTY_HASH_FREE_PROPS(is_temp, props);
+ return NULL;
+} /* }}} */
+
+/* {{{ proto void MongoDB\BSON\Javascript::__construct(string $code[, array|object $scope])
+ Construct a new BSON Javascript type. The scope is a document mapping
+ identifiers and values, representing the scope in which the code string will
+ be evaluated. Note that this type cannot be represented as Extended JSON. */
+static PHP_METHOD(Javascript, __construct)
+{
+ zend_error_handling error_handling;
+ php_phongo_javascript_t* intern;
+ char* code;
+ size_t code_len;
+ zval* scope = NULL;
+
+ intern = Z_JAVASCRIPT_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|A!", &code, &code_len, &scope) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ php_phongo_javascript_init(intern, code, code_len, scope);
+} /* }}} */
+
+/* {{{ proto MongoDB\BSON\Javascript MongoDB\BSON\Javascript::__set_state(array $properties)
+*/
+static PHP_METHOD(Javascript, __set_state)
+{
+ zend_error_handling error_handling;
+ php_phongo_javascript_t* intern;
+ HashTable* props;
+ zval* array;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &array) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ object_init_ex(return_value, php_phongo_javascript_ce);
+
+ intern = Z_JAVASCRIPT_OBJ_P(return_value);
+ props = Z_ARRVAL_P(array);
+
+ php_phongo_javascript_init_from_hash(intern, props);
+} /* }}} */
+
+/* {{{ proto string MongoDB\BSON\Javascript::__toString()
+ Return the Javascript's code string. */
+static PHP_METHOD(Javascript, __toString)
+{
+ zend_error_handling error_handling;
+ php_phongo_javascript_t* intern;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ intern = Z_JAVASCRIPT_OBJ_P(getThis());
+
+ RETURN_STRINGL(intern->code, intern->code_len);
+} /* }}} */
+
+/* {{{ proto string MongoDB\BSON\Javascript::getCode()
+*/
+static PHP_METHOD(Javascript, getCode)
+{
+ zend_error_handling error_handling;
+ php_phongo_javascript_t* intern;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ intern = Z_JAVASCRIPT_OBJ_P(getThis());
+
+ RETURN_STRINGL(intern->code, intern->code_len);
+} /* }}} */
+
+/* {{{ proto object|null MongoDB\BSON\Javascript::getScope()
+*/
+static PHP_METHOD(Javascript, getScope)
+{
+ zend_error_handling error_handling;
+ php_phongo_javascript_t* intern;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ intern = Z_JAVASCRIPT_OBJ_P(getThis());
+
+ if (!intern->scope) {
+ RETURN_NULL();
+ }
+
+ if (intern->scope->len) {
+ php_phongo_bson_state state;
+
+ PHONGO_BSON_INIT_STATE(state);
+
+ if (!php_phongo_bson_to_zval_ex(bson_get_data(intern->scope), intern->scope->len, &state)) {
+ zval_ptr_dtor(&state.zchild);
+ return;
+ }
+
+ RETURN_ZVAL(&state.zchild, 0, 1);
+ } else {
+ RETURN_NULL();
+ }
+} /* }}} */
+
+/* {{{ proto array MongoDB\BSON\Javascript::jsonSerialize()
+*/
+static PHP_METHOD(Javascript, jsonSerialize)
+{
+ zend_error_handling error_handling;
+ php_phongo_javascript_t* intern;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ intern = Z_JAVASCRIPT_OBJ_P(getThis());
+
+ array_init_size(return_value, 2);
+ ADD_ASSOC_STRINGL(return_value, "$code", intern->code, intern->code_len);
+
+ if (intern->scope && intern->scope->len) {
+ php_phongo_bson_state state;
+
+ PHONGO_BSON_INIT_STATE(state);
+ if (!php_phongo_bson_to_zval_ex(bson_get_data(intern->scope), intern->scope->len, &state)) {
+ zval_ptr_dtor(&state.zchild);
+ return;
+ }
+
+ ADD_ASSOC_ZVAL_EX(return_value, "$scope", &state.zchild);
+ }
+} /* }}} */
+
+/* {{{ proto string MongoDB\BSON\Javascript::serialize()
+*/
+static PHP_METHOD(Javascript, serialize)
+{
+ zend_error_handling error_handling;
+ php_phongo_javascript_t* intern;
+ zval retval;
+ php_phongo_bson_state state;
+ php_serialize_data_t var_hash;
+ smart_str buf = { 0 };
+
+ PHONGO_BSON_INIT_STATE(state);
+
+ intern = Z_JAVASCRIPT_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ if (intern->scope && intern->scope->len) {
+ if (!php_phongo_bson_to_zval_ex(bson_get_data(intern->scope), intern->scope->len, &state)) {
+ zval_ptr_dtor(&state.zchild);
+ return;
+ }
+ } else {
+ ZVAL_NULL(&state.zchild);
+ }
+
+ array_init_size(&retval, 2);
+ ADD_ASSOC_STRINGL(&retval, "code", intern->code, intern->code_len);
+ ADD_ASSOC_ZVAL(&retval, "scope", &state.zchild);
+
+ PHP_VAR_SERIALIZE_INIT(var_hash);
+ php_var_serialize(&buf, &retval, &var_hash);
+ smart_str_0(&buf);
+ PHP_VAR_SERIALIZE_DESTROY(var_hash);
+
+ PHONGO_RETVAL_SMART_STR(buf);
+
+ smart_str_free(&buf);
+ zval_ptr_dtor(&retval);
+} /* }}} */
+
+/* {{{ proto void MongoDB\BSON\Javascript::unserialize(string $serialized)
+*/
+static PHP_METHOD(Javascript, unserialize)
+{
+ zend_error_handling error_handling;
+ php_phongo_javascript_t* intern;
+ char* serialized;
+ size_t serialized_len;
+ zval props;
+ php_unserialize_data_t var_hash;
+
+ intern = Z_JAVASCRIPT_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &serialized, &serialized_len) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ PHP_VAR_UNSERIALIZE_INIT(var_hash);
+ if (!php_var_unserialize(&props, (const unsigned char**) &serialized, (unsigned char*) serialized + serialized_len, &var_hash)) {
+ zval_ptr_dtor(&props);
+ phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "%s unserialization failed", ZSTR_VAL(php_phongo_javascript_ce->name));
+
+ PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+ return;
+ }
+ PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+
+ php_phongo_javascript_init_from_hash(intern, HASH_OF(&props));
+ zval_ptr_dtor(&props);
+} /* }}} */
+
+/* {{{ proto array MongoDB\Driver\Javascript::__serialize()
+*/
+static PHP_METHOD(Javascript, __serialize)
+{
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ RETURN_ARR(php_phongo_javascript_get_properties_hash(PHONGO_COMPAT_OBJ_P(getThis()), true));
+} /* }}} */
+
+/* {{{ proto void MongoDB\Driver\Javascript::__unserialize(array $data)
+*/
+static PHP_METHOD(Javascript, __unserialize)
+{
+ zval* data;
+
+ PHONGO_PARSE_PARAMETERS_START(1, 1)
+ Z_PARAM_ARRAY(data)
+ PHONGO_PARSE_PARAMETERS_END();
+
+ php_phongo_javascript_init_from_hash(Z_JAVASCRIPT_OBJ_P(getThis()), Z_ARRVAL_P(data));
+} /* }}} */
+
+/* {{{ MongoDB\BSON\Javascript function entries */
+/* clang-format off */
+ZEND_BEGIN_ARG_INFO_EX(ai_Javascript___construct, 0, 0, 1)
+ ZEND_ARG_INFO(0, javascript)
+ ZEND_ARG_INFO(0, scope)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_Javascript___set_state, 0, 0, 1)
+ ZEND_ARG_ARRAY_INFO(0, properties, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(ai_Javascript___toString, 0, 0, IS_STRING, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_Javascript___unserialize, 0, 0, 1)
+ ZEND_ARG_ARRAY_INFO(0, data, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(ai_Javascript_jsonSerialize, 0, 0, IS_ARRAY, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_Javascript_unserialize, 0, 0, 1)
+ ZEND_ARG_INFO(0, serialized)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_Javascript_void, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry php_phongo_javascript_me[] = {
+ PHP_ME(Javascript, __construct, ai_Javascript___construct, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Javascript, __serialize, ai_Javascript_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Javascript, __set_state, ai_Javascript___set_state, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+ PHP_ME(Javascript, __toString, ai_Javascript___toString, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Javascript, __unserialize, ai_Javascript___unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Javascript, jsonSerialize, ai_Javascript_jsonSerialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Javascript, serialize, ai_Javascript_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Javascript, unserialize, ai_Javascript_unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Javascript, getCode, ai_Javascript_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Javascript, getScope, ai_Javascript_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_FE_END
+};
+/* clang-format on */
+/* }}} */
+
+/* {{{ MongoDB\BSON\Javascript object handlers */
+static zend_object_handlers php_phongo_handler_javascript;
+
+static void php_phongo_javascript_free_object(zend_object* object) /* {{{ */
+{
+ php_phongo_javascript_t* intern = Z_OBJ_JAVASCRIPT(object);
+
+ zend_object_std_dtor(&intern->std);
+
+ if (intern->code) {
+ efree(intern->code);
+ }
+ if (intern->scope) {
+ bson_destroy(intern->scope);
+ intern->scope = NULL;
+ }
+
+ if (intern->properties) {
+ zend_hash_destroy(intern->properties);
+ FREE_HASHTABLE(intern->properties);
+ }
+} /* }}} */
+
+zend_object* php_phongo_javascript_create_object(zend_class_entry* class_type) /* {{{ */
+{
+ php_phongo_javascript_t* intern = zend_object_alloc(sizeof(php_phongo_javascript_t), class_type);
+
+ zend_object_std_init(&intern->std, class_type);
+ object_properties_init(&intern->std, class_type);
+
+ intern->std.handlers = &php_phongo_handler_javascript;
+
+ return &intern->std;
+} /* }}} */
+
+static zend_object* php_phongo_javascript_clone_object(phongo_compat_object_handler_type* object) /* {{{ */
+{
+ php_phongo_javascript_t* intern;
+ php_phongo_javascript_t* new_intern;
+ zend_object* new_object;
+
+ intern = Z_OBJ_JAVASCRIPT(PHONGO_COMPAT_GET_OBJ(object));
+ new_object = php_phongo_javascript_create_object(PHONGO_COMPAT_GET_OBJ(object)->ce);
+
+ new_intern = Z_OBJ_JAVASCRIPT(new_object);
+ zend_objects_clone_members(&new_intern->std, &intern->std);
+
+ php_phongo_javascript_init(new_intern, intern->code, intern->code_len, NULL);
+ new_intern->scope = bson_copy(intern->scope);
+
+ return new_object;
+} /* }}} */
+
+static int php_phongo_javascript_compare_objects(zval* o1, zval* o2) /* {{{ */
+{
+ php_phongo_javascript_t *intern1, *intern2;
+
+ ZEND_COMPARE_OBJECTS_FALLBACK(o1, o2);
+
+ intern1 = Z_JAVASCRIPT_OBJ_P(o1);
+ intern2 = Z_JAVASCRIPT_OBJ_P(o2);
+
+ /* Do not consider the scope document for comparisons */
+ return strcmp(intern1->code, intern2->code);
+} /* }}} */
+
+static HashTable* php_phongo_javascript_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
+{
+ *is_temp = 1;
+ return php_phongo_javascript_get_properties_hash(object, true);
+} /* }}} */
+
+static HashTable* php_phongo_javascript_get_properties(phongo_compat_object_handler_type* object) /* {{{ */
+{
+ return php_phongo_javascript_get_properties_hash(object, false);
+} /* }}} */
+/* }}} */
+
+void php_phongo_javascript_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\BSON", "Javascript", php_phongo_javascript_me);
+ php_phongo_javascript_ce = zend_register_internal_class(&ce);
+ php_phongo_javascript_ce->create_object = php_phongo_javascript_create_object;
+ PHONGO_CE_FINAL(php_phongo_javascript_ce);
+
+ zend_class_implements(php_phongo_javascript_ce, 1, php_phongo_javascript_interface_ce);
+ zend_class_implements(php_phongo_javascript_ce, 1, php_phongo_json_serializable_ce);
+ zend_class_implements(php_phongo_javascript_ce, 1, php_phongo_type_ce);
+ zend_class_implements(php_phongo_javascript_ce, 1, zend_ce_serializable);
+
+#if PHP_VERSION_ID >= 80000
+ zend_class_implements(php_phongo_javascript_ce, 1, zend_ce_stringable);
+#endif
+
+ memcpy(&php_phongo_handler_javascript, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
+ PHONGO_COMPAT_SET_COMPARE_OBJECTS_HANDLER(javascript);
+ php_phongo_handler_javascript.clone_obj = php_phongo_javascript_clone_object;
+ php_phongo_handler_javascript.get_debug_info = php_phongo_javascript_get_debug_info;
+ php_phongo_handler_javascript.get_properties = php_phongo_javascript_get_properties;
+ php_phongo_handler_javascript.free_obj = php_phongo_javascript_free_object;
+ php_phongo_handler_javascript.offset = XtOffsetOf(php_phongo_javascript_t, std);
+} /* }}} */
diff --git a/mongodb-1.13.0/src/BSON/JavascriptInterface.c b/mongodb-1.13.0/src/BSON/JavascriptInterface.c
new file mode 100644
index 00000000..a7f41476
--- /dev/null
+++ b/mongodb-1.13.0/src/BSON/JavascriptInterface.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2017-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <php.h>
+
+#include "php_phongo.h"
+
+zend_class_entry* php_phongo_javascript_interface_ce;
+
+/* {{{ MongoDB\BSON\JavascriptInterface function entries */
+/* clang-format off */
+ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(ai_JavascriptInterface___toString, 0, 0, IS_STRING, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_JavascriptInterface_void, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry php_phongo_javascript_interface_me[] = {
+ ZEND_ABSTRACT_ME(JavascriptInterface, getCode, ai_JavascriptInterface_void)
+ ZEND_ABSTRACT_ME(JavascriptInterface, getScope, ai_JavascriptInterface_void)
+ ZEND_ABSTRACT_ME(JavascriptInterface, __toString, ai_JavascriptInterface___toString)
+ PHP_FE_END
+};
+/* clang-format on */
+/* }}} */
+
+void php_phongo_javascript_interface_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\BSON", "JavascriptInterface", php_phongo_javascript_interface_me);
+ php_phongo_javascript_interface_ce = zend_register_internal_interface(&ce);
+} /* }}} */
diff --git a/mongodb-1.13.0/src/BSON/MaxKey.c b/mongodb-1.13.0/src/BSON/MaxKey.c
new file mode 100644
index 00000000..8d0b14ad
--- /dev/null
+++ b/mongodb-1.13.0/src/BSON/MaxKey.c
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2014-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <php.h>
+#include <zend_smart_str.h>
+#include <ext/standard/php_var.h>
+#include <Zend/zend_interfaces.h>
+
+#include "php_phongo.h"
+#include "phongo_error.h"
+
+zend_class_entry* php_phongo_maxkey_ce;
+
+/* {{{ proto MongoDB\BSON\MaxKey MongoDB\BSON\MaxKey::__set_state(array $properties)
+*/
+static PHP_METHOD(MaxKey, __set_state)
+{
+ zend_error_handling error_handling;
+ zval* array;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &array) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ object_init_ex(return_value, php_phongo_maxkey_ce);
+} /* }}} */
+
+/* {{{ proto array MongoDB\BSON\MaxKey::jsonSerialize()
+*/
+static PHP_METHOD(MaxKey, jsonSerialize)
+{
+ zend_error_handling error_handling;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ array_init_size(return_value, 1);
+ ADD_ASSOC_LONG_EX(return_value, "$maxKey", 1);
+} /* }}} */
+
+/* {{{ proto string MongoDB\BSON\MaxKey::serialize()
+*/
+static PHP_METHOD(MaxKey, serialize)
+{
+ zend_error_handling error_handling;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ RETURN_STRING("");
+} /* }}} */
+
+/* {{{ proto void MongoDB\BSON\MaxKey::unserialize(string $serialized)
+*/
+static PHP_METHOD(MaxKey, unserialize)
+{
+ zend_error_handling error_handling;
+ char* serialized;
+ size_t serialized_len;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &serialized, &serialized_len) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+} /* }}} */
+
+/* {{{ proto array MongoDB\Driver\MaxKey::__serialize()
+*/
+static PHP_METHOD(MaxKey, __serialize)
+{
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ array_init_size(return_value, 0);
+} /* }}} */
+
+/* {{{ proto void MongoDB\Driver\MaxKey::__unserialize(array $data)
+*/
+static PHP_METHOD(MaxKey, __unserialize)
+{
+ zval* data;
+
+ PHONGO_PARSE_PARAMETERS_START(1, 1)
+ Z_PARAM_ARRAY(data)
+ PHONGO_PARSE_PARAMETERS_END();
+} /* }}} */
+
+/* {{{ MongoDB\BSON\MaxKey function entries */
+/* clang-format off */
+ZEND_BEGIN_ARG_INFO_EX(ai_MaxKey___set_state, 0, 0, 1)
+ ZEND_ARG_ARRAY_INFO(0, properties, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_MaxKey___unserialize, 0, 0, 1)
+ ZEND_ARG_ARRAY_INFO(0, data, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(ai_MaxKey_jsonSerialize, 0, 0, IS_ARRAY, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_MaxKey_unserialize, 0, 0, 1)
+ ZEND_ARG_INFO(0, serialized)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_MaxKey_void, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry php_phongo_maxkey_me[] = {
+ PHP_ME(MaxKey, __serialize, ai_MaxKey_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(MaxKey, __set_state, ai_MaxKey___set_state, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+ PHP_ME(MaxKey, __unserialize, ai_MaxKey___unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(MaxKey, jsonSerialize, ai_MaxKey_jsonSerialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(MaxKey, serialize, ai_MaxKey_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(MaxKey, unserialize, ai_MaxKey_unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_FE_END
+};
+/* clang-format on */
+/* }}} */
+
+/* {{{ MongoDB\BSON\MaxKey object handlers */
+static zend_object_handlers php_phongo_handler_maxkey;
+
+static void php_phongo_maxkey_free_object(zend_object* object) /* {{{ */
+{
+ php_phongo_maxkey_t* intern = Z_OBJ_MAXKEY(object);
+
+ zend_object_std_dtor(&intern->std);
+} /* }}} */
+
+static zend_object* php_phongo_maxkey_create_object(zend_class_entry* class_type) /* {{{ */
+{
+ php_phongo_maxkey_t* intern = zend_object_alloc(sizeof(php_phongo_maxkey_t), class_type);
+
+ zend_object_std_init(&intern->std, class_type);
+ object_properties_init(&intern->std, class_type);
+
+ intern->std.handlers = &php_phongo_handler_maxkey;
+
+ return &intern->std;
+} /* }}} */
+/* }}} */
+
+void php_phongo_maxkey_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\BSON", "MaxKey", php_phongo_maxkey_me);
+ php_phongo_maxkey_ce = zend_register_internal_class(&ce);
+ php_phongo_maxkey_ce->create_object = php_phongo_maxkey_create_object;
+ PHONGO_CE_FINAL(php_phongo_maxkey_ce);
+
+ zend_class_implements(php_phongo_maxkey_ce, 1, php_phongo_maxkey_interface_ce);
+ zend_class_implements(php_phongo_maxkey_ce, 1, php_phongo_json_serializable_ce);
+ zend_class_implements(php_phongo_maxkey_ce, 1, php_phongo_type_ce);
+ zend_class_implements(php_phongo_maxkey_ce, 1, zend_ce_serializable);
+
+ memcpy(&php_phongo_handler_maxkey, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
+ /* Re-assign default handler previously removed in php_phongo.c */
+ php_phongo_handler_maxkey.clone_obj = zend_objects_clone_obj;
+ php_phongo_handler_maxkey.free_obj = php_phongo_maxkey_free_object;
+ php_phongo_handler_maxkey.offset = XtOffsetOf(php_phongo_maxkey_t, std);
+} /* }}} */
diff --git a/mongodb-1.13.0/src/BSON/MaxKeyInterface.c b/mongodb-1.13.0/src/BSON/MaxKeyInterface.c
new file mode 100644
index 00000000..99cbb564
--- /dev/null
+++ b/mongodb-1.13.0/src/BSON/MaxKeyInterface.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2017-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <php.h>
+
+#include "php_phongo.h"
+
+zend_class_entry* php_phongo_maxkey_interface_ce;
+
+/* {{{ MongoDB\BSON\MaxKeyInterface function entries */
+static zend_function_entry php_phongo_maxkey_interface_me[] = {
+ PHP_FE_END
+};
+/* }}} */
+
+void php_phongo_maxkey_interface_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\BSON", "MaxKeyInterface", php_phongo_maxkey_interface_me);
+ php_phongo_maxkey_interface_ce = zend_register_internal_interface(&ce);
+} /* }}} */
diff --git a/mongodb-1.13.0/src/BSON/MinKey.c b/mongodb-1.13.0/src/BSON/MinKey.c
new file mode 100644
index 00000000..d3e775ee
--- /dev/null
+++ b/mongodb-1.13.0/src/BSON/MinKey.c
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2014-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <php.h>
+#include <zend_smart_str.h>
+#include <ext/standard/php_var.h>
+#include <Zend/zend_interfaces.h>
+
+#include "php_phongo.h"
+#include "phongo_error.h"
+
+zend_class_entry* php_phongo_minkey_ce;
+
+/* {{{ proto MongoDB\BSON\MinKey MongoDB\BSON\MinKey::__set_state(array $properties)
+*/
+static PHP_METHOD(MinKey, __set_state)
+{
+ zend_error_handling error_handling;
+ zval* array;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &array) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ object_init_ex(return_value, php_phongo_minkey_ce);
+} /* }}} */
+
+/* {{{ proto array MongoDB\BSON\MinKey::jsonSerialize()
+*/
+static PHP_METHOD(MinKey, jsonSerialize)
+{
+ zend_error_handling error_handling;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ array_init_size(return_value, 1);
+ ADD_ASSOC_LONG_EX(return_value, "$minKey", 1);
+} /* }}} */
+
+/* {{{ proto string MongoDB\BSON\MinKey::serialize()
+*/
+static PHP_METHOD(MinKey, serialize)
+{
+ zend_error_handling error_handling;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ RETURN_STRING("");
+} /* }}} */
+
+/* {{{ proto void MongoDB\BSON\MinKey::unserialize(string $serialized)
+*/
+static PHP_METHOD(MinKey, unserialize)
+{
+ zend_error_handling error_handling;
+ char* serialized;
+ size_t serialized_len;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &serialized, &serialized_len) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+} /* }}} */
+
+/* {{{ proto array MongoDB\Driver\MinKey::__serialize()
+*/
+static PHP_METHOD(MinKey, __serialize)
+{
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ array_init_size(return_value, 0);
+} /* }}} */
+
+/* {{{ proto void MongoDB\Driver\MinKey::__unserialize(array $data)
+*/
+static PHP_METHOD(MinKey, __unserialize)
+{
+ zval* data;
+
+ PHONGO_PARSE_PARAMETERS_START(1, 1)
+ Z_PARAM_ARRAY(data)
+ PHONGO_PARSE_PARAMETERS_END();
+} /* }}} */
+
+/* {{{ MongoDB\BSON\MinKey function entries */
+/* clang-format off */
+ZEND_BEGIN_ARG_INFO_EX(ai_MinKey___set_state, 0, 0, 1)
+ ZEND_ARG_ARRAY_INFO(0, properties, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_MinKey___unserialize, 0, 0, 1)
+ ZEND_ARG_ARRAY_INFO(0, data, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(ai_MinKey_jsonSerialize, 0, 0, IS_ARRAY, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_MinKey_unserialize, 0, 0, 1)
+ ZEND_ARG_INFO(0, serialized)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_MinKey_void, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry php_phongo_minkey_me[] = {
+ PHP_ME(MinKey, __serialize, ai_MinKey_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(MinKey, __set_state, ai_MinKey___set_state, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+ PHP_ME(MinKey, __unserialize, ai_MinKey___unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(MinKey, jsonSerialize, ai_MinKey_jsonSerialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(MinKey, serialize, ai_MinKey_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(MinKey, unserialize, ai_MinKey_unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_FE_END
+};
+/* clang-format on */
+/* }}} */
+
+/* {{{ MongoDB\BSON\MinKey object handlers */
+static zend_object_handlers php_phongo_handler_minkey;
+
+static void php_phongo_minkey_free_object(zend_object* object) /* {{{ */
+{
+ php_phongo_minkey_t* intern = Z_OBJ_MINKEY(object);
+
+ zend_object_std_dtor(&intern->std);
+} /* }}} */
+
+static zend_object* php_phongo_minkey_create_object(zend_class_entry* class_type) /* {{{ */
+{
+ php_phongo_minkey_t* intern = zend_object_alloc(sizeof(php_phongo_minkey_t), class_type);
+
+ zend_object_std_init(&intern->std, class_type);
+ object_properties_init(&intern->std, class_type);
+
+ intern->std.handlers = &php_phongo_handler_minkey;
+
+ return &intern->std;
+} /* }}} */
+/* }}} */
+
+void php_phongo_minkey_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\BSON", "MinKey", php_phongo_minkey_me);
+ php_phongo_minkey_ce = zend_register_internal_class(&ce);
+ php_phongo_minkey_ce->create_object = php_phongo_minkey_create_object;
+ PHONGO_CE_FINAL(php_phongo_minkey_ce);
+
+ zend_class_implements(php_phongo_minkey_ce, 1, php_phongo_minkey_interface_ce);
+ zend_class_implements(php_phongo_minkey_ce, 1, php_phongo_json_serializable_ce);
+ zend_class_implements(php_phongo_minkey_ce, 1, php_phongo_type_ce);
+ zend_class_implements(php_phongo_minkey_ce, 1, zend_ce_serializable);
+
+ memcpy(&php_phongo_handler_minkey, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
+ /* Re-assign default handler previously removed in php_phongo.c */
+ php_phongo_handler_minkey.clone_obj = zend_objects_clone_obj;
+ php_phongo_handler_minkey.free_obj = php_phongo_minkey_free_object;
+ php_phongo_handler_minkey.offset = XtOffsetOf(php_phongo_minkey_t, std);
+} /* }}} */
diff --git a/mongodb-1.13.0/src/BSON/MinKeyInterface.c b/mongodb-1.13.0/src/BSON/MinKeyInterface.c
new file mode 100644
index 00000000..44025a9f
--- /dev/null
+++ b/mongodb-1.13.0/src/BSON/MinKeyInterface.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2017-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <php.h>
+
+#include "php_phongo.h"
+
+zend_class_entry* php_phongo_minkey_interface_ce;
+
+/* {{{ MongoDB\BSON\MinKeyInterface function entries */
+static zend_function_entry php_phongo_minkey_interface_me[] = {
+ PHP_FE_END
+};
+/* }}} */
+
+void php_phongo_minkey_interface_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\BSON", "MinKeyInterface", php_phongo_minkey_interface_me);
+ php_phongo_minkey_interface_ce = zend_register_internal_interface(&ce);
+} /* }}} */
diff --git a/mongodb-1.13.0/src/BSON/ObjectId.c b/mongodb-1.13.0/src/BSON/ObjectId.c
new file mode 100644
index 00000000..351b7947
--- /dev/null
+++ b/mongodb-1.13.0/src/BSON/ObjectId.c
@@ -0,0 +1,452 @@
+/*
+ * Copyright 2014-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bson/bson.h"
+
+#include <php.h>
+#include <zend_smart_str.h>
+#include <ext/standard/php_var.h>
+#include <Zend/zend_interfaces.h>
+
+#include "php_phongo.h"
+#include "phongo_error.h"
+
+#define PHONGO_OID_SIZE sizeof(((php_phongo_objectid_t*) 0)->oid)
+#define PHONGO_OID_LEN (PHONGO_OID_SIZE - 1)
+
+zend_class_entry* php_phongo_objectid_ce;
+
+/* Initialize the object with a generated value and return whether it was
+ * successful. */
+static bool php_phongo_objectid_init(php_phongo_objectid_t* intern)
+{
+ bson_oid_t oid;
+
+ intern->initialized = true;
+
+ bson_oid_init(&oid, NULL);
+ bson_oid_to_string(&oid, intern->oid);
+
+ return true;
+}
+
+/* Initialize the object from a hex string and return whether it was successful.
+ * An exception will be thrown on error. */
+static bool php_phongo_objectid_init_from_hex_string(php_phongo_objectid_t* intern, const char* hex, size_t hex_len) /* {{{ */
+{
+ if (bson_oid_is_valid(hex, hex_len)) {
+ bson_oid_t oid;
+
+ bson_oid_init_from_string(&oid, hex);
+ bson_oid_to_string(&oid, intern->oid);
+ intern->initialized = true;
+
+ return true;
+ }
+
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Error parsing ObjectId string: %s", hex);
+
+ return false;
+} /* }}} */
+
+/* Initialize the object from a HashTable and return whether it was successful.
+ * An exception will be thrown on error. */
+static bool php_phongo_objectid_init_from_hash(php_phongo_objectid_t* intern, HashTable* props) /* {{{ */
+{
+ zval* z_oid;
+
+ z_oid = zend_hash_str_find(props, "oid", sizeof("oid") - 1);
+
+ if (z_oid && Z_TYPE_P(z_oid) == IS_STRING) {
+ return php_phongo_objectid_init_from_hex_string(intern, Z_STRVAL_P(z_oid), Z_STRLEN_P(z_oid));
+ }
+
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"oid\" string field", ZSTR_VAL(php_phongo_objectid_ce->name));
+ return false;
+} /* }}} */
+
+static HashTable* php_phongo_objectid_get_properties_hash(phongo_compat_object_handler_type* object, bool is_temp) /* {{{ */
+{
+ php_phongo_objectid_t* intern;
+ HashTable* props;
+
+ intern = Z_OBJ_OBJECTID(PHONGO_COMPAT_GET_OBJ(object));
+
+ PHONGO_GET_PROPERTY_HASH_INIT_PROPS(is_temp, intern, props, 1);
+
+ if (!intern->initialized) {
+ return props;
+ }
+
+ {
+ zval zv;
+
+ ZVAL_STRING(&zv, intern->oid);
+ zend_hash_str_update(props, "oid", sizeof("oid") - 1, &zv);
+ }
+
+ return props;
+} /* }}} */
+
+/* {{{ proto void MongoDB\BSON\ObjectId::__construct([string $id])
+ Constructs a new BSON ObjectId type, optionally from a hex string. */
+static PHP_METHOD(ObjectId, __construct)
+{
+ zend_error_handling error_handling;
+ php_phongo_objectid_t* intern;
+ char* id = NULL;
+ size_t id_len;
+
+ intern = Z_OBJECTID_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s!", &id, &id_len) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ if (id) {
+ php_phongo_objectid_init_from_hex_string(intern, id, id_len);
+ } else {
+ php_phongo_objectid_init(intern);
+ }
+} /* }}} */
+
+/* {{{ proto integer MongoDB\BSON\ObjectId::getTimestamp()
+*/
+static PHP_METHOD(ObjectId, getTimestamp)
+{
+ zend_error_handling error_handling;
+ php_phongo_objectid_t* intern;
+ bson_oid_t tmp_oid;
+
+ intern = Z_OBJECTID_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ bson_oid_init_from_string(&tmp_oid, intern->oid);
+ RETVAL_LONG(bson_oid_get_time_t(&tmp_oid));
+} /* }}} */
+
+/* {{{ proto MongoDB\BSON\ObjectId MongoDB\BSON\ObjectId::__set_state(array $properties)
+*/
+static PHP_METHOD(ObjectId, __set_state)
+{
+ zend_error_handling error_handling;
+ php_phongo_objectid_t* intern;
+ HashTable* props;
+ zval* array;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &array) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ object_init_ex(return_value, php_phongo_objectid_ce);
+
+ intern = Z_OBJECTID_OBJ_P(return_value);
+ props = Z_ARRVAL_P(array);
+
+ php_phongo_objectid_init_from_hash(intern, props);
+} /* }}} */
+
+/* {{{ proto string MongoDB\BSON\ObjectId::__toString()
+*/
+static PHP_METHOD(ObjectId, __toString)
+{
+ zend_error_handling error_handling;
+ php_phongo_objectid_t* intern;
+
+ intern = Z_OBJECTID_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ RETURN_STRINGL(intern->oid, PHONGO_OID_LEN);
+} /* }}} */
+
+/* {{{ proto array MongoDB\BSON\ObjectId::jsonSerialize()
+*/
+static PHP_METHOD(ObjectId, jsonSerialize)
+{
+ zend_error_handling error_handling;
+ php_phongo_objectid_t* intern;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ intern = Z_OBJECTID_OBJ_P(getThis());
+
+ array_init_size(return_value, 1);
+ ADD_ASSOC_STRINGL(return_value, "$oid", intern->oid, PHONGO_OID_LEN);
+} /* }}} */
+
+/* {{{ proto string MongoDB\BSON\ObjectId::serialize()
+*/
+static PHP_METHOD(ObjectId, serialize)
+{
+ zend_error_handling error_handling;
+ php_phongo_objectid_t* intern;
+ zval retval;
+ php_serialize_data_t var_hash;
+ smart_str buf = { 0 };
+
+ intern = Z_OBJECTID_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ array_init_size(&retval, 1);
+ ADD_ASSOC_STRINGL(&retval, "oid", intern->oid, PHONGO_OID_LEN);
+
+ PHP_VAR_SERIALIZE_INIT(var_hash);
+ php_var_serialize(&buf, &retval, &var_hash);
+ smart_str_0(&buf);
+ PHP_VAR_SERIALIZE_DESTROY(var_hash);
+
+ PHONGO_RETVAL_SMART_STR(buf);
+
+ smart_str_free(&buf);
+ zval_ptr_dtor(&retval);
+} /* }}} */
+
+/* {{{ proto void MongoDB\BSON\ObjectId::unserialize(string $serialized)
+*/
+static PHP_METHOD(ObjectId, unserialize)
+{
+ zend_error_handling error_handling;
+ php_phongo_objectid_t* intern;
+ char* serialized;
+ size_t serialized_len;
+ zval props;
+ php_unserialize_data_t var_hash;
+
+ intern = Z_OBJECTID_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &serialized, &serialized_len) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ PHP_VAR_UNSERIALIZE_INIT(var_hash);
+ if (!php_var_unserialize(&props, (const unsigned char**) &serialized, (unsigned char*) serialized + serialized_len, &var_hash)) {
+ zval_ptr_dtor(&props);
+ phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "%s unserialization failed", ZSTR_VAL(php_phongo_objectid_ce->name));
+
+ PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+ return;
+ }
+ PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+
+ php_phongo_objectid_init_from_hash(intern, HASH_OF(&props));
+ zval_ptr_dtor(&props);
+} /* }}} */
+
+/* {{{ proto array MongoDB\Driver\ObjectId::__serialize()
+*/
+static PHP_METHOD(ObjectId, __serialize)
+{
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ RETURN_ARR(php_phongo_objectid_get_properties_hash(PHONGO_COMPAT_OBJ_P(getThis()), true));
+} /* }}} */
+
+/* {{{ proto void MongoDB\Driver\ObjectId::__unserialize(array $data)
+*/
+static PHP_METHOD(ObjectId, __unserialize)
+{
+ zval* data;
+
+ PHONGO_PARSE_PARAMETERS_START(1, 1)
+ Z_PARAM_ARRAY(data)
+ PHONGO_PARSE_PARAMETERS_END();
+
+ php_phongo_objectid_init_from_hash(Z_OBJECTID_OBJ_P(getThis()), Z_ARRVAL_P(data));
+} /* }}} */
+
+/* {{{ MongoDB\BSON\ObjectId function entries */
+/* clang-format off */
+ZEND_BEGIN_ARG_INFO_EX(ai_ObjectId___construct, 0, 0, 0)
+ ZEND_ARG_INFO(0, id)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_ObjectId___set_state, 0, 0, 1)
+ ZEND_ARG_ARRAY_INFO(0, properties, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(ai_ObjectId___toString, 0, 0, IS_STRING, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_ObjectId___unserialize, 0, 0, 1)
+ ZEND_ARG_ARRAY_INFO(0, data, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(ai_ObjectId_jsonSerialize, 0, 0, IS_ARRAY, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_ObjectId_unserialize, 0, 0, 1)
+ ZEND_ARG_INFO(0, serialized)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_ObjectId_void, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry php_phongo_objectid_me[] = {
+ PHP_ME(ObjectId, __construct, ai_ObjectId___construct, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(ObjectId, getTimestamp, ai_ObjectId_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(ObjectId, __serialize, ai_ObjectId_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(ObjectId, __set_state, ai_ObjectId___set_state, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+ PHP_ME(ObjectId, __toString, ai_ObjectId___toString, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(ObjectId, __unserialize, ai_ObjectId___unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(ObjectId, jsonSerialize, ai_ObjectId_jsonSerialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(ObjectId, serialize, ai_ObjectId_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(ObjectId, unserialize, ai_ObjectId_unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_FE_END
+};
+/* clang-format on */
+/* }}} */
+
+/* {{{ MongoDB\BSON\ObjectId object handlers */
+static zend_object_handlers php_phongo_handler_objectid;
+
+static void php_phongo_objectid_free_object(zend_object* object) /* {{{ */
+{
+ php_phongo_objectid_t* intern = Z_OBJ_OBJECTID(object);
+
+ zend_object_std_dtor(&intern->std);
+
+ if (intern->properties) {
+ zend_hash_destroy(intern->properties);
+ FREE_HASHTABLE(intern->properties);
+ }
+} /* }}} */
+
+static zend_object* php_phongo_objectid_create_object(zend_class_entry* class_type) /* {{{ */
+{
+ php_phongo_objectid_t* intern = zend_object_alloc(sizeof(php_phongo_objectid_t), class_type);
+
+ zend_object_std_init(&intern->std, class_type);
+ object_properties_init(&intern->std, class_type);
+
+ intern->std.handlers = &php_phongo_handler_objectid;
+
+ return &intern->std;
+} /* }}} */
+
+static zend_object* php_phongo_objectid_clone_object(phongo_compat_object_handler_type* object) /* {{{ */
+{
+ php_phongo_objectid_t* intern;
+ php_phongo_objectid_t* new_intern;
+ zend_object* new_object;
+
+ intern = Z_OBJ_OBJECTID(PHONGO_COMPAT_GET_OBJ(object));
+ new_object = php_phongo_objectid_create_object(PHONGO_COMPAT_GET_OBJ(object)->ce);
+
+ new_intern = Z_OBJ_OBJECTID(new_object);
+ zend_objects_clone_members(&new_intern->std, &intern->std);
+
+ // Use memcpy to copy bson value to avoid converting to string and back
+ memcpy(&new_intern->oid, &intern->oid, PHONGO_OID_SIZE);
+ new_intern->initialized = true;
+
+ return new_object;
+} /* }}} */
+
+static int php_phongo_objectid_compare_objects(zval* o1, zval* o2) /* {{{ */
+{
+ php_phongo_objectid_t* intern1;
+ php_phongo_objectid_t* intern2;
+
+ ZEND_COMPARE_OBJECTS_FALLBACK(o1, o2);
+
+ intern1 = Z_OBJECTID_OBJ_P(o1);
+ intern2 = Z_OBJECTID_OBJ_P(o2);
+
+ return strcmp(intern1->oid, intern2->oid);
+} /* }}} */
+
+static HashTable* php_phongo_objectid_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
+{
+ *is_temp = 1;
+ return php_phongo_objectid_get_properties_hash(object, true);
+} /* }}} */
+
+static HashTable* php_phongo_objectid_get_properties(phongo_compat_object_handler_type* object) /* {{{ */
+{
+ return php_phongo_objectid_get_properties_hash(object, false);
+} /* }}} */
+/* }}} */
+
+void php_phongo_objectid_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\BSON", "ObjectId", php_phongo_objectid_me);
+ php_phongo_objectid_ce = zend_register_internal_class(&ce);
+ php_phongo_objectid_ce->create_object = php_phongo_objectid_create_object;
+ PHONGO_CE_FINAL(php_phongo_objectid_ce);
+
+ zend_class_implements(php_phongo_objectid_ce, 1, php_phongo_objectid_interface_ce);
+ zend_class_implements(php_phongo_objectid_ce, 1, php_phongo_json_serializable_ce);
+ zend_class_implements(php_phongo_objectid_ce, 1, php_phongo_type_ce);
+ zend_class_implements(php_phongo_objectid_ce, 1, zend_ce_serializable);
+
+#if PHP_VERSION_ID >= 80000
+ zend_class_implements(php_phongo_objectid_ce, 1, zend_ce_stringable);
+#endif
+
+ memcpy(&php_phongo_handler_objectid, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
+ PHONGO_COMPAT_SET_COMPARE_OBJECTS_HANDLER(objectid);
+ php_phongo_handler_objectid.clone_obj = php_phongo_objectid_clone_object;
+ php_phongo_handler_objectid.get_debug_info = php_phongo_objectid_get_debug_info;
+ php_phongo_handler_objectid.get_properties = php_phongo_objectid_get_properties;
+ php_phongo_handler_objectid.free_obj = php_phongo_objectid_free_object;
+ php_phongo_handler_objectid.offset = XtOffsetOf(php_phongo_objectid_t, std);
+} /* }}} */
+
+void phongo_objectid_init(zval* return_value, const bson_oid_t* oid) /* {{{ */
+{
+ php_phongo_objectid_t* intern;
+
+ object_init_ex(return_value, php_phongo_objectid_ce);
+
+ intern = Z_OBJECTID_OBJ_P(return_value);
+ bson_oid_to_string(oid, intern->oid);
+ intern->initialized = true;
+}
+/* }}} */
diff --git a/mongodb-1.13.0/src/BSON/ObjectId.h b/mongodb-1.13.0/src/BSON/ObjectId.h
new file mode 100644
index 00000000..ef01e32a
--- /dev/null
+++ b/mongodb-1.13.0/src/BSON/ObjectId.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2022-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PHONGO_BSON_OBJECTID_H
+#define PHONGO_BSON_OBJECTID_H
+
+#include "bson/bson.h"
+
+#include <php.h>
+
+void phongo_objectid_init(zval* return_value, const bson_oid_t* oid);
+
+#endif /* PHONGO_BSON_OBJECTID_H */
diff --git a/mongodb-1.13.0/src/BSON/ObjectIdInterface.c b/mongodb-1.13.0/src/BSON/ObjectIdInterface.c
new file mode 100644
index 00000000..a572b5b9
--- /dev/null
+++ b/mongodb-1.13.0/src/BSON/ObjectIdInterface.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2017-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <php.h>
+
+#include "php_phongo.h"
+
+zend_class_entry* php_phongo_objectid_interface_ce;
+
+/* {{{ MongoDB\BSON\ObjectIdInterface function entries */
+/* clang-format off */
+ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(ai_ObjectIdInterface___toString, 0, 0, IS_STRING, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_ObjectIdInterface_void, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry php_phongo_objectid_interface_me[] = {
+ ZEND_ABSTRACT_ME(ObjectIdInterface, getTimestamp, ai_ObjectIdInterface_void)
+ ZEND_ABSTRACT_ME(ObjectIdInterface, __toString, ai_ObjectIdInterface___toString)
+ PHP_FE_END
+};
+/* clang-format on */
+/* }}} */
+
+void php_phongo_objectid_interface_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\BSON", "ObjectIdInterface", php_phongo_objectid_interface_me);
+ php_phongo_objectid_interface_ce = zend_register_internal_interface(&ce);
+} /* }}} */
diff --git a/mongodb-1.13.0/src/BSON/Persistable.c b/mongodb-1.13.0/src/BSON/Persistable.c
new file mode 100644
index 00000000..29949f4a
--- /dev/null
+++ b/mongodb-1.13.0/src/BSON/Persistable.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2014-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <php.h>
+
+#include "php_phongo.h"
+
+zend_class_entry* php_phongo_persistable_ce;
+
+/* {{{ MongoDB\BSON\Persistable function entries */
+static zend_function_entry php_phongo_persistable_me[] = {
+ PHP_FE_END
+};
+/* }}} */
+
+void php_phongo_persistable_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\BSON", "Persistable", php_phongo_persistable_me);
+ php_phongo_persistable_ce = zend_register_internal_interface(&ce);
+ zend_class_implements(php_phongo_persistable_ce, 2, php_phongo_unserializable_ce, php_phongo_serializable_ce);
+} /* }}} */
diff --git a/mongodb-1.13.0/src/BSON/Regex.c b/mongodb-1.13.0/src/BSON/Regex.c
new file mode 100644
index 00000000..8dfe34f6
--- /dev/null
+++ b/mongodb-1.13.0/src/BSON/Regex.c
@@ -0,0 +1,479 @@
+/*
+ * Copyright 2014-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <php.h>
+#include <zend_smart_str.h>
+#include <ext/standard/php_var.h>
+#include <Zend/zend_interfaces.h>
+
+#include "php_phongo.h"
+#include "phongo_error.h"
+
+zend_class_entry* php_phongo_regex_ce;
+
+/* qsort() compare callback for alphabetizing regex flags upon initialization */
+static int php_phongo_regex_compare_flags(const void* f1, const void* f2) /* {{{ */
+{
+ if (*(const char*) f1 == *(const char*) f2) {
+ return 0;
+ }
+
+ return (*(const char*) f1 > *(const char*) f2) ? 1 : -1;
+} /* }}} */
+
+/* Initialize the object and return whether it was successful. An exception will
+ * be thrown on error. */
+static bool php_phongo_regex_init(php_phongo_regex_t* intern, const char* pattern, size_t pattern_len, const char* flags, size_t flags_len) /* {{{ */
+{
+ if (strlen(pattern) != (size_t) pattern_len) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Pattern cannot contain null bytes");
+ return false;
+ }
+ intern->pattern = estrndup(pattern, pattern_len);
+ intern->pattern_len = pattern_len;
+
+ if (flags) {
+ if (strlen(flags) != (size_t) flags_len) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Flags cannot contain null bytes");
+ return false;
+ }
+ intern->flags = estrndup(flags, flags_len);
+ intern->flags_len = flags_len;
+ /* Ensure flags are alphabetized upon initialization */
+ qsort((void*) intern->flags, flags_len, 1, php_phongo_regex_compare_flags);
+ } else {
+ intern->flags = estrdup("");
+ intern->flags_len = 0;
+ }
+
+ return true;
+} /* }}} */
+
+/* Initialize the object from a HashTable and return whether it was successful.
+ * An exception will be thrown on error. */
+static bool php_phongo_regex_init_from_hash(php_phongo_regex_t* intern, HashTable* props) /* {{{ */
+{
+ zval *pattern, *flags;
+
+ if ((pattern = zend_hash_str_find(props, "pattern", sizeof("pattern") - 1)) && Z_TYPE_P(pattern) == IS_STRING &&
+ (flags = zend_hash_str_find(props, "flags", sizeof("flags") - 1)) && Z_TYPE_P(flags) == IS_STRING) {
+
+ return php_phongo_regex_init(intern, Z_STRVAL_P(pattern), Z_STRLEN_P(pattern), Z_STRVAL_P(flags), Z_STRLEN_P(flags));
+ }
+
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"pattern\" and \"flags\" string fields", ZSTR_VAL(php_phongo_regex_ce->name));
+ return false;
+} /* }}} */
+
+static HashTable* php_phongo_regex_get_properties_hash(phongo_compat_object_handler_type* object, bool is_temp) /* {{{ */
+{
+ php_phongo_regex_t* intern;
+ HashTable* props;
+
+ intern = Z_OBJ_REGEX(PHONGO_COMPAT_GET_OBJ(object));
+
+ PHONGO_GET_PROPERTY_HASH_INIT_PROPS(is_temp, intern, props, 2);
+
+ if (!intern->pattern) {
+ return props;
+ }
+
+ {
+ zval pattern, flags;
+
+ ZVAL_STRINGL(&pattern, intern->pattern, intern->pattern_len);
+ zend_hash_str_update(props, "pattern", sizeof("pattern") - 1, &pattern);
+
+ ZVAL_STRINGL(&flags, intern->flags, intern->flags_len);
+ zend_hash_str_update(props, "flags", sizeof("flags") - 1, &flags);
+ }
+
+ return props;
+} /* }}} */
+
+/* {{{ proto void MongoDB\BSON\Regex::__construct(string $pattern [, string $flags])
+ Constructs a new BSON regular expression type. */
+static PHP_METHOD(Regex, __construct)
+{
+ zend_error_handling error_handling;
+ php_phongo_regex_t* intern;
+ char* pattern;
+ size_t pattern_len;
+ char* flags = NULL;
+ size_t flags_len = 0;
+
+ intern = Z_REGEX_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|s", &pattern, &pattern_len, &flags, &flags_len) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ php_phongo_regex_init(intern, pattern, pattern_len, flags, flags_len);
+} /* }}} */
+
+/* {{{ proto string MongoDB\BSON\Regex::getPattern()
+*/
+static PHP_METHOD(Regex, getPattern)
+{
+ zend_error_handling error_handling;
+ php_phongo_regex_t* intern;
+
+ intern = Z_REGEX_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ RETURN_STRINGL(intern->pattern, intern->pattern_len);
+} /* }}} */
+
+/* {{{ proto string MongoDB\BSON\Regex::getFlags()
+*/
+static PHP_METHOD(Regex, getFlags)
+{
+ zend_error_handling error_handling;
+ php_phongo_regex_t* intern;
+
+ intern = Z_REGEX_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ RETURN_STRINGL(intern->flags, intern->flags_len);
+} /* }}} */
+
+/* {{{ proto MongoDB\BSON\Regex MongoDB\BSON\Regex::__set_state(array $properties)
+*/
+static PHP_METHOD(Regex, __set_state)
+{
+ zend_error_handling error_handling;
+ php_phongo_regex_t* intern;
+ HashTable* props;
+ zval* array;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &array) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ object_init_ex(return_value, php_phongo_regex_ce);
+
+ intern = Z_REGEX_OBJ_P(return_value);
+ props = Z_ARRVAL_P(array);
+
+ php_phongo_regex_init_from_hash(intern, props);
+} /* }}} */
+
+/* {{{ proto string MongoDB\BSON\Regex::__toString()
+ Returns a string in the form: /pattern/flags */
+static PHP_METHOD(Regex, __toString)
+{
+ zend_error_handling error_handling;
+ php_phongo_regex_t* intern;
+ char* regex;
+ int regex_len;
+
+ intern = Z_REGEX_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ regex_len = spprintf(&regex, 0, "/%s/%s", intern->pattern, intern->flags);
+ RETVAL_STRINGL(regex, regex_len);
+ efree(regex);
+} /* }}} */
+
+/* {{{ proto array MongoDB\BSON\Regex::jsonSerialize()
+*/
+static PHP_METHOD(Regex, jsonSerialize)
+{
+ zend_error_handling error_handling;
+ php_phongo_regex_t* intern;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ intern = Z_REGEX_OBJ_P(getThis());
+
+ array_init_size(return_value, 2);
+ ADD_ASSOC_STRINGL(return_value, "$regex", intern->pattern, intern->pattern_len);
+ ADD_ASSOC_STRINGL(return_value, "$options", intern->flags, intern->flags_len);
+} /* }}} */
+
+/* {{{ proto string MongoDB\BSON\Regex::serialize()
+*/
+static PHP_METHOD(Regex, serialize)
+{
+ zend_error_handling error_handling;
+ php_phongo_regex_t* intern;
+ zval retval;
+ php_serialize_data_t var_hash;
+ smart_str buf = { 0 };
+
+ intern = Z_REGEX_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ array_init_size(&retval, 2);
+ ADD_ASSOC_STRINGL(&retval, "pattern", intern->pattern, intern->pattern_len);
+ ADD_ASSOC_STRINGL(&retval, "flags", intern->flags, intern->flags_len);
+
+ PHP_VAR_SERIALIZE_INIT(var_hash);
+ php_var_serialize(&buf, &retval, &var_hash);
+ smart_str_0(&buf);
+ PHP_VAR_SERIALIZE_DESTROY(var_hash);
+
+ PHONGO_RETVAL_SMART_STR(buf);
+
+ smart_str_free(&buf);
+ zval_ptr_dtor(&retval);
+} /* }}} */
+
+/* {{{ proto void MongoDB\BSON\Regex::unserialize(string $serialized)
+*/
+static PHP_METHOD(Regex, unserialize)
+{
+ zend_error_handling error_handling;
+ php_phongo_regex_t* intern;
+ char* serialized;
+ size_t serialized_len;
+ zval props;
+ php_unserialize_data_t var_hash;
+
+ intern = Z_REGEX_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &serialized, &serialized_len) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ PHP_VAR_UNSERIALIZE_INIT(var_hash);
+ if (!php_var_unserialize(&props, (const unsigned char**) &serialized, (unsigned char*) serialized + serialized_len, &var_hash)) {
+ zval_ptr_dtor(&props);
+ phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "%s unserialization failed", ZSTR_VAL(php_phongo_regex_ce->name));
+
+ PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+ return;
+ }
+ PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+
+ php_phongo_regex_init_from_hash(intern, HASH_OF(&props));
+ zval_ptr_dtor(&props);
+} /* }}} */
+
+/* {{{ proto array MongoDB\Driver\Regex::__serialize()
+*/
+static PHP_METHOD(Regex, __serialize)
+{
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ RETURN_ARR(php_phongo_regex_get_properties_hash(PHONGO_COMPAT_OBJ_P(getThis()), true));
+} /* }}} */
+
+/* {{{ proto void MongoDB\Driver\Regex::__unserialize(array $data)
+*/
+static PHP_METHOD(Regex, __unserialize)
+{
+ zval* data;
+
+ PHONGO_PARSE_PARAMETERS_START(1, 1)
+ Z_PARAM_ARRAY(data)
+ PHONGO_PARSE_PARAMETERS_END();
+
+ php_phongo_regex_init_from_hash(Z_REGEX_OBJ_P(getThis()), Z_ARRVAL_P(data));
+} /* }}} */
+
+/* {{{ MongoDB\BSON\Regex function entries */
+/* clang-format off */
+ZEND_BEGIN_ARG_INFO_EX(ai_Regex___construct, 0, 0, 1)
+ ZEND_ARG_INFO(0, pattern)
+ ZEND_ARG_INFO(0, flags)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_Regex___set_state, 0, 0, 1)
+ ZEND_ARG_ARRAY_INFO(0, properties, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(ai_Regex___toString, 0, 0, IS_STRING, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_Regex___unserialize, 0, 0, 1)
+ ZEND_ARG_ARRAY_INFO(0, data, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(ai_Regex_jsonSerialize, 0, 0, IS_ARRAY, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_Regex_unserialize, 0, 0, 1)
+ ZEND_ARG_INFO(0, serialized)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_Regex_void, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry php_phongo_regex_me[] = {
+ PHP_ME(Regex, __construct, ai_Regex___construct, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Regex, __serialize, ai_Regex_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Regex, __set_state, ai_Regex___set_state, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+ PHP_ME(Regex, __toString, ai_Regex___toString, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Regex, __unserialize, ai_Regex___unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Regex, jsonSerialize, ai_Regex_jsonSerialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Regex, serialize, ai_Regex_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Regex, unserialize, ai_Regex_unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Regex, getPattern, ai_Regex_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Regex, getFlags, ai_Regex_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_FE_END
+};
+/* clang-format on */
+/* }}} */
+
+/* {{{ MongoDB\BSON\Regex object handlers */
+static zend_object_handlers php_phongo_handler_regex;
+
+static void php_phongo_regex_free_object(zend_object* object) /* {{{ */
+{
+ php_phongo_regex_t* intern = Z_OBJ_REGEX(object);
+
+ zend_object_std_dtor(&intern->std);
+
+ if (intern->pattern) {
+ efree(intern->pattern);
+ }
+
+ if (intern->flags) {
+ efree(intern->flags);
+ }
+
+ if (intern->properties) {
+ zend_hash_destroy(intern->properties);
+ FREE_HASHTABLE(intern->properties);
+ }
+} /* }}} */
+
+static zend_object* php_phongo_regex_create_object(zend_class_entry* class_type) /* {{{ */
+{
+ php_phongo_regex_t* intern = zend_object_alloc(sizeof(php_phongo_regex_t), class_type);
+
+ zend_object_std_init(&intern->std, class_type);
+ object_properties_init(&intern->std, class_type);
+
+ intern->std.handlers = &php_phongo_handler_regex;
+
+ return &intern->std;
+} /* }}} */
+
+static zend_object* php_phongo_regex_clone_object(phongo_compat_object_handler_type* object) /* {{{ */
+{
+ php_phongo_regex_t* intern;
+ php_phongo_regex_t* new_intern;
+ zend_object* new_object;
+
+ intern = Z_OBJ_REGEX(PHONGO_COMPAT_GET_OBJ(object));
+ new_object = php_phongo_regex_create_object(PHONGO_COMPAT_GET_OBJ(object)->ce);
+
+ new_intern = Z_OBJ_REGEX(new_object);
+ zend_objects_clone_members(&new_intern->std, &intern->std);
+
+ php_phongo_regex_init(new_intern, intern->pattern, intern->pattern_len, intern->flags, intern->flags_len);
+
+ return new_object;
+} /* }}} */
+
+static int php_phongo_regex_compare_objects(zval* o1, zval* o2) /* {{{ */
+{
+ php_phongo_regex_t *intern1, *intern2;
+ int retval;
+
+ ZEND_COMPARE_OBJECTS_FALLBACK(o1, o2);
+
+ intern1 = Z_REGEX_OBJ_P(o1);
+ intern2 = Z_REGEX_OBJ_P(o2);
+
+ /* MongoDB compares the pattern string before the flags. */
+ retval = strcmp(intern1->pattern, intern2->pattern);
+
+ if (retval != 0) {
+ return retval;
+ }
+
+ return strcmp(intern1->flags, intern2->flags);
+} /* }}} */
+
+static HashTable* php_phongo_regex_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
+{
+ *is_temp = 1;
+ return php_phongo_regex_get_properties_hash(object, true);
+} /* }}} */
+
+static HashTable* php_phongo_regex_get_properties(phongo_compat_object_handler_type* object) /* {{{ */
+{
+ return php_phongo_regex_get_properties_hash(object, false);
+} /* }}} */
+/* }}} */
+
+void php_phongo_regex_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\BSON", "Regex", php_phongo_regex_me);
+ php_phongo_regex_ce = zend_register_internal_class(&ce);
+ php_phongo_regex_ce->create_object = php_phongo_regex_create_object;
+ PHONGO_CE_FINAL(php_phongo_regex_ce);
+
+ zend_class_implements(php_phongo_regex_ce, 1, php_phongo_regex_interface_ce);
+ zend_class_implements(php_phongo_regex_ce, 1, php_phongo_type_ce);
+ zend_class_implements(php_phongo_regex_ce, 1, zend_ce_serializable);
+ zend_class_implements(php_phongo_regex_ce, 1, php_phongo_json_serializable_ce);
+
+#if PHP_VERSION_ID >= 80000
+ zend_class_implements(php_phongo_regex_ce, 1, zend_ce_stringable);
+#endif
+
+ memcpy(&php_phongo_handler_regex, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
+ PHONGO_COMPAT_SET_COMPARE_OBJECTS_HANDLER(regex);
+ php_phongo_handler_regex.clone_obj = php_phongo_regex_clone_object;
+ php_phongo_handler_regex.get_debug_info = php_phongo_regex_get_debug_info;
+ php_phongo_handler_regex.get_properties = php_phongo_regex_get_properties;
+ php_phongo_handler_regex.free_obj = php_phongo_regex_free_object;
+ php_phongo_handler_regex.offset = XtOffsetOf(php_phongo_regex_t, std);
+} /* }}} */
diff --git a/mongodb-1.13.0/src/BSON/RegexInterface.c b/mongodb-1.13.0/src/BSON/RegexInterface.c
new file mode 100644
index 00000000..c8c0e267
--- /dev/null
+++ b/mongodb-1.13.0/src/BSON/RegexInterface.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2017-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <php.h>
+
+#include "php_phongo.h"
+
+zend_class_entry* php_phongo_regex_interface_ce;
+
+/* {{{ MongoDB\BSON\RegexInterface function entries */
+/* clang-format off */
+ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(ai_RegexInterface___toString, 0, 0, IS_STRING, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_RegexInterface_void, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry php_phongo_regex_interface_me[] = {
+ ZEND_ABSTRACT_ME(RegexInterface, getFlags, ai_RegexInterface_void)
+ ZEND_ABSTRACT_ME(RegexInterface, getPattern, ai_RegexInterface_void)
+ ZEND_ABSTRACT_ME(RegexInterface, __toString, ai_RegexInterface___toString)
+ PHP_FE_END
+};
+/* clang-format on */
+/* }}} */
+
+void php_phongo_regex_interface_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\BSON", "RegexInterface", php_phongo_regex_interface_me);
+ php_phongo_regex_interface_ce = zend_register_internal_interface(&ce);
+} /* }}} */
diff --git a/mongodb-1.13.0/src/BSON/Serializable.c b/mongodb-1.13.0/src/BSON/Serializable.c
new file mode 100644
index 00000000..5563b29e
--- /dev/null
+++ b/mongodb-1.13.0/src/BSON/Serializable.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2014-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <php.h>
+
+#include "php_phongo.h"
+
+zend_class_entry* php_phongo_serializable_ce;
+
+/* {{{ MongoDB\BSON\Serializable function entries */
+ZEND_BEGIN_ARG_INFO_EX(ai_Serializable_void, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry php_phongo_serializable_me[] = {
+ /* clang-format off */
+ ZEND_ABSTRACT_ME(Serializable, bsonSerialize, ai_Serializable_void)
+ PHP_FE_END
+ /* clang-format on */
+};
+/* }}} */
+
+void php_phongo_serializable_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\BSON", "Serializable", php_phongo_serializable_me);
+ php_phongo_serializable_ce = zend_register_internal_interface(&ce);
+ zend_class_implements(php_phongo_serializable_ce, 1, php_phongo_type_ce);
+} /* }}} */
diff --git a/mongodb-1.13.0/src/BSON/Symbol.c b/mongodb-1.13.0/src/BSON/Symbol.c
new file mode 100644
index 00000000..c547be37
--- /dev/null
+++ b/mongodb-1.13.0/src/BSON/Symbol.c
@@ -0,0 +1,336 @@
+/*
+ * Copyright 2014-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <php.h>
+#include <zend_smart_str.h>
+#include <ext/standard/php_var.h>
+#include <Zend/zend_interfaces.h>
+
+#include "php_phongo.h"
+#include "phongo_error.h"
+
+zend_class_entry* php_phongo_symbol_ce;
+
+/* Initialize the object and return whether it was successful. An exception will
+ * be thrown on error. */
+static bool php_phongo_symbol_init(php_phongo_symbol_t* intern, const char* symbol, size_t symbol_len) /* {{{ */
+{
+ if (strlen(symbol) != (size_t) symbol_len) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Symbol cannot contain null bytes");
+ return false;
+ }
+
+ intern->symbol = estrndup(symbol, symbol_len);
+ intern->symbol_len = symbol_len;
+
+ return true;
+} /* }}} */
+
+/* Initialize the object from a HashTable and return whether it was successful.
+ * An exception will be thrown on error. */
+static bool php_phongo_symbol_init_from_hash(php_phongo_symbol_t* intern, HashTable* props) /* {{{ */
+{
+ zval* symbol;
+
+ if ((symbol = zend_hash_str_find(props, "symbol", sizeof("symbol") - 1)) && Z_TYPE_P(symbol) == IS_STRING) {
+ return php_phongo_symbol_init(intern, Z_STRVAL_P(symbol), Z_STRLEN_P(symbol));
+ }
+
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"symbol\" string field", ZSTR_VAL(php_phongo_symbol_ce->name));
+ return false;
+} /* }}} */
+
+HashTable* php_phongo_symbol_get_properties_hash(phongo_compat_object_handler_type* object, bool is_temp) /* {{{ */
+{
+ php_phongo_symbol_t* intern;
+ HashTable* props;
+
+ intern = Z_OBJ_SYMBOL(PHONGO_COMPAT_GET_OBJ(object));
+
+ PHONGO_GET_PROPERTY_HASH_INIT_PROPS(is_temp, intern, props, 2);
+
+ if (!intern->symbol) {
+ return props;
+ }
+
+ {
+ zval symbol;
+
+ ZVAL_STRING(&symbol, intern->symbol);
+ zend_hash_str_update(props, "symbol", sizeof("symbol") - 1, &symbol);
+ }
+
+ return props;
+} /* }}} */
+
+/* {{{ proto string MongoDB\BSON\Symbol::__toString()
+ Return the Symbol's symbol string. */
+static PHP_METHOD(Symbol, __toString)
+{
+ zend_error_handling error_handling;
+ php_phongo_symbol_t* intern;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ intern = Z_SYMBOL_OBJ_P(getThis());
+
+ RETURN_STRINGL(intern->symbol, intern->symbol_len);
+} /* }}} */
+
+/* {{{ proto array MongoDB\BSON\Symbol::jsonSerialize()
+*/
+static PHP_METHOD(Symbol, jsonSerialize)
+{
+ zend_error_handling error_handling;
+ php_phongo_symbol_t* intern;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ intern = Z_SYMBOL_OBJ_P(getThis());
+
+ array_init_size(return_value, 1);
+ ADD_ASSOC_STRINGL(return_value, "$symbol", intern->symbol, intern->symbol_len);
+} /* }}} */
+
+/* {{{ proto string MongoDB\BSON\Symbol::serialize()
+*/
+static PHP_METHOD(Symbol, serialize)
+{
+ zend_error_handling error_handling;
+ php_phongo_symbol_t* intern;
+ zval retval;
+ php_serialize_data_t var_hash;
+ smart_str buf = { 0 };
+
+ intern = Z_SYMBOL_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ array_init_size(&retval, 1);
+ ADD_ASSOC_STRINGL(&retval, "symbol", intern->symbol, intern->symbol_len);
+
+ PHP_VAR_SERIALIZE_INIT(var_hash);
+ php_var_serialize(&buf, &retval, &var_hash);
+ smart_str_0(&buf);
+ PHP_VAR_SERIALIZE_DESTROY(var_hash);
+
+ PHONGO_RETVAL_SMART_STR(buf);
+
+ smart_str_free(&buf);
+ zval_ptr_dtor(&retval);
+} /* }}} */
+
+/* {{{ proto void MongoDB\BSON\Symbol::unserialize(string $serialized)
+*/
+static PHP_METHOD(Symbol, unserialize)
+{
+ zend_error_handling error_handling;
+ php_phongo_symbol_t* intern;
+ char* serialized;
+ size_t serialized_len;
+ zval props;
+ php_unserialize_data_t var_hash;
+
+ intern = Z_SYMBOL_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &serialized, &serialized_len) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ PHP_VAR_UNSERIALIZE_INIT(var_hash);
+ if (!php_var_unserialize(&props, (const unsigned char**) &serialized, (unsigned char*) serialized + serialized_len, &var_hash)) {
+ zval_ptr_dtor(&props);
+ phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "%s unserialization failed", ZSTR_VAL(php_phongo_symbol_ce->name));
+
+ PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+ return;
+ }
+ PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+
+ php_phongo_symbol_init_from_hash(intern, HASH_OF(&props));
+ zval_ptr_dtor(&props);
+} /* }}} */
+
+/* {{{ proto array MongoDB\Driver\Symbol::__serialize()
+*/
+static PHP_METHOD(Symbol, __serialize)
+{
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ ZVAL_ARR(return_value, php_phongo_symbol_get_properties_hash(PHONGO_COMPAT_OBJ_P(getThis()), true));
+} /* }}} */
+
+/* {{{ proto void MongoDB\Driver\Symbol::__unserialize(array $data)
+*/
+static PHP_METHOD(Symbol, __unserialize)
+{
+ zval* data;
+
+ PHONGO_PARSE_PARAMETERS_START(1, 1)
+ Z_PARAM_ARRAY(data)
+ PHONGO_PARSE_PARAMETERS_END();
+
+ php_phongo_symbol_init_from_hash(Z_SYMBOL_OBJ_P(getThis()), Z_ARRVAL_P(data));
+} /* }}} */
+
+/* {{{ MongoDB\BSON\Symbol function entries */
+/* clang-format off */
+ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(ai_Symbol___toString, 0, 0, IS_STRING, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_Symbol___unserialize, 0, 0, 1)
+ ZEND_ARG_ARRAY_INFO(0, data, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(ai_Symbol_jsonSerialize, 0, 0, IS_ARRAY, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_Symbol_unserialize, 0, 0, 1)
+ ZEND_ARG_INFO(0, serialized)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_Symbol_void, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry php_phongo_symbol_me[] = {
+ /* __set_state intentionally missing */
+ PHP_ME(Symbol, __serialize, ai_Symbol_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Symbol, __toString, ai_Symbol___toString, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Symbol, __unserialize, ai_Symbol___unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Symbol, jsonSerialize, ai_Symbol_jsonSerialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Symbol, serialize, ai_Symbol_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Symbol, unserialize, ai_Symbol_unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ ZEND_NAMED_ME(__construct, PHP_FN(MongoDB_disabled___construct), ai_Symbol_void, ZEND_ACC_PRIVATE | ZEND_ACC_FINAL)
+ PHP_FE_END
+};
+/* clang-format on */
+/* }}} */
+
+/* {{{ MongoDB\BSON\Symbol object handlers */
+static zend_object_handlers php_phongo_handler_symbol;
+
+static void php_phongo_symbol_free_object(zend_object* object) /* {{{ */
+{
+ php_phongo_symbol_t* intern = Z_OBJ_SYMBOL(object);
+
+ zend_object_std_dtor(&intern->std);
+
+ if (intern->symbol) {
+ efree(intern->symbol);
+ }
+
+ if (intern->properties) {
+ zend_hash_destroy(intern->properties);
+ FREE_HASHTABLE(intern->properties);
+ }
+} /* }}} */
+
+zend_object* php_phongo_symbol_create_object(zend_class_entry* class_type) /* {{{ */
+{
+ php_phongo_symbol_t* intern = zend_object_alloc(sizeof(php_phongo_symbol_t), class_type);
+
+ zend_object_std_init(&intern->std, class_type);
+ object_properties_init(&intern->std, class_type);
+
+ intern->std.handlers = &php_phongo_handler_symbol;
+
+ return &intern->std;
+} /* }}} */
+
+static zend_object* php_phongo_symbol_clone_object(phongo_compat_object_handler_type* object) /* {{{ */
+{
+ php_phongo_symbol_t* intern;
+ php_phongo_symbol_t* new_intern;
+ zend_object* new_object;
+
+ intern = Z_OBJ_SYMBOL(PHONGO_COMPAT_GET_OBJ(object));
+ new_object = php_phongo_symbol_create_object(PHONGO_COMPAT_GET_OBJ(object)->ce);
+
+ new_intern = Z_OBJ_SYMBOL(new_object);
+ zend_objects_clone_members(&new_intern->std, &intern->std);
+
+ php_phongo_symbol_init(new_intern, intern->symbol, intern->symbol_len);
+
+ return new_object;
+} /* }}} */
+
+static int php_phongo_symbol_compare_objects(zval* o1, zval* o2) /* {{{ */
+{
+ php_phongo_symbol_t *intern1, *intern2;
+
+ ZEND_COMPARE_OBJECTS_FALLBACK(o1, o2);
+
+ intern1 = Z_SYMBOL_OBJ_P(o1);
+ intern2 = Z_SYMBOL_OBJ_P(o2);
+
+ return strcmp(intern1->symbol, intern2->symbol);
+} /* }}} */
+
+static HashTable* php_phongo_symbol_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
+{
+ *is_temp = 1;
+ return php_phongo_symbol_get_properties_hash(object, true);
+} /* }}} */
+
+static HashTable* php_phongo_symbol_get_properties(phongo_compat_object_handler_type* object) /* {{{ */
+{
+ return php_phongo_symbol_get_properties_hash(object, false);
+} /* }}} */
+/* }}} */
+
+void php_phongo_symbol_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\BSON", "Symbol", php_phongo_symbol_me);
+ php_phongo_symbol_ce = zend_register_internal_class(&ce);
+ php_phongo_symbol_ce->create_object = php_phongo_symbol_create_object;
+ PHONGO_CE_FINAL(php_phongo_symbol_ce);
+
+ zend_class_implements(php_phongo_symbol_ce, 1, php_phongo_json_serializable_ce);
+ zend_class_implements(php_phongo_symbol_ce, 1, php_phongo_type_ce);
+ zend_class_implements(php_phongo_symbol_ce, 1, zend_ce_serializable);
+
+#if PHP_VERSION_ID >= 80000
+ zend_class_implements(php_phongo_symbol_ce, 1, zend_ce_stringable);
+#endif
+
+ memcpy(&php_phongo_handler_symbol, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
+ PHONGO_COMPAT_SET_COMPARE_OBJECTS_HANDLER(symbol);
+ php_phongo_handler_symbol.clone_obj = php_phongo_symbol_clone_object;
+ php_phongo_handler_symbol.get_debug_info = php_phongo_symbol_get_debug_info;
+ php_phongo_handler_symbol.get_properties = php_phongo_symbol_get_properties;
+ php_phongo_handler_symbol.free_obj = php_phongo_symbol_free_object;
+ php_phongo_handler_symbol.offset = XtOffsetOf(php_phongo_symbol_t, std);
+} /* }}} */
diff --git a/mongodb-1.13.0/src/BSON/Timestamp.c b/mongodb-1.13.0/src/BSON/Timestamp.c
new file mode 100644
index 00000000..23d141ce
--- /dev/null
+++ b/mongodb-1.13.0/src/BSON/Timestamp.c
@@ -0,0 +1,522 @@
+/*
+ * Copyright 2014-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <php.h>
+#include <zend_smart_str.h>
+#include <ext/standard/php_var.h>
+#include <Zend/zend_interfaces.h>
+
+#include "php_phongo.h"
+#include "phongo_error.h"
+#include "phongo_util.h"
+
+zend_class_entry* php_phongo_timestamp_ce;
+
+/* Initialize the object and return whether it was successful. An exception will
+ * be thrown on error. */
+static bool php_phongo_timestamp_init(php_phongo_timestamp_t* intern, int64_t increment, int64_t timestamp) /* {{{ */
+{
+ if (increment < 0 || increment > UINT32_MAX) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected increment to be an unsigned 32-bit integer, %" PRId64 " given", increment);
+ return false;
+ }
+
+ if (timestamp < 0 || timestamp > UINT32_MAX) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected timestamp to be an unsigned 32-bit integer, %" PRId64 " given", timestamp);
+ return false;
+ }
+
+ intern->increment = (uint32_t) increment;
+ intern->timestamp = (uint32_t) timestamp;
+ intern->initialized = true;
+
+ return true;
+} /* }}} */
+
+/* Initialize the object from numeric strings and return whether it was
+ * successful. An exception will be thrown on error. */
+static bool php_phongo_timestamp_init_from_string(php_phongo_timestamp_t* intern, const char* s_increment, size_t s_increment_len, const char* s_timestamp, size_t s_timestamp_len) /* {{{ */
+{
+ int64_t increment, timestamp;
+
+ if (!php_phongo_parse_int64(&increment, s_increment, s_increment_len)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Error parsing \"%s\" as 64-bit integer increment for %s initialization", s_increment, ZSTR_VAL(php_phongo_timestamp_ce->name));
+ return false;
+ }
+
+ if (!php_phongo_parse_int64(&timestamp, s_timestamp, s_timestamp_len)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Error parsing \"%s\" as 64-bit integer timestamp for %s initialization", s_timestamp, ZSTR_VAL(php_phongo_timestamp_ce->name));
+ return false;
+ }
+
+ return php_phongo_timestamp_init(intern, increment, timestamp);
+} /* }}} */
+
+/* Initialize the object from a HashTable and return whether it was successful.
+ * An exception will be thrown on error. */
+static bool php_phongo_timestamp_init_from_hash(php_phongo_timestamp_t* intern, HashTable* props) /* {{{ */
+{
+ zval *increment, *timestamp;
+
+ if ((increment = zend_hash_str_find(props, "increment", sizeof("increment") - 1)) && Z_TYPE_P(increment) == IS_LONG &&
+ (timestamp = zend_hash_str_find(props, "timestamp", sizeof("timestamp") - 1)) && Z_TYPE_P(timestamp) == IS_LONG) {
+
+ return php_phongo_timestamp_init(intern, Z_LVAL_P(increment), Z_LVAL_P(timestamp));
+ }
+ if ((increment = zend_hash_str_find(props, "increment", sizeof("increment") - 1)) && Z_TYPE_P(increment) == IS_STRING &&
+ (timestamp = zend_hash_str_find(props, "timestamp", sizeof("timestamp") - 1)) && Z_TYPE_P(timestamp) == IS_STRING) {
+
+ return php_phongo_timestamp_init_from_string(intern, Z_STRVAL_P(increment), Z_STRLEN_P(increment), Z_STRVAL_P(timestamp), Z_STRLEN_P(timestamp));
+ }
+
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"increment\" and \"timestamp\" integer or numeric string fields", ZSTR_VAL(php_phongo_timestamp_ce->name));
+ return false;
+} /* }}} */
+
+static HashTable* php_phongo_timestamp_get_properties_hash(phongo_compat_object_handler_type* object, bool is_temp) /* {{{ */
+{
+ php_phongo_timestamp_t* intern;
+ HashTable* props;
+ char s_increment[24];
+ char s_timestamp[24];
+ int s_increment_len;
+ int s_timestamp_len;
+
+ intern = Z_OBJ_TIMESTAMP(PHONGO_COMPAT_GET_OBJ(object));
+
+ PHONGO_GET_PROPERTY_HASH_INIT_PROPS(is_temp, intern, props, 2);
+
+ if (!intern->initialized) {
+ return props;
+ }
+
+ s_increment_len = snprintf(s_increment, sizeof(s_increment), "%" PRIu32, intern->increment);
+ s_timestamp_len = snprintf(s_timestamp, sizeof(s_timestamp), "%" PRIu32, intern->timestamp);
+
+ {
+ zval increment, timestamp;
+
+ ZVAL_STRINGL(&increment, s_increment, s_increment_len);
+ zend_hash_str_update(props, "increment", sizeof("increment") - 1, &increment);
+
+ ZVAL_STRINGL(&timestamp, s_timestamp, s_timestamp_len);
+ zend_hash_str_update(props, "timestamp", sizeof("timestamp") - 1, &timestamp);
+ }
+
+ return props;
+} /* }}} */
+
+/* {{{ proto void MongoDB\BSON\Timestamp::__construct(int|string $increment, int|string $timestamp)
+ Construct a new BSON timestamp type, which consists of a 4-byte increment and
+ 4-byte timestamp. */
+static PHP_METHOD(Timestamp, __construct)
+{
+ zend_error_handling error_handling;
+ php_phongo_timestamp_t* intern;
+ zval * increment = NULL, *timestamp = NULL;
+
+ intern = Z_TIMESTAMP_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &increment, &timestamp) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ if (Z_TYPE_P(increment) == IS_LONG && Z_TYPE_P(timestamp) == IS_LONG) {
+ php_phongo_timestamp_init(intern, Z_LVAL_P(increment), Z_LVAL_P(timestamp));
+ return;
+ }
+
+ if (Z_TYPE_P(increment) == IS_LONG) {
+ convert_to_string(increment);
+ }
+
+ if (Z_TYPE_P(increment) != IS_STRING) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected increment to be an unsigned 32-bit integer or string, %s given", PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(increment));
+ return;
+ }
+
+ if (Z_TYPE_P(timestamp) == IS_LONG) {
+ convert_to_string(timestamp);
+ }
+
+ if (Z_TYPE_P(timestamp) != IS_STRING) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected timestamp to be an unsigned 32-bit integer or string, %s given", PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(timestamp));
+ return;
+ }
+
+ php_phongo_timestamp_init_from_string(intern, Z_STRVAL_P(increment), Z_STRLEN_P(increment), Z_STRVAL_P(timestamp), Z_STRLEN_P(timestamp));
+} /* }}} */
+
+/* {{{ proto integer MongoDB\BSON\Timestamp::getIncrement()
+*/
+static PHP_METHOD(Timestamp, getIncrement)
+{
+ zend_error_handling error_handling;
+ php_phongo_timestamp_t* intern;
+
+ intern = Z_TIMESTAMP_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ RETVAL_LONG(intern->increment);
+} /* }}} */
+
+/* {{{ proto integer MongoDB\BSON\Timestamp::getTimestamp()
+*/
+static PHP_METHOD(Timestamp, getTimestamp)
+{
+ zend_error_handling error_handling;
+ php_phongo_timestamp_t* intern;
+
+ intern = Z_TIMESTAMP_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ RETVAL_LONG(intern->timestamp);
+} /* }}} */
+
+/* {{{ proto MongoDB\BSON\Timestamp MongoDB\BSON\Timestamp::__set_state(array $properties)
+*/
+static PHP_METHOD(Timestamp, __set_state)
+{
+ zend_error_handling error_handling;
+ php_phongo_timestamp_t* intern;
+ HashTable* props;
+ zval* array;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &array) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ object_init_ex(return_value, php_phongo_timestamp_ce);
+
+ intern = Z_TIMESTAMP_OBJ_P(return_value);
+ props = Z_ARRVAL_P(array);
+
+ php_phongo_timestamp_init_from_hash(intern, props);
+} /* }}} */
+
+/* {{{ proto string MongoDB\BSON\Timestamp::__toString()
+ Returns a string in the form: [increment:timestamp] */
+static PHP_METHOD(Timestamp, __toString)
+{
+ zend_error_handling error_handling;
+ php_phongo_timestamp_t* intern;
+ char* retval;
+ int retval_len;
+
+ intern = Z_TIMESTAMP_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ retval_len = spprintf(&retval, 0, "[%" PRIu32 ":%" PRIu32 "]", intern->increment, intern->timestamp);
+ RETVAL_STRINGL(retval, retval_len);
+ efree(retval);
+} /* }}} */
+
+/* {{{ proto array MongoDB\BSON\Timestamp::jsonSerialize()
+*/
+static PHP_METHOD(Timestamp, jsonSerialize)
+{
+ zend_error_handling error_handling;
+ php_phongo_timestamp_t* intern;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ intern = Z_TIMESTAMP_OBJ_P(getThis());
+
+ array_init_size(return_value, 1);
+
+ {
+ zval ts;
+
+ array_init_size(&ts, 2);
+ ADD_ASSOC_LONG_EX(&ts, "t", intern->timestamp);
+ ADD_ASSOC_LONG_EX(&ts, "i", intern->increment);
+ ADD_ASSOC_ZVAL_EX(return_value, "$timestamp", &ts);
+ }
+} /* }}} */
+
+/* {{{ proto string MongoDB\BSON\Timestamp::serialize()
+*/
+static PHP_METHOD(Timestamp, serialize)
+{
+ zend_error_handling error_handling;
+ php_phongo_timestamp_t* intern;
+ zval retval;
+ php_serialize_data_t var_hash;
+ smart_str buf = { 0 };
+ char s_increment[12];
+ char s_timestamp[12];
+ int s_increment_len;
+ int s_timestamp_len;
+
+ intern = Z_TIMESTAMP_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ s_increment_len = snprintf(s_increment, sizeof(s_increment), "%" PRIu32, intern->increment);
+ s_timestamp_len = snprintf(s_timestamp, sizeof(s_timestamp), "%" PRIu32, intern->timestamp);
+
+ array_init_size(&retval, 2);
+ ADD_ASSOC_STRINGL(&retval, "increment", s_increment, s_increment_len);
+ ADD_ASSOC_STRINGL(&retval, "timestamp", s_timestamp, s_timestamp_len);
+
+ PHP_VAR_SERIALIZE_INIT(var_hash);
+ php_var_serialize(&buf, &retval, &var_hash);
+ smart_str_0(&buf);
+ PHP_VAR_SERIALIZE_DESTROY(var_hash);
+
+ PHONGO_RETVAL_SMART_STR(buf);
+
+ smart_str_free(&buf);
+ zval_ptr_dtor(&retval);
+} /* }}} */
+
+/* {{{ proto void MongoDB\BSON\Timestamp::unserialize(string $serialized)
+*/
+static PHP_METHOD(Timestamp, unserialize)
+{
+ zend_error_handling error_handling;
+ php_phongo_timestamp_t* intern;
+ char* serialized;
+ size_t serialized_len;
+ zval props;
+ php_unserialize_data_t var_hash;
+
+ intern = Z_TIMESTAMP_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &serialized, &serialized_len) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ PHP_VAR_UNSERIALIZE_INIT(var_hash);
+ if (!php_var_unserialize(&props, (const unsigned char**) &serialized, (unsigned char*) serialized + serialized_len, &var_hash)) {
+ zval_ptr_dtor(&props);
+ phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "%s unserialization failed", ZSTR_VAL(php_phongo_timestamp_ce->name));
+
+ PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+ return;
+ }
+ PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+
+ php_phongo_timestamp_init_from_hash(intern, HASH_OF(&props));
+ zval_ptr_dtor(&props);
+} /* }}} */
+
+/* {{{ proto array MongoDB\Driver\Timestamp::__serialize()
+*/
+static PHP_METHOD(Timestamp, __serialize)
+{
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ RETURN_ARR(php_phongo_timestamp_get_properties_hash(PHONGO_COMPAT_OBJ_P(getThis()), true));
+} /* }}} */
+
+/* {{{ proto void MongoDB\Driver\Timestamp::__unserialize(array $data)
+*/
+static PHP_METHOD(Timestamp, __unserialize)
+{
+ zval* data;
+
+ PHONGO_PARSE_PARAMETERS_START(1, 1)
+ Z_PARAM_ARRAY(data)
+ PHONGO_PARSE_PARAMETERS_END();
+
+ php_phongo_timestamp_init_from_hash(Z_TIMESTAMP_OBJ_P(getThis()), Z_ARRVAL_P(data));
+} /* }}} */
+
+/* {{{ MongoDB\BSON\Timestamp function entries */
+/* clang-format off */
+ZEND_BEGIN_ARG_INFO_EX(ai_Timestamp___construct, 0, 0, 2)
+ ZEND_ARG_INFO(0, increment)
+ ZEND_ARG_INFO(0, timestamp)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_Timestamp___set_state, 0, 0, 1)
+ ZEND_ARG_ARRAY_INFO(0, properties, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(ai_Timestamp___toString, 0, 0, IS_STRING, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_Timestamp___unserialize, 0, 0, 1)
+ ZEND_ARG_ARRAY_INFO(0, data, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(ai_Timestamp_jsonSerialize, 0, 0, IS_ARRAY, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_Timestamp_unserialize, 0, 0, 1)
+ ZEND_ARG_INFO(0, serialized)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_Timestamp_void, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry php_phongo_timestamp_me[] = {
+ PHP_ME(Timestamp, __construct, ai_Timestamp___construct, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Timestamp, __serialize, ai_Timestamp_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Timestamp, __set_state, ai_Timestamp___set_state, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+ PHP_ME(Timestamp, __toString, ai_Timestamp___toString, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Timestamp, __unserialize, ai_Timestamp___unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Timestamp, jsonSerialize, ai_Timestamp_jsonSerialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Timestamp, serialize, ai_Timestamp_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Timestamp, unserialize, ai_Timestamp_unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Timestamp, getIncrement, ai_Timestamp_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Timestamp, getTimestamp, ai_Timestamp_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_FE_END
+};
+/* clang-format on */
+/* }}} */
+
+/* {{{ MongoDB\BSON\Timestamp object handlers */
+static zend_object_handlers php_phongo_handler_timestamp;
+
+static void php_phongo_timestamp_free_object(zend_object* object) /* {{{ */
+{
+ php_phongo_timestamp_t* intern = Z_OBJ_TIMESTAMP(object);
+
+ zend_object_std_dtor(&intern->std);
+
+ if (intern->properties) {
+ zend_hash_destroy(intern->properties);
+ FREE_HASHTABLE(intern->properties);
+ }
+} /* }}} */
+
+static zend_object* php_phongo_timestamp_create_object(zend_class_entry* class_type) /* {{{ */
+{
+ php_phongo_timestamp_t* intern = zend_object_alloc(sizeof(php_phongo_timestamp_t), class_type);
+
+ zend_object_std_init(&intern->std, class_type);
+ object_properties_init(&intern->std, class_type);
+
+ intern->std.handlers = &php_phongo_handler_timestamp;
+
+ return &intern->std;
+} /* }}} */
+
+static zend_object* php_phongo_timestamp_clone_object(phongo_compat_object_handler_type* object) /* {{{ */
+{
+ php_phongo_timestamp_t* intern;
+ php_phongo_timestamp_t* new_intern;
+ zend_object* new_object;
+
+ intern = Z_OBJ_TIMESTAMP(PHONGO_COMPAT_GET_OBJ(object));
+ new_object = php_phongo_timestamp_create_object(PHONGO_COMPAT_GET_OBJ(object)->ce);
+
+ new_intern = Z_OBJ_TIMESTAMP(new_object);
+ zend_objects_clone_members(&new_intern->std, &intern->std);
+
+ php_phongo_timestamp_init(new_intern, intern->increment, intern->timestamp);
+
+ return new_object;
+} /* }}} */
+
+static int php_phongo_timestamp_compare_objects(zval* o1, zval* o2) /* {{{ */
+{
+ php_phongo_timestamp_t *intern1, *intern2;
+
+ ZEND_COMPARE_OBJECTS_FALLBACK(o1, o2);
+
+ intern1 = Z_TIMESTAMP_OBJ_P(o1);
+ intern2 = Z_TIMESTAMP_OBJ_P(o2);
+
+ /* MongoDB compares the timestamp before the increment. */
+ if (intern1->timestamp != intern2->timestamp) {
+ return intern1->timestamp < intern2->timestamp ? -1 : 1;
+ }
+
+ if (intern1->increment != intern2->increment) {
+ return intern1->increment < intern2->increment ? -1 : 1;
+ }
+
+ return 0;
+} /* }}} */
+
+static HashTable* php_phongo_timestamp_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
+{
+ *is_temp = 1;
+ return php_phongo_timestamp_get_properties_hash(object, true);
+} /* }}} */
+
+static HashTable* php_phongo_timestamp_get_properties(phongo_compat_object_handler_type* object) /* {{{ */
+{
+ return php_phongo_timestamp_get_properties_hash(object, false);
+} /* }}} */
+/* }}} */
+
+void php_phongo_timestamp_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\BSON", "Timestamp", php_phongo_timestamp_me);
+ php_phongo_timestamp_ce = zend_register_internal_class(&ce);
+ php_phongo_timestamp_ce->create_object = php_phongo_timestamp_create_object;
+ PHONGO_CE_FINAL(php_phongo_timestamp_ce);
+
+ zend_class_implements(php_phongo_timestamp_ce, 1, php_phongo_timestamp_interface_ce);
+ zend_class_implements(php_phongo_timestamp_ce, 1, php_phongo_json_serializable_ce);
+ zend_class_implements(php_phongo_timestamp_ce, 1, php_phongo_type_ce);
+ zend_class_implements(php_phongo_timestamp_ce, 1, zend_ce_serializable);
+
+#if PHP_VERSION_ID >= 80000
+ zend_class_implements(php_phongo_timestamp_ce, 1, zend_ce_stringable);
+#endif
+
+ memcpy(&php_phongo_handler_timestamp, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
+ PHONGO_COMPAT_SET_COMPARE_OBJECTS_HANDLER(timestamp);
+ php_phongo_handler_timestamp.clone_obj = php_phongo_timestamp_clone_object;
+ php_phongo_handler_timestamp.get_debug_info = php_phongo_timestamp_get_debug_info;
+ php_phongo_handler_timestamp.get_properties = php_phongo_timestamp_get_properties;
+ php_phongo_handler_timestamp.free_obj = php_phongo_timestamp_free_object;
+ php_phongo_handler_timestamp.offset = XtOffsetOf(php_phongo_timestamp_t, std);
+} /* }}} */
diff --git a/mongodb-1.13.0/src/BSON/TimestampInterface.c b/mongodb-1.13.0/src/BSON/TimestampInterface.c
new file mode 100644
index 00000000..4963eae0
--- /dev/null
+++ b/mongodb-1.13.0/src/BSON/TimestampInterface.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2017-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <php.h>
+
+#include "php_phongo.h"
+
+zend_class_entry* php_phongo_timestamp_interface_ce;
+
+/* {{{ MongoDB\BSON\TimestampInterface function entries */
+/* clang-format off */
+ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(ai_TimestampInterface___toString, 0, 0, IS_STRING, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_TimestampInterface_void, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry php_phongo_timestamp_interface_me[] = {
+ ZEND_ABSTRACT_ME(TimestampInterface, getIncrement, ai_TimestampInterface_void)
+ ZEND_ABSTRACT_ME(TimestampInterface, getTimestamp, ai_TimestampInterface_void)
+ ZEND_ABSTRACT_ME(TimestampInterface, __toString, ai_TimestampInterface___toString)
+ PHP_FE_END
+};
+/* clang-format on */
+/* }}} */
+
+void php_phongo_timestamp_interface_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\BSON", "TimestampInterface", php_phongo_timestamp_interface_me);
+ php_phongo_timestamp_interface_ce = zend_register_internal_interface(&ce);
+} /* }}} */
diff --git a/mongodb-1.13.0/src/BSON/Type.c b/mongodb-1.13.0/src/BSON/Type.c
new file mode 100644
index 00000000..34ff9e52
--- /dev/null
+++ b/mongodb-1.13.0/src/BSON/Type.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2014-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <php.h>
+
+#include "php_phongo.h"
+
+zend_class_entry* php_phongo_type_ce;
+
+/* {{{ MongoDB\BSON\Type function entries */
+static zend_function_entry php_phongo_type_me[] = {
+ PHP_FE_END
+};
+/* }}} */
+
+void php_phongo_type_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\BSON", "Type", php_phongo_type_me);
+ php_phongo_type_ce = zend_register_internal_interface(&ce);
+} /* }}} */
diff --git a/mongodb-1.13.0/src/BSON/UTCDateTime.c b/mongodb-1.13.0/src/BSON/UTCDateTime.c
new file mode 100644
index 00000000..3c467153
--- /dev/null
+++ b/mongodb-1.13.0/src/BSON/UTCDateTime.c
@@ -0,0 +1,514 @@
+/*
+ * Copyright 2014-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <math.h>
+
+#include <php.h>
+#include <zend_smart_str.h>
+#include <ext/date/php_date.h>
+#include <ext/standard/php_var.h>
+#include <Zend/zend_interfaces.h>
+
+#include "php_phongo.h"
+#include "phongo_error.h"
+#include "phongo_util.h"
+
+zend_class_entry* php_phongo_utcdatetime_ce;
+
+/* Initialize the object and return whether it was successful. */
+static bool php_phongo_utcdatetime_init(php_phongo_utcdatetime_t* intern, int64_t milliseconds) /* {{{ */
+{
+ intern->milliseconds = milliseconds;
+ intern->initialized = true;
+
+ return true;
+} /* }}} */
+
+/* Initialize the object from a numeric string and return whether it was
+ * successful. An exception will be thrown on error. */
+static bool php_phongo_utcdatetime_init_from_string(php_phongo_utcdatetime_t* intern, const char* s_milliseconds, size_t s_milliseconds_len) /* {{{ */
+{
+ int64_t milliseconds;
+
+ if (!php_phongo_parse_int64(&milliseconds, s_milliseconds, s_milliseconds_len)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Error parsing \"%s\" as 64-bit integer for %s initialization", s_milliseconds, ZSTR_VAL(php_phongo_utcdatetime_ce->name));
+ return false;
+ }
+
+ return php_phongo_utcdatetime_init(intern, milliseconds);
+} /* }}} */
+
+/* Initialize the object from a HashTable and return whether it was successful.
+ * An exception will be thrown on error. */
+static bool php_phongo_utcdatetime_init_from_hash(php_phongo_utcdatetime_t* intern, HashTable* props) /* {{{ */
+{
+ zval* milliseconds;
+
+ if ((milliseconds = zend_hash_str_find(props, "milliseconds", sizeof("milliseconds") - 1)) && Z_TYPE_P(milliseconds) == IS_LONG) {
+ return php_phongo_utcdatetime_init(intern, Z_LVAL_P(milliseconds));
+ }
+
+ if ((milliseconds = zend_hash_str_find(props, "milliseconds", sizeof("milliseconds") - 1)) && Z_TYPE_P(milliseconds) == IS_STRING) {
+ return php_phongo_utcdatetime_init_from_string(intern, Z_STRVAL_P(milliseconds), Z_STRLEN_P(milliseconds));
+ }
+
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"milliseconds\" integer or numeric string field", ZSTR_VAL(php_phongo_utcdatetime_ce->name));
+ return false;
+} /* }}} */
+
+/* Initialize the object from the current time and return whether it was
+ * successful. */
+static bool php_phongo_utcdatetime_init_from_current_time(php_phongo_utcdatetime_t* intern) /* {{{ */
+{
+ int64_t sec, usec;
+ struct timeval cur_time;
+
+ bson_gettimeofday(&cur_time);
+ sec = cur_time.tv_sec;
+ usec = cur_time.tv_usec;
+
+ intern->milliseconds = (sec * 1000) + (usec / 1000);
+ intern->initialized = true;
+
+ return true;
+} /* }}} */
+
+/* Initialize the object from a DateTime object and return whether it was
+ * successful. */
+static bool php_phongo_utcdatetime_init_from_date(php_phongo_utcdatetime_t* intern, php_date_obj* datetime_obj) /* {{{ */
+{
+ int64_t sec, usec;
+
+ /* The following assignments use the same logic as date_format() in php_date.c */
+ sec = datetime_obj->time->sse;
+ usec = (int64_t) floor(datetime_obj->time->us);
+
+ intern->milliseconds = (sec * 1000) + (usec / 1000);
+ intern->initialized = true;
+
+ return true;
+} /* }}} */
+
+static HashTable* php_phongo_utcdatetime_get_properties_hash(phongo_compat_object_handler_type* object, bool is_temp) /* {{{ */
+{
+ php_phongo_utcdatetime_t* intern;
+ HashTable* props;
+
+ intern = Z_OBJ_UTCDATETIME(PHONGO_COMPAT_GET_OBJ(object));
+
+ PHONGO_GET_PROPERTY_HASH_INIT_PROPS(is_temp, intern, props, 1);
+
+ if (!intern->initialized) {
+ return props;
+ }
+
+ {
+ zval milliseconds;
+
+ ZVAL_INT64_STRING(&milliseconds, intern->milliseconds);
+ zend_hash_str_update(props, "milliseconds", sizeof("milliseconds") - 1, &milliseconds);
+ }
+
+ return props;
+} /* }}} */
+
+/* {{{ proto void MongoDB\BSON\UTCDateTime::__construct([int|float|string|DateTimeInterface $milliseconds = null])
+ Construct a new BSON UTCDateTime type from either the current time,
+ milliseconds since the epoch, or a DateTimeInterface object. Defaults to the
+ current time. */
+static PHP_METHOD(UTCDateTime, __construct)
+{
+ zend_error_handling error_handling;
+ php_phongo_utcdatetime_t* intern;
+ zval* milliseconds = NULL;
+
+ intern = Z_UTCDATETIME_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "|z!", &milliseconds) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ if (milliseconds == NULL) {
+ php_phongo_utcdatetime_init_from_current_time(intern);
+ return;
+ }
+
+ if (Z_TYPE_P(milliseconds) == IS_OBJECT) {
+ if (instanceof_function(Z_OBJCE_P(milliseconds), php_date_get_date_ce()) ||
+ (php_phongo_date_immutable_ce && instanceof_function(Z_OBJCE_P(milliseconds), php_phongo_date_immutable_ce))) {
+
+ php_phongo_utcdatetime_init_from_date(intern, Z_PHPDATE_P(milliseconds));
+ } else {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected instance of DateTimeInterface, %s given", ZSTR_VAL(Z_OBJCE_P(milliseconds)->name));
+ }
+ return;
+ }
+
+ if (Z_TYPE_P(milliseconds) == IS_LONG) {
+ php_phongo_utcdatetime_init(intern, Z_LVAL_P(milliseconds));
+ return;
+ }
+
+ if (Z_TYPE_P(milliseconds) == IS_DOUBLE) {
+ char tmp[24];
+ int tmp_len;
+
+ tmp_len = snprintf(tmp, sizeof(tmp), "%.0f", Z_DVAL_P(milliseconds) > 0 ? floor(Z_DVAL_P(milliseconds)) : ceil(Z_DVAL_P(milliseconds)));
+
+ php_phongo_utcdatetime_init_from_string(intern, tmp, tmp_len);
+ return;
+ }
+
+ if (Z_TYPE_P(milliseconds) != IS_STRING) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected integer or string, %s given", PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(milliseconds));
+ return;
+ }
+
+ php_phongo_utcdatetime_init_from_string(intern, Z_STRVAL_P(milliseconds), Z_STRLEN_P(milliseconds));
+} /* }}} */
+
+/* {{{ proto MongoDB\BSON\UTCDateTime MongoDB\BSON\UTCDateTime::__set_state(array $properties)
+*/
+static PHP_METHOD(UTCDateTime, __set_state)
+{
+ zend_error_handling error_handling;
+ php_phongo_utcdatetime_t* intern;
+ HashTable* props;
+ zval* array;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &array) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ object_init_ex(return_value, php_phongo_utcdatetime_ce);
+
+ intern = Z_UTCDATETIME_OBJ_P(return_value);
+ props = Z_ARRVAL_P(array);
+
+ php_phongo_utcdatetime_init_from_hash(intern, props);
+} /* }}} */
+
+/* {{{ proto string MongoDB\BSON\UTCDateTime::__toString()
+ Returns the UTCDateTime's milliseconds as a string */
+static PHP_METHOD(UTCDateTime, __toString)
+{
+ zend_error_handling error_handling;
+ php_phongo_utcdatetime_t* intern;
+
+ intern = Z_UTCDATETIME_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ ZVAL_INT64_STRING(return_value, intern->milliseconds);
+} /* }}} */
+
+/* {{{ proto DateTime MongoDB\BSON\UTCDateTime::toDateTime()
+ Returns a DateTime object representing this UTCDateTime */
+static PHP_METHOD(UTCDateTime, toDateTime)
+{
+ zend_error_handling error_handling;
+ php_phongo_utcdatetime_t* intern;
+ php_date_obj* datetime_obj;
+ char* sec;
+ size_t sec_len;
+
+ intern = Z_UTCDATETIME_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ object_init_ex(return_value, php_date_get_date_ce());
+ datetime_obj = Z_PHPDATE_P(return_value);
+
+ sec_len = spprintf(&sec, 0, "@%" PRId64, intern->milliseconds / 1000);
+ php_date_initialize(datetime_obj, sec, sec_len, NULL, NULL, 0);
+ efree(sec);
+
+ datetime_obj->time->us = (intern->milliseconds % 1000) * 1000;
+}
+/* }}} */
+
+/* {{{ proto array MongoDB\BSON\UTCDateTime::jsonSerialize()
+*/
+static PHP_METHOD(UTCDateTime, jsonSerialize)
+{
+ zend_error_handling error_handling;
+ php_phongo_utcdatetime_t* intern;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ intern = Z_UTCDATETIME_OBJ_P(getThis());
+
+ array_init_size(return_value, 1);
+
+ {
+ zval udt;
+
+ array_init_size(&udt, 1);
+ ADD_ASSOC_INT64_AS_STRING(&udt, "$numberLong", intern->milliseconds);
+ ADD_ASSOC_ZVAL_EX(return_value, "$date", &udt);
+ }
+} /* }}} */
+
+/* {{{ proto string MongoDB\BSON\UTCDateTime::serialize()
+*/
+static PHP_METHOD(UTCDateTime, serialize)
+{
+ zend_error_handling error_handling;
+ php_phongo_utcdatetime_t* intern;
+ zval retval;
+ php_serialize_data_t var_hash;
+ smart_str buf = { 0 };
+
+ intern = Z_UTCDATETIME_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ array_init_size(&retval, 1);
+ ADD_ASSOC_INT64_AS_STRING(&retval, "milliseconds", intern->milliseconds);
+
+ PHP_VAR_SERIALIZE_INIT(var_hash);
+ php_var_serialize(&buf, &retval, &var_hash);
+ smart_str_0(&buf);
+ PHP_VAR_SERIALIZE_DESTROY(var_hash);
+
+ PHONGO_RETVAL_SMART_STR(buf);
+
+ smart_str_free(&buf);
+ zval_ptr_dtor(&retval);
+} /* }}} */
+
+/* {{{ proto void MongoDB\BSON\UTCDateTime::unserialize(string $serialized)
+*/
+static PHP_METHOD(UTCDateTime, unserialize)
+{
+ zend_error_handling error_handling;
+ php_phongo_utcdatetime_t* intern;
+ char* serialized;
+ size_t serialized_len;
+ zval props;
+ php_unserialize_data_t var_hash;
+
+ intern = Z_UTCDATETIME_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &serialized, &serialized_len) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ PHP_VAR_UNSERIALIZE_INIT(var_hash);
+ if (!php_var_unserialize(&props, (const unsigned char**) &serialized, (unsigned char*) serialized + serialized_len, &var_hash)) {
+ zval_ptr_dtor(&props);
+ phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "%s unserialization failed", ZSTR_VAL(php_phongo_utcdatetime_ce->name));
+
+ PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+ return;
+ }
+ PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+
+ php_phongo_utcdatetime_init_from_hash(intern, HASH_OF(&props));
+ zval_ptr_dtor(&props);
+} /* }}} */
+
+/* {{{ proto array MongoDB\Driver\UTCDateTime::__serialize()
+*/
+static PHP_METHOD(UTCDateTime, __serialize)
+{
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ RETURN_ARR(php_phongo_utcdatetime_get_properties_hash(PHONGO_COMPAT_OBJ_P(getThis()), true));
+} /* }}} */
+
+/* {{{ proto void MongoDB\Driver\UTCDateTime::__unserialize(array $data)
+*/
+static PHP_METHOD(UTCDateTime, __unserialize)
+{
+ zval* data;
+
+ PHONGO_PARSE_PARAMETERS_START(1, 1)
+ Z_PARAM_ARRAY(data)
+ PHONGO_PARSE_PARAMETERS_END();
+
+ php_phongo_utcdatetime_init_from_hash(Z_UTCDATETIME_OBJ_P(getThis()), Z_ARRVAL_P(data));
+} /* }}} */
+
+/* {{{ MongoDB\BSON\UTCDateTime function entries */
+/* clang-format off */
+ZEND_BEGIN_ARG_INFO_EX(ai_UTCDateTime___construct, 0, 0, 0)
+ ZEND_ARG_INFO(0, milliseconds)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_UTCDateTime___set_state, 0, 0, 1)
+ ZEND_ARG_ARRAY_INFO(0, properties, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(ai_UTCDateTime___toString, 0, 0, IS_STRING, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_UTCDateTime___unserialize, 0, 0, 1)
+ ZEND_ARG_ARRAY_INFO(0, data, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(ai_UTCDateTime_jsonSerialize, 0, 0, IS_ARRAY, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_UTCDateTime_unserialize, 0, 0, 1)
+ ZEND_ARG_INFO(0, serialized)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_UTCDateTime_void, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry php_phongo_utcdatetime_me[] = {
+ PHP_ME(UTCDateTime, __construct, ai_UTCDateTime___construct, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(UTCDateTime, __serialize, ai_UTCDateTime_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(UTCDateTime, __set_state, ai_UTCDateTime___set_state, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+ PHP_ME(UTCDateTime, __toString, ai_UTCDateTime___toString, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(UTCDateTime, __unserialize, ai_UTCDateTime___unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(UTCDateTime, jsonSerialize, ai_UTCDateTime_jsonSerialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(UTCDateTime, serialize, ai_UTCDateTime_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(UTCDateTime, unserialize, ai_UTCDateTime_unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(UTCDateTime, toDateTime, ai_UTCDateTime_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_FE_END
+};
+/* clang-format on */
+/* }}} */
+
+/* {{{ MongoDB\BSON\UTCDateTime object handlers */
+static zend_object_handlers php_phongo_handler_utcdatetime;
+
+static void php_phongo_utcdatetime_free_object(zend_object* object) /* {{{ */
+{
+ php_phongo_utcdatetime_t* intern = Z_OBJ_UTCDATETIME(object);
+
+ zend_object_std_dtor(&intern->std);
+
+ if (intern->properties) {
+ zend_hash_destroy(intern->properties);
+ FREE_HASHTABLE(intern->properties);
+ }
+} /* }}} */
+
+static zend_object* php_phongo_utcdatetime_create_object(zend_class_entry* class_type) /* {{{ */
+{
+ php_phongo_utcdatetime_t* intern = zend_object_alloc(sizeof(php_phongo_utcdatetime_t), class_type);
+
+ zend_object_std_init(&intern->std, class_type);
+ object_properties_init(&intern->std, class_type);
+
+ intern->std.handlers = &php_phongo_handler_utcdatetime;
+
+ return &intern->std;
+} /* }}} */
+
+static zend_object* php_phongo_utcdatetime_clone_object(phongo_compat_object_handler_type* object) /* {{{ */
+{
+ php_phongo_utcdatetime_t* intern;
+ php_phongo_utcdatetime_t* new_intern;
+ zend_object* new_object;
+
+ intern = Z_OBJ_UTCDATETIME(PHONGO_COMPAT_GET_OBJ(object));
+ new_object = php_phongo_utcdatetime_create_object(PHONGO_COMPAT_GET_OBJ(object)->ce);
+
+ new_intern = Z_OBJ_UTCDATETIME(new_object);
+ zend_objects_clone_members(&new_intern->std, &intern->std);
+
+ php_phongo_utcdatetime_init(new_intern, intern->milliseconds);
+
+ return new_object;
+} /* }}} */
+
+static int php_phongo_utcdatetime_compare_objects(zval* o1, zval* o2) /* {{{ */
+{
+ php_phongo_utcdatetime_t *intern1, *intern2;
+
+ ZEND_COMPARE_OBJECTS_FALLBACK(o1, o2);
+
+ intern1 = Z_UTCDATETIME_OBJ_P(o1);
+ intern2 = Z_UTCDATETIME_OBJ_P(o2);
+
+ if (intern1->milliseconds != intern2->milliseconds) {
+ return intern1->milliseconds < intern2->milliseconds ? -1 : 1;
+ }
+
+ return 0;
+} /* }}} */
+
+static HashTable* php_phongo_utcdatetime_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
+{
+ *is_temp = 1;
+ return php_phongo_utcdatetime_get_properties_hash(object, true);
+} /* }}} */
+
+static HashTable* php_phongo_utcdatetime_get_properties(phongo_compat_object_handler_type* object) /* {{{ */
+{
+ return php_phongo_utcdatetime_get_properties_hash(object, false);
+} /* }}} */
+/* }}} */
+
+void php_phongo_utcdatetime_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\BSON", "UTCDateTime", php_phongo_utcdatetime_me);
+ php_phongo_utcdatetime_ce = zend_register_internal_class(&ce);
+ php_phongo_utcdatetime_ce->create_object = php_phongo_utcdatetime_create_object;
+ PHONGO_CE_FINAL(php_phongo_utcdatetime_ce);
+
+ zend_class_implements(php_phongo_utcdatetime_ce, 1, php_phongo_utcdatetime_interface_ce);
+ zend_class_implements(php_phongo_utcdatetime_ce, 1, php_phongo_json_serializable_ce);
+ zend_class_implements(php_phongo_utcdatetime_ce, 1, php_phongo_type_ce);
+ zend_class_implements(php_phongo_utcdatetime_ce, 1, zend_ce_serializable);
+
+#if PHP_VERSION_ID >= 80000
+ zend_class_implements(php_phongo_utcdatetime_ce, 1, zend_ce_stringable);
+#endif
+
+ memcpy(&php_phongo_handler_utcdatetime, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
+ PHONGO_COMPAT_SET_COMPARE_OBJECTS_HANDLER(utcdatetime);
+ php_phongo_handler_utcdatetime.clone_obj = php_phongo_utcdatetime_clone_object;
+ php_phongo_handler_utcdatetime.get_debug_info = php_phongo_utcdatetime_get_debug_info;
+ php_phongo_handler_utcdatetime.get_properties = php_phongo_utcdatetime_get_properties;
+ php_phongo_handler_utcdatetime.free_obj = php_phongo_utcdatetime_free_object;
+ php_phongo_handler_utcdatetime.offset = XtOffsetOf(php_phongo_utcdatetime_t, std);
+} /* }}} */
diff --git a/mongodb-1.13.0/src/BSON/UTCDateTimeInterface.c b/mongodb-1.13.0/src/BSON/UTCDateTimeInterface.c
new file mode 100644
index 00000000..7c5e8947
--- /dev/null
+++ b/mongodb-1.13.0/src/BSON/UTCDateTimeInterface.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2017-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <php.h>
+
+#include "php_phongo.h"
+
+zend_class_entry* php_phongo_utcdatetime_interface_ce;
+
+/* {{{ MongoDB\BSON\UTCDateTimeInterface function entries */
+/* clang-format off */
+ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(ai_UTCDateTimeInterface___toString, 0, 0, IS_STRING, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_UTCDateTimeInterface_void, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry php_phongo_utcdatetime_interface_me[] = {
+ ZEND_ABSTRACT_ME(UTCDateTimeInterface, toDateTime, ai_UTCDateTimeInterface_void)
+ ZEND_ABSTRACT_ME(UTCDateTimeInterface, __toString, ai_UTCDateTimeInterface___toString)
+ PHP_FE_END
+};
+/* clang-format on */
+/* }}} */
+
+void php_phongo_utcdatetime_interface_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\BSON", "UTCDateTimeInterface", php_phongo_utcdatetime_interface_me);
+ php_phongo_utcdatetime_interface_ce = zend_register_internal_interface(&ce);
+} /* }}} */
diff --git a/mongodb-1.13.0/src/BSON/Undefined.c b/mongodb-1.13.0/src/BSON/Undefined.c
new file mode 100644
index 00000000..5244e500
--- /dev/null
+++ b/mongodb-1.13.0/src/BSON/Undefined.c
@@ -0,0 +1,190 @@
+/*
+ * Copyright 2014-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <php.h>
+#include <zend_smart_str.h>
+#include <ext/standard/php_var.h>
+#include <Zend/zend_interfaces.h>
+
+#include "php_phongo.h"
+#include "phongo_error.h"
+
+zend_class_entry* php_phongo_undefined_ce;
+
+/* {{{ proto string MongoDB\BSON\Undefined::__toString()
+ Return the empty string. */
+static PHP_METHOD(Undefined, __toString)
+{
+ zend_error_handling error_handling;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ RETURN_STRINGL("", 0);
+} /* }}} */
+
+/* {{{ proto array MongoDB\BSON\Undefined::jsonSerialize()
+*/
+static PHP_METHOD(Undefined, jsonSerialize)
+{
+ zend_error_handling error_handling;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ array_init_size(return_value, 1);
+ ADD_ASSOC_BOOL_EX(return_value, "$undefined", 1);
+} /* }}} */
+
+/* {{{ proto string MongoDB\BSON\Undefined::serialize()
+*/
+static PHP_METHOD(Undefined, serialize)
+{
+ zend_error_handling error_handling;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ RETURN_STRING("");
+} /* }}} */
+
+/* {{{ proto void MongoDB\BSON\Undefined::unserialize(string $serialized)
+*/
+static PHP_METHOD(Undefined, unserialize)
+{
+ zend_error_handling error_handling;
+ char* serialized;
+ size_t serialized_len;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &serialized, &serialized_len) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+} /* }}} */
+
+/* {{{ proto array MongoDB\Driver\Undefined::__serialize()
+*/
+static PHP_METHOD(Undefined, __serialize)
+{
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ array_init_size(return_value, 0);
+} /* }}} */
+
+/* {{{ proto void MongoDB\Driver\Undefined::__unserialize(array $data)
+*/
+static PHP_METHOD(Undefined, __unserialize)
+{
+ zval* data;
+
+ PHONGO_PARSE_PARAMETERS_START(1, 1)
+ Z_PARAM_ARRAY(data)
+ PHONGO_PARSE_PARAMETERS_END();
+} /* }}} */
+
+/* {{{ MongoDB\BSON\Undefined function entries */
+/* clang-format off */
+ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(ai_Undefined___toString, 0, 0, IS_STRING, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_Undefined___unserialize, 0, 0, 1)
+ ZEND_ARG_ARRAY_INFO(0, data, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(ai_Undefined_jsonSerialize, 0, 0, IS_ARRAY, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_Undefined_unserialize, 0, 0, 1)
+ ZEND_ARG_INFO(0, serialized)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_Undefined_void, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry php_phongo_undefined_me[] = {
+ /* __set_state intentionally missing */
+ PHP_ME(Undefined, __serialize, ai_Undefined_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Undefined, __toString, ai_Undefined___toString, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Undefined, __unserialize, ai_Undefined___unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Undefined, jsonSerialize, ai_Undefined_jsonSerialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Undefined, serialize, ai_Undefined_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Undefined, unserialize, ai_Undefined_unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ ZEND_NAMED_ME(__construct, PHP_FN(MongoDB_disabled___construct), ai_Undefined_void, ZEND_ACC_PRIVATE | ZEND_ACC_FINAL)
+ PHP_FE_END
+};
+/* clang-format on */
+/* }}} */
+
+/* {{{ MongoDB\BSON\Undefined object handlers */
+static zend_object_handlers php_phongo_handler_undefined;
+
+static void php_phongo_undefined_free_object(zend_object* object) /* {{{ */
+{
+ php_phongo_undefined_t* intern = Z_OBJ_UNDEFINED(object);
+
+ zend_object_std_dtor(&intern->std);
+} /* }}} */
+
+static zend_object* php_phongo_undefined_create_object(zend_class_entry* class_type) /* {{{ */
+{
+ php_phongo_undefined_t* intern = zend_object_alloc(sizeof(php_phongo_undefined_t), class_type);
+
+ zend_object_std_init(&intern->std, class_type);
+ object_properties_init(&intern->std, class_type);
+
+ intern->std.handlers = &php_phongo_handler_undefined;
+
+ return &intern->std;
+} /* }}} */
+/* }}} */
+
+void php_phongo_undefined_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\BSON", "Undefined", php_phongo_undefined_me);
+ php_phongo_undefined_ce = zend_register_internal_class(&ce);
+ php_phongo_undefined_ce->create_object = php_phongo_undefined_create_object;
+ PHONGO_CE_FINAL(php_phongo_undefined_ce);
+
+ zend_class_implements(php_phongo_undefined_ce, 1, php_phongo_json_serializable_ce);
+ zend_class_implements(php_phongo_undefined_ce, 1, php_phongo_type_ce);
+ zend_class_implements(php_phongo_undefined_ce, 1, zend_ce_serializable);
+
+#if PHP_VERSION_ID >= 80000
+ zend_class_implements(php_phongo_undefined_ce, 1, zend_ce_stringable);
+#endif
+
+ memcpy(&php_phongo_handler_undefined, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
+ /* Re-assign default handler previously removed in php_phongo.c */
+ php_phongo_handler_undefined.clone_obj = zend_objects_clone_obj;
+ php_phongo_handler_undefined.free_obj = php_phongo_undefined_free_object;
+ php_phongo_handler_undefined.offset = XtOffsetOf(php_phongo_undefined_t, std);
+} /* }}} */
diff --git a/mongodb-1.13.0/src/BSON/Unserializable.c b/mongodb-1.13.0/src/BSON/Unserializable.c
new file mode 100644
index 00000000..62eb49c2
--- /dev/null
+++ b/mongodb-1.13.0/src/BSON/Unserializable.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2014-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <php.h>
+
+#include "php_phongo.h"
+
+zend_class_entry* php_phongo_unserializable_ce;
+
+/* {{{ MongoDB\BSON\Unserializable function entries */
+ZEND_BEGIN_ARG_INFO_EX(ai_Unserializable_bsonUnserialize, 0, 0, 1)
+ ZEND_ARG_ARRAY_INFO(0, data, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry php_phongo_unserializable_me[] = {
+ /* clang-format off */
+ ZEND_ABSTRACT_ME(Unserializable, bsonUnserialize, ai_Unserializable_bsonUnserialize)
+ PHP_FE_END
+ /* clang-format on */
+};
+/* }}} */
+
+void php_phongo_unserializable_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\BSON", "Unserializable", php_phongo_unserializable_me);
+ php_phongo_unserializable_ce = zend_register_internal_interface(&ce);
+} /* }}} */
diff --git a/mongodb-1.13.0/src/BSON/functions.c b/mongodb-1.13.0/src/BSON/functions.c
new file mode 100644
index 00000000..0f8a50a8
--- /dev/null
+++ b/mongodb-1.13.0/src/BSON/functions.c
@@ -0,0 +1,182 @@
+/*
+ * Copyright 2014-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bson/bson.h"
+
+#include <php.h>
+
+#include "php_phongo.h"
+#include "phongo_bson_encode.h"
+#include "phongo_error.h"
+
+typedef enum {
+ PHONGO_JSON_MODE_LEGACY,
+ PHONGO_JSON_MODE_CANONICAL,
+ PHONGO_JSON_MODE_RELAXED,
+} php_phongo_json_mode_t;
+
+/* {{{ proto string MongoDB\BSON\fromPHP(array|object $value)
+ Returns the BSON representation of a PHP value */
+PHP_FUNCTION(MongoDB_BSON_fromPHP)
+{
+ zend_error_handling error_handling;
+ zval* data;
+ bson_t* bson;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "A", &data) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ bson = bson_new();
+ php_phongo_zval_to_bson(data, PHONGO_BSON_NONE, bson, NULL);
+
+ RETVAL_STRINGL((const char*) bson_get_data(bson), bson->len);
+ bson_destroy(bson);
+} /* }}} */
+
+/* {{{ proto array|object MongoDB\BSON\toPHP(string $bson [, array $typemap = array()])
+ Returns the PHP representation of a BSON value, optionally converting it into a custom class */
+PHP_FUNCTION(MongoDB_BSON_toPHP)
+{
+ zend_error_handling error_handling;
+ char* data;
+ size_t data_len;
+ zval* typemap = NULL;
+ php_phongo_bson_state state;
+
+ PHONGO_BSON_INIT_STATE(state);
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|a!", &data, &data_len, &typemap) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ if (!php_phongo_bson_typemap_to_state(typemap, &state.map)) {
+ return;
+ }
+
+ if (!php_phongo_bson_to_zval_ex((const unsigned char*) data, data_len, &state)) {
+ zval_ptr_dtor(&state.zchild);
+ php_phongo_bson_typemap_dtor(&state.map);
+ RETURN_NULL();
+ }
+
+ php_phongo_bson_typemap_dtor(&state.map);
+
+ RETURN_ZVAL(&state.zchild, 0, 1);
+} /* }}} */
+
+/* {{{ proto string MongoDB\BSON\fromJSON(string $json)
+ Returns the BSON representation of a JSON value */
+PHP_FUNCTION(MongoDB_BSON_fromJSON)
+{
+ zend_error_handling error_handling;
+ char* json;
+ size_t json_len;
+ bson_t bson = BSON_INITIALIZER;
+ bson_error_t error = { 0 };
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &json, &json_len) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ if (bson_init_from_json(&bson, (const char*) json, json_len, &error)) {
+ RETVAL_STRINGL((const char*) bson_get_data(&bson), bson.len);
+ bson_destroy(&bson);
+ } else {
+ phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "%s", error.domain == BSON_ERROR_JSON ? error.message : "Error parsing JSON");
+ }
+} /* }}} */
+
+static void phongo_bson_to_json(INTERNAL_FUNCTION_PARAMETERS, php_phongo_json_mode_t mode)
+{
+ zend_error_handling error_handling;
+ char* data;
+ size_t data_len;
+ const bson_t* bson;
+ bool eof = false;
+ bson_reader_t* reader;
+ char* json = NULL;
+ size_t json_len;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &data, &data_len) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ reader = bson_reader_new_from_data((const unsigned char*) data, data_len);
+ bson = bson_reader_read(reader, NULL);
+
+ if (!bson) {
+ phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "Could not read document from BSON reader");
+ bson_reader_destroy(reader);
+ return;
+ }
+
+ if (mode == PHONGO_JSON_MODE_LEGACY) {
+ json = bson_as_json(bson, &json_len);
+ } else if (mode == PHONGO_JSON_MODE_CANONICAL) {
+ json = bson_as_canonical_extended_json(bson, &json_len);
+ } else if (mode == PHONGO_JSON_MODE_RELAXED) {
+ json = bson_as_relaxed_extended_json(bson, &json_len);
+ }
+
+ if (!json) {
+ phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "Could not convert BSON document to a JSON string");
+ bson_reader_destroy(reader);
+ return;
+ }
+
+ RETVAL_STRINGL(json, json_len);
+ bson_free(json);
+
+ if (bson_reader_read(reader, &eof) || !eof) {
+ phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "Reading document did not exhaust input buffer");
+ }
+
+ bson_reader_destroy(reader);
+} /* }}} */
+
+/* {{{ proto string MongoDB\BSON\toJSON(string $bson)
+ Returns the legacy extended JSON representation of a BSON value */
+PHP_FUNCTION(MongoDB_BSON_toJSON)
+{
+ phongo_bson_to_json(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHONGO_JSON_MODE_LEGACY);
+} /* }}} */
+
+/* {{{ proto string MongoDB\BSON\toCanonicalExtendedJSON(string $bson)
+ Returns the canonical extended JSON representation of a BSON value */
+PHP_FUNCTION(MongoDB_BSON_toCanonicalExtendedJSON)
+{
+ phongo_bson_to_json(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHONGO_JSON_MODE_CANONICAL);
+} /* }}} */
+
+/* {{{ proto string MongoDB\BSON\toRelaxedExtendedJSON(string $bson)
+ Returns the relaxed extended JSON representation of a BSON value */
+PHP_FUNCTION(MongoDB_BSON_toRelaxedExtendedJSON)
+{
+ phongo_bson_to_json(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHONGO_JSON_MODE_RELAXED);
+} /* }}} */
diff --git a/mongodb-1.13.0/src/BSON/functions.h b/mongodb-1.13.0/src/BSON/functions.h
new file mode 100644
index 00000000..83f2b5d7
--- /dev/null
+++ b/mongodb-1.13.0/src/BSON/functions.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2014-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PHONGO_BSON_FUNCTIONS_H
+#define PHONGO_BSON_FUNCTIONS_H
+
+#include <php.h>
+
+PHP_FUNCTION(MongoDB_BSON_fromPHP);
+PHP_FUNCTION(MongoDB_BSON_toPHP);
+
+PHP_FUNCTION(MongoDB_BSON_fromJSON);
+PHP_FUNCTION(MongoDB_BSON_toJSON);
+PHP_FUNCTION(MongoDB_BSON_toCanonicalExtendedJSON);
+PHP_FUNCTION(MongoDB_BSON_toRelaxedExtendedJSON);
+
+#endif /* PHONGO_BSON_FUNCTIONS_H */
diff --git a/mongodb-1.13.0/src/LIBMONGOCRYPT_VERSION_CURRENT b/mongodb-1.13.0/src/LIBMONGOCRYPT_VERSION_CURRENT
new file mode 100644
index 00000000..1892b926
--- /dev/null
+++ b/mongodb-1.13.0/src/LIBMONGOCRYPT_VERSION_CURRENT
@@ -0,0 +1 @@
+1.3.2
diff --git a/mongodb-1.13.0/src/LIBMONGOC_VERSION_CURRENT b/mongodb-1.13.0/src/LIBMONGOC_VERSION_CURRENT
new file mode 100644
index 00000000..28449774
--- /dev/null
+++ b/mongodb-1.13.0/src/LIBMONGOC_VERSION_CURRENT
@@ -0,0 +1 @@
+1.21.1
diff --git a/mongodb-1.13.0/src/MongoDB/BulkWrite.c b/mongodb-1.13.0/src/MongoDB/BulkWrite.c
new file mode 100644
index 00000000..7dc20ea8
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/BulkWrite.c
@@ -0,0 +1,675 @@
+/*
+ * Copyright 2015-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bson/bson.h"
+#include "mongoc/mongoc.h"
+
+#include <php.h>
+#include <Zend/zend_interfaces.h>
+
+#include "php_array_api.h"
+
+#include "php_phongo.h"
+#include "phongo_bson_encode.h"
+#include "phongo_error.h"
+
+#include "MongoDB/WriteConcern.h"
+
+#define PHONGO_BULKWRITE_BYPASS_UNSET -1
+
+zend_class_entry* php_phongo_bulkwrite_ce;
+
+/* Extracts the "_id" field of a BSON document into a return value. */
+static void php_phongo_bulkwrite_extract_id(bson_t* doc, zval** return_value) /* {{{ */
+{
+ zval* id = NULL;
+ php_phongo_bson_state state;
+
+ PHONGO_BSON_INIT_STATE(state);
+ state.map.root_type = PHONGO_TYPEMAP_NATIVE_ARRAY;
+
+ if (!php_phongo_bson_to_zval_ex(bson_get_data(doc), doc->len, &state)) {
+ goto cleanup;
+ }
+
+ id = php_array_fetchc(&state.zchild, "_id");
+
+ if (id) {
+ ZVAL_ZVAL(*return_value, id, 1, 0);
+ }
+
+cleanup:
+ zval_ptr_dtor(&state.zchild);
+} /* }}} */
+
+/* Returns whether any top-level field names in the document contain a "$". */
+static inline bool php_phongo_bulkwrite_update_has_operators(bson_t* bupdate) /* {{{ */
+{
+ bson_iter_t iter;
+
+ if (bson_iter_init(&iter, bupdate)) {
+ while (bson_iter_next(&iter)) {
+ if (strchr(bson_iter_key(&iter), '$')) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+} /* }}} */
+
+/* Returns whether the update document is considered an aggregation pipeline */
+static inline bool php_phongo_bulkwrite_update_is_pipeline(bson_t* bupdate) /* {{{ */
+{
+ bson_iter_t iter;
+ bson_iter_t child;
+ const char* key;
+ int i = 0;
+ char* i_str;
+
+ if (!bson_iter_init(&iter, bupdate)) {
+ return false;
+ }
+
+ while (bson_iter_next(&iter)) {
+ key = bson_iter_key(&iter);
+ i_str = bson_strdup_printf("%d", i++);
+
+ if (strcmp(key, i_str)) {
+ bson_free(i_str);
+ return false;
+ }
+
+ bson_free(i_str);
+
+ if (BSON_ITER_HOLDS_DOCUMENT(&iter)) {
+ if (!bson_iter_recurse(&iter, &child)) {
+ return false;
+ }
+ if (!bson_iter_next(&child)) {
+ return false;
+ }
+ key = bson_iter_key(&child);
+ if (key[0] != '$') {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+
+ /* should return false when the document is empty */
+ return i != 0;
+} /* }}} */
+
+/* Returns whether the BSON array's keys are a sequence of integer strings
+ * starting with "0". BSON_APPEND_ARRAY considers it the caller's responsibility
+ * to ensure that the array's keys are properly formatted. */
+static inline bool php_phongo_bulkwrite_bson_array_has_valid_keys(bson_t* array) /* {{{ */
+{
+ bson_iter_t iter;
+
+ if (bson_empty(array)) {
+ return true;
+ }
+
+ if (bson_iter_init(&iter, array)) {
+ char key[12];
+ int count = 0;
+
+ while (bson_iter_next(&iter)) {
+ bson_snprintf(key, sizeof(key), "%d", count);
+
+ if (0 != strcmp(key, bson_iter_key(&iter))) {
+ return false;
+ }
+
+ count++;
+ }
+ }
+
+ return true;
+} /* }}} */
+
+/* Appends an array field for the given opts document and key. Returns true on
+ * success; otherwise, false is returned and an exception is thrown. */
+static bool php_phongo_bulkwrite_opts_append_array(bson_t* opts, const char* key, zval* zarr) /* {{{ */
+{
+ zval* value = php_array_fetch(zarr, key);
+ bson_t b = BSON_INITIALIZER;
+
+ if (Z_TYPE_P(value) != IS_OBJECT && Z_TYPE_P(value) != IS_ARRAY) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"%s\" option to be array or object, %s given", key, zend_get_type_by_const(Z_TYPE_P(value)));
+ return false;
+ }
+
+ php_phongo_zval_to_bson(value, PHONGO_BSON_NONE, &b, NULL);
+
+ if (EG(exception)) {
+ bson_destroy(&b);
+ return false;
+ }
+
+ if (!php_phongo_bulkwrite_bson_array_has_valid_keys(&b)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "\"%s\" option has invalid keys for a BSON array", key);
+ bson_destroy(&b);
+ return false;
+ }
+
+ if (!BSON_APPEND_ARRAY(opts, key, &b)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Error appending \"%s\" option", key);
+ bson_destroy(&b);
+ return false;
+ }
+
+ bson_destroy(&b);
+ return true;
+} /* }}} */
+
+/* Appends a document field for the given opts document and key. Returns true on
+ * success; otherwise, false is returned and an exception is thrown. */
+static bool php_phongo_bulkwrite_opts_append_document(bson_t* opts, const char* key, zval* zarr) /* {{{ */
+{
+ zval* value = php_array_fetch(zarr, key);
+ bson_t b = BSON_INITIALIZER;
+
+ if (Z_TYPE_P(value) != IS_OBJECT && Z_TYPE_P(value) != IS_ARRAY) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"%s\" option to be array or object, %s given", key, zend_get_type_by_const(Z_TYPE_P(value)));
+ return false;
+ }
+
+ php_phongo_zval_to_bson(value, PHONGO_BSON_NONE, &b, NULL);
+
+ if (EG(exception)) {
+ bson_destroy(&b);
+ return false;
+ }
+
+ if (!BSON_APPEND_DOCUMENT(opts, key, &b)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Error appending \"%s\" option", key);
+ bson_destroy(&b);
+ return false;
+ }
+
+ bson_destroy(&b);
+ return true;
+} /* }}} */
+
+#define PHONGO_BULKWRITE_APPEND_BOOL(opt, value) \
+ if (!BSON_APPEND_BOOL(boptions, (opt), (value))) { \
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Error appending \"%s\" option", (opt)); \
+ return false; \
+ }
+
+#define PHONGO_BULKWRITE_APPEND_INT32(opt, value) \
+ if (!BSON_APPEND_INT32(boptions, (opt), (value))) { \
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Error appending \"%s\" option", (opt)); \
+ return false; \
+ }
+
+#define PHONGO_BULKWRITE_OPT_ARRAY(opt) \
+ if (zoptions && php_array_existsc(zoptions, (opt))) { \
+ if (!php_phongo_bulkwrite_opts_append_array(boptions, (opt), zoptions)) { \
+ return false; \
+ } \
+ }
+
+#define PHONGO_BULKWRITE_OPT_DOCUMENT(opt) \
+ if (zoptions && php_array_existsc(zoptions, (opt))) { \
+ if (!php_phongo_bulkwrite_opts_append_document(boptions, (opt), zoptions)) { \
+ return false; \
+ } \
+ }
+
+/* Initialize the "hint" option. Returns true on success; otherwise, false is
+ * returned and an exception is thrown.
+ *
+ * The "hint" option must be a string or document. Check for both types and
+ * merge into BSON options accordingly. */
+static bool php_phongo_bulkwrite_opt_hint(bson_t* boptions, zval* zoptions) /* {{{ */
+{
+ /* The "hint" option (or "$hint" modifier) must be a string or document.
+ * Check for both types and merge into BSON options accordingly. */
+ if (zoptions && php_array_existsc(zoptions, "hint")) {
+ zend_uchar type = Z_TYPE_P(php_array_fetchc(zoptions, "hint"));
+
+ if (type == IS_STRING) {
+ zval* value = php_array_fetchc(zoptions, "hint");
+
+ if (!bson_append_utf8(boptions, "hint", 4, Z_STRVAL_P(value), Z_STRLEN_P(value))) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Error appending \"hint\" option");
+ return false;
+ }
+ } else if (type == IS_OBJECT || type == IS_ARRAY) {
+ PHONGO_BULKWRITE_OPT_DOCUMENT("hint");
+ } else {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"hint\" option to be string, array, or object, %s given", zend_get_type_by_const(type));
+ return false;
+ }
+ }
+
+ return true;
+} /* }}} */
+
+/* Applies options (including defaults) for an update operation. */
+static bool php_phongo_bulkwrite_update_apply_options(bson_t* boptions, zval* zoptions) /* {{{ */
+{
+ bool multi = false, upsert = false;
+
+ if (zoptions) {
+ multi = php_array_fetchc_bool(zoptions, "multi");
+ upsert = php_array_fetchc_bool(zoptions, "upsert");
+ }
+
+ PHONGO_BULKWRITE_APPEND_BOOL("multi", multi);
+ PHONGO_BULKWRITE_APPEND_BOOL("upsert", upsert);
+ PHONGO_BULKWRITE_OPT_ARRAY("arrayFilters");
+ PHONGO_BULKWRITE_OPT_DOCUMENT("collation");
+
+ if (!php_phongo_bulkwrite_opt_hint(boptions, zoptions)) {
+ return false;
+ }
+
+ return true;
+} /* }}} */
+
+/* Applies options (including defaults) for an delete operation. */
+static bool php_phongo_bulkwrite_delete_apply_options(bson_t* boptions, zval* zoptions) /* {{{ */
+{
+ int32_t limit = 0;
+
+ if (zoptions) {
+ limit = php_array_fetchc_bool(zoptions, "limit") ? 1 : 0;
+ }
+
+ PHONGO_BULKWRITE_APPEND_INT32("limit", limit);
+ PHONGO_BULKWRITE_OPT_DOCUMENT("collation");
+
+ if (!php_phongo_bulkwrite_opt_hint(boptions, zoptions)) {
+ return false;
+ }
+
+ return true;
+} /* }}} */
+
+#undef PHONGO_BULKWRITE_APPEND_BOOL
+#undef PHONGO_BULKWRITE_APPEND_INT32
+#undef PHONGO_BULKWRITE_OPT_DOCUMENT
+
+/* {{{ proto void MongoDB\Driver\BulkWrite::__construct([array $options = array()])
+ Constructs a new BulkWrite */
+static PHP_METHOD(BulkWrite, __construct)
+{
+ zend_error_handling error_handling;
+ php_phongo_bulkwrite_t* intern;
+ zval* options = NULL;
+ zend_bool ordered = 1;
+
+ intern = Z_BULKWRITE_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "|a!", &options) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ if (options && php_array_existsc(options, "ordered")) {
+ ordered = php_array_fetchc_bool(options, "ordered");
+ }
+
+ intern->bulk = mongoc_bulk_operation_new(ordered);
+ intern->ordered = ordered;
+ intern->bypass = PHONGO_BULKWRITE_BYPASS_UNSET;
+ intern->num_ops = 0;
+ intern->executed = false;
+
+ if (options && php_array_existsc(options, "bypassDocumentValidation")) {
+ zend_bool bypass = php_array_fetchc_bool(options, "bypassDocumentValidation");
+ mongoc_bulk_operation_set_bypass_document_validation(intern->bulk, bypass);
+ intern->bypass = bypass;
+ }
+} /* }}} */
+
+/* {{{ proto mixed MongoDB\Driver\BulkWrite::insert(array|object $document)
+ Adds an insert operation to the BulkWrite */
+static PHP_METHOD(BulkWrite, insert)
+{
+ zend_error_handling error_handling;
+ php_phongo_bulkwrite_t* intern;
+ zval* zdocument;
+ bson_t bdocument = BSON_INITIALIZER, boptions = BSON_INITIALIZER;
+ bson_t* bson_out = NULL;
+ int bson_flags = PHONGO_BSON_ADD_ID;
+ bson_error_t error = { 0 };
+
+ intern = Z_BULKWRITE_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "A", &zdocument) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ bson_flags |= PHONGO_BSON_RETURN_ID;
+
+ php_phongo_zval_to_bson(zdocument, bson_flags, &bdocument, &bson_out);
+
+ if (EG(exception)) {
+ goto cleanup;
+ }
+
+ if (!mongoc_bulk_operation_insert_with_opts(intern->bulk, &bdocument, &boptions, &error)) {
+ phongo_throw_exception_from_bson_error_t(&error);
+ goto cleanup;
+ }
+
+ intern->num_ops++;
+
+ if (!bson_out) {
+ phongo_throw_exception(PHONGO_ERROR_LOGIC, "Did not receive result from bulk write. Please file a bug report.");
+ goto cleanup;
+ }
+
+ php_phongo_bulkwrite_extract_id(bson_out, &return_value);
+
+cleanup:
+ bson_destroy(&bdocument);
+ bson_destroy(&boptions);
+ bson_clear(&bson_out);
+} /* }}} */
+
+/* {{{ proto void MongoDB\Driver\BulkWrite::update(array|object $query, array|object $newObj[, array $updateOptions = array()])
+ Adds an update operation to the BulkWrite */
+static PHP_METHOD(BulkWrite, update)
+{
+ zend_error_handling error_handling;
+ php_phongo_bulkwrite_t* intern;
+ zval * zquery, *zupdate, *zoptions = NULL;
+ bson_t bquery = BSON_INITIALIZER, bupdate = BSON_INITIALIZER, boptions = BSON_INITIALIZER;
+ bson_error_t error = { 0 };
+
+ intern = Z_BULKWRITE_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "AA|a!", &zquery, &zupdate, &zoptions) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ php_phongo_zval_to_bson(zquery, PHONGO_BSON_NONE, &bquery, NULL);
+
+ if (EG(exception)) {
+ goto cleanup;
+ }
+
+ php_phongo_zval_to_bson(zupdate, PHONGO_BSON_NONE, &bupdate, NULL);
+
+ if (EG(exception)) {
+ goto cleanup;
+ }
+
+ if (!php_phongo_bulkwrite_update_apply_options(&boptions, zoptions)) {
+ goto cleanup;
+ }
+
+ if (php_phongo_bulkwrite_update_has_operators(&bupdate) || php_phongo_bulkwrite_update_is_pipeline(&bupdate)) {
+ if (zoptions && php_array_fetchc_bool(zoptions, "multi")) {
+ if (!mongoc_bulk_operation_update_many_with_opts(intern->bulk, &bquery, &bupdate, &boptions, &error)) {
+ phongo_throw_exception_from_bson_error_t(&error);
+ goto cleanup;
+ }
+ } else {
+ if (!mongoc_bulk_operation_update_one_with_opts(intern->bulk, &bquery, &bupdate, &boptions, &error)) {
+ phongo_throw_exception_from_bson_error_t(&error);
+ goto cleanup;
+ }
+ }
+ } else {
+ if (zoptions && php_array_fetchc_bool(zoptions, "multi")) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Replacement document conflicts with true \"multi\" option");
+ goto cleanup;
+ }
+
+ if (!mongoc_bulk_operation_replace_one_with_opts(intern->bulk, &bquery, &bupdate, &boptions, &error)) {
+ phongo_throw_exception_from_bson_error_t(&error);
+ goto cleanup;
+ }
+ }
+
+ intern->num_ops++;
+
+cleanup:
+ bson_destroy(&bquery);
+ bson_destroy(&bupdate);
+ bson_destroy(&boptions);
+} /* }}} */
+
+/* {{{ proto void MongoDB\Driver\BulkWrite::delete(array|object $query[, array $deleteOptions = array()])
+ Adds a delete operation to the BulkWrite */
+static PHP_METHOD(BulkWrite, delete)
+{
+ zend_error_handling error_handling;
+ php_phongo_bulkwrite_t* intern;
+ zval * zquery, *zoptions = NULL;
+ bson_t bquery = BSON_INITIALIZER, boptions = BSON_INITIALIZER;
+ bson_error_t error = { 0 };
+
+ intern = Z_BULKWRITE_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "A|a!", &zquery, &zoptions) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ php_phongo_zval_to_bson(zquery, PHONGO_BSON_NONE, &bquery, NULL);
+
+ if (EG(exception)) {
+ goto cleanup;
+ }
+
+ if (!php_phongo_bulkwrite_delete_apply_options(&boptions, zoptions)) {
+ goto cleanup;
+ }
+
+ if (zoptions && php_array_fetchc_bool(zoptions, "limit")) {
+ if (!mongoc_bulk_operation_remove_one_with_opts(intern->bulk, &bquery, &boptions, &error)) {
+ phongo_throw_exception_from_bson_error_t(&error);
+ goto cleanup;
+ }
+ } else {
+ if (!mongoc_bulk_operation_remove_many_with_opts(intern->bulk, &bquery, &boptions, &error)) {
+ phongo_throw_exception_from_bson_error_t(&error);
+ goto cleanup;
+ }
+ }
+
+ intern->num_ops++;
+
+cleanup:
+ bson_destroy(&bquery);
+ bson_destroy(&boptions);
+} /* }}} */
+
+/* {{{ proto integer MongoDB\Driver\BulkWrite::count()
+ Returns the number of operations that have been added to the BulkWrite */
+static PHP_METHOD(BulkWrite, count)
+{
+ zend_error_handling error_handling;
+ php_phongo_bulkwrite_t* intern;
+
+ intern = Z_BULKWRITE_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ RETURN_LONG(intern->num_ops);
+} /* }}} */
+
+/* {{{ MongoDB\Driver\BulkWrite function entries */
+/* clang-format off */
+ZEND_BEGIN_ARG_INFO_EX(ai_BulkWrite___construct, 0, 0, 0)
+ ZEND_ARG_ARRAY_INFO(0, options, 1)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(ai_BulkWrite_count, 0, 0, IS_LONG, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_BulkWrite_insert, 0, 0, 1)
+ ZEND_ARG_INFO(0, document)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_BulkWrite_update, 0, 0, 2)
+ ZEND_ARG_INFO(0, query)
+ ZEND_ARG_INFO(0, newObj)
+ ZEND_ARG_ARRAY_INFO(0, updateOptions, 1)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_BulkWrite_delete, 0, 0, 1)
+ ZEND_ARG_INFO(0, query)
+ ZEND_ARG_ARRAY_INFO(0, deleteOptions, 1)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_BulkWrite_void, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry php_phongo_bulkwrite_me[] = {
+ PHP_ME(BulkWrite, __construct, ai_BulkWrite___construct, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(BulkWrite, insert, ai_BulkWrite_insert, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(BulkWrite, update, ai_BulkWrite_update, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(BulkWrite, delete, ai_BulkWrite_delete, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(BulkWrite, count, ai_BulkWrite_count, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ ZEND_NAMED_ME(__wakeup, PHP_FN(MongoDB_disabled___wakeup), ai_BulkWrite_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_FE_END
+};
+/* clang-format on */
+/* }}} */
+
+/* {{{ MongoDB\Driver\BulkWrite object handlers */
+static zend_object_handlers php_phongo_handler_bulkwrite;
+
+static void php_phongo_bulkwrite_free_object(zend_object* object) /* {{{ */
+{
+ php_phongo_bulkwrite_t* intern = Z_OBJ_BULKWRITE(object);
+
+ zend_object_std_dtor(&intern->std);
+
+ if (intern->bulk) {
+ mongoc_bulk_operation_destroy(intern->bulk);
+ }
+
+ if (intern->database) {
+ efree(intern->database);
+ }
+
+ if (intern->collection) {
+ efree(intern->collection);
+ }
+
+ if (!Z_ISUNDEF(intern->session)) {
+ zval_ptr_dtor(&intern->session);
+ }
+} /* }}} */
+
+static zend_object* php_phongo_bulkwrite_create_object(zend_class_entry* class_type) /* {{{ */
+{
+ php_phongo_bulkwrite_t* intern = zend_object_alloc(sizeof(php_phongo_bulkwrite_t), class_type);
+
+ zend_object_std_init(&intern->std, class_type);
+ object_properties_init(&intern->std, class_type);
+
+ intern->std.handlers = &php_phongo_handler_bulkwrite;
+
+ return &intern->std;
+} /* }}} */
+
+static HashTable* php_phongo_bulkwrite_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
+{
+ zval retval = ZVAL_STATIC_INIT;
+ php_phongo_bulkwrite_t* intern = NULL;
+
+ *is_temp = 1;
+ intern = Z_OBJ_BULKWRITE(PHONGO_COMPAT_GET_OBJ(object));
+ array_init(&retval);
+
+ if (intern->database) {
+ ADD_ASSOC_STRING(&retval, "database", intern->database);
+ } else {
+ ADD_ASSOC_NULL_EX(&retval, "database");
+ }
+
+ if (intern->collection) {
+ ADD_ASSOC_STRING(&retval, "collection", intern->collection);
+ } else {
+ ADD_ASSOC_NULL_EX(&retval, "collection");
+ }
+
+ ADD_ASSOC_BOOL_EX(&retval, "ordered", intern->ordered);
+
+ if (intern->bypass != PHONGO_BULKWRITE_BYPASS_UNSET) {
+ ADD_ASSOC_BOOL_EX(&retval, "bypassDocumentValidation", intern->bypass);
+ } else {
+ ADD_ASSOC_NULL_EX(&retval, "bypassDocumentValidation");
+ }
+
+ ADD_ASSOC_BOOL_EX(&retval, "executed", intern->executed);
+ ADD_ASSOC_LONG_EX(&retval, "server_id", mongoc_bulk_operation_get_hint(intern->bulk));
+
+ if (!Z_ISUNDEF(intern->session)) {
+ ADD_ASSOC_ZVAL_EX(&retval, "session", &intern->session);
+ Z_ADDREF(intern->session);
+ } else {
+ ADD_ASSOC_NULL_EX(&retval, "session");
+ }
+
+ if (mongoc_bulk_operation_get_write_concern(intern->bulk)) {
+ zval write_concern;
+
+ php_phongo_write_concern_to_zval(&write_concern, mongoc_bulk_operation_get_write_concern(intern->bulk));
+ ADD_ASSOC_ZVAL_EX(&retval, "write_concern", &write_concern);
+ } else {
+ ADD_ASSOC_NULL_EX(&retval, "write_concern");
+ }
+
+ return Z_ARRVAL(retval);
+} /* }}} */
+/* }}} */
+
+void php_phongo_bulkwrite_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver", "BulkWrite", php_phongo_bulkwrite_me);
+ php_phongo_bulkwrite_ce = zend_register_internal_class(&ce);
+ php_phongo_bulkwrite_ce->create_object = php_phongo_bulkwrite_create_object;
+ PHONGO_CE_FINAL(php_phongo_bulkwrite_ce);
+ PHONGO_CE_DISABLE_SERIALIZATION(php_phongo_bulkwrite_ce);
+
+ memcpy(&php_phongo_handler_bulkwrite, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
+ php_phongo_handler_bulkwrite.get_debug_info = php_phongo_bulkwrite_get_debug_info;
+ php_phongo_handler_bulkwrite.free_obj = php_phongo_bulkwrite_free_object;
+ php_phongo_handler_bulkwrite.offset = XtOffsetOf(php_phongo_bulkwrite_t, std);
+
+ zend_class_implements(php_phongo_bulkwrite_ce, 1, zend_ce_countable);
+} /* }}} */
diff --git a/mongodb-1.13.0/src/MongoDB/ClientEncryption.c b/mongodb-1.13.0/src/MongoDB/ClientEncryption.c
new file mode 100644
index 00000000..792dead2
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/ClientEncryption.c
@@ -0,0 +1,581 @@
+/*
+ * Copyright 2019-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bson/bson.h"
+#include "mongoc/mongoc.h"
+
+#include <php.h>
+#include <Zend/zend_interfaces.h>
+
+#include "php_array_api.h"
+
+#include "php_phongo.h"
+#include "phongo_bson_encode.h"
+#include "phongo_error.h"
+#include "phongo_util.h"
+
+zend_class_entry* php_phongo_clientencryption_ce;
+
+/* Forward declarations */
+static void phongo_clientencryption_create_datakey(php_phongo_clientencryption_t* clientencryption, zval* return_value, char* kms_provider, zval* options);
+static void phongo_clientencryption_encrypt(php_phongo_clientencryption_t* clientencryption, zval* zvalue, zval* zciphertext, zval* options);
+static void phongo_clientencryption_decrypt(php_phongo_clientencryption_t* clientencryption, zval* zciphertext, zval* zvalue);
+
+/* {{{ proto MongoDB\BSON\Binary MongoDB\Driver\ClientEncryption::createDataKey(string $kmsProvider[, array $options])
+ Creates a new key document and inserts into the key vault collection. */
+static PHP_METHOD(ClientEncryption, createDataKey)
+{
+ char* kms_provider = NULL;
+ size_t kms_provider_len = 0;
+ zval* options = NULL;
+ zend_error_handling error_handling;
+ php_phongo_clientencryption_t* intern;
+
+ intern = Z_CLIENTENCRYPTION_OBJ_P(getThis());
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|a!", &kms_provider, &kms_provider_len, &options) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+
+ zend_restore_error_handling(&error_handling);
+
+ phongo_clientencryption_create_datakey(intern, return_value, kms_provider, options);
+} /* }}} */
+
+/* {{{ proto MongoDB\BSON\Binary MongoDB\Driver\ClientEncryption::encrypt(mixed $value[, array $options])
+ Encrypts a value with a given key and algorithm */
+static PHP_METHOD(ClientEncryption, encrypt)
+{
+ zval* value = NULL;
+ zval* options = NULL;
+ zend_error_handling error_handling;
+ php_phongo_clientencryption_t* intern;
+
+ intern = Z_CLIENTENCRYPTION_OBJ_P(getThis());
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|a!", &value, &options) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+
+ zend_restore_error_handling(&error_handling);
+
+ phongo_clientencryption_encrypt(intern, value, return_value, options);
+} /* }}} */
+
+/* {{{ proto mixed MongoDB\Driver\ClientEncryption::decrypt(MongoDB\BSON\BinaryInterface $value)
+ Decrypts an encrypted value (BSON binary of subtype 6). Returns the original BSON value */
+static PHP_METHOD(ClientEncryption, decrypt)
+{
+ zval* ciphertext;
+ zend_error_handling error_handling;
+ php_phongo_clientencryption_t* intern;
+
+ intern = Z_CLIENTENCRYPTION_OBJ_P(getThis());
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &ciphertext, php_phongo_binary_interface_ce) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+
+ zend_restore_error_handling(&error_handling);
+
+ phongo_clientencryption_decrypt(intern, ciphertext, return_value);
+} /* }}} */
+
+ZEND_BEGIN_ARG_INFO_EX(ai_ClientEncryption_createDataKey, 0, 0, 1)
+ ZEND_ARG_INFO(0, kmsProvider)
+ ZEND_ARG_ARRAY_INFO(0, options, 1)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_ClientEncryption_encrypt, 0, 0, 1)
+ ZEND_ARG_INFO(0, value)
+ ZEND_ARG_ARRAY_INFO(0, options, 1)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_ClientEncryption_decrypt, 0, 0, 1)
+ ZEND_ARG_OBJ_INFO(0, keyVaultClient, MongoDB\\BSON\\BinaryInterface, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_ClientEncryption_void, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry php_phongo_clientencryption_me[] = {
+ /* clang-format off */
+ PHP_ME(ClientEncryption, createDataKey, ai_ClientEncryption_createDataKey, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(ClientEncryption, encrypt, ai_ClientEncryption_encrypt, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(ClientEncryption, decrypt, ai_ClientEncryption_decrypt, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ ZEND_NAMED_ME(__construct, PHP_FN(MongoDB_disabled___construct), ai_ClientEncryption_void, ZEND_ACC_PRIVATE | ZEND_ACC_FINAL)
+ ZEND_NAMED_ME(__wakeup, PHP_FN(MongoDB_disabled___wakeup), ai_ClientEncryption_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_FE_END
+ /* clang-format on */
+};
+/* }}} */
+
+/* {{{ MongoDB\Driver\ClientEncryption object handlers */
+static zend_object_handlers php_phongo_handler_clientencryption;
+
+static void php_phongo_clientencryption_free_object(zend_object* object) /* {{{ */
+{
+ php_phongo_clientencryption_t* intern = Z_OBJ_CLIENTENCRYPTION(object);
+
+ zend_object_std_dtor(&intern->std);
+
+ if (intern->client_encryption) {
+ mongoc_client_encryption_destroy(intern->client_encryption);
+ }
+
+ /* Free the keyVaultClient last to ensure that a potential non-persistent
+ * client outlives the mongoc_client_encryption_t as needed */
+ if (!Z_ISUNDEF(intern->key_vault_client_manager)) {
+ zval_ptr_dtor(&intern->key_vault_client_manager);
+ }
+} /* }}} */
+
+static zend_object* php_phongo_clientencryption_create_object(zend_class_entry* class_type) /* {{{ */
+{
+ php_phongo_clientencryption_t* intern = zend_object_alloc(sizeof(php_phongo_clientencryption_t), class_type);
+
+ zend_object_std_init(&intern->std, class_type);
+ object_properties_init(&intern->std, class_type);
+
+ intern->std.handlers = &php_phongo_handler_clientencryption;
+
+ return &intern->std;
+} /* }}} */
+
+static HashTable* php_phongo_clientencryption_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
+{
+ php_phongo_clientencryption_t* intern = NULL;
+ zval retval = ZVAL_STATIC_INIT;
+
+ *is_temp = 1;
+ intern = Z_OBJ_CLIENTENCRYPTION(PHONGO_COMPAT_GET_OBJ(object));
+
+ array_init(&retval);
+
+ return Z_ARRVAL(retval);
+} /* }}} */
+/* }}} */
+
+void php_phongo_clientencryption_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver", "ClientEncryption", php_phongo_clientencryption_me);
+ php_phongo_clientencryption_ce = zend_register_internal_class(&ce);
+ php_phongo_clientencryption_ce->create_object = php_phongo_clientencryption_create_object;
+ PHONGO_CE_FINAL(php_phongo_clientencryption_ce);
+ PHONGO_CE_DISABLE_SERIALIZATION(php_phongo_clientencryption_ce);
+
+ memcpy(&php_phongo_handler_clientencryption, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
+ php_phongo_handler_clientencryption.get_debug_info = php_phongo_clientencryption_get_debug_info;
+ php_phongo_handler_clientencryption.free_obj = php_phongo_clientencryption_free_object;
+ php_phongo_handler_clientencryption.offset = XtOffsetOf(php_phongo_clientencryption_t, std);
+
+ zend_declare_class_constant_string(php_phongo_clientencryption_ce, ZEND_STRL("AEAD_AES_256_CBC_HMAC_SHA_512_DETERMINISTIC"), MONGOC_AEAD_AES_256_CBC_HMAC_SHA_512_DETERMINISTIC);
+ zend_declare_class_constant_string(php_phongo_clientencryption_ce, ZEND_STRL("AEAD_AES_256_CBC_HMAC_SHA_512_RANDOM"), MONGOC_AEAD_AES_256_CBC_HMAC_SHA_512_RANDOM);
+} /* }}} */
+
+#ifdef MONGOC_ENABLE_CLIENT_SIDE_ENCRYPTION
+/* keyVaultClientManager is an output parameter and will be assigned the
+ * keyVaultNamespace Manager (if any). */
+static mongoc_client_encryption_opts_t* phongo_clientencryption_opts_from_zval(zval* defaultKeyVaultClient, zval* options, zval** keyVaultClientManager) /* {{{ */
+{
+ mongoc_client_encryption_opts_t* opts;
+
+ opts = mongoc_client_encryption_opts_new();
+ *keyVaultClientManager = NULL;
+
+ if (!options || Z_TYPE_P(options) != IS_ARRAY) {
+ /* Returning opts as-is will defer to mongoc_client_encryption_new to
+ * raise an error for missing required options */
+ return opts;
+ }
+
+ if (php_array_existsc(options, "keyVaultClient")) {
+ zval* key_vault_client = php_array_fetch(options, "keyVaultClient");
+
+ if (Z_TYPE_P(key_vault_client) != IS_OBJECT || !instanceof_function(Z_OBJCE_P(key_vault_client), php_phongo_manager_ce)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"keyVaultClient\" encryption option to be %s, %s given", ZSTR_VAL(php_phongo_manager_ce->name), PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(key_vault_client));
+ goto cleanup;
+ }
+
+ mongoc_client_encryption_opts_set_keyvault_client(opts, Z_MANAGER_OBJ_P(key_vault_client)->client);
+ *keyVaultClientManager = key_vault_client;
+ } else {
+ mongoc_client_encryption_opts_set_keyvault_client(opts, Z_MANAGER_OBJ_P(defaultKeyVaultClient)->client);
+ *keyVaultClientManager = defaultKeyVaultClient;
+ }
+
+ if (php_array_existsc(options, "keyVaultNamespace")) {
+ char* keyvault_namespace;
+ char* db_name;
+ char* coll_name;
+ int plen;
+ zend_bool pfree;
+
+ keyvault_namespace = php_array_fetchc_string(options, "keyVaultNamespace", &plen, &pfree);
+
+ if (!phongo_split_namespace(keyvault_namespace, &db_name, &coll_name)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"keyVaultNamespace\" encryption option to contain a full collection name");
+
+ if (pfree) {
+ efree(keyvault_namespace);
+ }
+
+ goto cleanup;
+ }
+
+ mongoc_client_encryption_opts_set_keyvault_namespace(opts, db_name, coll_name);
+ efree(db_name);
+ efree(coll_name);
+
+ if (pfree) {
+ efree(keyvault_namespace);
+ }
+ }
+
+ if (php_array_existsc(options, "kmsProviders")) {
+ zval* kms_providers = php_array_fetchc(options, "kmsProviders");
+ bson_t bson_providers = BSON_INITIALIZER;
+
+ if (Z_TYPE_P(kms_providers) != IS_ARRAY && Z_TYPE_P(kms_providers) != IS_OBJECT) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"kmsProviders\" encryption option to be an array or object");
+ goto cleanup;
+ }
+
+ php_phongo_zval_to_bson(kms_providers, PHONGO_BSON_NONE, &bson_providers, NULL);
+ if (EG(exception)) {
+ goto cleanup;
+ }
+
+ mongoc_client_encryption_opts_set_kms_providers(opts, &bson_providers);
+ bson_destroy(&bson_providers);
+ }
+
+ if (php_array_existsc(options, "tlsOptions")) {
+ zval* tls_options = php_array_fetchc(options, "tlsOptions");
+ bson_t bson_options = BSON_INITIALIZER;
+
+ if (Z_TYPE_P(tls_options) != IS_ARRAY && Z_TYPE_P(tls_options) != IS_OBJECT) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"tlsOptions\" encryption option to be an array or object");
+ goto cleanup;
+ }
+
+ php_phongo_zval_to_bson(tls_options, PHONGO_BSON_NONE, &bson_options, NULL);
+ if (EG(exception)) {
+ goto cleanup;
+ }
+
+ mongoc_client_encryption_opts_set_tls_opts(opts, &bson_options);
+ bson_destroy(&bson_options);
+ }
+
+ return opts;
+
+cleanup:
+ if (opts) {
+ mongoc_client_encryption_opts_destroy(opts);
+ }
+
+ return NULL;
+} /* }}} */
+
+void phongo_clientencryption_init(zval* return_value, zval* manager, zval* options) /* {{{ */
+{
+ php_phongo_clientencryption_t* intern;
+ mongoc_client_encryption_t* client_encryption;
+ mongoc_client_encryption_opts_t* opts;
+ zval* key_vault_client_manager = manager;
+ bson_error_t error = { 0 };
+
+ opts = phongo_clientencryption_opts_from_zval(manager, options, &key_vault_client_manager);
+ if (!opts) {
+ /* Exception already thrown */
+ goto cleanup;
+ }
+
+ client_encryption = mongoc_client_encryption_new(opts, &error);
+ if (!client_encryption) {
+ phongo_throw_exception_from_bson_error_t(&error);
+
+ goto cleanup;
+ }
+
+ object_init_ex(return_value, php_phongo_clientencryption_ce);
+
+ intern = Z_CLIENTENCRYPTION_OBJ_P(return_value);
+ intern->client_encryption = client_encryption;
+ ZVAL_ZVAL(&intern->key_vault_client_manager, key_vault_client_manager, 1, 0);
+
+cleanup:
+ if (opts) {
+ mongoc_client_encryption_opts_destroy(opts);
+ }
+} /* }}} */
+
+static mongoc_client_encryption_datakey_opts_t* phongo_clientencryption_datakey_opts_from_zval(zval* options) /* {{{ */
+{
+ mongoc_client_encryption_datakey_opts_t* opts;
+
+ opts = mongoc_client_encryption_datakey_opts_new();
+
+ if (!options || Z_TYPE_P(options) != IS_ARRAY) {
+ return opts;
+ }
+
+ if (php_array_existsc(options, "keyAltNames")) {
+ zval* zkeyaltnames = php_array_fetchc(options, "keyAltNames");
+ HashTable* ht_data;
+ uint32_t keyaltnames_count;
+ char** keyaltnames;
+ uint32_t i = 0;
+ uint32_t j = 0;
+ bool failed = false;
+
+ if (!zkeyaltnames || Z_TYPE_P(zkeyaltnames) != IS_ARRAY) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected keyAltNames to be array, %s given", PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(zkeyaltnames));
+ goto cleanup;
+ }
+
+ ht_data = HASH_OF(zkeyaltnames);
+ keyaltnames_count = ht_data ? zend_hash_num_elements(ht_data) : 0;
+ keyaltnames = ecalloc(keyaltnames_count, sizeof(char*));
+
+ {
+ zend_string* string_key = NULL;
+ zend_ulong num_key = 0;
+ zval* keyaltname;
+
+ ZEND_HASH_FOREACH_KEY_VAL(ht_data, num_key, string_key, keyaltname)
+ {
+ if (i >= keyaltnames_count) {
+ phongo_throw_exception(PHONGO_ERROR_LOGIC, "Iterating over too many keyAltNames. Please file a bug report");
+ failed = true;
+ break;
+ }
+
+ if (Z_TYPE_P(keyaltname) != IS_STRING) {
+ if (string_key) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected keyAltName with index \"%s\" to be string, %s given", ZSTR_VAL(string_key), PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(keyaltname));
+ } else {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected keyAltName with index \"%lu\" to be string, %s given", num_key, PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(keyaltname));
+ }
+
+ failed = true;
+ break;
+ }
+
+ keyaltnames[i] = estrdup(Z_STRVAL_P(keyaltname));
+ i++;
+ }
+ ZEND_HASH_FOREACH_END();
+ }
+
+ if (!failed) {
+ mongoc_client_encryption_datakey_opts_set_keyaltnames(opts, keyaltnames, keyaltnames_count);
+ }
+
+ for (j = 0; j < i; j++) {
+ efree(keyaltnames[j]);
+ }
+ efree(keyaltnames);
+
+ if (failed) {
+ goto cleanup;
+ }
+ }
+
+ if (php_array_existsc(options, "masterKey")) {
+ bson_t masterkey = BSON_INITIALIZER;
+
+ php_phongo_zval_to_bson(php_array_fetchc(options, "masterKey"), PHONGO_BSON_NONE, &masterkey, NULL);
+ if (EG(exception)) {
+ goto cleanup;
+ }
+
+ mongoc_client_encryption_datakey_opts_set_masterkey(opts, &masterkey);
+ }
+
+ return opts;
+
+cleanup:
+ if (opts) {
+ mongoc_client_encryption_datakey_opts_destroy(opts);
+ }
+
+ return NULL;
+} /* }}} */
+
+static void phongo_clientencryption_create_datakey(php_phongo_clientencryption_t* clientencryption, zval* return_value, char* kms_provider, zval* options) /* {{{ */
+{
+ mongoc_client_encryption_datakey_opts_t* opts;
+ bson_value_t keyid;
+ bson_error_t error = { 0 };
+
+ opts = phongo_clientencryption_datakey_opts_from_zval(options);
+ if (!opts) {
+ /* Exception already thrown */
+ goto cleanup;
+ }
+
+ if (!mongoc_client_encryption_create_datakey(clientencryption->client_encryption, kms_provider, opts, &keyid, &error)) {
+ phongo_throw_exception_from_bson_error_t(&error);
+ goto cleanup;
+ }
+
+ if (!php_phongo_bson_value_to_zval(&keyid, return_value)) {
+ /* Exception already thrown */
+ goto cleanup;
+ }
+
+cleanup:
+ if (opts) {
+ mongoc_client_encryption_datakey_opts_destroy(opts);
+ }
+} /* }}} */
+
+static mongoc_client_encryption_encrypt_opts_t* phongo_clientencryption_encrypt_opts_from_zval(zval* options) /* {{{ */
+{
+ mongoc_client_encryption_encrypt_opts_t* opts;
+
+ opts = mongoc_client_encryption_encrypt_opts_new();
+
+ if (!options || Z_TYPE_P(options) != IS_ARRAY) {
+ return opts;
+ }
+
+ if (php_array_existsc(options, "keyId")) {
+ bson_value_t keyid;
+
+ php_phongo_zval_to_bson_value(php_array_fetchc(options, "keyId"), PHONGO_BSON_NONE, &keyid);
+ if (EG(exception)) {
+ goto cleanup;
+ }
+
+ mongoc_client_encryption_encrypt_opts_set_keyid(opts, &keyid);
+ }
+
+ if (php_array_existsc(options, "keyAltName")) {
+ char* keyaltname;
+ int plen;
+ zend_bool pfree;
+
+ keyaltname = php_array_fetch_string(options, "keyAltName", &plen, &pfree);
+ mongoc_client_encryption_encrypt_opts_set_keyaltname(opts, keyaltname);
+
+ if (pfree) {
+ efree(keyaltname);
+ }
+ }
+
+ if (php_array_existsc(options, "algorithm")) {
+ char* algorithm;
+ int plen;
+ zend_bool pfree;
+
+ algorithm = php_array_fetch_string(options, "algorithm", &plen, &pfree);
+ mongoc_client_encryption_encrypt_opts_set_algorithm(opts, algorithm);
+
+ if (pfree) {
+ efree(algorithm);
+ }
+ }
+
+ return opts;
+
+cleanup:
+ if (opts) {
+ mongoc_client_encryption_encrypt_opts_destroy(opts);
+ }
+
+ return NULL;
+} /* }}} */
+
+static void phongo_clientencryption_encrypt(php_phongo_clientencryption_t* clientencryption, zval* zvalue, zval* zciphertext, zval* options) /* {{{ */
+{
+ mongoc_client_encryption_encrypt_opts_t* opts;
+ bson_value_t ciphertext, value;
+ bson_error_t error = { 0 };
+
+ php_phongo_zval_to_bson_value(zvalue, PHONGO_BSON_NONE, &value);
+
+ opts = phongo_clientencryption_encrypt_opts_from_zval(options);
+ if (!opts) {
+ /* Exception already thrown */
+ goto cleanup;
+ }
+
+ if (!mongoc_client_encryption_encrypt(clientencryption->client_encryption, &value, opts, &ciphertext, &error)) {
+ phongo_throw_exception_from_bson_error_t(&error);
+ goto cleanup;
+ }
+
+ if (!php_phongo_bson_value_to_zval(&ciphertext, zciphertext)) {
+ /* Exception already thrown */
+ goto cleanup;
+ }
+
+cleanup:
+ if (opts) {
+ mongoc_client_encryption_encrypt_opts_destroy(opts);
+ }
+} /* }}} */
+
+static void phongo_clientencryption_decrypt(php_phongo_clientencryption_t* clientencryption, zval* zciphertext, zval* zvalue) /* {{{ */
+{
+ bson_value_t ciphertext, value;
+ bson_error_t error = { 0 };
+
+ php_phongo_zval_to_bson_value(zciphertext, PHONGO_BSON_NONE, &ciphertext);
+
+ if (!mongoc_client_encryption_decrypt(clientencryption->client_encryption, &ciphertext, &value, &error)) {
+ phongo_throw_exception_from_bson_error_t(&error);
+ return;
+ }
+
+ if (!php_phongo_bson_value_to_zval(&value, zvalue)) {
+ /* Exception already thrown */
+ return;
+ }
+} /* }}} */
+#else /* MONGOC_ENABLE_CLIENT_SIDE_ENCRYPTION */
+void phongo_clientencryption_init(php_phongo_clientencryption_t* clientencryption, zval* manager, zval* options) /* {{{ */
+{
+ phongo_throw_exception_no_cse(PHONGO_ERROR_RUNTIME, "Cannot configure clientEncryption object.");
+}
+/* }}} */
+
+static void phongo_clientencryption_create_datakey(php_phongo_clientencryption_t* clientencryption, zval* return_value, char* kms_provider, zval* options) /* {{{ */
+{
+ phongo_throw_exception_no_cse(PHONGO_ERROR_RUNTIME, "Cannot create encryption key.");
+}
+/* }}} */
+
+static void phongo_clientencryption_encrypt(php_phongo_clientencryption_t* clientencryption, zval* zvalue, zval* zciphertext, zval* options) /* {{{ */
+{
+ phongo_throw_exception_no_cse(PHONGO_ERROR_RUNTIME, "Cannot encrypt value.");
+}
+/* }}} */
+
+static void phongo_clientencryption_decrypt(php_phongo_clientencryption_t* clientencryption, zval* zciphertext, zval* zvalue) /* {{{ */
+{
+ phongo_throw_exception_no_cse(PHONGO_ERROR_RUNTIME, "Cannot decrypt value.");
+}
+/* }}} */
+#endif /* MONGOC_ENABLE_CLIENT_SIDE_ENCRYPTION */
diff --git a/mongodb-1.13.0/src/MongoDB/ClientEncryption.h b/mongodb-1.13.0/src/MongoDB/ClientEncryption.h
new file mode 100644
index 00000000..51fe33da
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/ClientEncryption.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2022-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PHONGO_CLIENTENCRYPTION_H
+#define PHONGO_CLIENTENCRYPTION_H
+
+#include <php.h>
+
+void phongo_clientencryption_init(zval* return_value, zval* manager, zval* options);
+
+#endif /* PHONGO_CLIENTENCRYPTION_H */
diff --git a/mongodb-1.13.0/src/MongoDB/Command.c b/mongodb-1.13.0/src/MongoDB/Command.c
new file mode 100644
index 00000000..4745ab64
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/Command.c
@@ -0,0 +1,207 @@
+/*
+ * Copyright 2014-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bson/bson.h"
+
+#include <php.h>
+#include <Zend/zend_interfaces.h>
+
+#include "php_array_api.h"
+
+#include "php_phongo.h"
+#include "phongo_bson_encode.h"
+#include "phongo_error.h"
+
+zend_class_entry* php_phongo_command_ce;
+
+/* Initialize the "maxAwaitTimeMS" option. Returns true on success; otherwise,
+ * false is returned and an exception is thrown.
+ *
+ * The "maxAwaitTimeMS" option is assigned to the cursor after query execution
+ * via mongoc_cursor_set_max_await_time_ms(). */
+static bool php_phongo_command_init_max_await_time_ms(php_phongo_command_t* intern, zval* options) /* {{{ */
+{
+ int64_t max_await_time_ms;
+
+ if (!php_array_existsc(options, "maxAwaitTimeMS")) {
+ return true;
+ }
+
+ max_await_time_ms = php_array_fetchc_long(options, "maxAwaitTimeMS");
+
+ if (max_await_time_ms < 0) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"maxAwaitTimeMS\" option to be >= 0, %" PRId64 " given", max_await_time_ms);
+ return false;
+ }
+
+ if (max_await_time_ms > UINT32_MAX) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"maxAwaitTimeMS\" option to be <= %" PRIu32 ", %" PRId64 " given", UINT32_MAX, max_await_time_ms);
+ return false;
+ }
+
+ intern->max_await_time_ms = (uint32_t) max_await_time_ms;
+
+ return true;
+} /* }}} */
+
+/* Initializes the php_phongo_command_init from options argument. This
+ * function will fall back to a modifier in the absence of a top-level option
+ * (where applicable). */
+static bool php_phongo_command_init(php_phongo_command_t* intern, zval* filter, zval* options) /* {{{ */
+{
+ bson_iter_t iter;
+ bson_iter_t sub_iter;
+
+ intern->bson = bson_new();
+ intern->batch_size = 0;
+ intern->max_await_time_ms = 0;
+
+ php_phongo_zval_to_bson(filter, PHONGO_BSON_NONE, intern->bson, NULL);
+
+ /* Note: if any exceptions are thrown, we can simply return as PHP will
+ * invoke php_phongo_query_free_object to destruct the object. */
+ if (EG(exception)) {
+ return false;
+ }
+
+ if (bson_iter_init(&iter, intern->bson) && bson_iter_find_descendant(&iter, "cursor.batchSize", &sub_iter) && BSON_ITER_HOLDS_INT(&sub_iter)) {
+ int64_t batch_size = bson_iter_as_int64(&sub_iter);
+
+ if (batch_size >= 0 && batch_size <= UINT32_MAX) {
+ intern->batch_size = (uint32_t) batch_size;
+ }
+ }
+
+ if (!options) {
+ return true;
+ }
+
+ if (!php_phongo_command_init_max_await_time_ms(intern, options)) {
+ return false;
+ }
+
+ return true;
+} /* }}} */
+
+/* {{{ proto void MongoDB\Driver\Command::__construct(array|object $document[, array $options = array()])
+ Constructs a new Command */
+static PHP_METHOD(Command, __construct)
+{
+ zend_error_handling error_handling;
+ php_phongo_command_t* intern;
+ zval* document;
+ zval* options = NULL;
+
+ intern = Z_COMMAND_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "A|a!", &document, &options) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ php_phongo_command_init(intern, document, options);
+} /* }}} */
+
+/* {{{ MongoDB\Driver\Command function entries */
+ZEND_BEGIN_ARG_INFO_EX(ai_Command___construct, 0, 0, 1)
+ ZEND_ARG_INFO(0, document)
+ ZEND_ARG_ARRAY_INFO(0, options, 1)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_Command_void, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry php_phongo_command_me[] = {
+ /* clang-format off */
+ PHP_ME(Command, __construct, ai_Command___construct, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ ZEND_NAMED_ME(__wakeup, PHP_FN(MongoDB_disabled___wakeup), ai_Command_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_FE_END
+ /* clang-format on */
+};
+/* }}} */
+
+/* {{{ MongoDB\Driver\Command object handlers */
+static zend_object_handlers php_phongo_handler_command;
+
+static void php_phongo_command_free_object(zend_object* object) /* {{{ */
+{
+ php_phongo_command_t* intern = Z_OBJ_COMMAND(object);
+
+ zend_object_std_dtor(&intern->std);
+
+ if (intern->bson) {
+ bson_clear(&intern->bson);
+ }
+} /* }}} */
+
+static zend_object* php_phongo_command_create_object(zend_class_entry* class_type) /* {{{ */
+{
+ php_phongo_command_t* intern = zend_object_alloc(sizeof(php_phongo_command_t), class_type);
+
+ zend_object_std_init(&intern->std, class_type);
+ object_properties_init(&intern->std, class_type);
+
+ intern->std.handlers = &php_phongo_handler_command;
+
+ return &intern->std;
+} /* }}} */
+
+static HashTable* php_phongo_command_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
+{
+ php_phongo_command_t* intern;
+ zval retval = ZVAL_STATIC_INIT;
+
+ *is_temp = 1;
+ intern = Z_OBJ_COMMAND(PHONGO_COMPAT_GET_OBJ(object));
+
+ array_init_size(&retval, 1);
+
+ if (intern->bson) {
+ zval zv;
+
+ if (!php_phongo_bson_to_zval(bson_get_data(intern->bson), intern->bson->len, &zv)) {
+ zval_ptr_dtor(&zv);
+ goto done;
+ }
+
+ ADD_ASSOC_ZVAL_EX(&retval, "command", &zv);
+ } else {
+ ADD_ASSOC_NULL_EX(&retval, "command");
+ }
+
+done:
+ return Z_ARRVAL(retval);
+
+} /* }}} */
+/* }}} */
+
+void php_phongo_command_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver", "Command", php_phongo_command_me);
+ php_phongo_command_ce = zend_register_internal_class(&ce);
+ php_phongo_command_ce->create_object = php_phongo_command_create_object;
+ PHONGO_CE_FINAL(php_phongo_command_ce);
+ PHONGO_CE_DISABLE_SERIALIZATION(php_phongo_command_ce);
+
+ memcpy(&php_phongo_handler_command, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
+ php_phongo_handler_command.get_debug_info = php_phongo_command_get_debug_info;
+ php_phongo_handler_command.free_obj = php_phongo_command_free_object;
+ php_phongo_handler_command.offset = XtOffsetOf(php_phongo_command_t, std);
+} /* }}} */
diff --git a/mongodb-1.13.0/src/MongoDB/Cursor.c b/mongodb-1.13.0/src/MongoDB/Cursor.c
new file mode 100644
index 00000000..0eada5ff
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/Cursor.c
@@ -0,0 +1,576 @@
+/*
+ * Copyright 2014-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <php.h>
+#include <ext/spl/spl_iterators.h>
+#include <Zend/zend_interfaces.h>
+
+#include "php_phongo.h"
+#include "phongo_bson.h"
+#include "phongo_client.h"
+#include "phongo_error.h"
+
+#include "MongoDB/Cursor.h"
+#include "MongoDB/Server.h"
+
+zend_class_entry* php_phongo_cursor_ce;
+
+/* Check if the cursor is exhausted (i.e. ID is zero) and free any reference to
+ * the session. Calling this function during iteration will allow an implicit
+ * session to return to the pool immediately after a getMore indicates that the
+ * server has no more results to return. */
+static void php_phongo_cursor_free_session_if_exhausted(php_phongo_cursor_t* cursor) /* {{{ */
+{
+ if (mongoc_cursor_get_id(cursor->cursor)) {
+ return;
+ }
+
+ if (!Z_ISUNDEF(cursor->session)) {
+ zval_ptr_dtor(&cursor->session);
+ ZVAL_UNDEF(&cursor->session);
+ }
+} /* }}} */
+
+static void php_phongo_cursor_free_current(php_phongo_cursor_t* cursor) /* {{{ */
+{
+ if (!Z_ISUNDEF(cursor->visitor_data.zchild)) {
+ zval_ptr_dtor(&cursor->visitor_data.zchild);
+ ZVAL_UNDEF(&cursor->visitor_data.zchild);
+ }
+} /* }}} */
+
+/* {{{ proto void MongoDB\Driver\Cursor::setTypeMap(array $typemap)
+ Sets a type map to use for BSON unserialization */
+static PHP_METHOD(Cursor, setTypeMap)
+{
+ zend_error_handling error_handling;
+ php_phongo_cursor_t* intern;
+ php_phongo_bson_state state;
+ zval* typemap = NULL;
+ bool restore_current_element = false;
+
+ PHONGO_BSON_INIT_STATE(state);
+
+ intern = Z_CURSOR_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "a!", &typemap) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ if (!php_phongo_bson_typemap_to_state(typemap, &state.map)) {
+ return;
+ }
+
+ /* Check if the existing element needs to be freed before we overwrite
+ * visitor_data, which contains the only reference to it. */
+ if (!Z_ISUNDEF(intern->visitor_data.zchild)) {
+ php_phongo_cursor_free_current(intern);
+ restore_current_element = true;
+ }
+
+ php_phongo_bson_typemap_dtor(&intern->visitor_data.map);
+
+ intern->visitor_data = state;
+
+ /* If the cursor has a current element, we just freed it and should restore
+ * it with a new type map applied. */
+ if (restore_current_element && mongoc_cursor_current(intern->cursor)) {
+ const bson_t* doc = mongoc_cursor_current(intern->cursor);
+
+ if (!php_phongo_bson_to_zval_ex(bson_get_data(doc), doc->len, &intern->visitor_data)) {
+ php_phongo_cursor_free_current(intern);
+ }
+ }
+} /* }}} */
+
+static int php_phongo_cursor_to_array_apply(zend_object_iterator* iter, void* puser) /* {{{ */
+{
+ zval* data;
+ zval* return_value = (zval*) puser;
+
+ data = iter->funcs->get_current_data(iter);
+
+ if (EG(exception)) {
+ return ZEND_HASH_APPLY_STOP;
+ }
+ if (Z_ISUNDEF_P(data)) {
+ return ZEND_HASH_APPLY_STOP;
+ }
+ Z_TRY_ADDREF_P(data);
+ add_next_index_zval(return_value, data);
+
+ return ZEND_HASH_APPLY_KEEP;
+} /* }}} */
+
+static void php_phongo_cursor_id_new_from_id(zval* object, int64_t cursorid) /* {{{ */
+{
+ php_phongo_cursorid_t* intern;
+
+ object_init_ex(object, php_phongo_cursorid_ce);
+
+ intern = Z_CURSORID_OBJ_P(object);
+ intern->id = cursorid;
+ intern->initialized = true;
+} /* }}} */
+
+/* {{{ proto array MongoDB\Driver\Cursor::toArray()
+ Returns an array of all result documents for this cursor */
+static PHP_METHOD(Cursor, toArray)
+{
+ zend_error_handling error_handling;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ array_init(return_value);
+
+ if (spl_iterator_apply(getThis(), php_phongo_cursor_to_array_apply, (void*) return_value) != SUCCESS) {
+ zval_dtor(return_value);
+ RETURN_NULL();
+ }
+} /* }}} */
+
+/* {{{ proto MongoDB\Driver\CursorId MongoDB\Driver\Cursor::getId()
+ Returns the CursorId for this cursor */
+static PHP_METHOD(Cursor, getId)
+{
+ zend_error_handling error_handling;
+ php_phongo_cursor_t* intern;
+
+ intern = Z_CURSOR_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ php_phongo_cursor_id_new_from_id(return_value, mongoc_cursor_get_id(intern->cursor));
+} /* }}} */
+
+/* {{{ proto MongoDB\Driver\Server MongoDB\Driver\Cursor::getServer()
+ Returns the Server object to which this cursor is attached */
+static PHP_METHOD(Cursor, getServer)
+{
+ zend_error_handling error_handling;
+ php_phongo_cursor_t* intern;
+
+ intern = Z_CURSOR_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ phongo_server_init(return_value, &intern->manager, intern->server_id);
+} /* }}} */
+
+/* {{{ proto boolean MongoDB\Driver\Cursor::isDead()
+ Checks if a cursor is still alive */
+static PHP_METHOD(Cursor, isDead)
+{
+ zend_error_handling error_handling;
+ php_phongo_cursor_t* intern;
+
+ intern = Z_CURSOR_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ RETURN_BOOL(!mongoc_cursor_more(intern->cursor));
+} /* }}} */
+
+PHP_METHOD(Cursor, current)
+{
+ zend_error_handling error_handling;
+ php_phongo_cursor_t* intern = Z_CURSOR_OBJ_P(getThis());
+ zval* data;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ data = &intern->visitor_data.zchild;
+
+ if (Z_ISUNDEF_P(data)) {
+ RETURN_NULL();
+ } else {
+ ZVAL_COPY_DEREF(return_value, data);
+ }
+}
+
+PHP_METHOD(Cursor, key)
+{
+ zend_error_handling error_handling;
+ php_phongo_cursor_t* intern = Z_CURSOR_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ if (Z_ISUNDEF(intern->visitor_data.zchild)) {
+ RETURN_NULL();
+ }
+
+ RETURN_LONG(intern->current);
+}
+
+PHP_METHOD(Cursor, next)
+{
+ zend_error_handling error_handling;
+ php_phongo_cursor_t* intern = Z_CURSOR_OBJ_P(getThis());
+ const bson_t* doc;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ php_phongo_cursor_free_current(intern);
+
+ /* If the intern has already advanced, increment its position. Otherwise,
+ * the first call to mongoc_cursor_next() will be made below and we should
+ * leave its position at zero. */
+ if (intern->advanced) {
+ intern->current++;
+ } else {
+ intern->advanced = true;
+ }
+
+ if (mongoc_cursor_next(intern->cursor, &doc)) {
+ if (!php_phongo_bson_to_zval_ex(bson_get_data(doc), doc->len, &intern->visitor_data)) {
+ /* Free invalid result, but don't return as we want to free the
+ * session if the intern is exhausted. */
+ php_phongo_cursor_free_current(intern);
+ }
+ } else {
+ bson_error_t error = { 0 };
+ const bson_t* doc = NULL;
+
+ if (mongoc_cursor_error_document(intern->cursor, &error, &doc)) {
+ /* Intentionally not destroying the intern as it will happen
+ * naturally now that there are no more results */
+ phongo_throw_exception_from_bson_error_t_and_reply(&error, doc);
+ }
+ }
+
+ php_phongo_cursor_free_session_if_exhausted(intern);
+}
+
+PHP_METHOD(Cursor, valid)
+{
+ zend_error_handling error_handling;
+ php_phongo_cursor_t* intern = Z_CURSOR_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ RETURN_BOOL(!Z_ISUNDEF(intern->visitor_data.zchild));
+}
+
+PHP_METHOD(Cursor, rewind)
+{
+ zend_error_handling error_handling;
+ php_phongo_cursor_t* intern = Z_CURSOR_OBJ_P(getThis());
+ const bson_t* doc;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ /* If the intern was never advanced (e.g. command intern), do so now */
+ if (!intern->advanced) {
+ intern->advanced = true;
+
+ if (!phongo_cursor_advance_and_check_for_error(intern->cursor)) {
+ /* Exception should already have been thrown */
+ return;
+ }
+ }
+
+ if (intern->current > 0) {
+ phongo_throw_exception(PHONGO_ERROR_LOGIC, "Cursors cannot rewind after starting iteration");
+ return;
+ }
+
+ php_phongo_cursor_free_current(intern);
+
+ doc = mongoc_cursor_current(intern->cursor);
+
+ if (doc) {
+ if (!php_phongo_bson_to_zval_ex(bson_get_data(doc), doc->len, &intern->visitor_data)) {
+ /* Free invalid result, but don't return as we want to free the
+ * session if the intern is exhausted. */
+ php_phongo_cursor_free_current(intern);
+ }
+ }
+
+ php_phongo_cursor_free_session_if_exhausted(intern);
+}
+
+/* {{{ MongoDB\Driver\Cursor function entries */
+/* clang-format off */
+ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(ai_Cursor_current, 0, 0, IS_MIXED, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(ai_Cursor_key, 0, 0, IS_MIXED, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(ai_Cursor_next, 0, 0, IS_VOID, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(ai_Cursor_valid, 0, 0, _IS_BOOL, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(ai_Cursor_rewind, 0, 0, IS_VOID, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_Cursor_setTypeMap, 0, 0, 1)
+ ZEND_ARG_ARRAY_INFO(0, typemap, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_Cursor_void, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry php_phongo_cursor_me[] = {
+ PHP_ME(Cursor, setTypeMap, ai_Cursor_setTypeMap, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Cursor, toArray, ai_Cursor_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Cursor, getId, ai_Cursor_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Cursor, getServer, ai_Cursor_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Cursor, isDead, ai_Cursor_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+
+ PHP_ME(Cursor, current, ai_Cursor_current, ZEND_ACC_PUBLIC)
+ PHP_ME(Cursor, key, ai_Cursor_key, ZEND_ACC_PUBLIC)
+ PHP_ME(Cursor, next, ai_Cursor_next, ZEND_ACC_PUBLIC)
+ PHP_ME(Cursor, valid, ai_Cursor_valid, ZEND_ACC_PUBLIC)
+ PHP_ME(Cursor, rewind, ai_Cursor_rewind, ZEND_ACC_PUBLIC)
+
+ ZEND_NAMED_ME(__construct, PHP_FN(MongoDB_disabled___construct), ai_Cursor_void, ZEND_ACC_PRIVATE | ZEND_ACC_FINAL)
+ ZEND_NAMED_ME(__wakeup, PHP_FN(MongoDB_disabled___wakeup), ai_Cursor_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_FE_END
+};
+/* clang-format on */
+/* }}} */
+
+/* {{{ MongoDB\Driver\Cursor object handlers */
+static zend_object_handlers php_phongo_handler_cursor;
+
+static void php_phongo_cursor_free_object(zend_object* object) /* {{{ */
+{
+ php_phongo_cursor_t* intern = Z_OBJ_CURSOR(object);
+
+ zend_object_std_dtor(&intern->std);
+
+ /* If this Cursor was created in a different process, reset the client so
+ * that mongoc_cursor_destroy does not issue a killCursors command for an
+ * active cursor owned by a parent process. */
+ PHONGO_RESET_CLIENT_IF_PID_DIFFERS(intern, Z_MANAGER_OBJ_P(&intern->manager));
+
+ if (intern->cursor) {
+ mongoc_cursor_destroy(intern->cursor);
+ }
+
+ if (intern->database) {
+ efree(intern->database);
+ }
+
+ if (intern->collection) {
+ efree(intern->collection);
+ }
+
+ if (!Z_ISUNDEF(intern->query)) {
+ zval_ptr_dtor(&intern->query);
+ }
+
+ if (!Z_ISUNDEF(intern->command)) {
+ zval_ptr_dtor(&intern->command);
+ }
+
+ if (!Z_ISUNDEF(intern->read_preference)) {
+ zval_ptr_dtor(&intern->read_preference);
+ }
+
+ if (!Z_ISUNDEF(intern->session)) {
+ zval_ptr_dtor(&intern->session);
+ }
+
+ if (!Z_ISUNDEF(intern->manager)) {
+ zval_ptr_dtor(&intern->manager);
+ }
+
+ php_phongo_bson_typemap_dtor(&intern->visitor_data.map);
+
+ php_phongo_cursor_free_current(intern);
+} /* }}} */
+
+static zend_object* php_phongo_cursor_create_object(zend_class_entry* class_type) /* {{{ */
+{
+ php_phongo_cursor_t* intern = zend_object_alloc(sizeof(php_phongo_cursor_t), class_type);
+
+ zend_object_std_init(&intern->std, class_type);
+ object_properties_init(&intern->std, class_type);
+
+ PHONGO_SET_CREATED_BY_PID(intern);
+
+ intern->std.handlers = &php_phongo_handler_cursor;
+
+ return &intern->std;
+} /* }}} */
+
+static HashTable* php_phongo_cursor_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
+{
+ php_phongo_cursor_t* intern;
+ zval retval = ZVAL_STATIC_INIT;
+
+ *is_temp = 1;
+ intern = Z_OBJ_CURSOR(PHONGO_COMPAT_GET_OBJ(object));
+
+ array_init_size(&retval, 10);
+
+ if (intern->database) {
+ ADD_ASSOC_STRING(&retval, "database", intern->database);
+ } else {
+ ADD_ASSOC_NULL_EX(&retval, "database");
+ }
+
+ if (intern->collection) {
+ ADD_ASSOC_STRING(&retval, "collection", intern->collection);
+ } else {
+ ADD_ASSOC_NULL_EX(&retval, "collection");
+ }
+
+ if (!Z_ISUNDEF(intern->query)) {
+ ADD_ASSOC_ZVAL_EX(&retval, "query", &intern->query);
+ Z_ADDREF(intern->query);
+ } else {
+ ADD_ASSOC_NULL_EX(&retval, "query");
+ }
+
+ if (!Z_ISUNDEF(intern->command)) {
+ ADD_ASSOC_ZVAL_EX(&retval, "command", &intern->command);
+ Z_ADDREF(intern->command);
+ } else {
+ ADD_ASSOC_NULL_EX(&retval, "command");
+ }
+
+ if (!Z_ISUNDEF(intern->read_preference)) {
+ ADD_ASSOC_ZVAL_EX(&retval, "readPreference", &intern->read_preference);
+ Z_ADDREF(intern->read_preference);
+ } else {
+ ADD_ASSOC_NULL_EX(&retval, "readPreference");
+ }
+
+ if (!Z_ISUNDEF(intern->session)) {
+ ADD_ASSOC_ZVAL_EX(&retval, "session", &intern->session);
+ Z_ADDREF(intern->session);
+ } else {
+ ADD_ASSOC_NULL_EX(&retval, "session");
+ }
+
+ ADD_ASSOC_BOOL_EX(&retval, "isDead", !mongoc_cursor_more(intern->cursor));
+
+ ADD_ASSOC_LONG_EX(&retval, "currentIndex", intern->current);
+
+ if (!Z_ISUNDEF(intern->visitor_data.zchild)) {
+ ADD_ASSOC_ZVAL_EX(&retval, "currentDocument", &intern->visitor_data.zchild);
+ Z_ADDREF(intern->visitor_data.zchild);
+ } else {
+ ADD_ASSOC_NULL_EX(&retval, "currentDocument");
+ }
+
+ {
+ zval server;
+
+ phongo_server_init(&server, &intern->manager, intern->server_id);
+ ADD_ASSOC_ZVAL_EX(&retval, "server", &server);
+ }
+
+ return Z_ARRVAL(retval);
+
+} /* }}} */
+/* }}} */
+
+void php_phongo_cursor_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver", "Cursor", php_phongo_cursor_me);
+ php_phongo_cursor_ce = zend_register_internal_class(&ce);
+ php_phongo_cursor_ce->create_object = php_phongo_cursor_create_object;
+ PHONGO_CE_FINAL(php_phongo_cursor_ce);
+ PHONGO_CE_DISABLE_SERIALIZATION(php_phongo_cursor_ce);
+
+ zend_class_implements(php_phongo_cursor_ce, 1, zend_ce_iterator);
+ zend_class_implements(php_phongo_cursor_ce, 1, php_phongo_cursor_interface_ce);
+
+ memcpy(&php_phongo_handler_cursor, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
+ php_phongo_handler_cursor.get_debug_info = php_phongo_cursor_get_debug_info;
+ php_phongo_handler_cursor.free_obj = php_phongo_cursor_free_object;
+ php_phongo_handler_cursor.offset = XtOffsetOf(php_phongo_cursor_t, std);
+} /* }}} */
+
+/* Advance the cursor and return whether there is an error. On error, false is
+ * returned and an exception is thrown. */
+bool phongo_cursor_advance_and_check_for_error(mongoc_cursor_t* cursor) /* {{{ */
+{
+ const bson_t* doc = NULL;
+
+ if (!mongoc_cursor_next(cursor, &doc)) {
+ bson_error_t error = { 0 };
+
+ /* Check for connection related exceptions */
+ if (EG(exception)) {
+ return false;
+ }
+
+ /* Could simply be no docs, which is not an error */
+ if (mongoc_cursor_error_document(cursor, &error, &doc)) {
+ phongo_throw_exception_from_bson_error_t_and_reply(&error, doc);
+ return false;
+ }
+ }
+
+ return true;
+} /* }}} */
diff --git a/mongodb-1.13.0/src/MongoDB/Cursor.h b/mongodb-1.13.0/src/MongoDB/Cursor.h
new file mode 100644
index 00000000..5a7db233
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/Cursor.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2022-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PHONGO_CURSOR_H
+#define PHONGO_CURSOR_H
+
+#include "mongoc/mongoc.h"
+
+bool phongo_cursor_advance_and_check_for_error(mongoc_cursor_t* cursor);
+
+#endif /* PHONGO_CURSOR_H */
diff --git a/mongodb-1.13.0/src/MongoDB/CursorId.c b/mongodb-1.13.0/src/MongoDB/CursorId.c
new file mode 100644
index 00000000..7acc96d7
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/CursorId.c
@@ -0,0 +1,321 @@
+/*
+ * Copyright 2014-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <php.h>
+#include <zend_smart_str.h>
+#include <ext/standard/php_var.h>
+#include <Zend/zend_interfaces.h>
+
+#include "php_phongo.h"
+#include "phongo_error.h"
+#include "phongo_util.h"
+
+zend_class_entry* php_phongo_cursorid_ce;
+
+/* Initialize the object from a numeric string and return whether it was
+ * successful. An exception will be thrown on error. */
+static bool php_phongo_cursorid_init_from_string(php_phongo_cursorid_t* intern, const char* s_id, size_t s_id_len) /* {{{ */
+{
+ int64_t id;
+
+ if (!php_phongo_parse_int64(&id, s_id, s_id_len)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Error parsing \"%s\" as 64-bit id for %s initialization", s_id, ZSTR_VAL(php_phongo_cursorid_ce->name));
+ return false;
+ }
+
+ intern->id = id;
+ intern->initialized = true;
+ return true;
+} /* }}} */
+
+/* Initialize the object from a HashTable and return whether it was successful.
+ * An exception will be thrown on error. */
+static bool php_phongo_cursorid_init_from_hash(php_phongo_cursorid_t* intern, HashTable* props) /* {{{ */
+{
+ zval* value;
+
+ if ((value = zend_hash_str_find(props, "id", sizeof("id") - 1)) && Z_TYPE_P(value) == IS_STRING) {
+ return php_phongo_cursorid_init_from_string(intern, Z_STRVAL_P(value), Z_STRLEN_P(value));
+ }
+
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"id\" string field", ZSTR_VAL(php_phongo_cursorid_ce->name));
+ return false;
+} /* }}} */
+
+static HashTable* php_phongo_cursorid_get_properties_hash(phongo_compat_object_handler_type* object, bool is_temp, bool is_serialize) /* {{{ */
+{
+ php_phongo_cursorid_t* intern;
+ HashTable* props;
+
+ intern = Z_OBJ_CURSORID(PHONGO_COMPAT_GET_OBJ(object));
+
+ PHONGO_GET_PROPERTY_HASH_INIT_PROPS(is_temp, intern, props, 1);
+
+ if (!intern->initialized) {
+ return props;
+ }
+
+ {
+ zval value;
+
+ if (is_serialize) {
+ ZVAL_INT64_STRING(&value, intern->id);
+ } else {
+#if SIZEOF_ZEND_LONG == 4
+ if (intern->id > INT32_MAX || intern->id < INT32_MIN) {
+ ZVAL_INT64_STRING(&value, intern->id);
+ } else {
+ ZVAL_LONG(&value, intern->id);
+ }
+#else
+ ZVAL_LONG(&value, intern->id);
+#endif
+ }
+ zend_hash_str_update(props, "id", sizeof("id") - 1, &value);
+ }
+
+ return props;
+} /* }}} */
+
+/* {{{ proto MongoDB\Driver\CursorId MongoDB\Driver\CursorId::__set_state(array $properties)
+*/
+static PHP_METHOD(CursorId, __set_state)
+{
+ zend_error_handling error_handling;
+ php_phongo_cursorid_t* intern;
+ HashTable* props;
+ zval* array;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &array) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ object_init_ex(return_value, php_phongo_cursorid_ce);
+
+ intern = Z_CURSORID_OBJ_P(return_value);
+ props = Z_ARRVAL_P(array);
+
+ php_phongo_cursorid_init_from_hash(intern, props);
+} /* }}} */
+
+/* {{{ proto string MongoDB\Driver\CursorId::__toString()
+ Returns the string representation of the CursorId */
+static PHP_METHOD(CursorId, __toString)
+{
+ zend_error_handling error_handling;
+ php_phongo_cursorid_t* intern;
+ char* tmp;
+ int tmp_len;
+
+ intern = Z_CURSORID_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ tmp_len = spprintf(&tmp, 0, "%" PRId64, intern->id);
+ RETVAL_STRINGL(tmp, tmp_len);
+ efree(tmp);
+} /* }}} */
+
+/* {{{ proto string MongoDB\Driver\CursorId::serialize()
+*/
+static PHP_METHOD(CursorId, serialize)
+{
+ zend_error_handling error_handling;
+ php_phongo_cursorid_t* intern;
+ zval retval;
+ php_serialize_data_t var_hash;
+ smart_str buf = { 0 };
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ intern = Z_CURSORID_OBJ_P(getThis());
+
+ array_init_size(&retval, 1);
+ ADD_ASSOC_INT64_AS_STRING(&retval, "id", intern->id);
+
+ PHP_VAR_SERIALIZE_INIT(var_hash);
+ php_var_serialize(&buf, &retval, &var_hash);
+ smart_str_0(&buf);
+ PHP_VAR_SERIALIZE_DESTROY(var_hash);
+
+ PHONGO_RETVAL_SMART_STR(buf);
+
+ smart_str_free(&buf);
+ zval_ptr_dtor(&retval);
+} /* }}} */
+
+/* {{{ proto void MongoDB\Driver\CursorId::unserialize(string $serialized)
+*/
+static PHP_METHOD(CursorId, unserialize)
+{
+ zend_error_handling error_handling;
+ php_phongo_cursorid_t* intern;
+ char* serialized;
+ size_t serialized_len;
+ zval props;
+ php_unserialize_data_t var_hash;
+
+ intern = Z_CURSORID_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &serialized, &serialized_len) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ PHP_VAR_UNSERIALIZE_INIT(var_hash);
+ if (!php_var_unserialize(&props, (const unsigned char**) &serialized, (unsigned char*) serialized + serialized_len, &var_hash)) {
+ zval_ptr_dtor(&props);
+ phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "%s unserialization failed", ZSTR_VAL(php_phongo_cursorid_ce->name));
+
+ PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+ return;
+ }
+ PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+
+ php_phongo_cursorid_init_from_hash(intern, HASH_OF(&props));
+ zval_ptr_dtor(&props);
+} /* }}} */
+
+/* {{{ proto array MongoDB\Driver\CursorId::__serialize()
+*/
+static PHP_METHOD(CursorId, __serialize)
+{
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ RETURN_ARR(php_phongo_cursorid_get_properties_hash(PHONGO_COMPAT_OBJ_P(getThis()), true, true));
+} /* }}} */
+
+/* {{{ proto void MongoDB\Driver\CursorId::__unserialize(array $data)
+*/
+static PHP_METHOD(CursorId, __unserialize)
+{
+ zval* data;
+
+ PHONGO_PARSE_PARAMETERS_START(1, 1)
+ Z_PARAM_ARRAY(data)
+ PHONGO_PARSE_PARAMETERS_END();
+
+ php_phongo_cursorid_init_from_hash(Z_CURSORID_OBJ_P(getThis()), Z_ARRVAL_P(data));
+} /* }}} */
+
+/* {{{ MongoDB\Driver\CursorId function entries */
+/* clang-format off */
+ZEND_BEGIN_ARG_INFO_EX(ai_CursorId___set_state, 0, 0, 1)
+ ZEND_ARG_ARRAY_INFO(0, properties, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(ai_CursorId___toString, 0, 0, IS_STRING, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_CursorId___unserialize, 0, 0, 1)
+ ZEND_ARG_ARRAY_INFO(0, data, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_CursorId_unserialize, 0, 0, 1)
+ ZEND_ARG_INFO(0, serialized)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_CursorId_void, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry php_phongo_cursorid_me[] = {
+ PHP_ME(CursorId, __serialize, ai_CursorId_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(CursorId, __set_state, ai_CursorId___set_state, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+ PHP_ME(CursorId, __toString, ai_CursorId___toString, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(CursorId, __unserialize, ai_CursorId___unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(CursorId, serialize, ai_CursorId_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(CursorId, unserialize, ai_CursorId_unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ ZEND_NAMED_ME(__construct, PHP_FN(MongoDB_disabled___construct), ai_CursorId_void, ZEND_ACC_PRIVATE | ZEND_ACC_FINAL)
+ PHP_FE_END
+};
+/* clang-format on */
+/* }}} */
+
+/* {{{ MongoDB\Driver\CursorId object handlers */
+static zend_object_handlers php_phongo_handler_cursorid;
+
+static void php_phongo_cursorid_free_object(zend_object* object) /* {{{ */
+{
+ php_phongo_cursorid_t* intern = Z_OBJ_CURSORID(object);
+
+ zend_object_std_dtor(&intern->std);
+
+ if (intern->properties) {
+ zend_hash_destroy(intern->properties);
+ FREE_HASHTABLE(intern->properties);
+ }
+} /* }}} */
+
+static zend_object* php_phongo_cursorid_create_object(zend_class_entry* class_type) /* {{{ */
+{
+ php_phongo_cursorid_t* intern = zend_object_alloc(sizeof(php_phongo_cursorid_t), class_type);
+
+ zend_object_std_init(&intern->std, class_type);
+ object_properties_init(&intern->std, class_type);
+
+ intern->std.handlers = &php_phongo_handler_cursorid;
+
+ return &intern->std;
+} /* }}} */
+
+static HashTable* php_phongo_cursorid_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
+{
+ *is_temp = 1;
+ return php_phongo_cursorid_get_properties_hash(object, true, false);
+} /* }}} */
+/* }}} */
+
+static HashTable* php_phongo_cursorid_get_properties(phongo_compat_object_handler_type* object) /* {{{ */
+{
+ return php_phongo_cursorid_get_properties_hash(object, false, false);
+} /* }}} */
+
+void php_phongo_cursorid_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver", "CursorId", php_phongo_cursorid_me);
+ php_phongo_cursorid_ce = zend_register_internal_class(&ce);
+ php_phongo_cursorid_ce->create_object = php_phongo_cursorid_create_object;
+ PHONGO_CE_FINAL(php_phongo_cursorid_ce);
+
+ zend_class_implements(php_phongo_cursorid_ce, 1, zend_ce_serializable);
+
+#if PHP_VERSION_ID >= 80000
+ zend_class_implements(php_phongo_cursorid_ce, 1, zend_ce_stringable);
+#endif
+
+ memcpy(&php_phongo_handler_cursorid, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
+ php_phongo_handler_cursorid.get_debug_info = php_phongo_cursorid_get_debug_info;
+ php_phongo_handler_cursorid.get_properties = php_phongo_cursorid_get_properties;
+ php_phongo_handler_cursorid.free_obj = php_phongo_cursorid_free_object;
+ php_phongo_handler_cursorid.offset = XtOffsetOf(php_phongo_cursorid_t, std);
+} /* }}} */
diff --git a/mongodb-1.13.0/src/MongoDB/CursorInterface.c b/mongodb-1.13.0/src/MongoDB/CursorInterface.c
new file mode 100644
index 00000000..23797ae5
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/CursorInterface.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2018-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <php.h>
+#include <Zend/zend_interfaces.h>
+
+#include "php_phongo.h"
+
+zend_class_entry* php_phongo_cursor_interface_ce;
+
+/* {{{ MongoDB\BSON\CursorInterface function entries */
+ZEND_BEGIN_ARG_INFO_EX(ai_CursorInterface_setTypeMap, 0, 0, 1)
+ ZEND_ARG_ARRAY_INFO(0, typemap, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_CursorInterface_void, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry php_phongo_cursor_interface_me[] = {
+ /* clang-format off */
+ ZEND_ABSTRACT_ME(CursorInterface, getId, ai_CursorInterface_void)
+ ZEND_ABSTRACT_ME(CursorInterface, getServer, ai_CursorInterface_void)
+ ZEND_ABSTRACT_ME(CursorInterface, isDead, ai_CursorInterface_void)
+ ZEND_ABSTRACT_ME(CursorInterface, setTypeMap, ai_CursorInterface_setTypeMap)
+ ZEND_ABSTRACT_ME(CursorInterface, toArray, ai_CursorInterface_void)
+ PHP_FE_END
+ /* clang-format on */
+};
+/* }}} */
+
+void php_phongo_cursor_interface_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver", "CursorInterface", php_phongo_cursor_interface_me);
+ php_phongo_cursor_interface_ce = zend_register_internal_interface(&ce);
+
+ zend_class_implements(php_phongo_cursor_interface_ce, 1, zend_ce_traversable);
+} /* }}} */
diff --git a/mongodb-1.13.0/src/MongoDB/Exception/AuthenticationException.c b/mongodb-1.13.0/src/MongoDB/Exception/AuthenticationException.c
new file mode 100644
index 00000000..c118a117
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/Exception/AuthenticationException.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2014-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <php.h>
+
+#include "php_phongo.h"
+
+zend_class_entry* php_phongo_authenticationexception_ce;
+
+/* {{{ MongoDB\Driver\Exception\AuthenticationException function entries */
+static zend_function_entry php_phongo_authenticationexception_me[] = {
+ PHP_FE_END
+};
+/* }}} */
+
+void php_phongo_authenticationexception_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver\\Exception", "AuthenticationException", php_phongo_authenticationexception_me);
+ php_phongo_authenticationexception_ce = zend_register_internal_class_ex(&ce, php_phongo_connectionexception_ce);
+} /* }}} */
diff --git a/mongodb-1.13.0/src/MongoDB/Exception/BulkWriteException.c b/mongodb-1.13.0/src/MongoDB/Exception/BulkWriteException.c
new file mode 100644
index 00000000..3549f368
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/Exception/BulkWriteException.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2015-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <php.h>
+
+#include "php_phongo.h"
+
+zend_class_entry* php_phongo_bulkwriteexception_ce;
+
+/* {{{ MongoDB\Driver\Exception\BulkWriteException function entries */
+static zend_function_entry php_phongo_bulkwriteexception_me[] = {
+ PHP_FE_END
+};
+/* }}} */
+
+void php_phongo_bulkwriteexception_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver\\Exception", "BulkWriteException", php_phongo_bulkwriteexception_me);
+ php_phongo_bulkwriteexception_ce = zend_register_internal_class_ex(&ce, php_phongo_writeexception_ce);
+} /* }}} */
diff --git a/mongodb-1.13.0/src/MongoDB/Exception/CommandException.c b/mongodb-1.13.0/src/MongoDB/Exception/CommandException.c
new file mode 100644
index 00000000..a2dae4bc
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/Exception/CommandException.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2018-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <php.h>
+
+#include "php_phongo.h"
+#include "phongo_error.h"
+
+zend_class_entry* php_phongo_commandexception_ce;
+
+/* {{{ proto document MongoDB\Driver\Exception\CommandException::getResultDocument()
+ Returns the result document from the failed command. */
+static PHP_METHOD(CommandException, getResultDocument)
+{
+ zend_error_handling error_handling;
+ zval* resultdocument;
+ zval rv;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ resultdocument = zend_read_property(php_phongo_commandexception_ce, PHONGO_COMPAT_OBJ_P(getThis()), ZEND_STRL("resultDocument"), 0, &rv);
+
+ RETURN_ZVAL(resultdocument, 1, 0);
+} /* }}} */
+
+/* {{{ MongoDB\Driver\Exception\CommandException function entries */
+ZEND_BEGIN_ARG_INFO_EX(ai_CommandException_void, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry php_phongo_commandexception_me[] = {
+ /* clang-format off */
+ PHP_ME(CommandException, getResultDocument, ai_CommandException_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_FE_END
+ /* clang-format on */
+};
+/* }}} */
+
+void php_phongo_commandexception_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver\\Exception", "CommandException", php_phongo_commandexception_me);
+ php_phongo_commandexception_ce = zend_register_internal_class_ex(&ce, php_phongo_serverexception_ce);
+
+ zend_declare_property_null(php_phongo_commandexception_ce, ZEND_STRL("resultDocument"), ZEND_ACC_PROTECTED);
+} /* }}} */
diff --git a/mongodb-1.13.0/src/MongoDB/Exception/ConnectionException.c b/mongodb-1.13.0/src/MongoDB/Exception/ConnectionException.c
new file mode 100644
index 00000000..2650a9ae
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/Exception/ConnectionException.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2014-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <php.h>
+
+#include "php_phongo.h"
+
+zend_class_entry* php_phongo_connectionexception_ce;
+
+/* {{{ MongoDB\Driver\Exception\ConnectionException function entries */
+static zend_function_entry php_phongo_connectionexception_me[] = {
+ PHP_FE_END
+};
+/* }}} */
+
+void php_phongo_connectionexception_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver\\Exception", "ConnectionException", php_phongo_connectionexception_me);
+ php_phongo_connectionexception_ce = zend_register_internal_class_ex(&ce, php_phongo_runtimeexception_ce);
+} /* }}} */
diff --git a/mongodb-1.13.0/src/MongoDB/Exception/ConnectionTimeoutException.c b/mongodb-1.13.0/src/MongoDB/Exception/ConnectionTimeoutException.c
new file mode 100644
index 00000000..32bfebbb
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/Exception/ConnectionTimeoutException.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2015-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <php.h>
+
+#include "php_phongo.h"
+
+zend_class_entry* php_phongo_connectiontimeoutexception_ce;
+
+/* {{{ MongoDB\Driver\Exception\ConnectionTimeoutException function entries */
+static zend_function_entry php_phongo_connectiontimeoutexception_me[] = {
+ PHP_FE_END
+};
+/* }}} */
+
+void php_phongo_connectiontimeoutexception_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver\\Exception", "ConnectionTimeoutException", php_phongo_connectiontimeoutexception_me);
+ php_phongo_connectiontimeoutexception_ce = zend_register_internal_class_ex(&ce, php_phongo_connectionexception_ce);
+ PHONGO_CE_FINAL(php_phongo_connectiontimeoutexception_ce);
+} /* }}} */
diff --git a/mongodb-1.13.0/src/MongoDB/Exception/EncryptionException.c b/mongodb-1.13.0/src/MongoDB/Exception/EncryptionException.c
new file mode 100644
index 00000000..9016225e
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/Exception/EncryptionException.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2014-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <php.h>
+
+#include "php_phongo.h"
+
+zend_class_entry* php_phongo_encryptionexception_ce;
+
+/* {{{ MongoDB\Driver\Exception\EncryptionException function entries */
+static zend_function_entry php_phongo_encryptionexception_me[] = {
+ PHP_FE_END
+};
+/* }}} */
+
+void php_phongo_encryptionexception_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver\\Exception", "EncryptionException", php_phongo_encryptionexception_me);
+ php_phongo_encryptionexception_ce = zend_register_internal_class_ex(&ce, php_phongo_runtimeexception_ce);
+} /* }}} */
diff --git a/mongodb-1.13.0/src/MongoDB/Exception/Exception.c b/mongodb-1.13.0/src/MongoDB/Exception/Exception.c
new file mode 100644
index 00000000..3a3705a8
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/Exception/Exception.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2014-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <php.h>
+#include <zend_exceptions.h>
+
+#include "php_phongo.h"
+
+zend_class_entry* php_phongo_exception_ce;
+
+/* {{{ MongoDB\Driver\Exception\Exception function entries */
+static zend_function_entry php_phongo_exception_me[] = {
+ PHP_FE_END
+};
+/* }}} */
+
+void php_phongo_exception_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver\\Exception", "Exception", php_phongo_exception_me);
+ php_phongo_exception_ce = zend_register_internal_interface(&ce);
+ zend_class_implements(php_phongo_exception_ce, 1, zend_ce_throwable);
+} /* }}} */
diff --git a/mongodb-1.13.0/src/MongoDB/Exception/ExecutionTimeoutException.c b/mongodb-1.13.0/src/MongoDB/Exception/ExecutionTimeoutException.c
new file mode 100644
index 00000000..dd4d16ef
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/Exception/ExecutionTimeoutException.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2015-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <php.h>
+
+#include "php_phongo.h"
+
+zend_class_entry* php_phongo_executiontimeoutexception_ce;
+
+/* {{{ MongoDB\Driver\Exception\ExecutionTimeoutException function entries */
+static zend_function_entry php_phongo_executiontimeoutexception_me[] = {
+ PHP_FE_END
+};
+/* }}} */
+
+void php_phongo_executiontimeoutexception_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver\\Exception", "ExecutionTimeoutException", php_phongo_executiontimeoutexception_me);
+ php_phongo_executiontimeoutexception_ce = zend_register_internal_class_ex(&ce, php_phongo_serverexception_ce);
+ PHONGO_CE_FINAL(php_phongo_executiontimeoutexception_ce);
+} /* }}} */
diff --git a/mongodb-1.13.0/src/MongoDB/Exception/InvalidArgumentException.c b/mongodb-1.13.0/src/MongoDB/Exception/InvalidArgumentException.c
new file mode 100644
index 00000000..515e3062
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/Exception/InvalidArgumentException.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2015-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <php.h>
+#include <ext/spl/spl_exceptions.h>
+
+#include "php_phongo.h"
+
+zend_class_entry* php_phongo_invalidargumentexception_ce;
+
+/* {{{ MongoDB\Driver\Exception\InvalidArgumentException function entries */
+static zend_function_entry php_phongo_invalidargumentexception_me[] = {
+ PHP_FE_END
+};
+/* }}} */
+
+void php_phongo_invalidargumentexception_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver\\Exception", "InvalidArgumentException", php_phongo_invalidargumentexception_me);
+ php_phongo_invalidargumentexception_ce = zend_register_internal_class_ex(&ce, spl_ce_InvalidArgumentException);
+ zend_class_implements(php_phongo_invalidargumentexception_ce, 1, php_phongo_exception_ce);
+} /* }}} */
diff --git a/mongodb-1.13.0/src/MongoDB/Exception/LogicException.c b/mongodb-1.13.0/src/MongoDB/Exception/LogicException.c
new file mode 100644
index 00000000..5970953f
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/Exception/LogicException.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2015-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <php.h>
+#include <ext/spl/spl_exceptions.h>
+
+#include "php_phongo.h"
+
+zend_class_entry* php_phongo_logicexception_ce;
+
+/* {{{ MongoDB\Driver\Exception\LogicException function entries */
+static zend_function_entry php_phongo_logicexception_me[] = {
+ PHP_FE_END
+};
+/* }}} */
+
+void php_phongo_logicexception_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver\\Exception", "LogicException", php_phongo_logicexception_me);
+ php_phongo_logicexception_ce = zend_register_internal_class_ex(&ce, spl_ce_LogicException);
+ zend_class_implements(php_phongo_logicexception_ce, 1, php_phongo_exception_ce);
+} /* }}} */
diff --git a/mongodb-1.13.0/src/MongoDB/Exception/RuntimeException.c b/mongodb-1.13.0/src/MongoDB/Exception/RuntimeException.c
new file mode 100644
index 00000000..e06e70c5
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/Exception/RuntimeException.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2015-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <php.h>
+#include <ext/spl/spl_exceptions.h>
+
+#include "php_array_api.h"
+
+#include "php_phongo.h"
+#include "phongo_error.h"
+
+zend_class_entry* php_phongo_runtimeexception_ce;
+
+static bool php_phongo_has_string_array_element(zval* labels, char* label)
+{
+ HashTable* ht_data;
+
+ if (Z_TYPE_P(labels) != IS_ARRAY) {
+ return false;
+ }
+
+ ht_data = HASH_OF(labels);
+
+ {
+ zval* z_label;
+
+ ZEND_HASH_FOREACH_VAL_IND(ht_data, z_label)
+ {
+ if ((Z_TYPE_P(z_label) == IS_STRING) && (strcmp(Z_STRVAL_P(z_label), label) == 0)) {
+ return true;
+ }
+ }
+ ZEND_HASH_FOREACH_END();
+ }
+
+ return false;
+}
+
+/* {{{ proto bool MongoDB\Driver\Exception\RuntimeException::hasErrorLabel(string $label)
+ Returns whether a specific error label has been set */
+static PHP_METHOD(RuntimeException, hasErrorLabel)
+{
+ zend_error_handling error_handling;
+ char* label;
+ size_t label_len;
+ zval* error_labels;
+ zval rv;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &label, &label_len) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ error_labels = zend_read_property(php_phongo_runtimeexception_ce, PHONGO_COMPAT_OBJ_P(getThis()), ZEND_STRL("errorLabels"), 0, &rv);
+
+ RETURN_BOOL(php_phongo_has_string_array_element(error_labels, label));
+} /* }}} */
+
+ZEND_BEGIN_ARG_INFO_EX(ai_RuntimeException_hasErrorLabel, 0, 0, 1)
+ ZEND_ARG_INFO(0, label)
+ZEND_END_ARG_INFO()
+
+/* {{{ MongoDB\Driver\Exception\RuntimeException function entries */
+static zend_function_entry php_phongo_runtimeexception_me[] = {
+ /* clang-format off */
+ PHP_ME(RuntimeException, hasErrorLabel, ai_RuntimeException_hasErrorLabel, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_FE_END
+ /* clang-format on */
+};
+/* }}} */
+
+void php_phongo_runtimeexception_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver\\Exception", "RuntimeException", php_phongo_runtimeexception_me);
+ php_phongo_runtimeexception_ce = zend_register_internal_class_ex(&ce, spl_ce_RuntimeException);
+ zend_class_implements(php_phongo_runtimeexception_ce, 1, php_phongo_exception_ce);
+
+ zend_declare_property_null(php_phongo_runtimeexception_ce, ZEND_STRL("errorLabels"), ZEND_ACC_PROTECTED);
+} /* }}} */
diff --git a/mongodb-1.13.0/src/MongoDB/Exception/SSLConnectionException.c b/mongodb-1.13.0/src/MongoDB/Exception/SSLConnectionException.c
new file mode 100644
index 00000000..31f98a3a
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/Exception/SSLConnectionException.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2014-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <php.h>
+
+#include "php_phongo.h"
+
+zend_class_entry* php_phongo_sslconnectionexception_ce;
+
+/* {{{ MongoDB\Driver\Exception\SSLConnectionException function entries */
+static zend_function_entry php_phongo_sslconnectionexception_me[] = {
+ PHP_FE_END
+};
+/* }}} */
+
+void php_phongo_sslconnectionexception_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver\\Exception", "SSLConnectionException", php_phongo_sslconnectionexception_me);
+ php_phongo_sslconnectionexception_ce = zend_register_internal_class_ex(&ce, php_phongo_connectionexception_ce);
+ PHONGO_CE_FINAL(php_phongo_sslconnectionexception_ce);
+} /* }}} */
diff --git a/mongodb-1.13.0/src/MongoDB/Exception/ServerException.c b/mongodb-1.13.0/src/MongoDB/Exception/ServerException.c
new file mode 100644
index 00000000..fdd5df60
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/Exception/ServerException.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2018-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <php.h>
+
+#include "php_phongo.h"
+
+zend_class_entry* php_phongo_serverexception_ce;
+
+/* {{{ MongoDB\Driver\Exception\ServerException function entries */
+static zend_function_entry php_phongo_serverexception_me[] = {
+ PHP_FE_END
+};
+/* }}} */
+
+void php_phongo_serverexception_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver\\Exception", "ServerException", php_phongo_serverexception_me);
+ php_phongo_serverexception_ce = zend_register_internal_class_ex(&ce, php_phongo_runtimeexception_ce);
+} /* }}} */
diff --git a/mongodb-1.13.0/src/MongoDB/Exception/UnexpectedValueException.c b/mongodb-1.13.0/src/MongoDB/Exception/UnexpectedValueException.c
new file mode 100644
index 00000000..b4e0f9f4
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/Exception/UnexpectedValueException.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2014-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <php.h>
+#include <ext/spl/spl_exceptions.h>
+
+#include "php_phongo.h"
+
+zend_class_entry* php_phongo_unexpectedvalueexception_ce;
+
+/* {{{ MongoDB\Driver\Exception\UnexpectedValueException function entries */
+static zend_function_entry php_phongo_unexpectedvalueexception_me[] = {
+ PHP_FE_END
+};
+/* }}} */
+
+void php_phongo_unexpectedvalueexception_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver\\Exception", "UnexpectedValueException", php_phongo_unexpectedvalueexception_me);
+ php_phongo_unexpectedvalueexception_ce = zend_register_internal_class_ex(&ce, spl_ce_UnexpectedValueException);
+ zend_class_implements(php_phongo_unexpectedvalueexception_ce, 1, php_phongo_exception_ce);
+} /* }}} */
diff --git a/mongodb-1.13.0/src/MongoDB/Exception/WriteException.c b/mongodb-1.13.0/src/MongoDB/Exception/WriteException.c
new file mode 100644
index 00000000..ecad4a32
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/Exception/WriteException.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2014-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <php.h>
+
+#include "php_phongo.h"
+#include "phongo_error.h"
+
+zend_class_entry* php_phongo_writeexception_ce;
+
+/* {{{ proto MongoDB\Driver\WriteResult MongoDB\Driver\Exception\WriteException::getWriteResult()
+ Returns the WriteResult from the failed write operation. */
+static PHP_METHOD(WriteException, getWriteResult)
+{
+ zend_error_handling error_handling;
+ zval* writeresult;
+ zval rv;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ writeresult = zend_read_property(php_phongo_writeexception_ce, PHONGO_COMPAT_OBJ_P(getThis()), ZEND_STRL("writeResult"), 0, &rv);
+
+ RETURN_ZVAL(writeresult, 1, 0);
+} /* }}} */
+
+/* {{{ MongoDB\Driver\Exception\WriteException function entries */
+ZEND_BEGIN_ARG_INFO_EX(ai_WriteException_void, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry php_phongo_writeexception_me[] = {
+ /* clang-format off */
+ PHP_ME(WriteException, getWriteResult, ai_WriteException_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_FE_END
+ /* clang-format on */
+};
+/* }}} */
+
+void php_phongo_writeexception_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver\\Exception", "WriteException", php_phongo_writeexception_me);
+ php_phongo_writeexception_ce = zend_register_internal_class_ex(&ce, php_phongo_serverexception_ce);
+ php_phongo_writeexception_ce->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;
+
+ zend_declare_property_null(php_phongo_writeexception_ce, ZEND_STRL("writeResult"), ZEND_ACC_PROTECTED);
+} /* }}} */
diff --git a/mongodb-1.13.0/src/MongoDB/Manager.c b/mongodb-1.13.0/src/MongoDB/Manager.c
new file mode 100644
index 00000000..5e85e043
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/Manager.c
@@ -0,0 +1,1022 @@
+/*
+ * Copyright 2014-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bson/bson.h"
+#include "mongoc/mongoc.h"
+
+#include <php.h>
+#include <ext/standard/file.h>
+#include <Zend/zend_interfaces.h>
+
+#include "php_array_api.h"
+
+#include "php_phongo.h"
+#include "phongo_apm.h"
+#include "phongo_client.h"
+#include "phongo_error.h"
+#include "phongo_execute.h"
+#include "phongo_util.h"
+
+#include "MongoDB/ClientEncryption.h"
+#include "MongoDB/ReadConcern.h"
+#include "MongoDB/ReadPreference.h"
+#include "MongoDB/Server.h"
+#include "MongoDB/Session.h"
+#include "MongoDB/WriteConcern.h"
+
+#define PHONGO_MANAGER_URI_DEFAULT "mongodb://127.0.0.1/"
+
+/**
+ * Manager abstracts a cluster of Server objects (i.e. socket connections).
+ *
+ * Typically, users will connect to a cluster using a URI, and the Manager will
+ * perform tasks such as replica set discovery and create the necessary Server
+ * objects. That said, it is also possible to create a Manager with an arbitrary
+ * collection of Server objects using the static factory method (this can be
+ * useful for testing or administration).
+ *
+ * Operation methods do not take socket-level options (e.g. socketTimeoutMS).
+ * Those options should be specified during construction.
+ */
+zend_class_entry* php_phongo_manager_ce;
+
+/* Checks if driverOptions contains a stream context resource in the "context"
+ * key and incorporates any of its SSL options into the base array that did not
+ * already exist (i.e. array union). The "context" key is then unset from the
+ * base array.
+ *
+ * This handles the merging of any legacy SSL context options and also makes
+ * driverOptions suitable for serialization by removing the resource zval. */
+static bool php_phongo_manager_merge_context_options(zval* zdriverOptions) /* {{{ */
+{
+ php_stream_context* context;
+ zval * zcontext, *zcontextOptions;
+
+ if (!php_array_existsc(zdriverOptions, "context")) {
+ return true;
+ }
+
+ zcontext = php_array_fetchc(zdriverOptions, "context");
+ context = php_stream_context_from_zval(zcontext, 1);
+
+ if (!context) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "\"context\" driver option is not a valid Stream-Context resource");
+ return false;
+ }
+
+ zcontextOptions = php_array_fetchc_array(&context->options, "ssl");
+
+ if (!zcontextOptions) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Stream-Context resource does not contain \"ssl\" options array");
+ return false;
+ }
+
+ /* When running PHP in debug mode, php_error_docref duplicates the current
+ * scope, leading to a COW violation in zend_hash_merge and
+ * zend_symtable_str_del (called by php_array_unsetc). This macro allows
+ * that violation in debug mode and is a NOOP when in non-debug. */
+ HT_ALLOW_COW_VIOLATION(Z_ARRVAL_P(zdriverOptions));
+
+ php_error_docref(NULL, E_DEPRECATED, "The \"context\" driver option is deprecated.");
+
+ /* Perform array union (see: add_function() in zend_operators.c) */
+ zend_hash_merge(Z_ARRVAL_P(zdriverOptions), Z_ARRVAL_P(zcontextOptions), zval_add_ref, 0);
+
+ php_array_unsetc(zdriverOptions, "context");
+
+ return true;
+} /* }}} */
+
+/* Prepare authMechanismProperties for BSON encoding by converting a boolean
+ * value for the "CANONICALIZE_HOST_NAME" option to a string.
+ *
+ * Note: URI options are case-insensitive, so we must iterate through the
+ * HashTable in order to detect options. */
+static void php_phongo_manager_prep_authmechanismproperties(zval* properties) /* {{{ */
+{
+ HashTable* ht_data;
+
+ if (Z_TYPE_P(properties) != IS_ARRAY && Z_TYPE_P(properties) != IS_OBJECT) {
+ return;
+ }
+
+ ht_data = HASH_OF(properties);
+
+ {
+ zend_string* string_key = NULL;
+ zend_ulong num_key = 0;
+ zval* property;
+
+ ZEND_HASH_FOREACH_KEY_VAL_IND(ht_data, num_key, string_key, property)
+ {
+ if (!string_key) {
+ continue;
+ }
+
+ /* URI options are case-insensitive */
+ if (!strcasecmp(ZSTR_VAL(string_key), "CANONICALIZE_HOST_NAME")) {
+ ZVAL_DEREF(property);
+ if (Z_TYPE_P(property) != IS_STRING && zend_is_true(property)) {
+ SEPARATE_ZVAL_NOREF(property);
+ ZVAL_NEW_STR(property, zend_string_init(ZEND_STRL("true"), 0));
+ }
+ }
+ }
+ ZEND_HASH_FOREACH_END();
+ }
+} /* }}} */
+
+/* Prepare URI options for BSON encoding.
+ *
+ * Read preference tag sets must be an array of documents. In order to ensure
+ * that empty arrays serialize as empty documents, array elements will be
+ * converted to objects. php_phongo_read_preference_tags_are_valid() handles
+ * actual validation of the tag set structure.
+ *
+ * Auth mechanism properties must have string values, so a boolean true value
+ * for the "CANONICALIZE_HOST_NAME" property will be converted to "true".
+ *
+ * Note: URI options are case-insensitive, so we must iterate through the
+ * HashTable in order to detect options. */
+static void php_phongo_manager_prep_uri_options(zval* options) /* {{{ */
+{
+ HashTable* ht_data;
+
+ if (Z_TYPE_P(options) != IS_ARRAY) {
+ return;
+ }
+
+ ht_data = HASH_OF(options);
+
+ {
+ zend_string* string_key = NULL;
+ zend_ulong num_key = 0;
+ zval* option;
+
+ ZEND_HASH_FOREACH_KEY_VAL_IND(ht_data, num_key, string_key, option)
+ {
+ if (!string_key) {
+ continue;
+ }
+
+ if (!strcasecmp(ZSTR_VAL(string_key), MONGOC_URI_READPREFERENCETAGS)) {
+ ZVAL_DEREF(option);
+ SEPARATE_ZVAL_NOREF(option);
+ php_phongo_read_preference_prep_tagsets(option);
+ continue;
+ }
+
+ if (!strcasecmp(ZSTR_VAL(string_key), MONGOC_URI_AUTHMECHANISMPROPERTIES)) {
+ ZVAL_DEREF(option);
+ SEPARATE_ZVAL_NOREF(option);
+ php_phongo_manager_prep_authmechanismproperties(option);
+ continue;
+ }
+ }
+ ZEND_HASH_FOREACH_END();
+ }
+} /* }}} */
+
+/* Selects a server for an execute method. If "for_writes" is true, a primary
+ * will be selected. Otherwise, a read preference will be used to select the
+ * server. If zreadPreference is NULL, the client's read preference will be
+ * used. If zsession is a session object in a sharded transaction, the session
+ * will be checked whether it is pinned to a server. If so, that server will be
+ * selected. Otherwise, server selection
+ *
+ * On success, server_id will be set and the function will return true;
+ * otherwise, false is returned and an exception is thrown. */
+static bool php_phongo_manager_select_server(bool for_writes, bool inherit_read_preference, zval* zreadPreference, zval* zsession, mongoc_client_t* client, uint32_t* server_id) /* {{{ */
+{
+ mongoc_server_description_t* selected_server;
+ const mongoc_read_prefs_t* read_preference = NULL;
+ bson_error_t error = { 0 };
+
+ if (zsession) {
+ const mongoc_client_session_t* session = Z_SESSION_OBJ_P(zsession)->client_session;
+
+ /* Attempt to fetch server pinned to session */
+ if (mongoc_client_session_get_server_id(session) > 0) {
+ *server_id = mongoc_client_session_get_server_id(session);
+
+ return true;
+ }
+ }
+
+ if (!for_writes) {
+ if (zreadPreference) {
+ read_preference = phongo_read_preference_from_zval(zreadPreference);
+ } else if (inherit_read_preference) {
+ read_preference = mongoc_client_get_read_prefs(client);
+ }
+ }
+
+ selected_server = mongoc_client_select_server(client, for_writes, read_preference, &error);
+
+ if (selected_server) {
+ *server_id = mongoc_server_description_id(selected_server);
+ mongoc_server_description_destroy(selected_server);
+
+ return true;
+ }
+
+ /* Check for connection related exceptions */
+ if (!EG(exception)) {
+ phongo_throw_exception_from_bson_error_t(&error);
+ }
+
+ return false;
+} /* }}} */
+
+/* {{{ proto void MongoDB\Driver\Manager::__construct([string $uri = "mongodb://127.0.0.1/"[, array $options = array()[, array $driverOptions = array()]]])
+ Constructs a new Manager */
+static PHP_METHOD(Manager, __construct)
+{
+ zend_error_handling error_handling;
+ php_phongo_manager_t* intern;
+ char* uri_string = NULL;
+ size_t uri_string_len = 0;
+ zval* options = NULL;
+ zval* driverOptions = NULL;
+
+ intern = Z_MANAGER_OBJ_P(getThis());
+
+ /* Separate the options and driverOptions zvals, since we may end up
+ * modifying them in php_phongo_manager_prep_uri_options() and
+ * php_phongo_manager_merge_context_options() below, respectively. */
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s!a/!a/!", &uri_string, &uri_string_len, &options, &driverOptions) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ if (options) {
+ php_phongo_manager_prep_uri_options(options);
+ }
+
+ if (driverOptions && !php_phongo_manager_merge_context_options(driverOptions)) {
+ /* Exception should already have been thrown */
+ return;
+ }
+
+ phongo_manager_init(intern, uri_string ? uri_string : PHONGO_MANAGER_URI_DEFAULT, options, driverOptions);
+
+ if (EG(exception)) {
+ return;
+ }
+
+ /* Update the request-scoped Manager registry */
+ if (!php_phongo_manager_register(intern)) {
+ phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "Failed to add Manager to internal registry");
+ }
+} /* }}} */
+
+/* {{{ proto void MongoDB\Driver\Manager::addSubscriber(MongoDB\Driver\Monitoring\Subscriber $subscriber)
+ Registers an event subscriber for this Manager */
+static PHP_METHOD(Manager, addSubscriber)
+{
+ php_phongo_manager_t* intern;
+ zval* subscriber;
+
+ PHONGO_PARSE_PARAMETERS_START(1, 1)
+ Z_PARAM_OBJECT_OF_CLASS(subscriber, php_phongo_subscriber_ce)
+ PHONGO_PARSE_PARAMETERS_END();
+
+ intern = Z_MANAGER_OBJ_P(getThis());
+
+ /* Lazily initialize the subscriber HashTable */
+ if (!intern->subscribers) {
+ ALLOC_HASHTABLE(intern->subscribers);
+ zend_hash_init(intern->subscribers, 0, NULL, ZVAL_PTR_DTOR, 0);
+ }
+
+ phongo_apm_add_subscriber(intern->subscribers, subscriber);
+} /* }}} */
+
+/* {{{ proto MongoDB\Driver\ClientEncryption MongoDB\Driver\Manager::createClientEncryption(array $options)
+ Return a ClientEncryption instance */
+static PHP_METHOD(Manager, createClientEncryption)
+{
+ zend_error_handling error_handling;
+ zval* options;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &options) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ /* An exception will be thrown on error. */
+ phongo_clientencryption_init(return_value, getThis(), options);
+} /* }}} */
+
+/* {{{ proto MongoDB\Driver\Cursor MongoDB\Driver\Manager::executeCommand(string $db, MongoDB\Driver\Command $command[, array $options = null])
+ Execute a Command */
+static PHP_METHOD(Manager, executeCommand)
+{
+ zend_error_handling error_handling;
+ php_phongo_manager_t* intern;
+ char* db;
+ size_t db_len;
+ zval* command;
+ zval* options = NULL;
+ bool free_options = false;
+ zval* zreadPreference = NULL;
+ zval* zsession = NULL;
+ uint32_t server_id = 0;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "sO|z!", &db, &db_len, &command, php_phongo_command_ce, &options) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ intern = Z_MANAGER_OBJ_P(getThis());
+
+ options = php_phongo_prep_legacy_option(options, "readPreference", &free_options);
+
+ if (!phongo_parse_session(options, intern->client, NULL, &zsession)) {
+ /* Exception should already have been thrown */
+ goto cleanup;
+ }
+
+ if (!phongo_parse_read_preference(options, &zreadPreference)) {
+ /* Exception should already have been thrown */
+ goto cleanup;
+ }
+
+ if (!php_phongo_manager_select_server(false, false, zreadPreference, zsession, intern->client, &server_id)) {
+ /* Exception should already have been thrown */
+ goto cleanup;
+ }
+
+ /* If the Manager was created in a different process, reset the client so
+ * that cursors created by this process can be differentiated and its
+ * session pool is cleared. */
+ PHONGO_RESET_CLIENT_IF_PID_DIFFERS(intern, intern);
+
+ phongo_execute_command(getThis(), PHONGO_COMMAND_RAW, db, command, options, server_id, return_value);
+
+cleanup:
+ if (free_options) {
+ php_phongo_prep_legacy_option_free(options);
+ }
+} /* }}} */
+
+/* {{{ proto MongoDB\Driver\Cursor MongoDB\Driver\Manager::executeReadCommand(string $db, MongoDB\Driver\Command $command[, array $options = null])
+ Execute a ReadCommand */
+static PHP_METHOD(Manager, executeReadCommand)
+{
+ zend_error_handling error_handling;
+ php_phongo_manager_t* intern;
+ char* db;
+ size_t db_len;
+ zval* command;
+ zval* options = NULL;
+ zval* zreadPreference = NULL;
+ uint32_t server_id = 0;
+ zval* zsession = NULL;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "sO|a!", &db, &db_len, &command, php_phongo_command_ce, &options) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ intern = Z_MANAGER_OBJ_P(getThis());
+
+ if (!phongo_parse_session(options, intern->client, NULL, &zsession)) {
+ /* Exception should already have been thrown */
+ return;
+ }
+
+ if (!phongo_parse_read_preference(options, &zreadPreference)) {
+ /* Exception should already have been thrown */
+ return;
+ }
+
+ if (!php_phongo_manager_select_server(false, true, zreadPreference, zsession, intern->client, &server_id)) {
+ /* Exception should already have been thrown */
+ return;
+ }
+
+ /* If the Manager was created in a different process, reset the client so
+ * that cursors created by this process can be differentiated and its
+ * session pool is cleared. */
+ PHONGO_RESET_CLIENT_IF_PID_DIFFERS(intern, intern);
+
+ phongo_execute_command(getThis(), PHONGO_COMMAND_READ, db, command, options, server_id, return_value);
+} /* }}} */
+
+/* {{{ proto MongoDB\Driver\Cursor MongoDB\Driver\Manager::executeWriteCommand(string $db, MongoDB\Driver\Command $command[, array $options = null])
+ Execute a WriteCommand */
+static PHP_METHOD(Manager, executeWriteCommand)
+{
+ zend_error_handling error_handling;
+ php_phongo_manager_t* intern;
+ char* db;
+ size_t db_len;
+ zval* command;
+ zval* options = NULL;
+ uint32_t server_id = 0;
+ zval* zsession = NULL;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "sO|a!", &db, &db_len, &command, php_phongo_command_ce, &options) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ intern = Z_MANAGER_OBJ_P(getThis());
+
+ if (!phongo_parse_session(options, intern->client, NULL, &zsession)) {
+ /* Exception should already have been thrown */
+ return;
+ }
+
+ if (!php_phongo_manager_select_server(true, false, NULL, zsession, intern->client, &server_id)) {
+ /* Exception should already have been thrown */
+ return;
+ }
+
+ /* If the Manager was created in a different process, reset the client so
+ * that cursors created by this process can be differentiated and its
+ * session pool is cleared. */
+ PHONGO_RESET_CLIENT_IF_PID_DIFFERS(intern, intern);
+
+ phongo_execute_command(getThis(), PHONGO_COMMAND_WRITE, db, command, options, server_id, return_value);
+} /* }}} */
+
+/* {{{ proto MongoDB\Driver\Cursor MongoDB\Driver\Manager::executeReadWriteCommand(string $db, MongoDB\Driver\Command $command[, array $options = null])
+ Execute a ReadWriteCommand */
+static PHP_METHOD(Manager, executeReadWriteCommand)
+{
+ zend_error_handling error_handling;
+ php_phongo_manager_t* intern;
+ char* db;
+ size_t db_len;
+ zval* command;
+ zval* options = NULL;
+ uint32_t server_id = 0;
+ zval* zsession = NULL;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "sO|a!", &db, &db_len, &command, php_phongo_command_ce, &options) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ intern = Z_MANAGER_OBJ_P(getThis());
+
+ if (!phongo_parse_session(options, intern->client, NULL, &zsession)) {
+ /* Exception should already have been thrown */
+ return;
+ }
+
+ if (!php_phongo_manager_select_server(true, false, NULL, zsession, intern->client, &server_id)) {
+ /* Exception should already have been thrown */
+ return;
+ }
+
+ /* If the Manager was created in a different process, reset the client so
+ * that cursors created by this process can be differentiated and its
+ * session pool is cleared. */
+ PHONGO_RESET_CLIENT_IF_PID_DIFFERS(intern, intern);
+
+ phongo_execute_command(getThis(), PHONGO_COMMAND_READ_WRITE, db, command, options, server_id, return_value);
+} /* }}} */
+
+/* {{{ proto MongoDB\Driver\Cursor MongoDB\Driver\Manager::executeQuery(string $namespace, MongoDB\Driver\Query $query[, array $options = null])
+ Execute a Query */
+static PHP_METHOD(Manager, executeQuery)
+{
+ zend_error_handling error_handling;
+ php_phongo_manager_t* intern;
+ char* namespace;
+ size_t namespace_len;
+ zval* query;
+ zval* options = NULL;
+ bool free_options = false;
+ zval* zreadPreference = NULL;
+ uint32_t server_id = 0;
+ zval* zsession = NULL;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "sO|z!", &namespace, &namespace_len, &query, php_phongo_query_ce, &options) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ intern = Z_MANAGER_OBJ_P(getThis());
+
+ options = php_phongo_prep_legacy_option(options, "readPreference", &free_options);
+
+ if (!phongo_parse_session(options, intern->client, NULL, &zsession)) {
+ /* Exception should already have been thrown */
+ goto cleanup;
+ }
+
+ if (!phongo_parse_read_preference(options, &zreadPreference)) {
+ /* Exception should already have been thrown */
+ goto cleanup;
+ }
+
+ if (!php_phongo_manager_select_server(false, true, zreadPreference, zsession, intern->client, &server_id)) {
+ /* Exception should already have been thrown */
+ goto cleanup;
+ }
+
+ /* If the Manager was created in a different process, reset the client so
+ * that cursors created by this process can be differentiated and its
+ * session pool is cleared. */
+ PHONGO_RESET_CLIENT_IF_PID_DIFFERS(intern, intern);
+
+ phongo_execute_query(getThis(), namespace, query, options, server_id, return_value);
+
+cleanup:
+ if (free_options) {
+ php_phongo_prep_legacy_option_free(options);
+ }
+} /* }}} */
+
+/* {{{ proto MongoDB\Driver\WriteResult MongoDB\Driver\Manager::executeBulkWrite(string $namespace, MongoDB\Driver\BulkWrite $zbulk[, array $options = null])
+ Executes a BulkWrite (i.e. any number of insert, update, and delete ops) */
+static PHP_METHOD(Manager, executeBulkWrite)
+{
+ zend_error_handling error_handling;
+ php_phongo_manager_t* intern;
+ char* namespace;
+ size_t namespace_len;
+ zval* zbulk;
+ php_phongo_bulkwrite_t* bulk;
+ zval* options = NULL;
+ bool free_options = false;
+ uint32_t server_id = 0;
+ zval* zsession = NULL;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "sO|z!", &namespace, &namespace_len, &zbulk, php_phongo_bulkwrite_ce, &options) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ intern = Z_MANAGER_OBJ_P(getThis());
+ bulk = Z_BULKWRITE_OBJ_P(zbulk);
+
+ options = php_phongo_prep_legacy_option(options, "writeConcern", &free_options);
+
+ if (!phongo_parse_session(options, intern->client, NULL, &zsession)) {
+ /* Exception should already have been thrown */
+ return;
+ }
+
+ if (!php_phongo_manager_select_server(true, false, NULL, zsession, intern->client, &server_id)) {
+ /* Exception should already have been thrown */
+ goto cleanup;
+ }
+
+ /* If the Server was created in a different process, reset the client so
+ * that its session pool is cleared. */
+ PHONGO_RESET_CLIENT_IF_PID_DIFFERS(intern, intern);
+
+ phongo_execute_bulk_write(getThis(), namespace, bulk, options, server_id, return_value);
+
+cleanup:
+ if (free_options) {
+ php_phongo_prep_legacy_option_free(options);
+ }
+} /* }}} */
+
+/* {{{ proto MongoDB\Driver\ReadConcern MongoDB\Driver\Manager::getReadConcern()
+ Returns the ReadConcern associated with this Manager */
+static PHP_METHOD(Manager, getReadConcern)
+{
+ zend_error_handling error_handling;
+ php_phongo_manager_t* intern;
+
+ intern = Z_MANAGER_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ phongo_readconcern_init(return_value, mongoc_client_get_read_concern(intern->client));
+} /* }}} */
+
+/* {{{ proto MongoDB\Driver\ReadPreference MongoDB\Driver\Manager::getReadPreference()
+ Returns the ReadPreference associated with this Manager */
+static PHP_METHOD(Manager, getReadPreference)
+{
+ zend_error_handling error_handling;
+ php_phongo_manager_t* intern;
+
+ intern = Z_MANAGER_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ phongo_readpreference_init(return_value, mongoc_client_get_read_prefs(intern->client));
+} /* }}} */
+
+/* {{{ proto MongoDB\Driver\Server[] MongoDB\Driver\Manager::getServers()
+ Returns the Servers associated with this Manager */
+static PHP_METHOD(Manager, getServers)
+{
+ zend_error_handling error_handling;
+ php_phongo_manager_t* intern;
+ mongoc_server_description_t** sds;
+ size_t i, n = 0;
+
+ intern = Z_MANAGER_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ sds = mongoc_client_get_server_descriptions(intern->client, &n);
+ array_init_size(return_value, n);
+
+ for (i = 0; i < n; i++) {
+ zval obj;
+
+ phongo_server_init(&obj, getThis(), mongoc_server_description_id(sds[i]));
+ add_next_index_zval(return_value, &obj);
+ }
+
+ mongoc_server_descriptions_destroy_all(sds, n);
+} /* }}} */
+
+/* {{{ proto MongoDB\Driver\WriteConcern MongoDB\Driver\Manager::getWriteConcern()
+ Returns the WriteConcern associated with this Manager */
+static PHP_METHOD(Manager, getWriteConcern)
+{
+ zend_error_handling error_handling;
+ php_phongo_manager_t* intern;
+
+ intern = Z_MANAGER_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ phongo_writeconcern_init(return_value, mongoc_client_get_write_concern(intern->client));
+} /* }}} */
+
+/* {{{ proto void MongoDB\Driver\Manager::removeSubscriber(MongoDB\Driver\Monitoring\Subscriber $subscriber)
+ Unregisters an event subscriber for this Manager */
+static PHP_METHOD(Manager, removeSubscriber)
+{
+ php_phongo_manager_t* intern;
+ zval* subscriber;
+
+ PHONGO_PARSE_PARAMETERS_START(1, 1)
+ Z_PARAM_OBJECT_OF_CLASS(subscriber, php_phongo_subscriber_ce)
+ PHONGO_PARSE_PARAMETERS_END();
+
+ intern = Z_MANAGER_OBJ_P(getThis());
+
+ /* NOP if subscribers HashTable was never initialized by addSubscriber */
+ if (!intern->subscribers) {
+ return;
+ }
+
+ phongo_apm_remove_subscriber(intern->subscribers, subscriber);
+} /* }}} */
+
+/* {{{ proto MongoDB\Driver\Server MongoDB\Driver\Manager::selectServers([MongoDB\Driver\ReadPreference $readPreference = null])
+ Selects a Server for the given ReadPreference (default: primary). */
+static PHP_METHOD(Manager, selectServer)
+{
+ php_phongo_manager_t* intern;
+ zval* zreadPreference = NULL;
+ uint32_t server_id = 0;
+
+ PHONGO_PARSE_PARAMETERS_START(0, 1)
+ Z_PARAM_OPTIONAL
+ Z_PARAM_OBJECT_OF_CLASS_OR_NULL(zreadPreference, php_phongo_readpreference_ce)
+ PHONGO_PARSE_PARAMETERS_END();
+
+ intern = Z_MANAGER_OBJ_P(getThis());
+
+ if (!php_phongo_manager_select_server(false, false, zreadPreference, NULL, intern->client, &server_id)) {
+ /* Exception should already have been thrown */
+ return;
+ }
+
+ phongo_server_init(return_value, getThis(), server_id);
+} /* }}} */
+
+/* {{{ proto MongoDB\Driver\Session MongoDB\Driver\Manager::startSession([array $options = null])
+ Returns a new client session */
+static PHP_METHOD(Manager, startSession)
+{
+ zend_error_handling error_handling;
+ php_phongo_manager_t* intern;
+ zval* options = NULL;
+ mongoc_session_opt_t* cs_opts = NULL;
+ mongoc_client_session_t* cs;
+ bson_error_t error = { 0 };
+ mongoc_transaction_opt_t* txn_opts = NULL;
+
+ intern = Z_MANAGER_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "|a!", &options) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ if (options && php_array_existsc(options, "causalConsistency")) {
+ cs_opts = mongoc_session_opts_new();
+ mongoc_session_opts_set_causal_consistency(cs_opts, php_array_fetchc_bool(options, "causalConsistency"));
+ }
+
+ if (options && php_array_existsc(options, "defaultTransactionOptions")) {
+ zval* txn_options = php_array_fetchc(options, "defaultTransactionOptions");
+
+ /* Thrown exception and return if the defaultTransactionOptions is not an array */
+ if (Z_TYPE_P(txn_options) != IS_ARRAY) {
+ phongo_throw_exception(
+ PHONGO_ERROR_INVALID_ARGUMENT,
+ "Expected \"defaultTransactionOptions\" option to be an array, %s given",
+ PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(txn_options));
+ goto cleanup;
+ }
+
+ /* Parse transaction options */
+ txn_opts = php_mongodb_session_parse_transaction_options(txn_options);
+
+ /* If an exception is thrown while parsing, the txn_opts struct is also
+ * NULL, so no need to free it here */
+ if (EG(exception)) {
+ goto cleanup;
+ }
+
+ /* If the options are non-empty, add them to the client session opts struct */
+ if (txn_opts) {
+ if (!cs_opts) {
+ cs_opts = mongoc_session_opts_new();
+ }
+
+ mongoc_session_opts_set_default_transaction_opts(cs_opts, txn_opts);
+ mongoc_transaction_opts_destroy(txn_opts);
+ }
+ }
+
+ if (options && php_array_existsc(options, "snapshot")) {
+ if (!cs_opts) {
+ cs_opts = mongoc_session_opts_new();
+ }
+ mongoc_session_opts_set_snapshot(cs_opts, php_array_fetchc_bool(options, "snapshot"));
+ }
+
+ if (cs_opts && mongoc_session_opts_get_causal_consistency(cs_opts) && mongoc_session_opts_get_snapshot(cs_opts)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Only one of \"causalConsistency\" and \"snapshot\" can be enabled");
+ goto cleanup;
+ }
+
+ /* If the Manager was created in a different process, reset the client so
+ * that its session pool is cleared. This will ensure that we do not re-use
+ * a server session (i.e. LSID) created by a parent process. */
+ PHONGO_RESET_CLIENT_IF_PID_DIFFERS(intern, intern);
+
+ cs = mongoc_client_start_session(intern->client, cs_opts, &error);
+
+ if (cs) {
+ phongo_session_init(return_value, getThis(), cs);
+ } else {
+ phongo_throw_exception_from_bson_error_t(&error);
+ }
+
+cleanup:
+ if (cs_opts) {
+ mongoc_session_opts_destroy(cs_opts);
+ }
+} /* }}} */
+
+/* {{{ MongoDB\Driver\Manager function entries */
+ZEND_BEGIN_ARG_INFO_EX(ai_Manager___construct, 0, 0, 0)
+ ZEND_ARG_INFO(0, uri)
+ ZEND_ARG_ARRAY_INFO(0, options, 0)
+ ZEND_ARG_ARRAY_INFO(0, driverOptions, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_Manager_addSubscriber, 0, 0, 1)
+ ZEND_ARG_OBJ_INFO(0, subscriber, MongoDB\\Driver\\Monitoring\\Subscriber, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_Manager_createClientEncryption, 0, 0, 1)
+ ZEND_ARG_ARRAY_INFO(0, options, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_Manager_executeCommand, 0, 0, 2)
+ ZEND_ARG_INFO(0, db)
+ ZEND_ARG_OBJ_INFO(0, command, MongoDB\\Driver\\Command, 0)
+ ZEND_ARG_INFO(0, options)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_Manager_executeRWCommand, 0, 0, 2)
+ ZEND_ARG_INFO(0, db)
+ ZEND_ARG_OBJ_INFO(0, command, MongoDB\\Driver\\Command, 0)
+ ZEND_ARG_ARRAY_INFO(0, options, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_Manager_executeQuery, 0, 0, 2)
+ ZEND_ARG_INFO(0, namespace)
+ ZEND_ARG_OBJ_INFO(0, zquery, MongoDB\\Driver\\Query, 0)
+ ZEND_ARG_INFO(0, options)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_Manager_executeBulkWrite, 0, 0, 2)
+ ZEND_ARG_INFO(0, namespace)
+ ZEND_ARG_OBJ_INFO(0, zbulk, MongoDB\\Driver\\BulkWrite, 0)
+ ZEND_ARG_INFO(0, options)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_Manager_removeSubscriber, 0, 0, 1)
+ ZEND_ARG_OBJ_INFO(0, subscriber, MongoDB\\Driver\\Monitoring\\Subscriber, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_Manager_selectServer, 0, 0, 0)
+ ZEND_ARG_OBJ_INFO(0, readPreference, MongoDB\\Driver\\ReadPreference, 1)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_Manager_startSession, 0, 0, 0)
+ ZEND_ARG_ARRAY_INFO(0, options, 1)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_Manager_void, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry php_phongo_manager_me[] = {
+ /* clang-format off */
+ PHP_ME(Manager, __construct, ai_Manager___construct, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Manager, addSubscriber, ai_Manager_addSubscriber, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Manager, createClientEncryption, ai_Manager_createClientEncryption, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Manager, executeCommand, ai_Manager_executeCommand, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Manager, executeReadCommand, ai_Manager_executeRWCommand, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Manager, executeWriteCommand, ai_Manager_executeRWCommand, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Manager, executeReadWriteCommand, ai_Manager_executeCommand, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Manager, executeQuery, ai_Manager_executeQuery, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Manager, executeBulkWrite, ai_Manager_executeBulkWrite, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Manager, getReadConcern, ai_Manager_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Manager, getReadPreference, ai_Manager_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Manager, getServers, ai_Manager_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Manager, getWriteConcern, ai_Manager_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Manager, removeSubscriber, ai_Manager_removeSubscriber, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Manager, selectServer, ai_Manager_selectServer, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Manager, startSession, ai_Manager_startSession, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ ZEND_NAMED_ME(__wakeup, PHP_FN(MongoDB_disabled___wakeup), ai_Manager_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_FE_END
+ /* clang-format on */
+};
+/* }}} */
+
+/* {{{ MongoDB\Driver\Manager object handlers */
+static zend_object_handlers php_phongo_handler_manager;
+
+static void php_phongo_manager_free_object(zend_object* object) /* {{{ */
+{
+ php_phongo_manager_t* intern = Z_OBJ_MANAGER(object);
+
+ zend_object_std_dtor(&intern->std);
+
+ if (intern->client) {
+ /* Request-scoped clients will be removed from the registry and
+ * destroyed. This is a NOP for persistent clients. The return value is
+ * ignored because we can't reasonably report an error here. On the off
+ * chance any request-scoped clients are missed, they will ultimately be
+ * destroyed in RSHUTDOWN along with the registry HashTable. */
+ php_phongo_client_unregister(intern);
+ }
+
+ /* Update the request-scoped Manager registry. The return value is ignored
+ * because it's possible that the Manager was never registered due to a
+ * constructor exception.
+ *
+ * Note: this is done after unregistering a request-scoped client to ensure
+ * APM events can be observed by per-client subscribers, which are collected
+ * in phongo_apm_get_subscribers_to_notify. */
+ php_phongo_manager_unregister(intern);
+
+ if (intern->client_hash) {
+ efree(intern->client_hash);
+ }
+
+ /* Free the keyVaultClient last to ensure that potential non-persistent
+ * clients are destroyed in the correct order */
+ if (!Z_ISUNDEF(intern->key_vault_client_manager)) {
+ zval_ptr_dtor(&intern->key_vault_client_manager);
+ }
+
+ if (intern->subscribers) {
+ zend_hash_destroy(intern->subscribers);
+ FREE_HASHTABLE(intern->subscribers);
+ }
+} /* }}} */
+
+static zend_object* php_phongo_manager_create_object(zend_class_entry* class_type) /* {{{ */
+{
+ php_phongo_manager_t* intern = zend_object_alloc(sizeof(php_phongo_manager_t), class_type);
+
+ zend_object_std_init(&intern->std, class_type);
+ object_properties_init(&intern->std, class_type);
+
+ PHONGO_SET_CREATED_BY_PID(intern);
+
+ intern->std.handlers = &php_phongo_handler_manager;
+
+ return &intern->std;
+} /* }}} */
+
+static HashTable* php_phongo_manager_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
+{
+ php_phongo_manager_t* intern;
+ mongoc_server_description_t** sds;
+ size_t i, n = 0;
+ zval retval = ZVAL_STATIC_INIT;
+ zval cluster;
+
+ *is_temp = 1;
+ intern = Z_OBJ_MANAGER(PHONGO_COMPAT_GET_OBJ(object));
+
+ array_init_size(&retval, 2);
+
+ ADD_ASSOC_STRING(&retval, "uri", mongoc_uri_get_string(mongoc_client_get_uri(intern->client)));
+
+ sds = mongoc_client_get_server_descriptions(intern->client, &n);
+
+ array_init_size(&cluster, n);
+
+ for (i = 0; i < n; i++) {
+ zval obj;
+
+ if (!php_phongo_server_to_zval(&obj, intern->client, sds[i])) {
+ /* Exception already thrown */
+ zval_ptr_dtor(&obj);
+ zval_ptr_dtor(&cluster);
+ goto done;
+ }
+
+ add_next_index_zval(&cluster, &obj);
+ }
+
+ ADD_ASSOC_ZVAL_EX(&retval, "cluster", &cluster);
+
+done:
+ mongoc_server_descriptions_destroy_all(sds, n);
+
+ return Z_ARRVAL(retval);
+} /* }}} */
+/* }}} */
+
+void php_phongo_manager_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver", "Manager", php_phongo_manager_me);
+ php_phongo_manager_ce = zend_register_internal_class(&ce);
+ php_phongo_manager_ce->create_object = php_phongo_manager_create_object;
+ PHONGO_CE_FINAL(php_phongo_manager_ce);
+ PHONGO_CE_DISABLE_SERIALIZATION(php_phongo_manager_ce);
+
+ memcpy(&php_phongo_handler_manager, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
+ php_phongo_handler_manager.get_debug_info = php_phongo_manager_get_debug_info;
+ php_phongo_handler_manager.free_obj = php_phongo_manager_free_object;
+ php_phongo_handler_manager.offset = XtOffsetOf(php_phongo_manager_t, std);
+} /* }}} */
diff --git a/mongodb-1.13.0/src/MongoDB/Monitoring/CommandFailedEvent.c b/mongodb-1.13.0/src/MongoDB/Monitoring/CommandFailedEvent.c
new file mode 100644
index 00000000..4d710e28
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/Monitoring/CommandFailedEvent.c
@@ -0,0 +1,325 @@
+/*
+ * Copyright 2016-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bson/bson.h"
+
+#include <php.h>
+#include <Zend/zend_interfaces.h>
+
+#include "php_phongo.h"
+#include "phongo_bson_encode.h"
+#include "phongo_error.h"
+
+#include "BSON/ObjectId.h"
+#include "MongoDB/Server.h"
+
+zend_class_entry* php_phongo_commandfailedevent_ce;
+
+/* {{{ proto string CommandFailedEvent::getCommandName()
+ Returns the command name for this event */
+PHP_METHOD(CommandFailedEvent, getCommandName)
+{
+ zend_error_handling error_handling;
+ php_phongo_commandfailedevent_t* intern;
+
+ intern = Z_COMMANDFAILEDEVENT_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ RETVAL_STRING(intern->command_name);
+} /* }}} */
+
+/* {{{ proto int CommandFailedEvent::getDurationMicros()
+ Returns the event's duration in microseconds */
+PHP_METHOD(CommandFailedEvent, getDurationMicros)
+{
+ zend_error_handling error_handling;
+ php_phongo_commandfailedevent_t* intern;
+
+ intern = Z_COMMANDFAILEDEVENT_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ RETURN_LONG(intern->duration_micros);
+} /* }}} */
+
+/* {{{ proto Exception CommandFailedEvent::getError()
+ Returns the error document associated with the event */
+PHP_METHOD(CommandFailedEvent, getError)
+{
+ zend_error_handling error_handling;
+ php_phongo_commandfailedevent_t* intern;
+
+ intern = Z_COMMANDFAILEDEVENT_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ RETURN_ZVAL(&intern->z_error, 1, 0);
+} /* }}} */
+
+/* {{{ proto string CommandFailedEvent::getOperationId()
+ Returns the event's operation ID */
+PHP_METHOD(CommandFailedEvent, getOperationId)
+{
+ zend_error_handling error_handling;
+ php_phongo_commandfailedevent_t* intern;
+ char int_as_string[20];
+
+ intern = Z_COMMANDFAILEDEVENT_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ sprintf(int_as_string, "%" PRIu64, intern->operation_id);
+ RETVAL_STRING(int_as_string);
+} /* }}} */
+
+/* {{{ proto stdClass CommandFailedEvent::getReply()
+ Returns the reply document associated with the event */
+PHP_METHOD(CommandFailedEvent, getReply)
+{
+ zend_error_handling error_handling;
+ php_phongo_commandfailedevent_t* intern;
+ php_phongo_bson_state state;
+
+ PHONGO_BSON_INIT_STATE(state);
+
+ intern = Z_COMMANDFAILEDEVENT_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ if (!php_phongo_bson_to_zval_ex(bson_get_data(intern->reply), intern->reply->len, &state)) {
+ zval_ptr_dtor(&state.zchild);
+ return;
+ }
+
+ RETURN_ZVAL(&state.zchild, 0, 1);
+} /* }}} */
+
+/* {{{ proto string CommandFailedEvent::getRequestId()
+ Returns the event's request ID */
+PHP_METHOD(CommandFailedEvent, getRequestId)
+{
+ zend_error_handling error_handling;
+ php_phongo_commandfailedevent_t* intern;
+ char int_as_string[20];
+
+ intern = Z_COMMANDFAILEDEVENT_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ sprintf(int_as_string, "%" PRIu64, intern->request_id);
+ RETVAL_STRING(int_as_string);
+} /* }}} */
+
+/* {{{ proto MongoDB\Driver\Server CommandFailedEvent::getServer()
+ Returns the Server from which the event originated */
+PHP_METHOD(CommandFailedEvent, getServer)
+{
+ zend_error_handling error_handling;
+ php_phongo_commandfailedevent_t* intern;
+
+ intern = Z_COMMANDFAILEDEVENT_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ phongo_server_init(return_value, &intern->manager, intern->server_id);
+} /* }}} */
+
+/* {{{ proto MongoDB\BSON\ObjectId|null CommandFailedEvent::getServiceId()
+ Returns the event's service ID */
+PHP_METHOD(CommandFailedEvent, getServiceId)
+{
+ php_phongo_commandfailedevent_t* intern = Z_COMMANDFAILEDEVENT_OBJ_P(getThis());
+
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ if (!intern->has_service_id) {
+ RETURN_NULL();
+ }
+
+ phongo_objectid_init(return_value, &intern->service_id);
+} /* }}} */
+
+/**
+ * Event thrown when a command has failed to execute.
+ *
+ * This class is only constructed internally.
+ */
+
+/* {{{ MongoDB\Driver\Monitoring\CommandFailedEvent function entries */
+ZEND_BEGIN_ARG_INFO_EX(ai_CommandFailedEvent_void, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry php_phongo_commandfailedevent_me[] = {
+ /* clang-format off */
+ ZEND_NAMED_ME(__construct, PHP_FN(MongoDB_disabled___construct), ai_CommandFailedEvent_void, ZEND_ACC_PRIVATE | ZEND_ACC_FINAL)
+ PHP_ME(CommandFailedEvent, getCommandName, ai_CommandFailedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(CommandFailedEvent, getError, ai_CommandFailedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(CommandFailedEvent, getDurationMicros, ai_CommandFailedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(CommandFailedEvent, getOperationId, ai_CommandFailedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(CommandFailedEvent, getReply, ai_CommandFailedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(CommandFailedEvent, getRequestId, ai_CommandFailedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(CommandFailedEvent, getServer, ai_CommandFailedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(CommandFailedEvent, getServiceId, ai_CommandFailedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ ZEND_NAMED_ME(__wakeup, PHP_FN(MongoDB_disabled___wakeup), ai_CommandFailedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_FE_END
+ /* clang-format on */
+};
+/* }}} */
+
+/* {{{ MongoDB\Driver\Monitoring\CommandFailedEvent object handlers */
+static zend_object_handlers php_phongo_handler_commandfailedevent;
+
+static void php_phongo_commandfailedevent_free_object(zend_object* object) /* {{{ */
+{
+ php_phongo_commandfailedevent_t* intern = Z_OBJ_COMMANDFAILEDEVENT(object);
+
+ zend_object_std_dtor(&intern->std);
+
+ if (!Z_ISUNDEF(intern->z_error)) {
+ zval_ptr_dtor(&intern->z_error);
+ }
+
+ if (!Z_ISUNDEF(intern->manager)) {
+ zval_ptr_dtor(&intern->manager);
+ }
+
+ if (intern->reply) {
+ bson_destroy(intern->reply);
+ }
+
+ if (intern->command_name) {
+ efree(intern->command_name);
+ }
+} /* }}} */
+
+static zend_object* php_phongo_commandfailedevent_create_object(zend_class_entry* class_type) /* {{{ */
+{
+ php_phongo_commandfailedevent_t* intern = zend_object_alloc(sizeof(php_phongo_commandfailedevent_t), class_type);
+
+ zend_object_std_init(&intern->std, class_type);
+ object_properties_init(&intern->std, class_type);
+
+ intern->std.handlers = &php_phongo_handler_commandfailedevent;
+
+ return &intern->std;
+} /* }}} */
+
+static HashTable* php_phongo_commandfailedevent_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
+{
+ php_phongo_commandfailedevent_t* intern;
+ zval retval = ZVAL_STATIC_INIT;
+ char operation_id[20], request_id[20];
+ php_phongo_bson_state reply_state;
+
+ PHONGO_BSON_INIT_STATE(reply_state);
+
+ intern = Z_OBJ_COMMANDFAILEDEVENT(PHONGO_COMPAT_GET_OBJ(object));
+ *is_temp = 1;
+ array_init_size(&retval, 6);
+
+ ADD_ASSOC_STRING(&retval, "commandName", intern->command_name);
+ ADD_ASSOC_INT64(&retval, "durationMicros", (int64_t) intern->duration_micros);
+
+ ADD_ASSOC_ZVAL_EX(&retval, "error", &intern->z_error);
+ Z_ADDREF(intern->z_error);
+
+ sprintf(operation_id, "%" PRIu64, intern->operation_id);
+ ADD_ASSOC_STRING(&retval, "operationId", operation_id);
+
+ if (!php_phongo_bson_to_zval_ex(bson_get_data(intern->reply), intern->reply->len, &reply_state)) {
+ zval_ptr_dtor(&reply_state.zchild);
+ goto done;
+ }
+
+ ADD_ASSOC_ZVAL(&retval, "reply", &reply_state.zchild);
+
+ sprintf(request_id, "%" PRIu64, intern->request_id);
+ ADD_ASSOC_STRING(&retval, "requestId", request_id);
+
+ {
+ zval server;
+
+ phongo_server_init(&server, &intern->manager, intern->server_id);
+ ADD_ASSOC_ZVAL_EX(&retval, "server", &server);
+ }
+
+ if (intern->has_service_id) {
+ zval service_id;
+
+ phongo_objectid_init(&service_id, &intern->service_id);
+ ADD_ASSOC_ZVAL_EX(&retval, "serviceId", &service_id);
+ } else {
+ ADD_ASSOC_NULL_EX(&retval, "serviceId");
+ }
+
+done:
+ return Z_ARRVAL(retval);
+} /* }}} */
+/* }}} */
+
+void php_phongo_commandfailedevent_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+ (void) type;
+ (void) module_number;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver\\Monitoring", "CommandFailedEvent", php_phongo_commandfailedevent_me);
+ php_phongo_commandfailedevent_ce = zend_register_internal_class(&ce);
+ php_phongo_commandfailedevent_ce->create_object = php_phongo_commandfailedevent_create_object;
+ PHONGO_CE_FINAL(php_phongo_commandfailedevent_ce);
+ PHONGO_CE_DISABLE_SERIALIZATION(php_phongo_commandfailedevent_ce);
+
+ memcpy(&php_phongo_handler_commandfailedevent, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
+ php_phongo_handler_commandfailedevent.get_debug_info = php_phongo_commandfailedevent_get_debug_info;
+ php_phongo_handler_commandfailedevent.free_obj = php_phongo_commandfailedevent_free_object;
+ php_phongo_handler_commandfailedevent.offset = XtOffsetOf(php_phongo_commandfailedevent_t, std);
+} /* }}} */
diff --git a/mongodb-1.13.0/src/MongoDB/Monitoring/CommandStartedEvent.c b/mongodb-1.13.0/src/MongoDB/Monitoring/CommandStartedEvent.c
new file mode 100644
index 00000000..3ce634e5
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/Monitoring/CommandStartedEvent.c
@@ -0,0 +1,304 @@
+/*
+ * Copyright 2016-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bson/bson.h"
+
+#include <php.h>
+#include <Zend/zend_interfaces.h>
+
+#include "php_phongo.h"
+#include "phongo_bson_encode.h"
+#include "phongo_error.h"
+
+#include "BSON/ObjectId.h"
+#include "MongoDB/Server.h"
+
+zend_class_entry* php_phongo_commandstartedevent_ce;
+
+/* {{{ proto stdClass CommandStartedEvent::getCommand()
+ Returns the command document associated with the event */
+PHP_METHOD(CommandStartedEvent, getCommand)
+{
+ zend_error_handling error_handling;
+ php_phongo_commandstartedevent_t* intern;
+ php_phongo_bson_state state;
+
+ PHONGO_BSON_INIT_STATE(state);
+
+ intern = Z_COMMANDSTARTEDEVENT_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ if (!php_phongo_bson_to_zval_ex(bson_get_data(intern->command), intern->command->len, &state)) {
+ zval_ptr_dtor(&state.zchild);
+ return;
+ }
+
+ RETURN_ZVAL(&state.zchild, 0, 1);
+} /* }}} */
+
+/* {{{ proto string CommandStartedEvent::getCommandName()
+ Returns the command name for this event */
+PHP_METHOD(CommandStartedEvent, getCommandName)
+{
+ zend_error_handling error_handling;
+ php_phongo_commandstartedevent_t* intern;
+
+ intern = Z_COMMANDSTARTEDEVENT_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ RETVAL_STRING(intern->command_name);
+} /* }}} */
+
+/* {{{ proto string CommandStartedEvent::getDatabaseName()
+ Returns the database name for this event */
+PHP_METHOD(CommandStartedEvent, getDatabaseName)
+{
+ zend_error_handling error_handling;
+ php_phongo_commandstartedevent_t* intern;
+
+ intern = Z_COMMANDSTARTEDEVENT_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ RETVAL_STRING(intern->database_name);
+} /* }}} */
+
+/* {{{ proto string CommandStartedEvent::getOperationId()
+ Returns the event's operation ID */
+PHP_METHOD(CommandStartedEvent, getOperationId)
+{
+ zend_error_handling error_handling;
+ php_phongo_commandstartedevent_t* intern;
+ char int_as_string[20];
+
+ intern = Z_COMMANDSTARTEDEVENT_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ sprintf(int_as_string, "%" PRIu64, intern->operation_id);
+ RETVAL_STRING(int_as_string);
+} /* }}} */
+
+/* {{{ proto string CommandStartedEvent::getRequestId()
+ Returns the event's request ID */
+PHP_METHOD(CommandStartedEvent, getRequestId)
+{
+ zend_error_handling error_handling;
+ php_phongo_commandstartedevent_t* intern;
+ char int_as_string[20];
+
+ intern = Z_COMMANDSTARTEDEVENT_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ sprintf(int_as_string, "%" PRIu64, intern->request_id);
+ RETVAL_STRING(int_as_string);
+} /* }}} */
+
+/* {{{ proto MongoDB\Driver\Server CommandStartedEvent::getServer()
+ Returns the Server from which the event originated */
+PHP_METHOD(CommandStartedEvent, getServer)
+{
+ zend_error_handling error_handling;
+ php_phongo_commandstartedevent_t* intern;
+
+ intern = Z_COMMANDSTARTEDEVENT_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ phongo_server_init(return_value, &intern->manager, intern->server_id);
+} /* }}} */
+
+/* {{{ proto MongoDB\BSON\ObjectId|null CommandStartedEvent::getServiceId()
+ Returns the event's service ID */
+PHP_METHOD(CommandStartedEvent, getServiceId)
+{
+ php_phongo_commandstartedevent_t* intern = Z_COMMANDSTARTEDEVENT_OBJ_P(getThis());
+
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ if (!intern->has_service_id) {
+ RETURN_NULL();
+ }
+
+ phongo_objectid_init(return_value, &intern->service_id);
+} /* }}} */
+
+/**
+ * Event thrown when a command has started to execute.
+ *
+ * This class is only constructed internally.
+ */
+
+/* {{{ MongoDB\Driver\Monitoring\CommandStartedEvent function entries */
+ZEND_BEGIN_ARG_INFO_EX(ai_CommandStartedEvent_void, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry php_phongo_commandstartedevent_me[] = {
+ /* clang-format off */
+ ZEND_NAMED_ME(__construct, PHP_FN(MongoDB_disabled___construct), ai_CommandStartedEvent_void, ZEND_ACC_PRIVATE | ZEND_ACC_FINAL)
+ PHP_ME(CommandStartedEvent, getCommand, ai_CommandStartedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(CommandStartedEvent, getCommandName, ai_CommandStartedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(CommandStartedEvent, getDatabaseName, ai_CommandStartedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(CommandStartedEvent, getOperationId, ai_CommandStartedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(CommandStartedEvent, getRequestId, ai_CommandStartedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(CommandStartedEvent, getServer, ai_CommandStartedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(CommandStartedEvent, getServiceId, ai_CommandStartedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ ZEND_NAMED_ME(__wakeup, PHP_FN(MongoDB_disabled___wakeup), ai_CommandStartedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_FE_END
+ /* clang-format on */
+};
+/* }}} */
+
+/* {{{ MongoDB\Driver\Monitoring\CommandStartedEvent object handlers */
+static zend_object_handlers php_phongo_handler_commandstartedevent;
+
+static void php_phongo_commandstartedevent_free_object(zend_object* object) /* {{{ */
+{
+ php_phongo_commandstartedevent_t* intern = Z_OBJ_COMMANDSTARTEDEVENT(object);
+
+ zend_object_std_dtor(&intern->std);
+
+ if (!Z_ISUNDEF(intern->manager)) {
+ zval_ptr_dtor(&intern->manager);
+ }
+
+ if (intern->command) {
+ bson_destroy(intern->command);
+ }
+
+ if (intern->command_name) {
+ efree(intern->command_name);
+ }
+
+ if (intern->database_name) {
+ efree(intern->database_name);
+ }
+} /* }}} */
+
+static zend_object* php_phongo_commandstartedevent_create_object(zend_class_entry* class_type) /* {{{ */
+{
+ php_phongo_commandstartedevent_t* intern = zend_object_alloc(sizeof(php_phongo_commandstartedevent_t), class_type);
+
+ zend_object_std_init(&intern->std, class_type);
+ object_properties_init(&intern->std, class_type);
+
+ intern->std.handlers = &php_phongo_handler_commandstartedevent;
+
+ return &intern->std;
+} /* }}} */
+
+static HashTable* php_phongo_commandstartedevent_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
+{
+ php_phongo_commandstartedevent_t* intern;
+ zval retval = ZVAL_STATIC_INIT;
+ char operation_id[20], request_id[20];
+ php_phongo_bson_state command_state;
+
+ PHONGO_BSON_INIT_STATE(command_state);
+
+ intern = Z_OBJ_COMMANDSTARTEDEVENT(PHONGO_COMPAT_GET_OBJ(object));
+ *is_temp = 1;
+ array_init_size(&retval, 6);
+
+ if (!php_phongo_bson_to_zval_ex(bson_get_data(intern->command), intern->command->len, &command_state)) {
+ zval_ptr_dtor(&command_state.zchild);
+ goto done;
+ }
+
+ ADD_ASSOC_ZVAL(&retval, "command", &command_state.zchild);
+
+ ADD_ASSOC_STRING(&retval, "commandName", intern->command_name);
+ ADD_ASSOC_STRING(&retval, "databaseName", intern->database_name);
+
+ sprintf(operation_id, "%" PRIu64, intern->operation_id);
+ ADD_ASSOC_STRING(&retval, "operationId", operation_id);
+
+ sprintf(request_id, "%" PRIu64, intern->request_id);
+ ADD_ASSOC_STRING(&retval, "requestId", request_id);
+
+ {
+ zval server;
+
+ phongo_server_init(&server, &intern->manager, intern->server_id);
+ ADD_ASSOC_ZVAL_EX(&retval, "server", &server);
+ }
+
+ if (intern->has_service_id) {
+ zval service_id;
+
+ phongo_objectid_init(&service_id, &intern->service_id);
+ ADD_ASSOC_ZVAL_EX(&retval, "serviceId", &service_id);
+ } else {
+ ADD_ASSOC_NULL_EX(&retval, "serviceId");
+ }
+
+done:
+ return Z_ARRVAL(retval);
+} /* }}} */
+/* }}} */
+
+void php_phongo_commandstartedevent_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+ (void) type;
+ (void) module_number;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver\\Monitoring", "CommandStartedEvent", php_phongo_commandstartedevent_me);
+ php_phongo_commandstartedevent_ce = zend_register_internal_class(&ce);
+ php_phongo_commandstartedevent_ce->create_object = php_phongo_commandstartedevent_create_object;
+ PHONGO_CE_FINAL(php_phongo_commandstartedevent_ce);
+ PHONGO_CE_DISABLE_SERIALIZATION(php_phongo_commandstartedevent_ce);
+
+ memcpy(&php_phongo_handler_commandstartedevent, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
+ php_phongo_handler_commandstartedevent.get_debug_info = php_phongo_commandstartedevent_get_debug_info;
+ php_phongo_handler_commandstartedevent.free_obj = php_phongo_commandstartedevent_free_object;
+ php_phongo_handler_commandstartedevent.offset = XtOffsetOf(php_phongo_commandstartedevent_t, std);
+
+ return;
+} /* }}} */
diff --git a/mongodb-1.13.0/src/MongoDB/Monitoring/CommandSubscriber.c b/mongodb-1.13.0/src/MongoDB/Monitoring/CommandSubscriber.c
new file mode 100644
index 00000000..34d02eaa
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/Monitoring/CommandSubscriber.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2016-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <php.h>
+
+#include "php_phongo.h"
+
+zend_class_entry* php_phongo_commandsubscriber_ce;
+
+/* {{{ MongoDB\Driver\Monitoring\CommandSubscriber function entries */
+ZEND_BEGIN_ARG_INFO_EX(ai_CommandSubscriber_commandStarted, 0, 0, 1)
+ ZEND_ARG_OBJ_INFO(0, event, MongoDB\\Driver\\Monitoring\\CommandStartedEvent, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_CommandSubscriber_commandSucceeded, 0, 0, 1)
+ ZEND_ARG_OBJ_INFO(0, event, MongoDB\\Driver\\Monitoring\\CommandSucceededEvent, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_CommandSubscriber_commandFailed, 0, 0, 1)
+ ZEND_ARG_OBJ_INFO(0, event, MongoDB\\Driver\\Monitoring\\CommandFailedEvent, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry php_phongo_commandsubscriber_me[] = {
+ /* clang-format off */
+ ZEND_ABSTRACT_ME(CommandSubscriber, commandStarted, ai_CommandSubscriber_commandStarted)
+ ZEND_ABSTRACT_ME(CommandSubscriber, commandSucceeded, ai_CommandSubscriber_commandSucceeded)
+ ZEND_ABSTRACT_ME(CommandSubscriber, commandFailed, ai_CommandSubscriber_commandFailed)
+ PHP_FE_END
+ /* clang-format on */
+};
+/* }}} */
+
+void php_phongo_commandsubscriber_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+ (void) type;
+ (void) module_number;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver\\Monitoring", "CommandSubscriber", php_phongo_commandsubscriber_me);
+ php_phongo_commandsubscriber_ce = zend_register_internal_interface(&ce);
+ zend_class_implements(php_phongo_commandsubscriber_ce, 1, php_phongo_subscriber_ce);
+
+ return;
+} /* }}} */
diff --git a/mongodb-1.13.0/src/MongoDB/Monitoring/CommandSucceededEvent.c b/mongodb-1.13.0/src/MongoDB/Monitoring/CommandSucceededEvent.c
new file mode 100644
index 00000000..3fa47b77
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/Monitoring/CommandSucceededEvent.c
@@ -0,0 +1,300 @@
+/*
+ * Copyright 2016-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bson/bson.h"
+
+#include <php.h>
+#include <Zend/zend_interfaces.h>
+
+#include "php_phongo.h"
+#include "phongo_bson_encode.h"
+#include "phongo_error.h"
+
+#include "BSON/ObjectId.h"
+#include "MongoDB/Server.h"
+
+zend_class_entry* php_phongo_commandsucceededevent_ce;
+
+/* {{{ proto string CommandSucceededEvent::getCommandName()
+ Returns the command name for this event */
+PHP_METHOD(CommandSucceededEvent, getCommandName)
+{
+ zend_error_handling error_handling;
+ php_phongo_commandsucceededevent_t* intern;
+
+ intern = Z_COMMANDSUCCEEDEDEVENT_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ RETVAL_STRING(intern->command_name);
+} /* }}} */
+
+/* {{{ proto int CommandSucceededEvent::getDurationMicros()
+ Returns the event's duration in microseconds */
+PHP_METHOD(CommandSucceededEvent, getDurationMicros)
+{
+ zend_error_handling error_handling;
+ php_phongo_commandsucceededevent_t* intern;
+
+ intern = Z_COMMANDSUCCEEDEDEVENT_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ RETURN_LONG(intern->duration_micros);
+} /* }}} */
+
+/* {{{ proto string CommandSucceededEvent::getOperationId()
+ Returns the event's operation ID */
+PHP_METHOD(CommandSucceededEvent, getOperationId)
+{
+ zend_error_handling error_handling;
+ php_phongo_commandsucceededevent_t* intern;
+ char int_as_string[20];
+
+ intern = Z_COMMANDSUCCEEDEDEVENT_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ sprintf(int_as_string, "%" PRIu64, intern->operation_id);
+ RETVAL_STRING(int_as_string);
+} /* }}} */
+
+/* {{{ proto stdClass CommandSucceededEvent::getReply()
+ Returns the reply document associated with the event */
+PHP_METHOD(CommandSucceededEvent, getReply)
+{
+ zend_error_handling error_handling;
+ php_phongo_commandsucceededevent_t* intern;
+ php_phongo_bson_state state;
+
+ PHONGO_BSON_INIT_STATE(state);
+
+ intern = Z_COMMANDSUCCEEDEDEVENT_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ if (!php_phongo_bson_to_zval_ex(bson_get_data(intern->reply), intern->reply->len, &state)) {
+ zval_ptr_dtor(&state.zchild);
+ return;
+ }
+
+ RETURN_ZVAL(&state.zchild, 0, 1);
+} /* }}} */
+
+/* {{{ proto string CommandsucceededEvent::getRequestId()
+ Returns the event's request ID */
+PHP_METHOD(CommandSucceededEvent, getRequestId)
+{
+ zend_error_handling error_handling;
+ php_phongo_commandsucceededevent_t* intern;
+ char int_as_string[20];
+
+ intern = Z_COMMANDSUCCEEDEDEVENT_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ sprintf(int_as_string, "%" PRIu64, intern->request_id);
+ RETVAL_STRING(int_as_string);
+} /* }}} */
+
+/* {{{ proto MongoDB\Driver\Server CommandSucceededEvent::getServer()
+ Returns the Server from which the event originated */
+PHP_METHOD(CommandSucceededEvent, getServer)
+{
+ zend_error_handling error_handling;
+ php_phongo_commandsucceededevent_t* intern;
+
+ intern = Z_COMMANDSUCCEEDEDEVENT_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ phongo_server_init(return_value, &intern->manager, intern->server_id);
+} /* }}} */
+
+/* {{{ proto MongoDB\BSON\ObjectId|null CommandSucceededEvent::getServiceId()
+ Returns the event's service ID */
+PHP_METHOD(CommandSucceededEvent, getServiceId)
+{
+ php_phongo_commandsucceededevent_t* intern = Z_COMMANDSUCCEEDEDEVENT_OBJ_P(getThis());
+
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ if (!intern->has_service_id) {
+ RETURN_NULL();
+ }
+
+ phongo_objectid_init(return_value, &intern->service_id);
+} /* }}} */
+
+/**
+ * Event thrown when a command has succeeded to execute.
+ *
+ * This class is only constructed internally.
+ */
+
+/* {{{ MongoDB\Driver\Monitoring\CommandSucceededEvent function entries */
+ZEND_BEGIN_ARG_INFO_EX(ai_CommandSucceededEvent_void, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry php_phongo_commandsucceededevent_me[] = {
+ /* clang-format off */
+ ZEND_NAMED_ME(__construct, PHP_FN(MongoDB_disabled___construct), ai_CommandSucceededEvent_void, ZEND_ACC_PRIVATE | ZEND_ACC_FINAL)
+ PHP_ME(CommandSucceededEvent, getCommandName, ai_CommandSucceededEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(CommandSucceededEvent, getDurationMicros, ai_CommandSucceededEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(CommandSucceededEvent, getOperationId, ai_CommandSucceededEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(CommandSucceededEvent, getReply, ai_CommandSucceededEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(CommandSucceededEvent, getRequestId, ai_CommandSucceededEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(CommandSucceededEvent, getServer, ai_CommandSucceededEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(CommandSucceededEvent, getServiceId, ai_CommandSucceededEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ ZEND_NAMED_ME(__wakeup, PHP_FN(MongoDB_disabled___wakeup), ai_CommandSucceededEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_FE_END
+ /* clang-format on */
+};
+/* }}} */
+
+/* {{{ MongoDB\Driver\Monitoring\CommandSucceededEvent object handlers */
+static zend_object_handlers php_phongo_handler_commandsucceededevent;
+
+static void php_phongo_commandsucceededevent_free_object(zend_object* object) /* {{{ */
+{
+ php_phongo_commandsucceededevent_t* intern = Z_OBJ_COMMANDSUCCEEDEDEVENT(object);
+
+ zend_object_std_dtor(&intern->std);
+
+ if (!Z_ISUNDEF(intern->manager)) {
+ zval_ptr_dtor(&intern->manager);
+ }
+
+ if (intern->reply) {
+ bson_destroy(intern->reply);
+ }
+
+ if (intern->command_name) {
+ efree(intern->command_name);
+ }
+} /* }}} */
+
+static zend_object* php_phongo_commandsucceededevent_create_object(zend_class_entry* class_type) /* {{{ */
+{
+ php_phongo_commandsucceededevent_t* intern = zend_object_alloc(sizeof(php_phongo_commandsucceededevent_t), class_type);
+
+ zend_object_std_init(&intern->std, class_type);
+ object_properties_init(&intern->std, class_type);
+
+ intern->std.handlers = &php_phongo_handler_commandsucceededevent;
+
+ return &intern->std;
+} /* }}} */
+
+static HashTable* php_phongo_commandsucceededevent_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
+{
+ php_phongo_commandsucceededevent_t* intern;
+ zval retval = ZVAL_STATIC_INIT;
+ char operation_id[20], request_id[20];
+ php_phongo_bson_state reply_state;
+
+ PHONGO_BSON_INIT_STATE(reply_state);
+
+ intern = Z_OBJ_COMMANDSUCCEEDEDEVENT(PHONGO_COMPAT_GET_OBJ(object));
+ *is_temp = 1;
+ array_init_size(&retval, 6);
+
+ ADD_ASSOC_STRING(&retval, "commandName", intern->command_name);
+ ADD_ASSOC_INT64(&retval, "durationMicros", (int64_t) intern->duration_micros);
+
+ sprintf(operation_id, "%" PRIu64, intern->operation_id);
+ ADD_ASSOC_STRING(&retval, "operationId", operation_id);
+
+ if (!php_phongo_bson_to_zval_ex(bson_get_data(intern->reply), intern->reply->len, &reply_state)) {
+ zval_ptr_dtor(&reply_state.zchild);
+ goto done;
+ }
+
+ ADD_ASSOC_ZVAL(&retval, "reply", &reply_state.zchild);
+
+ sprintf(request_id, "%" PRIu64, intern->request_id);
+ ADD_ASSOC_STRING(&retval, "requestId", request_id);
+
+ {
+ zval server;
+
+ phongo_server_init(&server, &intern->manager, intern->server_id);
+ ADD_ASSOC_ZVAL_EX(&retval, "server", &server);
+ }
+
+ if (intern->has_service_id) {
+ zval service_id;
+
+ phongo_objectid_init(&service_id, &intern->service_id);
+ ADD_ASSOC_ZVAL_EX(&retval, "serviceId", &service_id);
+ } else {
+ ADD_ASSOC_NULL_EX(&retval, "serviceId");
+ }
+
+done:
+ return Z_ARRVAL(retval);
+} /* }}} */
+/* }}} */
+
+void php_phongo_commandsucceededevent_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+ (void) type;
+ (void) module_number;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver\\Monitoring", "CommandSucceededEvent", php_phongo_commandsucceededevent_me);
+ php_phongo_commandsucceededevent_ce = zend_register_internal_class(&ce);
+ php_phongo_commandsucceededevent_ce->create_object = php_phongo_commandsucceededevent_create_object;
+ PHONGO_CE_FINAL(php_phongo_commandsucceededevent_ce);
+ PHONGO_CE_DISABLE_SERIALIZATION(php_phongo_commandsucceededevent_ce);
+
+ memcpy(&php_phongo_handler_commandsucceededevent, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
+ php_phongo_handler_commandsucceededevent.get_debug_info = php_phongo_commandsucceededevent_get_debug_info;
+ php_phongo_handler_commandsucceededevent.free_obj = php_phongo_commandsucceededevent_free_object;
+ php_phongo_handler_commandsucceededevent.offset = XtOffsetOf(php_phongo_commandsucceededevent_t, std);
+
+ return;
+} /* }}} */
diff --git a/mongodb-1.13.0/src/MongoDB/Monitoring/SDAMSubscriber.c b/mongodb-1.13.0/src/MongoDB/Monitoring/SDAMSubscriber.c
new file mode 100644
index 00000000..a2e2cba9
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/Monitoring/SDAMSubscriber.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2021-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <php.h>
+
+#include "php_phongo.h"
+
+zend_class_entry* php_phongo_sdamsubscriber_ce;
+
+/* {{{ MongoDB\Driver\Monitoring\SDAMSubscriber function entries */
+ZEND_BEGIN_ARG_INFO_EX(ai_SDAMSubscriber_serverChanged, 0, 0, 1)
+ ZEND_ARG_OBJ_INFO(0, event, MongoDB\\Driver\\Monitoring\\ServerChangedEvent, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_SDAMSubscriber_serverClosed, 0, 0, 1)
+ ZEND_ARG_OBJ_INFO(0, event, MongoDB\\Driver\\Monitoring\\ServerClosedEvent, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_SDAMSubscriber_serverOpening, 0, 0, 1)
+ ZEND_ARG_OBJ_INFO(0, event, MongoDB\\Driver\\Monitoring\\ServerOpeningEvent, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_SDAMSubscriber_serverHeartbeatFailed, 0, 0, 1)
+ ZEND_ARG_OBJ_INFO(0, event, MongoDB\\Driver\\Monitoring\\ServerHeartbeatFailedEvent, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_SDAMSubscriber_serverHeartbeatStarted, 0, 0, 1)
+ ZEND_ARG_OBJ_INFO(0, event, MongoDB\\Driver\\Monitoring\\ServerHeartbeatStartedEvent, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_SDAMSubscriber_serverHeartbeatSucceeded, 0, 0, 1)
+ ZEND_ARG_OBJ_INFO(0, event, MongoDB\\Driver\\Monitoring\\ServerHeartbeatSucceededEvent, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_SDAMSubscriber_topologyChanged, 0, 0, 1)
+ ZEND_ARG_OBJ_INFO(0, event, MongoDB\\Driver\\Monitoring\\TopologyChangedEvent, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_SDAMSubscriber_topologyClosed, 0, 0, 1)
+ ZEND_ARG_OBJ_INFO(0, event, MongoDB\\Driver\\Monitoring\\TopologyClosedEvent, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_SDAMSubscriber_topologyOpening, 0, 0, 1)
+ ZEND_ARG_OBJ_INFO(0, event, MongoDB\\Driver\\Monitoring\\TopologyOpeningEvent, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry php_phongo_sdamsubscriber_me[] = {
+ /* clang-format off */
+ ZEND_ABSTRACT_ME(SDAMSubscriber, serverChanged, ai_SDAMSubscriber_serverChanged)
+ ZEND_ABSTRACT_ME(SDAMSubscriber, serverClosed, ai_SDAMSubscriber_serverClosed)
+ ZEND_ABSTRACT_ME(SDAMSubscriber, serverOpening, ai_SDAMSubscriber_serverOpening)
+ ZEND_ABSTRACT_ME(SDAMSubscriber, serverHeartbeatFailed, ai_SDAMSubscriber_serverHeartbeatFailed)
+ ZEND_ABSTRACT_ME(SDAMSubscriber, serverHeartbeatStarted, ai_SDAMSubscriber_serverHeartbeatStarted)
+ ZEND_ABSTRACT_ME(SDAMSubscriber, serverHeartbeatSucceeded, ai_SDAMSubscriber_serverHeartbeatSucceeded)
+ ZEND_ABSTRACT_ME(SDAMSubscriber, topologyChanged, ai_SDAMSubscriber_topologyChanged)
+ ZEND_ABSTRACT_ME(SDAMSubscriber, topologyClosed, ai_SDAMSubscriber_topologyClosed)
+ ZEND_ABSTRACT_ME(SDAMSubscriber, topologyOpening, ai_SDAMSubscriber_topologyOpening)
+ PHP_FE_END
+ /* clang-format on */
+};
+/* }}} */
+
+void php_phongo_sdamsubscriber_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+ (void) type;
+ (void) module_number;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver\\Monitoring", "SDAMSubscriber", php_phongo_sdamsubscriber_me);
+ php_phongo_sdamsubscriber_ce = zend_register_internal_interface(&ce);
+ zend_class_implements(php_phongo_sdamsubscriber_ce, 1, php_phongo_subscriber_ce);
+
+ return;
+} /* }}} */
diff --git a/mongodb-1.13.0/src/MongoDB/Monitoring/ServerChangedEvent.c b/mongodb-1.13.0/src/MongoDB/Monitoring/ServerChangedEvent.c
new file mode 100644
index 00000000..edb15cfe
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/Monitoring/ServerChangedEvent.c
@@ -0,0 +1,186 @@
+/*
+ * Copyright 2021-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mongoc/mongoc.h"
+
+#include <php.h>
+#include <Zend/zend_interfaces.h>
+
+#include "php_phongo.h"
+#include "phongo_error.h"
+
+#include "BSON/ObjectId.h"
+#include "MongoDB/Server.h"
+#include "MongoDB/ServerDescription.h"
+
+zend_class_entry* php_phongo_serverchangedevent_ce;
+
+/* {{{ proto string ServerChangedEvent::getHost()
+ Returns this event's host */
+static PHP_METHOD(ServerChangedEvent, getHost)
+{
+ php_phongo_serverchangedevent_t* intern = Z_SERVERCHANGEDEVENT_OBJ_P(getThis());
+
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ RETVAL_STRING(intern->host.host);
+} /* }}} */
+
+/* {{{ proto integer ServerChangedEvent::getPort()
+ Returns this event's port */
+static PHP_METHOD(ServerChangedEvent, getPort)
+{
+ php_phongo_serverchangedevent_t* intern = Z_SERVERCHANGEDEVENT_OBJ_P(getThis());
+
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ RETVAL_LONG(intern->host.port);
+} /* }}} */
+
+/* {{{ proto MongoDB\Driver\ServerDescription ServerChangedEvent::getNewDescription()
+ Returns this event's new description */
+static PHP_METHOD(ServerChangedEvent, getNewDescription)
+{
+ php_phongo_serverchangedevent_t* intern = Z_SERVERCHANGEDEVENT_OBJ_P(getThis());
+
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ phongo_serverdescription_init(return_value, intern->new_server_description);
+} /* }}} */
+
+/* {{{ proto MongoDB\Driver\ServerDescription ServerChangedEvent::getPreviousDescription()
+ Returns this event's previous description */
+static PHP_METHOD(ServerChangedEvent, getPreviousDescription)
+{
+ php_phongo_serverchangedevent_t* intern = Z_SERVERCHANGEDEVENT_OBJ_P(getThis());
+
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ phongo_serverdescription_init(return_value, intern->old_server_description);
+} /* }}} */
+
+/* {{{ proto MongoDB\BSON\ObjectId ServerChangedEvent::getTopologyId()
+ Returns this event's topology id */
+static PHP_METHOD(ServerChangedEvent, getTopologyId)
+{
+ php_phongo_serverchangedevent_t* intern = Z_SERVERCHANGEDEVENT_OBJ_P(getThis());
+
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ phongo_objectid_init(return_value, &intern->topology_id);
+} /* }}} */
+
+/* {{{ MongoDB\Driver\Monitoring\ServerChangedEvent function entries */
+ZEND_BEGIN_ARG_INFO_EX(ai_ServerChangedEvent_void, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry php_phongo_serverchangedevent_me[] = {
+ /* clang-format off */
+ ZEND_NAMED_ME(__construct, PHP_FN(MongoDB_disabled___construct), ai_ServerChangedEvent_void, ZEND_ACC_PRIVATE | ZEND_ACC_FINAL)
+ PHP_ME(ServerChangedEvent, getHost, ai_ServerChangedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(ServerChangedEvent, getPort, ai_ServerChangedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(ServerChangedEvent, getNewDescription, ai_ServerChangedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(ServerChangedEvent, getPreviousDescription, ai_ServerChangedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(ServerChangedEvent, getTopologyId, ai_ServerChangedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ ZEND_NAMED_ME(__wakeup, PHP_FN(MongoDB_disabled___wakeup), ai_ServerChangedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_FE_END
+ /* clang-format on */
+};
+/* }}} */
+
+/* {{{ MongoDB\Driver\Monitoring\ServerChangedEvent object handlers */
+static zend_object_handlers php_phongo_handler_serverchangedevent;
+
+static void php_phongo_serverchangedevent_free_object(zend_object* object) /* {{{ */
+{
+ php_phongo_serverchangedevent_t* intern = Z_OBJ_SERVERCHANGEDEVENT(object);
+
+ zend_object_std_dtor(&intern->std);
+
+ if (intern->new_server_description) {
+ mongoc_server_description_destroy(intern->new_server_description);
+ }
+
+ if (intern->old_server_description) {
+ mongoc_server_description_destroy(intern->old_server_description);
+ }
+} /* }}} */
+
+static zend_object* php_phongo_serverchangedevent_create_object(zend_class_entry* class_type) /* {{{ */
+{
+ php_phongo_serverchangedevent_t* intern = zend_object_alloc(sizeof(php_phongo_serverchangedevent_t), class_type);
+
+ zend_object_std_init(&intern->std, class_type);
+ object_properties_init(&intern->std, class_type);
+
+ intern->std.handlers = &php_phongo_handler_serverchangedevent;
+
+ return &intern->std;
+} /* }}} */
+
+static HashTable* php_phongo_serverchangedevent_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
+{
+ php_phongo_serverchangedevent_t* intern;
+ zval retval = ZVAL_STATIC_INIT;
+
+ intern = Z_OBJ_SERVERCHANGEDEVENT(PHONGO_COMPAT_GET_OBJ(object));
+ *is_temp = 1;
+ array_init_size(&retval, 4);
+
+ ADD_ASSOC_STRING(&retval, "host", intern->host.host);
+ ADD_ASSOC_LONG_EX(&retval, "port", intern->host.port);
+
+ {
+ zval topology_id;
+ phongo_objectid_init(&topology_id, &intern->topology_id);
+ ADD_ASSOC_ZVAL_EX(&retval, "topologyId", &topology_id);
+ }
+
+ {
+ zval new_sd;
+ phongo_serverdescription_init(&new_sd, intern->new_server_description);
+ ADD_ASSOC_ZVAL_EX(&retval, "newDescription", &new_sd);
+ }
+
+ {
+ zval old_sd;
+ phongo_serverdescription_init(&old_sd, intern->old_server_description);
+ ADD_ASSOC_ZVAL_EX(&retval, "oldDescription", &old_sd);
+ }
+
+ return Z_ARRVAL(retval);
+} /* }}} */
+/* }}} */
+
+void php_phongo_serverchangedevent_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+ (void) type;
+ (void) module_number;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver\\Monitoring", "ServerChangedEvent", php_phongo_serverchangedevent_me);
+ php_phongo_serverchangedevent_ce = zend_register_internal_class(&ce);
+ php_phongo_serverchangedevent_ce->create_object = php_phongo_serverchangedevent_create_object;
+ PHONGO_CE_FINAL(php_phongo_serverchangedevent_ce);
+ PHONGO_CE_DISABLE_SERIALIZATION(php_phongo_serverchangedevent_ce);
+
+ memcpy(&php_phongo_handler_serverchangedevent, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
+ php_phongo_handler_serverchangedevent.get_debug_info = php_phongo_serverchangedevent_get_debug_info;
+ php_phongo_handler_serverchangedevent.free_obj = php_phongo_serverchangedevent_free_object;
+ php_phongo_handler_serverchangedevent.offset = XtOffsetOf(php_phongo_serverchangedevent_t, std);
+
+ return;
+} /* }}} */
diff --git a/mongodb-1.13.0/src/MongoDB/Monitoring/ServerClosedEvent.c b/mongodb-1.13.0/src/MongoDB/Monitoring/ServerClosedEvent.c
new file mode 100644
index 00000000..132660c5
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/Monitoring/ServerClosedEvent.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2021-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <php.h>
+#include <Zend/zend_interfaces.h>
+
+#include "php_phongo.h"
+#include "phongo_error.h"
+
+#include "BSON/ObjectId.h"
+
+zend_class_entry* php_phongo_serverclosedevent_ce;
+
+/* {{{ proto string ServerClosedEvent::getHost()
+ Returns this event's host */
+static PHP_METHOD(ServerClosedEvent, getHost)
+{
+ php_phongo_serverclosedevent_t* intern = Z_SERVERCLOSEDEVENT_OBJ_P(getThis());
+
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ RETVAL_STRING(intern->host.host);
+} /* }}} */
+
+/* {{{ proto integer ServerClosedEvent::getPort()
+ Returns this event's port */
+static PHP_METHOD(ServerClosedEvent, getPort)
+{
+ php_phongo_serverclosedevent_t* intern = Z_SERVERCLOSEDEVENT_OBJ_P(getThis());
+
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ RETVAL_LONG(intern->host.port);
+} /* }}} */
+
+/* {{{ proto MongoDB\BSON\ObjectId ServerClosedEvent::getTopologyId()
+ Returns this event's topology id */
+static PHP_METHOD(ServerClosedEvent, getTopologyId)
+{
+ php_phongo_serverclosedevent_t* intern = Z_SERVERCLOSEDEVENT_OBJ_P(getThis());
+
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ phongo_objectid_init(return_value, &intern->topology_id);
+} /* }}} */
+
+/* {{{ MongoDB\Driver\Monitoring\ServerClosedEvent function entries */
+ZEND_BEGIN_ARG_INFO_EX(ai_ServerClosedEvent_void, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry php_phongo_serverclosedevent_me[] = {
+ /* clang-format off */
+ ZEND_NAMED_ME(__construct, PHP_FN(MongoDB_disabled___construct), ai_ServerClosedEvent_void, ZEND_ACC_PRIVATE | ZEND_ACC_FINAL)
+ PHP_ME(ServerClosedEvent, getHost, ai_ServerClosedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(ServerClosedEvent, getPort, ai_ServerClosedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(ServerClosedEvent, getTopologyId, ai_ServerClosedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ ZEND_NAMED_ME(__wakeup, PHP_FN(MongoDB_disabled___wakeup), ai_ServerClosedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_FE_END
+ /* clang-format on */
+};
+/* }}} */
+
+/* {{{ MongoDB\Driver\Monitoring\ServerClosedEvent object handlers */
+static zend_object_handlers php_phongo_handler_serverclosedevent;
+
+static void php_phongo_serverclosedevent_free_object(zend_object* object) /* {{{ */
+{
+ php_phongo_serverclosedevent_t* intern = Z_OBJ_SERVERCLOSEDEVENT(object);
+
+ zend_object_std_dtor(&intern->std);
+} /* }}} */
+
+static zend_object* php_phongo_serverclosedevent_create_object(zend_class_entry* class_type) /* {{{ */
+{
+ php_phongo_serverclosedevent_t* intern = zend_object_alloc(sizeof(php_phongo_serverclosedevent_t), class_type);
+
+ zend_object_std_init(&intern->std, class_type);
+ object_properties_init(&intern->std, class_type);
+
+ intern->std.handlers = &php_phongo_handler_serverclosedevent;
+
+ return &intern->std;
+} /* }}} */
+
+static HashTable* php_phongo_serverclosedevent_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
+{
+ php_phongo_serverclosedevent_t* intern;
+ zval retval = ZVAL_STATIC_INIT;
+
+ intern = Z_OBJ_SERVERCLOSEDEVENT(PHONGO_COMPAT_GET_OBJ(object));
+ *is_temp = 1;
+ array_init_size(&retval, 3);
+
+ ADD_ASSOC_STRING(&retval, "host", intern->host.host);
+ ADD_ASSOC_LONG_EX(&retval, "port", intern->host.port);
+
+ {
+ zval topology_id;
+ phongo_objectid_init(&topology_id, &intern->topology_id);
+ ADD_ASSOC_ZVAL_EX(&retval, "topologyId", &topology_id);
+ }
+
+ return Z_ARRVAL(retval);
+} /* }}} */
+/* }}} */
+
+void php_phongo_serverclosedevent_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+ (void) type;
+ (void) module_number;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver\\Monitoring", "ServerClosedEvent", php_phongo_serverclosedevent_me);
+ php_phongo_serverclosedevent_ce = zend_register_internal_class(&ce);
+ php_phongo_serverclosedevent_ce->create_object = php_phongo_serverclosedevent_create_object;
+ PHONGO_CE_FINAL(php_phongo_serverclosedevent_ce);
+ PHONGO_CE_DISABLE_SERIALIZATION(php_phongo_serverclosedevent_ce);
+
+ memcpy(&php_phongo_handler_serverclosedevent, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
+ php_phongo_handler_serverclosedevent.get_debug_info = php_phongo_serverclosedevent_get_debug_info;
+ php_phongo_handler_serverclosedevent.free_obj = php_phongo_serverclosedevent_free_object;
+ php_phongo_handler_serverclosedevent.offset = XtOffsetOf(php_phongo_serverclosedevent_t, std);
+
+ return;
+} /* }}} */
diff --git a/mongodb-1.13.0/src/MongoDB/Monitoring/ServerHeartbeatFailedEvent.c b/mongodb-1.13.0/src/MongoDB/Monitoring/ServerHeartbeatFailedEvent.c
new file mode 100644
index 00000000..7339839a
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/Monitoring/ServerHeartbeatFailedEvent.c
@@ -0,0 +1,163 @@
+/*
+ * Copyright 2021-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <php.h>
+#include <Zend/zend_interfaces.h>
+
+#include "php_phongo.h"
+#include "phongo_error.h"
+
+zend_class_entry* php_phongo_serverheartbeatfailedevent_ce;
+
+/* {{{ proto integer ServerHeartbeatFailedEvent::getDurationMicros()
+ Returns this event's duration in microseconds */
+static PHP_METHOD(ServerHeartbeatFailedEvent, getDurationMicros)
+{
+ php_phongo_serverheartbeatfailedevent_t* intern = Z_SERVERHEARTBEATFAILEDEVENT_OBJ_P(getThis());
+
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ RETVAL_LONG(intern->duration_micros);
+} /* }}} */
+
+/* {{{ proto Exception ServerHeartbeatFailedEvent::getError()
+ Returns the error associated with the event */
+PHP_METHOD(ServerHeartbeatFailedEvent, getError)
+{
+ php_phongo_serverheartbeatfailedevent_t* intern = Z_SERVERHEARTBEATFAILEDEVENT_OBJ_P(getThis());
+
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ RETURN_ZVAL(&intern->z_error, 1, 0);
+} /* }}} */
+
+/* {{{ proto string ServerHeartbeatFailedEvent::getHost()
+ Returns this event's host */
+static PHP_METHOD(ServerHeartbeatFailedEvent, getHost)
+{
+ php_phongo_serverheartbeatfailedevent_t* intern = Z_SERVERHEARTBEATFAILEDEVENT_OBJ_P(getThis());
+
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ RETVAL_STRING(intern->host.host);
+} /* }}} */
+
+/* {{{ proto integer ServerHeartbeatFailedEvent::getPort()
+ Returns this event's port */
+static PHP_METHOD(ServerHeartbeatFailedEvent, getPort)
+{
+ php_phongo_serverheartbeatfailedevent_t* intern = Z_SERVERHEARTBEATFAILEDEVENT_OBJ_P(getThis());
+
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ RETVAL_LONG(intern->host.port);
+} /* }}} */
+
+/* {{{ proto boolean ServerHeartbeatFailedEvent::isAwaited()
+ Returns whether this event came from an awaitable hello */
+static PHP_METHOD(ServerHeartbeatFailedEvent, isAwaited)
+{
+ php_phongo_serverheartbeatfailedevent_t* intern = Z_SERVERHEARTBEATFAILEDEVENT_OBJ_P(getThis());
+
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ RETVAL_BOOL(intern->awaited);
+} /* }}} */
+
+/* {{{ MongoDB\Driver\Monitoring\ServerHeartbeatFailedEvent function entries */
+ZEND_BEGIN_ARG_INFO_EX(ai_ServerHeartbeatFailedEvent_void, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry php_phongo_serverheartbeatfailedevent_me[] = {
+ /* clang-format off */
+ ZEND_NAMED_ME(__construct, PHP_FN(MongoDB_disabled___construct), ai_ServerHeartbeatFailedEvent_void, ZEND_ACC_PRIVATE | ZEND_ACC_FINAL)
+ PHP_ME(ServerHeartbeatFailedEvent, getDurationMicros, ai_ServerHeartbeatFailedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(ServerHeartbeatFailedEvent, getError, ai_ServerHeartbeatFailedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(ServerHeartbeatFailedEvent, getHost, ai_ServerHeartbeatFailedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(ServerHeartbeatFailedEvent, getPort, ai_ServerHeartbeatFailedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(ServerHeartbeatFailedEvent, isAwaited, ai_ServerHeartbeatFailedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ ZEND_NAMED_ME(__wakeup, PHP_FN(MongoDB_disabled___wakeup), ai_ServerHeartbeatFailedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_FE_END
+ /* clang-format on */
+};
+/* }}} */
+
+/* {{{ MongoDB\Driver\Monitoring\ServerHeartbeatFailedEvent object handlers */
+static zend_object_handlers php_phongo_handler_serverheartbeatfailedevent;
+
+static void php_phongo_serverheartbeatfailedevent_free_object(zend_object* object) /* {{{ */
+{
+ php_phongo_serverheartbeatfailedevent_t* intern = Z_OBJ_SERVERHEARTBEATFAILEDEVENT(object);
+
+ zend_object_std_dtor(&intern->std);
+
+ if (!Z_ISUNDEF(intern->z_error)) {
+ zval_ptr_dtor(&intern->z_error);
+ }
+} /* }}} */
+
+static zend_object* php_phongo_serverheartbeatfailedevent_create_object(zend_class_entry* class_type) /* {{{ */
+{
+ php_phongo_serverheartbeatfailedevent_t* intern = zend_object_alloc(sizeof(php_phongo_serverheartbeatfailedevent_t), class_type);
+
+ zend_object_std_init(&intern->std, class_type);
+ object_properties_init(&intern->std, class_type);
+
+ intern->std.handlers = &php_phongo_handler_serverheartbeatfailedevent;
+
+ return &intern->std;
+} /* }}} */
+
+static HashTable* php_phongo_serverheartbeatfailedevent_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
+{
+ php_phongo_serverheartbeatfailedevent_t* intern;
+ zval retval = ZVAL_STATIC_INIT;
+
+ intern = Z_OBJ_SERVERHEARTBEATFAILEDEVENT(PHONGO_COMPAT_GET_OBJ(object));
+ *is_temp = 1;
+ array_init_size(&retval, 5);
+
+ ADD_ASSOC_STRING(&retval, "host", intern->host.host);
+ ADD_ASSOC_LONG_EX(&retval, "port", intern->host.port);
+ ADD_ASSOC_BOOL_EX(&retval, "awaited", intern->awaited);
+ ADD_ASSOC_INT64(&retval, "durationMicros", intern->duration_micros);
+
+ ADD_ASSOC_ZVAL_EX(&retval, "error", &intern->z_error);
+ Z_ADDREF(intern->z_error);
+
+ return Z_ARRVAL(retval);
+} /* }}} */
+/* }}} */
+
+void php_phongo_serverheartbeatfailedevent_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+ (void) type;
+ (void) module_number;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver\\Monitoring", "ServerHeartbeatFailedEvent", php_phongo_serverheartbeatfailedevent_me);
+ php_phongo_serverheartbeatfailedevent_ce = zend_register_internal_class(&ce);
+ php_phongo_serverheartbeatfailedevent_ce->create_object = php_phongo_serverheartbeatfailedevent_create_object;
+ PHONGO_CE_FINAL(php_phongo_serverheartbeatfailedevent_ce);
+ PHONGO_CE_DISABLE_SERIALIZATION(php_phongo_serverheartbeatfailedevent_ce);
+
+ memcpy(&php_phongo_handler_serverheartbeatfailedevent, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
+ php_phongo_handler_serverheartbeatfailedevent.get_debug_info = php_phongo_serverheartbeatfailedevent_get_debug_info;
+ php_phongo_handler_serverheartbeatfailedevent.free_obj = php_phongo_serverheartbeatfailedevent_free_object;
+ php_phongo_handler_serverheartbeatfailedevent.offset = XtOffsetOf(php_phongo_serverheartbeatfailedevent_t, std);
+
+ return;
+} /* }}} */
diff --git a/mongodb-1.13.0/src/MongoDB/Monitoring/ServerHeartbeatStartedEvent.c b/mongodb-1.13.0/src/MongoDB/Monitoring/ServerHeartbeatStartedEvent.c
new file mode 100644
index 00000000..b2de5c86
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/Monitoring/ServerHeartbeatStartedEvent.c
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2021-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <php.h>
+#include <Zend/zend_interfaces.h>
+
+#include "php_phongo.h"
+#include "phongo_error.h"
+
+zend_class_entry* php_phongo_serverheartbeatstartedevent_ce;
+
+/* {{{ proto string ServerHeartbeatStartedEvent::getHost()
+ Returns this event's host */
+static PHP_METHOD(ServerHeartbeatStartedEvent, getHost)
+{
+ php_phongo_serverheartbeatstartedevent_t* intern = Z_SERVERHEARTBEATSTARTEDEVENT_OBJ_P(getThis());
+
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ RETVAL_STRING(intern->host.host);
+} /* }}} */
+
+/* {{{ proto integer ServerHeartbeatStartedEvent::getPort()
+ Returns this event's port */
+static PHP_METHOD(ServerHeartbeatStartedEvent, getPort)
+{
+ php_phongo_serverheartbeatstartedevent_t* intern = Z_SERVERHEARTBEATSTARTEDEVENT_OBJ_P(getThis());
+
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ RETVAL_LONG(intern->host.port);
+} /* }}} */
+
+/* {{{ proto boolean ServerHeartbeatStartedEvent::isAwaited()
+ Returns whether this event came from an awaitable hello */
+static PHP_METHOD(ServerHeartbeatStartedEvent, isAwaited)
+{
+ php_phongo_serverheartbeatstartedevent_t* intern = Z_SERVERHEARTBEATSTARTEDEVENT_OBJ_P(getThis());
+
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ RETVAL_BOOL(intern->awaited);
+} /* }}} */
+
+/* {{{ MongoDB\Driver\Monitoring\ServerHeartbeatStartedEvent function entries */
+ZEND_BEGIN_ARG_INFO_EX(ai_ServerHeartbeatStartedEvent_void, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry php_phongo_serverheartbeatstartedevent_me[] = {
+ /* clang-format off */
+ ZEND_NAMED_ME(__construct, PHP_FN(MongoDB_disabled___construct), ai_ServerHeartbeatStartedEvent_void, ZEND_ACC_PRIVATE | ZEND_ACC_FINAL)
+ PHP_ME(ServerHeartbeatStartedEvent, getHost, ai_ServerHeartbeatStartedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(ServerHeartbeatStartedEvent, getPort, ai_ServerHeartbeatStartedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(ServerHeartbeatStartedEvent, isAwaited, ai_ServerHeartbeatStartedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ ZEND_NAMED_ME(__wakeup, PHP_FN(MongoDB_disabled___wakeup), ai_ServerHeartbeatStartedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_FE_END
+ /* clang-format on */
+};
+/* }}} */
+
+/* {{{ MongoDB\Driver\Monitoring\ServerHeartbeatStartedEvent object handlers */
+static zend_object_handlers php_phongo_handler_serverheartbeatstartedevent;
+
+static void php_phongo_serverheartbeatstartedevent_free_object(zend_object* object) /* {{{ */
+{
+ php_phongo_serverheartbeatstartedevent_t* intern = Z_OBJ_SERVERHEARTBEATSTARTEDEVENT(object);
+
+ zend_object_std_dtor(&intern->std);
+} /* }}} */
+
+static zend_object* php_phongo_serverheartbeatstartedevent_create_object(zend_class_entry* class_type) /* {{{ */
+{
+ php_phongo_serverheartbeatstartedevent_t* intern = zend_object_alloc(sizeof(php_phongo_serverheartbeatstartedevent_t), class_type);
+
+ zend_object_std_init(&intern->std, class_type);
+ object_properties_init(&intern->std, class_type);
+
+ intern->std.handlers = &php_phongo_handler_serverheartbeatstartedevent;
+
+ return &intern->std;
+} /* }}} */
+
+static HashTable* php_phongo_serverheartbeatstartedevent_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
+{
+ php_phongo_serverheartbeatstartedevent_t* intern;
+ zval retval = ZVAL_STATIC_INIT;
+
+ intern = Z_OBJ_SERVERHEARTBEATSTARTEDEVENT(PHONGO_COMPAT_GET_OBJ(object));
+ *is_temp = 1;
+ array_init_size(&retval, 4);
+
+ ADD_ASSOC_STRING(&retval, "host", intern->host.host);
+ ADD_ASSOC_LONG_EX(&retval, "port", intern->host.port);
+ ADD_ASSOC_BOOL_EX(&retval, "awaited", intern->awaited);
+
+ return Z_ARRVAL(retval);
+} /* }}} */
+/* }}} */
+
+void php_phongo_serverheartbeatstartedevent_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+ (void) type;
+ (void) module_number;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver\\Monitoring", "ServerHeartbeatStartedEvent", php_phongo_serverheartbeatstartedevent_me);
+ php_phongo_serverheartbeatstartedevent_ce = zend_register_internal_class(&ce);
+ php_phongo_serverheartbeatstartedevent_ce->create_object = php_phongo_serverheartbeatstartedevent_create_object;
+ PHONGO_CE_FINAL(php_phongo_serverheartbeatstartedevent_ce);
+ PHONGO_CE_DISABLE_SERIALIZATION(php_phongo_serverheartbeatstartedevent_ce);
+
+ memcpy(&php_phongo_handler_serverheartbeatstartedevent, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
+ php_phongo_handler_serverheartbeatstartedevent.get_debug_info = php_phongo_serverheartbeatstartedevent_get_debug_info;
+ php_phongo_handler_serverheartbeatstartedevent.free_obj = php_phongo_serverheartbeatstartedevent_free_object;
+ php_phongo_handler_serverheartbeatstartedevent.offset = XtOffsetOf(php_phongo_serverheartbeatstartedevent_t, std);
+
+ return;
+} /* }}} */
diff --git a/mongodb-1.13.0/src/MongoDB/Monitoring/ServerHeartbeatSucceededEvent.c b/mongodb-1.13.0/src/MongoDB/Monitoring/ServerHeartbeatSucceededEvent.c
new file mode 100644
index 00000000..405392a5
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/Monitoring/ServerHeartbeatSucceededEvent.c
@@ -0,0 +1,178 @@
+/*
+ * Copyright 2021-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <php.h>
+#include <Zend/zend_interfaces.h>
+
+#include "php_phongo.h"
+#include "phongo_error.h"
+
+zend_class_entry* php_phongo_serverheartbeatsucceededevent_ce;
+
+/* {{{ proto integer ServerHeartbeatSucceededEvent::getDurationMicros()
+ Returns this event's duration in microseconds */
+static PHP_METHOD(ServerHeartbeatSucceededEvent, getDurationMicros)
+{
+ php_phongo_serverheartbeatsucceededevent_t* intern = Z_SERVERHEARTBEATSUCCEEDEDEVENT_OBJ_P(getThis());
+
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ RETVAL_LONG(intern->duration_micros);
+} /* }}} */
+
+/* {{{ proto string ServerHeartbeatSucceededEvent::getHost()
+ Returns this event's host */
+static PHP_METHOD(ServerHeartbeatSucceededEvent, getHost)
+{
+ php_phongo_serverheartbeatsucceededevent_t* intern = Z_SERVERHEARTBEATSUCCEEDEDEVENT_OBJ_P(getThis());
+
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ RETVAL_STRING(intern->host.host);
+} /* }}} */
+
+/* {{{ proto integer ServerHeartbeatSucceededEvent::getPort()
+ Returns this event's port */
+static PHP_METHOD(ServerHeartbeatSucceededEvent, getPort)
+{
+ php_phongo_serverheartbeatsucceededevent_t* intern = Z_SERVERHEARTBEATSUCCEEDEDEVENT_OBJ_P(getThis());
+
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ RETVAL_LONG(intern->host.port);
+} /* }}} */
+
+/* {{{ proto stdClass ServerHeartbeatSucceededEvent::getReply()
+ Returns this event's reply */
+static PHP_METHOD(ServerHeartbeatSucceededEvent, getReply)
+{
+ php_phongo_serverheartbeatsucceededevent_t* intern = Z_SERVERHEARTBEATSUCCEEDEDEVENT_OBJ_P(getThis());
+ php_phongo_bson_state state;
+
+ PHONGO_BSON_INIT_STATE(state);
+
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ if (!php_phongo_bson_to_zval_ex(bson_get_data(intern->reply), intern->reply->len, &state)) {
+ zval_ptr_dtor(&state.zchild);
+ return;
+ }
+
+ RETURN_ZVAL(&state.zchild, 0, 1);
+} /* }}} */
+
+/* {{{ proto boolean ServerHeartbeatSucceededEvent::isAwaited()
+ Returns whether this event came from an awaitable hello */
+static PHP_METHOD(ServerHeartbeatSucceededEvent, isAwaited)
+{
+ php_phongo_serverheartbeatsucceededevent_t* intern = Z_SERVERHEARTBEATSUCCEEDEDEVENT_OBJ_P(getThis());
+
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ RETVAL_BOOL(intern->awaited);
+} /* }}} */
+
+/* {{{ MongoDB\Driver\Monitoring\ServerHeartbeatSucceededEvent function entries */
+ZEND_BEGIN_ARG_INFO_EX(ai_ServerHeartbeatSucceededEvent_void, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry php_phongo_serverheartbeatsucceededevent_me[] = {
+ /* clang-format off */
+ ZEND_NAMED_ME(__construct, PHP_FN(MongoDB_disabled___construct), ai_ServerHeartbeatSucceededEvent_void, ZEND_ACC_PRIVATE | ZEND_ACC_FINAL)
+ PHP_ME(ServerHeartbeatSucceededEvent, getDurationMicros, ai_ServerHeartbeatSucceededEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(ServerHeartbeatSucceededEvent, getHost, ai_ServerHeartbeatSucceededEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(ServerHeartbeatSucceededEvent, getPort, ai_ServerHeartbeatSucceededEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(ServerHeartbeatSucceededEvent, getReply, ai_ServerHeartbeatSucceededEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(ServerHeartbeatSucceededEvent, isAwaited, ai_ServerHeartbeatSucceededEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ ZEND_NAMED_ME(__wakeup, PHP_FN(MongoDB_disabled___wakeup), ai_ServerHeartbeatSucceededEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_FE_END
+ /* clang-format on */
+};
+/* }}} */
+
+/* {{{ MongoDB\Driver\Monitoring\ServerHeartbeatSucceededEvent object handlers */
+static zend_object_handlers php_phongo_handler_serverheartbeatsucceededevent;
+
+static void php_phongo_serverheartbeatsucceededevent_free_object(zend_object* object) /* {{{ */
+{
+ php_phongo_serverheartbeatsucceededevent_t* intern = Z_OBJ_SERVERHEARTBEATSUCCEEDEDEVENT(object);
+
+ zend_object_std_dtor(&intern->std);
+
+ if (intern->reply) {
+ bson_destroy(intern->reply);
+ }
+} /* }}} */
+
+static zend_object* php_phongo_serverheartbeatsucceededevent_create_object(zend_class_entry* class_type) /* {{{ */
+{
+ php_phongo_serverheartbeatsucceededevent_t* intern = zend_object_alloc(sizeof(php_phongo_serverheartbeatsucceededevent_t), class_type);
+
+ zend_object_std_init(&intern->std, class_type);
+ object_properties_init(&intern->std, class_type);
+
+ intern->std.handlers = &php_phongo_handler_serverheartbeatsucceededevent;
+
+ return &intern->std;
+} /* }}} */
+
+static HashTable* php_phongo_serverheartbeatsucceededevent_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
+{
+ php_phongo_serverheartbeatsucceededevent_t* intern;
+ zval retval = ZVAL_STATIC_INIT;
+ php_phongo_bson_state reply_state;
+
+ PHONGO_BSON_INIT_STATE(reply_state);
+
+ intern = Z_OBJ_SERVERHEARTBEATSUCCEEDEDEVENT(PHONGO_COMPAT_GET_OBJ(object));
+ *is_temp = 1;
+ array_init_size(&retval, 4);
+
+ ADD_ASSOC_STRING(&retval, "host", intern->host.host);
+ ADD_ASSOC_LONG_EX(&retval, "port", intern->host.port);
+ ADD_ASSOC_BOOL_EX(&retval, "awaited", intern->awaited);
+
+ if (!php_phongo_bson_to_zval_ex(bson_get_data(intern->reply), intern->reply->len, &reply_state)) {
+ zval_ptr_dtor(&reply_state.zchild);
+ goto done;
+ }
+
+ ADD_ASSOC_ZVAL(&retval, "reply", &reply_state.zchild);
+
+done:
+ return Z_ARRVAL(retval);
+} /* }}} */
+/* }}} */
+
+void php_phongo_serverheartbeatsucceededevent_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+ (void) type;
+ (void) module_number;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver\\Monitoring", "ServerHeartbeatSucceededEvent", php_phongo_serverheartbeatsucceededevent_me);
+ php_phongo_serverheartbeatsucceededevent_ce = zend_register_internal_class(&ce);
+ php_phongo_serverheartbeatsucceededevent_ce->create_object = php_phongo_serverheartbeatsucceededevent_create_object;
+ PHONGO_CE_FINAL(php_phongo_serverheartbeatsucceededevent_ce);
+ PHONGO_CE_DISABLE_SERIALIZATION(php_phongo_serverheartbeatsucceededevent_ce);
+
+ memcpy(&php_phongo_handler_serverheartbeatsucceededevent, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
+ php_phongo_handler_serverheartbeatsucceededevent.get_debug_info = php_phongo_serverheartbeatsucceededevent_get_debug_info;
+ php_phongo_handler_serverheartbeatsucceededevent.free_obj = php_phongo_serverheartbeatsucceededevent_free_object;
+ php_phongo_handler_serverheartbeatsucceededevent.offset = XtOffsetOf(php_phongo_serverheartbeatsucceededevent_t, std);
+
+ return;
+} /* }}} */
diff --git a/mongodb-1.13.0/src/MongoDB/Monitoring/ServerOpeningEvent.c b/mongodb-1.13.0/src/MongoDB/Monitoring/ServerOpeningEvent.c
new file mode 100644
index 00000000..c378c722
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/Monitoring/ServerOpeningEvent.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2021-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <php.h>
+#include <Zend/zend_interfaces.h>
+
+#include "php_phongo.h"
+#include "phongo_error.h"
+
+#include "BSON/ObjectId.h"
+
+zend_class_entry* php_phongo_serveropeningevent_ce;
+
+/* {{{ proto string ServerOpeningEvent::getHost()
+ Returns this event's host */
+static PHP_METHOD(ServerOpeningEvent, getHost)
+{
+ php_phongo_serveropeningevent_t* intern = Z_SERVEROPENINGEVENT_OBJ_P(getThis());
+
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ RETVAL_STRING(intern->host.host);
+} /* }}} */
+
+/* {{{ proto integer ServerOpeningEvent::getPort()
+ Returns this event's port */
+static PHP_METHOD(ServerOpeningEvent, getPort)
+{
+ php_phongo_serveropeningevent_t* intern = Z_SERVEROPENINGEVENT_OBJ_P(getThis());
+
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ RETVAL_LONG(intern->host.port);
+} /* }}} */
+
+/* {{{ proto MongoDB\BSON\ObjectId ServerOpeningEvent::getTopologyId()
+ Returns this event's topology id */
+static PHP_METHOD(ServerOpeningEvent, getTopologyId)
+{
+ php_phongo_serveropeningevent_t* intern = Z_SERVEROPENINGEVENT_OBJ_P(getThis());
+
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ phongo_objectid_init(return_value, &intern->topology_id);
+} /* }}} */
+
+/* {{{ MongoDB\Driver\Monitoring\ServerOpeningEvent function entries */
+ZEND_BEGIN_ARG_INFO_EX(ai_ServerOpeningEvent_void, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry php_phongo_serveropeningevent_me[] = {
+ /* clang-format off */
+ ZEND_NAMED_ME(__construct, PHP_FN(MongoDB_disabled___construct), ai_ServerOpeningEvent_void, ZEND_ACC_PRIVATE | ZEND_ACC_FINAL)
+ PHP_ME(ServerOpeningEvent, getHost, ai_ServerOpeningEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(ServerOpeningEvent, getPort, ai_ServerOpeningEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(ServerOpeningEvent, getTopologyId, ai_ServerOpeningEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ ZEND_NAMED_ME(__wakeup, PHP_FN(MongoDB_disabled___wakeup), ai_ServerOpeningEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_FE_END
+ /* clang-format on */
+};
+/* }}} */
+
+/* {{{ MongoDB\Driver\Monitoring\ServerOpeningEvent object handlers */
+static zend_object_handlers php_phongo_handler_serveropeningevent;
+
+static void php_phongo_serveropeningevent_free_object(zend_object* object) /* {{{ */
+{
+ php_phongo_serveropeningevent_t* intern = Z_OBJ_SERVEROPENINGEVENT(object);
+
+ zend_object_std_dtor(&intern->std);
+} /* }}} */
+
+static zend_object* php_phongo_serveropeningevent_create_object(zend_class_entry* class_type) /* {{{ */
+{
+ php_phongo_serveropeningevent_t* intern = zend_object_alloc(sizeof(php_phongo_serveropeningevent_t), class_type);
+
+ zend_object_std_init(&intern->std, class_type);
+ object_properties_init(&intern->std, class_type);
+
+ intern->std.handlers = &php_phongo_handler_serveropeningevent;
+
+ return &intern->std;
+} /* }}} */
+
+static HashTable* php_phongo_serveropeningevent_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
+{
+ php_phongo_serveropeningevent_t* intern;
+ zval retval = ZVAL_STATIC_INIT;
+
+ intern = Z_OBJ_SERVEROPENINGEVENT(PHONGO_COMPAT_GET_OBJ(object));
+ *is_temp = 1;
+ array_init_size(&retval, 3);
+
+ ADD_ASSOC_STRING(&retval, "host", intern->host.host);
+ ADD_ASSOC_LONG_EX(&retval, "port", intern->host.port);
+
+ {
+ zval topology_id;
+ phongo_objectid_init(&topology_id, &intern->topology_id);
+ ADD_ASSOC_ZVAL_EX(&retval, "topologyId", &topology_id);
+ }
+
+ return Z_ARRVAL(retval);
+} /* }}} */
+/* }}} */
+
+void php_phongo_serveropeningevent_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+ (void) type;
+ (void) module_number;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver\\Monitoring", "ServerOpeningEvent", php_phongo_serveropeningevent_me);
+ php_phongo_serveropeningevent_ce = zend_register_internal_class(&ce);
+ php_phongo_serveropeningevent_ce->create_object = php_phongo_serveropeningevent_create_object;
+ PHONGO_CE_FINAL(php_phongo_serveropeningevent_ce);
+ PHONGO_CE_DISABLE_SERIALIZATION(php_phongo_serveropeningevent_ce);
+
+ memcpy(&php_phongo_handler_serveropeningevent, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
+ php_phongo_handler_serveropeningevent.get_debug_info = php_phongo_serveropeningevent_get_debug_info;
+ php_phongo_handler_serveropeningevent.free_obj = php_phongo_serveropeningevent_free_object;
+ php_phongo_handler_serveropeningevent.offset = XtOffsetOf(php_phongo_serveropeningevent_t, std);
+
+ return;
+} /* }}} */
diff --git a/mongodb-1.13.0/src/MongoDB/Monitoring/Subscriber.c b/mongodb-1.13.0/src/MongoDB/Monitoring/Subscriber.c
new file mode 100644
index 00000000..54005f79
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/Monitoring/Subscriber.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2016-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <php.h>
+
+#include "php_phongo.h"
+
+zend_class_entry* php_phongo_subscriber_ce;
+
+/* {{{ MongoDB\Driver\Monitoring\Subscriber function entries */
+static zend_function_entry php_phongo_subscriber_me[] = {
+ PHP_FE_END
+};
+/* }}} */
+
+void php_phongo_subscriber_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+ (void) type;
+ (void) module_number;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver\\Monitoring", "Subscriber", php_phongo_subscriber_me);
+ php_phongo_subscriber_ce = zend_register_internal_interface(&ce);
+
+ return;
+} /* }}} */
diff --git a/mongodb-1.13.0/src/MongoDB/Monitoring/TopologyChangedEvent.c b/mongodb-1.13.0/src/MongoDB/Monitoring/TopologyChangedEvent.c
new file mode 100644
index 00000000..94256865
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/Monitoring/TopologyChangedEvent.c
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2021-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mongoc/mongoc.h"
+
+#include <php.h>
+#include <Zend/zend_interfaces.h>
+
+#include "php_phongo.h"
+#include "phongo_error.h"
+
+#include "BSON/ObjectId.h"
+#include "MongoDB/TopologyDescription.h"
+
+zend_class_entry* php_phongo_topologychangedevent_ce;
+
+/* {{{ proto MongoDB\Driver\TopologyDescription TopologyChangedEvent::getNewDescription()
+ Returns this event's new description */
+static PHP_METHOD(TopologyChangedEvent, getNewDescription)
+{
+ php_phongo_topologychangedevent_t* intern = Z_TOPOLOGYCHANGEDEVENT_OBJ_P(getThis());
+
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ phongo_topologydescription_init(return_value, intern->new_topology_description);
+} /* }}} */
+
+/* {{{ proto MongoDB\Driver\TopologyDescription TopologyChangedEvent::getPreviousDescription()
+ Returns this event's previous description */
+static PHP_METHOD(TopologyChangedEvent, getPreviousDescription)
+{
+ php_phongo_topologychangedevent_t* intern = Z_TOPOLOGYCHANGEDEVENT_OBJ_P(getThis());
+
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ phongo_topologydescription_init(return_value, intern->old_topology_description);
+} /* }}} */
+
+/* {{{ proto MongoDB\BSON\ObjectId TopologyChangedEvent::getTopologyId()
+ Returns this event's topology id */
+static PHP_METHOD(TopologyChangedEvent, getTopologyId)
+{
+ php_phongo_topologychangedevent_t* intern = Z_TOPOLOGYCHANGEDEVENT_OBJ_P(getThis());
+
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ phongo_objectid_init(return_value, &intern->topology_id);
+} /* }}} */
+
+/* {{{ MongoDB\Driver\Monitoring\TopologyChangedEvent function entries */
+ZEND_BEGIN_ARG_INFO_EX(ai_TopologyChangedEvent_void, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry php_phongo_topologychangedevent_me[] = {
+ /* clang-format off */
+ ZEND_NAMED_ME(__construct, PHP_FN(MongoDB_disabled___construct), ai_TopologyChangedEvent_void, ZEND_ACC_PRIVATE | ZEND_ACC_FINAL)
+ PHP_ME(TopologyChangedEvent, getNewDescription, ai_TopologyChangedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(TopologyChangedEvent, getPreviousDescription, ai_TopologyChangedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(TopologyChangedEvent, getTopologyId, ai_TopologyChangedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ ZEND_NAMED_ME(__wakeup, PHP_FN(MongoDB_disabled___wakeup), ai_TopologyChangedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_FE_END
+ /* clang-format on */
+};
+/* }}} */
+
+/* {{{ MongoDB\Driver\Monitoring\TopologyChangedEvent object handlers */
+static zend_object_handlers php_phongo_handler_topologychangedevent;
+
+static void php_phongo_topologychangedevent_free_object(zend_object* object) /* {{{ */
+{
+ php_phongo_topologychangedevent_t* intern = Z_OBJ_TOPOLOGYCHANGEDEVENT(object);
+
+ zend_object_std_dtor(&intern->std);
+
+ if (intern->new_topology_description) {
+ mongoc_topology_description_destroy(intern->new_topology_description);
+ }
+
+ if (intern->old_topology_description) {
+ mongoc_topology_description_destroy(intern->old_topology_description);
+ }
+} /* }}} */
+
+static zend_object* php_phongo_topologychangedevent_create_object(zend_class_entry* class_type) /* {{{ */
+{
+ php_phongo_topologychangedevent_t* intern = zend_object_alloc(sizeof(php_phongo_topologychangedevent_t), class_type);
+
+ zend_object_std_init(&intern->std, class_type);
+ object_properties_init(&intern->std, class_type);
+
+ intern->std.handlers = &php_phongo_handler_topologychangedevent;
+
+ return &intern->std;
+} /* }}} */
+
+static HashTable* php_phongo_topologychangedevent_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
+{
+ php_phongo_topologychangedevent_t* intern;
+ zval retval = ZVAL_STATIC_INIT;
+
+ intern = Z_OBJ_TOPOLOGYCHANGEDEVENT(PHONGO_COMPAT_GET_OBJ(object));
+ *is_temp = 1;
+ array_init_size(&retval, 3);
+
+ {
+ zval topology_id;
+ phongo_objectid_init(&topology_id, &intern->topology_id);
+ ADD_ASSOC_ZVAL_EX(&retval, "topologyId", &topology_id);
+ }
+
+ {
+ zval new_td;
+ phongo_topologydescription_init(&new_td, intern->new_topology_description);
+ ADD_ASSOC_ZVAL_EX(&retval, "newDescription", &new_td);
+ }
+
+ {
+ zval old_td;
+ phongo_topologydescription_init(&old_td, intern->old_topology_description);
+ ADD_ASSOC_ZVAL_EX(&retval, "oldDescription", &old_td);
+ }
+
+ return Z_ARRVAL(retval);
+} /* }}} */
+/* }}} */
+
+void php_phongo_topologychangedevent_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver\\Monitoring", "TopologyChangedEvent", php_phongo_topologychangedevent_me);
+ php_phongo_topologychangedevent_ce = zend_register_internal_class(&ce);
+ php_phongo_topologychangedevent_ce->create_object = php_phongo_topologychangedevent_create_object;
+ PHONGO_CE_FINAL(php_phongo_topologychangedevent_ce);
+ PHONGO_CE_DISABLE_SERIALIZATION(php_phongo_topologychangedevent_ce);
+
+ memcpy(&php_phongo_handler_topologychangedevent, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
+ php_phongo_handler_topologychangedevent.get_debug_info = php_phongo_topologychangedevent_get_debug_info;
+ php_phongo_handler_topologychangedevent.free_obj = php_phongo_topologychangedevent_free_object;
+ php_phongo_handler_topologychangedevent.offset = XtOffsetOf(php_phongo_topologychangedevent_t, std);
+} /* }}} */
diff --git a/mongodb-1.13.0/src/MongoDB/Monitoring/TopologyClosedEvent.c b/mongodb-1.13.0/src/MongoDB/Monitoring/TopologyClosedEvent.c
new file mode 100644
index 00000000..dd4f18bb
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/Monitoring/TopologyClosedEvent.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2021-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <php.h>
+#include <Zend/zend_interfaces.h>
+
+#include "php_phongo.h"
+#include "phongo_error.h"
+
+#include "BSON/ObjectId.h"
+
+zend_class_entry* php_phongo_topologyclosedevent_ce;
+
+/* {{{ proto MongoDB\BSON\ObjectId TopologyClosedEvent::getTopologyId()
+ Returns this event's topology id */
+static PHP_METHOD(TopologyClosedEvent, getTopologyId)
+{
+ php_phongo_topologyclosedevent_t* intern = Z_TOPOLOGYCLOSEDEVENT_OBJ_P(getThis());
+
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ phongo_objectid_init(return_value, &intern->topology_id);
+} /* }}} */
+
+/* {{{ MongoDB\Driver\Monitoring\TopologyClosedEvent function entries */
+ZEND_BEGIN_ARG_INFO_EX(ai_TopologyClosedEvent_void, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry php_phongo_topologyclosedevent_me[] = {
+ /* clang-format off */
+ ZEND_NAMED_ME(__construct, PHP_FN(MongoDB_disabled___construct), ai_TopologyClosedEvent_void, ZEND_ACC_PRIVATE | ZEND_ACC_FINAL)
+ PHP_ME(TopologyClosedEvent, getTopologyId, ai_TopologyClosedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ ZEND_NAMED_ME(__wakeup, PHP_FN(MongoDB_disabled___wakeup), ai_TopologyClosedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_FE_END
+ /* clang-format on */
+};
+/* }}} */
+
+/* {{{ MongoDB\Driver\Monitoring\TopologyClosedEvent object handlers */
+static zend_object_handlers php_phongo_handler_topologyclosedevent;
+
+static void php_phongo_topologyclosedevent_free_object(zend_object* object) /* {{{ */
+{
+ php_phongo_topologyclosedevent_t* intern = Z_OBJ_TOPOLOGYCLOSEDEVENT(object);
+
+ zend_object_std_dtor(&intern->std);
+} /* }}} */
+
+static zend_object* php_phongo_topologyclosedevent_create_object(zend_class_entry* class_type) /* {{{ */
+{
+ php_phongo_topologyclosedevent_t* intern = zend_object_alloc(sizeof(php_phongo_topologyclosedevent_t), class_type);
+
+ zend_object_std_init(&intern->std, class_type);
+ object_properties_init(&intern->std, class_type);
+
+ intern->std.handlers = &php_phongo_handler_topologyclosedevent;
+
+ return &intern->std;
+} /* }}} */
+
+static HashTable* php_phongo_topologyclosedevent_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
+{
+ php_phongo_topologyclosedevent_t* intern;
+ zval retval = ZVAL_STATIC_INIT;
+
+ intern = Z_OBJ_TOPOLOGYCLOSEDEVENT(PHONGO_COMPAT_GET_OBJ(object));
+ *is_temp = 1;
+ array_init_size(&retval, 1);
+
+ {
+ zval topology_id;
+ phongo_objectid_init(&topology_id, &intern->topology_id);
+ ADD_ASSOC_ZVAL_EX(&retval, "topologyId", &topology_id);
+ }
+
+ return Z_ARRVAL(retval);
+} /* }}} */
+/* }}} */
+
+void php_phongo_topologyclosedevent_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver\\Monitoring", "TopologyClosedEvent", php_phongo_topologyclosedevent_me);
+ php_phongo_topologyclosedevent_ce = zend_register_internal_class(&ce);
+ php_phongo_topologyclosedevent_ce->create_object = php_phongo_topologyclosedevent_create_object;
+ PHONGO_CE_FINAL(php_phongo_topologyclosedevent_ce);
+ PHONGO_CE_DISABLE_SERIALIZATION(php_phongo_topologyclosedevent_ce);
+
+ memcpy(&php_phongo_handler_topologyclosedevent, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
+ php_phongo_handler_topologyclosedevent.get_debug_info = php_phongo_topologyclosedevent_get_debug_info;
+ php_phongo_handler_topologyclosedevent.free_obj = php_phongo_topologyclosedevent_free_object;
+ php_phongo_handler_topologyclosedevent.offset = XtOffsetOf(php_phongo_topologyclosedevent_t, std);
+} /* }}} */
diff --git a/mongodb-1.13.0/src/MongoDB/Monitoring/TopologyOpeningEvent.c b/mongodb-1.13.0/src/MongoDB/Monitoring/TopologyOpeningEvent.c
new file mode 100644
index 00000000..db1315b5
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/Monitoring/TopologyOpeningEvent.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2021-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <php.h>
+#include <Zend/zend_interfaces.h>
+
+#include "php_phongo.h"
+#include "phongo_error.h"
+
+#include "BSON/ObjectId.h"
+
+zend_class_entry* php_phongo_topologyopeningevent_ce;
+
+/* {{{ proto MongoDB\BSON\ObjectId TopologyOpeningEvent::getTopologyId()
+ Returns this event's topology id */
+static PHP_METHOD(TopologyOpeningEvent, getTopologyId)
+{
+ php_phongo_topologyopeningevent_t* intern = Z_TOPOLOGYOPENINGEVENT_OBJ_P(getThis());
+
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ phongo_objectid_init(return_value, &intern->topology_id);
+} /* }}} */
+
+/* {{{ MongoDB\Driver\Monitoring\TopologyOpeningEvent function entries */
+ZEND_BEGIN_ARG_INFO_EX(ai_TopologyOpeningEvent_void, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry php_phongo_topologyopeningevent_me[] = {
+ /* clang-format off */
+ ZEND_NAMED_ME(__construct, PHP_FN(MongoDB_disabled___construct), ai_TopologyOpeningEvent_void, ZEND_ACC_PRIVATE | ZEND_ACC_FINAL)
+ PHP_ME(TopologyOpeningEvent, getTopologyId, ai_TopologyOpeningEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ ZEND_NAMED_ME(__wakeup, PHP_FN(MongoDB_disabled___wakeup), ai_TopologyOpeningEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_FE_END
+ /* clang-format on */
+};
+/* }}} */
+
+/* {{{ MongoDB\Driver\Monitoring\TopologyOpeningEvent object handlers */
+static zend_object_handlers php_phongo_handler_topologyopeningevent;
+
+static void php_phongo_topologyopeningevent_free_object(zend_object* object) /* {{{ */
+{
+ php_phongo_topologyopeningevent_t* intern = Z_OBJ_TOPOLOGYOPENINGEVENT(object);
+
+ zend_object_std_dtor(&intern->std);
+} /* }}} */
+
+static zend_object* php_phongo_topologyopeningevent_create_object(zend_class_entry* class_type) /* {{{ */
+{
+ php_phongo_topologyopeningevent_t* intern = zend_object_alloc(sizeof(php_phongo_topologyopeningevent_t), class_type);
+
+ zend_object_std_init(&intern->std, class_type);
+ object_properties_init(&intern->std, class_type);
+
+ intern->std.handlers = &php_phongo_handler_topologyopeningevent;
+
+ return &intern->std;
+} /* }}} */
+
+static HashTable* php_phongo_topologyopeningevent_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
+{
+ php_phongo_topologyopeningevent_t* intern;
+ zval retval = ZVAL_STATIC_INIT;
+
+ intern = Z_OBJ_TOPOLOGYOPENINGEVENT(PHONGO_COMPAT_GET_OBJ(object));
+ *is_temp = 1;
+ array_init_size(&retval, 1);
+
+ {
+ zval topology_id;
+ phongo_objectid_init(&topology_id, &intern->topology_id);
+ ADD_ASSOC_ZVAL_EX(&retval, "topologyId", &topology_id);
+ }
+
+ return Z_ARRVAL(retval);
+} /* }}} */
+/* }}} */
+
+void php_phongo_topologyopeningevent_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver\\Monitoring", "TopologyOpeningEvent", php_phongo_topologyopeningevent_me);
+ php_phongo_topologyopeningevent_ce = zend_register_internal_class(&ce);
+ php_phongo_topologyopeningevent_ce->create_object = php_phongo_topologyopeningevent_create_object;
+ PHONGO_CE_FINAL(php_phongo_topologyopeningevent_ce);
+ PHONGO_CE_DISABLE_SERIALIZATION(php_phongo_topologyopeningevent_ce);
+
+ memcpy(&php_phongo_handler_topologyopeningevent, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
+ php_phongo_handler_topologyopeningevent.get_debug_info = php_phongo_topologyopeningevent_get_debug_info;
+ php_phongo_handler_topologyopeningevent.free_obj = php_phongo_topologyopeningevent_free_object;
+ php_phongo_handler_topologyopeningevent.offset = XtOffsetOf(php_phongo_topologyopeningevent_t, std);
+} /* }}} */
diff --git a/mongodb-1.13.0/src/MongoDB/Monitoring/functions.c b/mongodb-1.13.0/src/MongoDB/Monitoring/functions.c
new file mode 100644
index 00000000..b4108dcb
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/Monitoring/functions.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2016-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <php.h>
+
+#include "php_phongo.h"
+#include "phongo_apm.h"
+#include "phongo_error.h"
+
+ZEND_EXTERN_MODULE_GLOBALS(mongodb)
+
+/* {{{ proto void MongoDB\Driver\Monitoring\addSubscriber(MongoDB\Driver\Monitoring\Subscriber $subscriber)
+ Registers a global event subscriber */
+PHP_FUNCTION(MongoDB_Driver_Monitoring_addSubscriber)
+{
+ zval* subscriber;
+
+ PHONGO_PARSE_PARAMETERS_START(1, 1)
+ Z_PARAM_OBJECT_OF_CLASS(subscriber, php_phongo_subscriber_ce)
+ PHONGO_PARSE_PARAMETERS_END();
+
+ phongo_apm_add_subscriber(MONGODB_G(subscribers), subscriber);
+} /* }}} */
+
+/* {{{ proto void MongoDB\Driver\Monitoring\removeSubscriber(MongoDB\Driver\Monitoring\Subscriber $subscriber)
+ Unregisters a global event subscriber */
+PHP_FUNCTION(MongoDB_Driver_Monitoring_removeSubscriber)
+{
+ zval* subscriber;
+
+ PHONGO_PARSE_PARAMETERS_START(1, 1)
+ Z_PARAM_OBJECT_OF_CLASS(subscriber, php_phongo_subscriber_ce)
+ PHONGO_PARSE_PARAMETERS_END();
+
+ phongo_apm_remove_subscriber(MONGODB_G(subscribers), subscriber);
+} /* }}} */
diff --git a/mongodb-1.13.0/src/MongoDB/Monitoring/functions.h b/mongodb-1.13.0/src/MongoDB/Monitoring/functions.h
new file mode 100644
index 00000000..9696d659
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/Monitoring/functions.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2016-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PHONGO_MONITORING_FUNCTIONS_H
+#define PHONGO_MONITORING_FUNCTIONS_H
+
+#include <php.h>
+
+PHP_FUNCTION(MongoDB_Driver_Monitoring_addSubscriber);
+PHP_FUNCTION(MongoDB_Driver_Monitoring_removeSubscriber);
+
+#endif /* PHONGO_MONITORING_FUNCTIONS_H */
diff --git a/mongodb-1.13.0/src/MongoDB/Query.c b/mongodb-1.13.0/src/MongoDB/Query.c
new file mode 100644
index 00000000..f01d31cc
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/Query.c
@@ -0,0 +1,493 @@
+/*
+ * Copyright 2014-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bson/bson.h"
+#include "mongoc/mongoc.h"
+
+#include <php.h>
+#include <Zend/zend_interfaces.h>
+
+#include "php_array_api.h"
+
+#include "php_phongo.h"
+#include "phongo_bson_encode.h"
+#include "phongo_error.h"
+
+#include "MongoDB/ReadConcern.h"
+
+zend_class_entry* php_phongo_query_ce;
+
+/* Appends a string field into the BSON options. Returns true on success;
+ * otherwise, false is returned and an exception is thrown. */
+static bool php_phongo_query_opts_append_string(bson_t* opts, const char* opts_key, zval* zarr, const char* zarr_key) /* {{{ */
+{
+ zval* value = php_array_fetch(zarr, zarr_key);
+
+ if (Z_TYPE_P(value) != IS_STRING) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"%s\" %s to be string, %s given", zarr_key, zarr_key[0] == '$' ? "modifier" : "option", PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(value));
+ return false;
+ }
+
+ if (!bson_append_utf8(opts, opts_key, strlen(opts_key), Z_STRVAL_P(value), Z_STRLEN_P(value))) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Error appending \"%s\" option", opts_key);
+ return false;
+ }
+
+ return true;
+} /* }}} */
+
+/* Appends a document field for the given opts document and key. Returns true on
+ * success; otherwise, false is returned and an exception is thrown. */
+static bool php_phongo_query_opts_append_document(bson_t* opts, const char* opts_key, zval* zarr, const char* zarr_key) /* {{{ */
+{
+ zval* value = php_array_fetch(zarr, zarr_key);
+ bson_t b = BSON_INITIALIZER;
+
+ if (Z_TYPE_P(value) != IS_OBJECT && Z_TYPE_P(value) != IS_ARRAY) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"%s\" %s to be array or object, %s given", zarr_key, zarr_key[0] == '$' ? "modifier" : "option", PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(value));
+ return false;
+ }
+
+ php_phongo_zval_to_bson(value, PHONGO_BSON_NONE, &b, NULL);
+
+ if (EG(exception)) {
+ bson_destroy(&b);
+ return false;
+ }
+
+ if (!bson_validate(&b, BSON_VALIDATE_EMPTY_KEYS, NULL)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Cannot use empty keys in \"%s\" %s", zarr_key, zarr_key[0] == '$' ? "modifier" : "option");
+ bson_destroy(&b);
+ return false;
+ }
+
+ if (!BSON_APPEND_DOCUMENT(opts, opts_key, &b)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Error appending \"%s\" option", opts_key);
+ bson_destroy(&b);
+ return false;
+ }
+
+ bson_destroy(&b);
+ return true;
+} /* }}} */
+
+#define PHONGO_QUERY_OPT_BOOL_EX(opt, zarr, key, deprecated) \
+ if ((zarr) && php_array_existsc((zarr), (key))) { \
+ if ((deprecated)) { \
+ php_error_docref(NULL, E_DEPRECATED, "The \"%s\" option is deprecated and will be removed in a future release", key); \
+ } \
+ if (!BSON_APPEND_BOOL(intern->opts, (opt), php_array_fetchc_bool((zarr), (key)))) { \
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Error appending \"%s\" option", (opt)); \
+ return false; \
+ } \
+ }
+
+#define PHONGO_QUERY_OPT_BOOL(opt, zarr, key) PHONGO_QUERY_OPT_BOOL_EX((opt), (zarr), (key), 0)
+#define PHONGO_QUERY_OPT_BOOL_DEPRECATED(opt, zarr, key) PHONGO_QUERY_OPT_BOOL_EX((opt), (zarr), (key), 1)
+
+#define PHONGO_QUERY_OPT_DOCUMENT(opt, zarr, key) \
+ if ((zarr) && php_array_existsc((zarr), (key))) { \
+ if (!php_phongo_query_opts_append_document(intern->opts, (opt), (zarr), (key))) { \
+ return false; \
+ } \
+ }
+
+/* Note: handling of integer options will depend on SIZEOF_ZEND_LONG and we
+ * are not converting strings to 64-bit integers for 32-bit platforms. */
+
+#define PHONGO_QUERY_OPT_INT64_EX(opt, zarr, key, deprecated) \
+ if ((zarr) && php_array_existsc((zarr), (key))) { \
+ if ((deprecated)) { \
+ php_error_docref(NULL, E_DEPRECATED, "The \"%s\" option is deprecated and will be removed in a future release", key); \
+ } \
+ if (!BSON_APPEND_INT64(intern->opts, (opt), php_array_fetchc_long((zarr), (key)))) { \
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Error appending \"%s\" option", (opt)); \
+ return false; \
+ } \
+ }
+
+#define PHONGO_QUERY_OPT_INT64(opt, zarr, key) PHONGO_QUERY_OPT_INT64_EX((opt), (zarr), (key), 0)
+#define PHONGO_QUERY_OPT_INT64_DEPRECATED(opt, zarr, key) PHONGO_QUERY_OPT_INT64_EX((opt), (zarr), (key), 1)
+
+#define PHONGO_QUERY_OPT_STRING(opt, zarr, key) \
+ if ((zarr) && php_array_existsc((zarr), (key))) { \
+ if (!php_phongo_query_opts_append_string(intern->opts, (opt), (zarr), (key))) { \
+ return false; \
+ } \
+ }
+
+/* Initialize the "hint" option. Returns true on success; otherwise, false is
+ * returned and an exception is thrown.
+ *
+ * The "hint" option (or "$hint" modifier) must be a string or document. Check
+ * for both types and merge into BSON options accordingly. */
+static bool php_phongo_query_init_hint(php_phongo_query_t* intern, zval* options, zval* modifiers) /* {{{ */
+{
+ /* The "hint" option (or "$hint" modifier) must be a string or document.
+ * Check for both types and merge into BSON options accordingly. */
+ if (php_array_existsc(options, "hint")) {
+ zend_uchar type = Z_TYPE_P(php_array_fetchc(options, "hint"));
+
+ if (type == IS_STRING) {
+ PHONGO_QUERY_OPT_STRING("hint", options, "hint");
+ } else if (type == IS_OBJECT || type == IS_ARRAY) {
+ PHONGO_QUERY_OPT_DOCUMENT("hint", options, "hint");
+ } else {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"hint\" option to be string, array, or object, %s given", zend_get_type_by_const(type));
+ return false;
+ }
+ } else if (modifiers && php_array_existsc(modifiers, "$hint")) {
+ zend_uchar type = Z_TYPE_P(php_array_fetchc(modifiers, "$hint"));
+
+ if (type == IS_STRING) {
+ PHONGO_QUERY_OPT_STRING("hint", modifiers, "$hint");
+ } else if (type == IS_OBJECT || type == IS_ARRAY) {
+ PHONGO_QUERY_OPT_DOCUMENT("hint", modifiers, "$hint");
+ } else {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"$hint\" modifier to be string, array, or object, %s given", zend_get_type_by_const(type));
+ return false;
+ }
+ }
+
+ return true;
+} /* }}} */
+
+/* Initialize the "limit" and "singleBatch" options. Returns true on success;
+ * otherwise, false is returned and an exception is thrown.
+ *
+ * mongoc_collection_find_with_opts() requires a non-negative limit. For
+ * backwards compatibility, a negative limit should be set as a positive value
+ * and default singleBatch to true. */
+static bool php_phongo_query_init_limit_and_singlebatch(php_phongo_query_t* intern, zval* options) /* {{{ */
+{
+ if (php_array_fetchc_long(options, "limit") < 0) {
+ zend_long limit = php_array_fetchc_long(options, "limit");
+
+ if (!BSON_APPEND_INT64(intern->opts, "limit", -limit)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Error appending \"limit\" option");
+ return false;
+ }
+
+ if (php_array_existsc(options, "singleBatch") && !php_array_fetchc_bool(options, "singleBatch")) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Negative \"limit\" option conflicts with false \"singleBatch\" option");
+ return false;
+ } else {
+ if (!BSON_APPEND_BOOL(intern->opts, "singleBatch", true)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Error appending \"singleBatch\" option");
+ return false;
+ }
+ }
+ } else {
+ PHONGO_QUERY_OPT_INT64("limit", options, "limit");
+ PHONGO_QUERY_OPT_BOOL("singleBatch", options, "singleBatch");
+ }
+
+ return true;
+} /* }}} */
+
+/* Initialize the "readConcern" option. Returns true on success; otherwise,
+ * false is returned and an exception is thrown.
+ *
+ * The "readConcern" option should be a MongoDB\Driver\ReadConcern instance,
+ * which must be converted to a mongoc_read_concern_t. */
+static bool php_phongo_query_init_readconcern(php_phongo_query_t* intern, zval* options) /* {{{ */
+{
+ zval* read_concern;
+
+ if (!php_array_existsc(options, "readConcern")) {
+ return true;
+ }
+
+ read_concern = php_array_fetchc(options, "readConcern");
+
+ if (Z_TYPE_P(read_concern) != IS_OBJECT || !instanceof_function(Z_OBJCE_P(read_concern), php_phongo_readconcern_ce)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"readConcern\" option to be %s, %s given", ZSTR_VAL(php_phongo_readconcern_ce->name), PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(read_concern));
+ return false;
+ }
+
+ intern->read_concern = mongoc_read_concern_copy(phongo_read_concern_from_zval(read_concern));
+
+ return true;
+} /* }}} */
+
+/* Initialize the "maxAwaitTimeMS" option. Returns true on success; otherwise,
+ * false is returned and an exception is thrown.
+ *
+ * The "maxAwaitTimeMS" option is assigned to the cursor after query execution
+ * via mongoc_cursor_set_max_await_time_ms(). */
+static bool php_phongo_query_init_max_await_time_ms(php_phongo_query_t* intern, zval* options) /* {{{ */
+{
+ int64_t max_await_time_ms;
+
+ if (!php_array_existsc(options, "maxAwaitTimeMS")) {
+ return true;
+ }
+
+ max_await_time_ms = php_array_fetchc_long(options, "maxAwaitTimeMS");
+
+ if (max_await_time_ms < 0) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"maxAwaitTimeMS\" option to be >= 0, %" PRId64 " given", max_await_time_ms);
+ return false;
+ }
+
+ if (max_await_time_ms > UINT32_MAX) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"maxAwaitTimeMS\" option to be <= %" PRIu32 ", %" PRId64 " given", UINT32_MAX, max_await_time_ms);
+ return false;
+ }
+
+ intern->max_await_time_ms = (uint32_t) max_await_time_ms;
+
+ return true;
+} /* }}} */
+
+/* Initializes the php_phongo_query_t from filter and options arguments. This
+ * function will fall back to a modifier in the absence of a top-level option
+ * (where applicable). */
+static bool php_phongo_query_init(php_phongo_query_t* intern, zval* filter, zval* options) /* {{{ */
+{
+ zval* modifiers = NULL;
+
+ intern->filter = bson_new();
+ intern->opts = bson_new();
+ intern->max_await_time_ms = 0;
+
+ php_phongo_zval_to_bson(filter, PHONGO_BSON_NONE, intern->filter, NULL);
+
+ /* Note: if any exceptions are thrown, we can simply return as PHP will
+ * invoke php_phongo_query_free_object to destruct the object. */
+ if (EG(exception)) {
+ return false;
+ }
+
+ if (!bson_validate(intern->filter, BSON_VALIDATE_EMPTY_KEYS, NULL)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Cannot use empty keys in filter document");
+ return false;
+ }
+
+ if (!options) {
+ return true;
+ }
+
+ if (php_array_existsc(options, "modifiers")) {
+ modifiers = php_array_fetchc(options, "modifiers");
+
+ if (Z_TYPE_P(modifiers) != IS_ARRAY) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"modifiers\" option to be array, %s given", PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(modifiers));
+ return false;
+ }
+ }
+
+ PHONGO_QUERY_OPT_BOOL("allowDiskUse", options, "allowDiskUse")
+ PHONGO_QUERY_OPT_BOOL("allowPartialResults", options, "allowPartialResults")
+ else PHONGO_QUERY_OPT_BOOL("allowPartialResults", options, "partial");
+ PHONGO_QUERY_OPT_BOOL("awaitData", options, "awaitData");
+ PHONGO_QUERY_OPT_INT64("batchSize", options, "batchSize");
+ PHONGO_QUERY_OPT_DOCUMENT("collation", options, "collation");
+ PHONGO_QUERY_OPT_STRING("comment", options, "comment")
+ else PHONGO_QUERY_OPT_STRING("comment", modifiers, "$comment");
+ PHONGO_QUERY_OPT_BOOL("exhaust", options, "exhaust");
+ PHONGO_QUERY_OPT_DOCUMENT("max", options, "max")
+ else PHONGO_QUERY_OPT_DOCUMENT("max", modifiers, "$max");
+ PHONGO_QUERY_OPT_INT64_DEPRECATED("maxScan", options, "maxScan")
+ else PHONGO_QUERY_OPT_INT64_DEPRECATED("maxScan", modifiers, "$maxScan");
+ PHONGO_QUERY_OPT_INT64("maxTimeMS", options, "maxTimeMS")
+ else PHONGO_QUERY_OPT_INT64("maxTimeMS", modifiers, "$maxTimeMS");
+ PHONGO_QUERY_OPT_DOCUMENT("min", options, "min")
+ else PHONGO_QUERY_OPT_DOCUMENT("min", modifiers, "$min");
+ PHONGO_QUERY_OPT_BOOL("noCursorTimeout", options, "noCursorTimeout");
+ PHONGO_QUERY_OPT_BOOL_DEPRECATED("oplogReplay", options, "oplogReplay");
+ PHONGO_QUERY_OPT_DOCUMENT("projection", options, "projection");
+ PHONGO_QUERY_OPT_BOOL("returnKey", options, "returnKey")
+ else PHONGO_QUERY_OPT_BOOL("returnKey", modifiers, "$returnKey");
+ PHONGO_QUERY_OPT_BOOL("showRecordId", options, "showRecordId")
+ else PHONGO_QUERY_OPT_BOOL("showRecordId", modifiers, "$showDiskLoc");
+ PHONGO_QUERY_OPT_INT64("skip", options, "skip");
+ PHONGO_QUERY_OPT_DOCUMENT("sort", options, "sort")
+ else PHONGO_QUERY_OPT_DOCUMENT("sort", modifiers, "$orderby");
+ PHONGO_QUERY_OPT_BOOL_DEPRECATED("snapshot", options, "snapshot")
+ else PHONGO_QUERY_OPT_BOOL_DEPRECATED("snapshot", modifiers, "$snapshot");
+ PHONGO_QUERY_OPT_BOOL("tailable", options, "tailable");
+
+ /* The "$explain" modifier should be converted to an "explain" option, which
+ * libmongoc will later convert back to a modifier for the OP_QUERY code
+ * path. This modifier will be ignored for the find command code path. */
+ PHONGO_QUERY_OPT_BOOL("explain", modifiers, "$explain");
+
+ if (!php_phongo_query_init_hint(intern, options, modifiers)) {
+ return false;
+ }
+
+ if (!php_phongo_query_init_limit_and_singlebatch(intern, options)) {
+ return false;
+ }
+
+ if (!php_phongo_query_init_readconcern(intern, options)) {
+ return false;
+ }
+
+ if (!php_phongo_query_init_max_await_time_ms(intern, options)) {
+ return false;
+ }
+
+ return true;
+} /* }}} */
+
+#undef PHONGO_QUERY_OPT_BOOL
+#undef PHONGO_QUERY_OPT_DOCUMENT
+#undef PHONGO_QUERY_OPT_INT64
+#undef PHONGO_QUERY_OPT_STRING
+
+/* {{{ proto void MongoDB\Driver\Query::__construct(array|object $filter[, array $options = array()])
+ Constructs a new Query */
+static PHP_METHOD(Query, __construct)
+{
+ zend_error_handling error_handling;
+ php_phongo_query_t* intern;
+ zval* filter;
+ zval* options = NULL;
+
+ intern = Z_QUERY_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "A|a!", &filter, &options) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ php_phongo_query_init(intern, filter, options);
+} /* }}} */
+
+/* {{{ MongoDB\Driver\Query function entries */
+ZEND_BEGIN_ARG_INFO_EX(ai_Query___construct, 0, 0, 1)
+ ZEND_ARG_INFO(0, filter)
+ ZEND_ARG_ARRAY_INFO(0, options, 1)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_Query_void, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry php_phongo_query_me[] = {
+ /* clang-format off */
+ PHP_ME(Query, __construct, ai_Query___construct, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ ZEND_NAMED_ME(__wakeup, PHP_FN(MongoDB_disabled___wakeup), ai_Query_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_FE_END
+ /* clang-format on */
+};
+/* }}} */
+
+/* {{{ MongoDB\Driver\Query object handlers */
+static zend_object_handlers php_phongo_handler_query;
+
+static void php_phongo_query_free_object(zend_object* object) /* {{{ */
+{
+ php_phongo_query_t* intern = Z_OBJ_QUERY(object);
+
+ zend_object_std_dtor(&intern->std);
+
+ if (intern->filter) {
+ bson_clear(&intern->filter);
+ }
+
+ if (intern->opts) {
+ bson_clear(&intern->opts);
+ }
+
+ if (intern->read_concern) {
+ mongoc_read_concern_destroy(intern->read_concern);
+ }
+} /* }}} */
+
+static zend_object* php_phongo_query_create_object(zend_class_entry* class_type) /* {{{ */
+{
+ php_phongo_query_t* intern = zend_object_alloc(sizeof(php_phongo_query_t), class_type);
+
+ zend_object_std_init(&intern->std, class_type);
+ object_properties_init(&intern->std, class_type);
+
+ intern->std.handlers = &php_phongo_handler_query;
+
+ return &intern->std;
+} /* }}} */
+
+static HashTable* php_phongo_query_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
+{
+ php_phongo_query_t* intern;
+ zval retval = ZVAL_STATIC_INIT;
+
+ *is_temp = 1;
+ intern = Z_OBJ_QUERY(PHONGO_COMPAT_GET_OBJ(object));
+
+ array_init_size(&retval, 3);
+
+ /* Avoid using PHONGO_TYPEMAP_NATIVE_ARRAY for decoding filter and opts
+ * documents so that users can differentiate BSON arrays and documents. */
+ if (intern->filter) {
+ zval zv;
+
+ if (!php_phongo_bson_to_zval(bson_get_data(intern->filter), intern->filter->len, &zv)) {
+ zval_ptr_dtor(&zv);
+ goto done;
+ }
+
+ ADD_ASSOC_ZVAL_EX(&retval, "filter", &zv);
+ } else {
+ ADD_ASSOC_NULL_EX(&retval, "filter");
+ }
+
+ if (intern->opts) {
+ zval zv;
+
+ if (!php_phongo_bson_to_zval(bson_get_data(intern->opts), intern->opts->len, &zv)) {
+ zval_ptr_dtor(&zv);
+ goto done;
+ }
+
+ ADD_ASSOC_ZVAL_EX(&retval, "options", &zv);
+ } else {
+ ADD_ASSOC_NULL_EX(&retval, "options");
+ }
+
+ if (intern->read_concern) {
+ zval read_concern;
+
+ php_phongo_read_concern_to_zval(&read_concern, intern->read_concern);
+ ADD_ASSOC_ZVAL_EX(&retval, "readConcern", &read_concern);
+ } else {
+ ADD_ASSOC_NULL_EX(&retval, "readConcern");
+ }
+
+done:
+ return Z_ARRVAL(retval);
+
+} /* }}} */
+/* }}} */
+
+void php_phongo_query_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver", "Query", php_phongo_query_me);
+ php_phongo_query_ce = zend_register_internal_class(&ce);
+ php_phongo_query_ce->create_object = php_phongo_query_create_object;
+ PHONGO_CE_FINAL(php_phongo_query_ce);
+ PHONGO_CE_DISABLE_SERIALIZATION(php_phongo_query_ce);
+
+ memcpy(&php_phongo_handler_query, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
+ php_phongo_handler_query.get_debug_info = php_phongo_query_get_debug_info;
+ php_phongo_handler_query.free_obj = php_phongo_query_free_object;
+ php_phongo_handler_query.offset = XtOffsetOf(php_phongo_query_t, std);
+} /* }}} */
diff --git a/mongodb-1.13.0/src/MongoDB/ReadConcern.c b/mongodb-1.13.0/src/MongoDB/ReadConcern.c
new file mode 100644
index 00000000..edb58e0f
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/ReadConcern.c
@@ -0,0 +1,433 @@
+/*
+ * Copyright 2015-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mongoc/mongoc.h"
+
+#include <php.h>
+#include <zend_smart_str.h>
+#include <ext/standard/php_var.h>
+#include <Zend/zend_interfaces.h>
+
+#include "php_phongo.h"
+#include "phongo_error.h"
+
+zend_class_entry* php_phongo_readconcern_ce;
+
+/* Initialize the object from a HashTable and return whether it was successful.
+ * An exception will be thrown on error. */
+static bool php_phongo_readconcern_init_from_hash(php_phongo_readconcern_t* intern, HashTable* props) /* {{{ */
+{
+ zval* level;
+
+ intern->read_concern = mongoc_read_concern_new();
+
+ if ((level = zend_hash_str_find(props, "level", sizeof("level") - 1))) {
+ if (Z_TYPE_P(level) == IS_STRING) {
+ mongoc_read_concern_set_level(intern->read_concern, Z_STRVAL_P(level));
+ return true;
+ }
+
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"level\" string field", ZSTR_VAL(php_phongo_readconcern_ce->name));
+ goto failure;
+ }
+
+ return true;
+
+failure:
+ mongoc_read_concern_destroy(intern->read_concern);
+ intern->read_concern = NULL;
+ return false;
+} /* }}} */
+
+/* {{{ proto void MongoDB\Driver\ReadConcern::__construct([string $level])
+ Constructs a new ReadConcern */
+static PHP_METHOD(ReadConcern, __construct)
+{
+ zend_error_handling error_handling;
+ php_phongo_readconcern_t* intern;
+ char* level = NULL;
+ size_t level_len = 0;
+
+ intern = Z_READCONCERN_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s!", &level, &level_len) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ intern->read_concern = mongoc_read_concern_new();
+
+ if (level) {
+ mongoc_read_concern_set_level(intern->read_concern, level);
+ }
+} /* }}} */
+
+/* {{{ proto MongoDB\Driver\ReadConcern MongoDB\Driver\ReadConcern::__set_state(array $properties)
+*/
+static PHP_METHOD(ReadConcern, __set_state)
+{
+ zend_error_handling error_handling;
+ php_phongo_readconcern_t* intern;
+ HashTable* props;
+ zval* array;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &array) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ object_init_ex(return_value, php_phongo_readconcern_ce);
+
+ intern = Z_READCONCERN_OBJ_P(return_value);
+ props = Z_ARRVAL_P(array);
+
+ php_phongo_readconcern_init_from_hash(intern, props);
+} /* }}} */
+
+/* {{{ proto string|null MongoDB\Driver\ReadConcern::getLevel()
+ Returns the ReadConcern "level" option */
+static PHP_METHOD(ReadConcern, getLevel)
+{
+ zend_error_handling error_handling;
+ php_phongo_readconcern_t* intern;
+ const char* level;
+
+ intern = Z_READCONCERN_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ level = mongoc_read_concern_get_level(intern->read_concern);
+
+ if (level) {
+ RETURN_STRING(level);
+ }
+
+ RETURN_NULL();
+} /* }}} */
+
+/* {{{ proto boolean MongoDB\Driver\ReadConcern::isDefault()
+ Returns whether the read concern has not been modified (i.e. constructed
+ without a level or from a Manager with no read concern URI options). */
+static PHP_METHOD(ReadConcern, isDefault)
+{
+ zend_error_handling error_handling;
+ php_phongo_readconcern_t* intern;
+
+ intern = Z_READCONCERN_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ RETURN_BOOL(mongoc_read_concern_is_default(intern->read_concern));
+} /* }}} */
+
+static HashTable* php_phongo_readconcern_get_properties_hash(phongo_compat_object_handler_type* object, bool is_temp) /* {{{ */
+{
+ php_phongo_readconcern_t* intern;
+ HashTable* props;
+ const char* level;
+
+ intern = Z_OBJ_READCONCERN(PHONGO_COMPAT_GET_OBJ(object));
+
+ PHONGO_GET_PROPERTY_HASH_INIT_PROPS(is_temp, intern, props, 1);
+
+ if (!intern->read_concern) {
+ return props;
+ }
+
+ level = mongoc_read_concern_get_level(intern->read_concern);
+
+ if (level) {
+ zval z_level;
+
+ ZVAL_STRING(&z_level, level);
+ zend_hash_str_update(props, "level", sizeof("level") - 1, &z_level);
+ }
+
+ return props;
+} /* }}} */
+
+/* {{{ proto array MongoDB\Driver\ReadConcern::bsonSerialize()
+*/
+static PHP_METHOD(ReadConcern, bsonSerialize)
+{
+ zend_error_handling error_handling;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ ZVAL_ARR(return_value, php_phongo_readconcern_get_properties_hash(PHONGO_COMPAT_OBJ_P(getThis()), true));
+ convert_to_object(return_value);
+} /* }}} */
+
+/* {{{ proto string MongoDB\Driver\ReadConcern::serialize()
+*/
+static PHP_METHOD(ReadConcern, serialize)
+{
+ zend_error_handling error_handling;
+ php_phongo_readconcern_t* intern;
+ zval retval;
+ php_serialize_data_t var_hash;
+ smart_str buf = { 0 };
+ const char* level;
+
+ intern = Z_READCONCERN_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ if (!intern->read_concern) {
+ return;
+ }
+
+ level = mongoc_read_concern_get_level(intern->read_concern);
+
+ if (!level) {
+ RETURN_STRING("");
+ }
+
+ array_init_size(&retval, 1);
+ ADD_ASSOC_STRING(&retval, "level", level);
+
+ PHP_VAR_SERIALIZE_INIT(var_hash);
+ php_var_serialize(&buf, &retval, &var_hash);
+ smart_str_0(&buf);
+ PHP_VAR_SERIALIZE_DESTROY(var_hash);
+
+ PHONGO_RETVAL_SMART_STR(buf);
+
+ smart_str_free(&buf);
+ zval_ptr_dtor(&retval);
+} /* }}} */
+
+/* {{{ proto void MongoDB\Driver\ReadConcern::unserialize(string $serialized)
+*/
+static PHP_METHOD(ReadConcern, unserialize)
+{
+ zend_error_handling error_handling;
+ php_phongo_readconcern_t* intern;
+ char* serialized;
+ size_t serialized_len;
+ zval props;
+ php_unserialize_data_t var_hash;
+
+ intern = Z_READCONCERN_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &serialized, &serialized_len) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ if (!serialized_len) {
+ return;
+ }
+
+ PHP_VAR_UNSERIALIZE_INIT(var_hash);
+ if (!php_var_unserialize(&props, (const unsigned char**) &serialized, (unsigned char*) serialized + serialized_len, &var_hash)) {
+ zval_ptr_dtor(&props);
+ phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "%s unserialization failed", ZSTR_VAL(php_phongo_readconcern_ce->name));
+
+ PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+ return;
+ }
+ PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+
+ php_phongo_readconcern_init_from_hash(intern, HASH_OF(&props));
+ zval_ptr_dtor(&props);
+} /* }}} */
+
+/* {{{ proto array MongoDB\Driver\ReadConcern::__serialize()
+*/
+static PHP_METHOD(ReadConcern, __serialize)
+{
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ RETURN_ARR(php_phongo_readconcern_get_properties_hash(PHONGO_COMPAT_OBJ_P(getThis()), true));
+} /* }}} */
+
+/* {{{ proto void MongoDB\Driver\ReadConcern::__unserialize(array $data)
+*/
+static PHP_METHOD(ReadConcern, __unserialize)
+{
+ zval* data;
+
+ PHONGO_PARSE_PARAMETERS_START(1, 1)
+ Z_PARAM_ARRAY(data)
+ PHONGO_PARSE_PARAMETERS_END();
+
+ php_phongo_readconcern_init_from_hash(Z_READCONCERN_OBJ_P(getThis()), Z_ARRVAL_P(data));
+} /* }}} */
+
+/* {{{ MongoDB\Driver\ReadConcern function entries */
+ZEND_BEGIN_ARG_INFO_EX(ai_ReadConcern___construct, 0, 0, 0)
+ ZEND_ARG_INFO(0, level)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_ReadConcern___set_state, 0, 0, 1)
+ ZEND_ARG_ARRAY_INFO(0, properties, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_ReadConcern___unserialize, 0, 0, 1)
+ ZEND_ARG_ARRAY_INFO(0, data, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_ReadConcern_unserialize, 0, 0, 1)
+ ZEND_ARG_INFO(0, serialized)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_ReadConcern_void, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry php_phongo_readconcern_me[] = {
+ /* clang-format off */
+ PHP_ME(ReadConcern, __construct, ai_ReadConcern___construct, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(ReadConcern, __serialize, ai_ReadConcern_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(ReadConcern, __set_state, ai_ReadConcern___set_state, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+ PHP_ME(ReadConcern, __unserialize, ai_ReadConcern___unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(ReadConcern, getLevel, ai_ReadConcern_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(ReadConcern, isDefault, ai_ReadConcern_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(ReadConcern, bsonSerialize, ai_ReadConcern_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(ReadConcern, serialize, ai_ReadConcern_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(ReadConcern, unserialize, ai_ReadConcern_unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_FE_END
+ /* clang-format on */
+};
+/* }}} */
+
+/* {{{ MongoDB\Driver\ReadConcern object handlers */
+static zend_object_handlers php_phongo_handler_readconcern;
+
+static void php_phongo_readconcern_free_object(zend_object* object) /* {{{ */
+{
+ php_phongo_readconcern_t* intern = Z_OBJ_READCONCERN(object);
+
+ zend_object_std_dtor(&intern->std);
+
+ if (intern->properties) {
+ zend_hash_destroy(intern->properties);
+ FREE_HASHTABLE(intern->properties);
+ }
+
+ if (intern->read_concern) {
+ mongoc_read_concern_destroy(intern->read_concern);
+ }
+}
+
+static zend_object* php_phongo_readconcern_create_object(zend_class_entry* class_type) /* {{{ */
+{
+ php_phongo_readconcern_t* intern = zend_object_alloc(sizeof(php_phongo_readconcern_t), class_type);
+
+ zend_object_std_init(&intern->std, class_type);
+ object_properties_init(&intern->std, class_type);
+
+ intern->std.handlers = &php_phongo_handler_readconcern;
+
+ return &intern->std;
+} /* }}} */
+
+static HashTable* php_phongo_readconcern_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
+{
+ *is_temp = 1;
+ return php_phongo_readconcern_get_properties_hash(object, true);
+} /* }}} */
+
+static HashTable* php_phongo_readconcern_get_properties(phongo_compat_object_handler_type* object) /* {{{ */
+{
+ return php_phongo_readconcern_get_properties_hash(object, false);
+} /* }}} */
+
+void php_phongo_readconcern_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver", "ReadConcern", php_phongo_readconcern_me);
+ php_phongo_readconcern_ce = zend_register_internal_class(&ce);
+ php_phongo_readconcern_ce->create_object = php_phongo_readconcern_create_object;
+ PHONGO_CE_FINAL(php_phongo_readconcern_ce);
+
+ zend_class_implements(php_phongo_readconcern_ce, 1, php_phongo_serializable_ce);
+ zend_class_implements(php_phongo_readconcern_ce, 1, zend_ce_serializable);
+
+ memcpy(&php_phongo_handler_readconcern, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
+ php_phongo_handler_readconcern.get_debug_info = php_phongo_readconcern_get_debug_info;
+ php_phongo_handler_readconcern.get_properties = php_phongo_readconcern_get_properties;
+ php_phongo_handler_readconcern.free_obj = php_phongo_readconcern_free_object;
+ php_phongo_handler_readconcern.offset = XtOffsetOf(php_phongo_readconcern_t, std);
+
+ zend_declare_class_constant_stringl(php_phongo_readconcern_ce, ZEND_STRL("LOCAL"), ZEND_STRL(MONGOC_READ_CONCERN_LEVEL_LOCAL));
+ zend_declare_class_constant_stringl(php_phongo_readconcern_ce, ZEND_STRL("MAJORITY"), ZEND_STRL(MONGOC_READ_CONCERN_LEVEL_MAJORITY));
+ zend_declare_class_constant_stringl(php_phongo_readconcern_ce, ZEND_STRL("LINEARIZABLE"), ZEND_STRL(MONGOC_READ_CONCERN_LEVEL_LINEARIZABLE));
+ zend_declare_class_constant_stringl(php_phongo_readconcern_ce, ZEND_STRL("AVAILABLE"), ZEND_STRL(MONGOC_READ_CONCERN_LEVEL_AVAILABLE));
+ zend_declare_class_constant_stringl(php_phongo_readconcern_ce, ZEND_STRL("SNAPSHOT"), ZEND_STRL(MONGOC_READ_CONCERN_LEVEL_SNAPSHOT));
+} /* }}} */
+
+void phongo_readconcern_init(zval* return_value, const mongoc_read_concern_t* read_concern) /* {{{ */
+{
+ php_phongo_readconcern_t* intern;
+
+ object_init_ex(return_value, php_phongo_readconcern_ce);
+
+ intern = Z_READCONCERN_OBJ_P(return_value);
+ intern->read_concern = mongoc_read_concern_copy(read_concern);
+}
+/* }}} */
+
+const mongoc_read_concern_t* phongo_read_concern_from_zval(zval* zread_concern) /* {{{ */
+{
+ if (zread_concern) {
+ php_phongo_readconcern_t* intern = Z_READCONCERN_OBJ_P(zread_concern);
+
+ if (intern) {
+ return intern->read_concern;
+ }
+ }
+
+ return NULL;
+} /* }}} */
+
+void php_phongo_read_concern_to_zval(zval* retval, const mongoc_read_concern_t* read_concern) /* {{{ */
+{
+ const char* level = mongoc_read_concern_get_level(read_concern);
+
+ array_init_size(retval, 1);
+
+ if (level) {
+ ADD_ASSOC_STRING(retval, "level", level);
+ }
+} /* }}} */
diff --git a/mongodb-1.13.0/src/MongoDB/ReadConcern.h b/mongodb-1.13.0/src/MongoDB/ReadConcern.h
new file mode 100644
index 00000000..395de99b
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/ReadConcern.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2022-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PHONGO_READCONCERN_H
+#define PHONGO_READCONCERN_H
+
+#include "mongoc/mongoc.h"
+
+#include <php.h>
+
+void phongo_readconcern_init(zval* return_value, const mongoc_read_concern_t* read_concern);
+
+const mongoc_read_concern_t* phongo_read_concern_from_zval(zval* zread_concern);
+
+void php_phongo_read_concern_to_zval(zval* retval, const mongoc_read_concern_t* read_concern);
+
+#endif /* PHONGO_READCONCERN_H */
diff --git a/mongodb-1.13.0/src/MongoDB/ReadPreference.c b/mongodb-1.13.0/src/MongoDB/ReadPreference.c
new file mode 100644
index 00000000..3dafcbdb
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/ReadPreference.c
@@ -0,0 +1,894 @@
+/*
+ * Copyright 2014-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bson/bson.h"
+#include "mongoc/mongoc.h"
+
+#include <php.h>
+#include <zend_smart_str.h>
+#include <ext/standard/php_var.h>
+#include <Zend/zend_interfaces.h>
+
+#include "php_array_api.h"
+
+#include "php_phongo.h"
+#include "phongo_bson_encode.h"
+#include "phongo_error.h"
+
+#include "MongoDB/ReadPreference.h"
+
+zend_class_entry* php_phongo_readpreference_ce;
+
+#define PHONGO_READ_PRIMARY "primary"
+#define PHONGO_READ_PRIMARY_PREFERRED "primaryPreferred"
+#define PHONGO_READ_SECONDARY "secondary"
+#define PHONGO_READ_SECONDARY_PREFERRED "secondaryPreferred"
+#define PHONGO_READ_NEAREST "nearest"
+
+/* Initialize the object from a HashTable and return whether it was successful.
+ * An exception will be thrown on error. */
+static bool php_phongo_readpreference_init_from_hash(php_phongo_readpreference_t* intern, HashTable* props) /* {{{ */
+{
+ zval *mode, *tagSets, *maxStalenessSeconds, *hedge;
+
+ if ((mode = zend_hash_str_find(props, "mode", sizeof("mode") - 1)) && Z_TYPE_P(mode) == IS_STRING) {
+ if (strcasecmp(Z_STRVAL_P(mode), PHONGO_READ_PRIMARY) == 0) {
+ intern->read_preference = mongoc_read_prefs_new(MONGOC_READ_PRIMARY);
+ } else if (strcasecmp(Z_STRVAL_P(mode), PHONGO_READ_PRIMARY_PREFERRED) == 0) {
+ intern->read_preference = mongoc_read_prefs_new(MONGOC_READ_PRIMARY_PREFERRED);
+ } else if (strcasecmp(Z_STRVAL_P(mode), PHONGO_READ_SECONDARY) == 0) {
+ intern->read_preference = mongoc_read_prefs_new(MONGOC_READ_SECONDARY);
+ } else if (strcasecmp(Z_STRVAL_P(mode), PHONGO_READ_SECONDARY_PREFERRED) == 0) {
+ intern->read_preference = mongoc_read_prefs_new(MONGOC_READ_SECONDARY_PREFERRED);
+ } else if (strcasecmp(Z_STRVAL_P(mode), PHONGO_READ_NEAREST) == 0) {
+ intern->read_preference = mongoc_read_prefs_new(MONGOC_READ_NEAREST);
+ } else {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires specific values for \"mode\" string field", ZSTR_VAL(php_phongo_readpreference_ce->name));
+ return false;
+ }
+ } else {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"mode\" field to be string", ZSTR_VAL(php_phongo_readpreference_ce->name));
+ return false;
+ }
+
+ if ((tagSets = zend_hash_str_find(props, "tags", sizeof("tags") - 1))) {
+ ZVAL_DEREF(tagSets);
+ if (Z_TYPE_P(tagSets) == IS_ARRAY) {
+ bson_t* tags = bson_new();
+
+ /* Separate tagSets as php_phongo_read_preference_prep_tagsets may
+ * modify these tags. */
+ SEPARATE_ZVAL_NOREF(tagSets);
+
+ php_phongo_read_preference_prep_tagsets(tagSets);
+ php_phongo_zval_to_bson(tagSets, PHONGO_BSON_NONE, (bson_t*) tags, NULL);
+
+ if (!php_phongo_read_preference_tags_are_valid(tags)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"tags\" array field to have zero or more documents", ZSTR_VAL(php_phongo_readpreference_ce->name));
+ bson_destroy(tags);
+ goto failure;
+ }
+
+ if (!bson_empty(tags) && (mongoc_read_prefs_get_mode(intern->read_preference) == MONGOC_READ_PRIMARY)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"tags\" array field to not be present with \"primary\" mode", ZSTR_VAL(php_phongo_readpreference_ce->name));
+ bson_destroy(tags);
+ goto failure;
+ }
+
+ mongoc_read_prefs_set_tags(intern->read_preference, tags);
+ bson_destroy(tags);
+ } else {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"tags\" field to be array", ZSTR_VAL(php_phongo_readpreference_ce->name));
+ goto failure;
+ }
+ }
+
+ if ((maxStalenessSeconds = zend_hash_str_find(props, "maxStalenessSeconds", sizeof("maxStalenessSeconds") - 1))) {
+ if (Z_TYPE_P(maxStalenessSeconds) == IS_LONG) {
+ if (Z_LVAL_P(maxStalenessSeconds) != MONGOC_NO_MAX_STALENESS) {
+ if (mongoc_read_prefs_get_mode(intern->read_preference) == MONGOC_READ_PRIMARY) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"maxStalenessSeconds\" field to not be present with \"primary\" mode", ZSTR_VAL(php_phongo_readpreference_ce->name));
+ goto failure;
+ }
+ if (Z_LVAL_P(maxStalenessSeconds) < MONGOC_SMALLEST_MAX_STALENESS_SECONDS) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"maxStalenessSeconds\" integer field to be >= %d", ZSTR_VAL(php_phongo_readpreference_ce->name), MONGOC_SMALLEST_MAX_STALENESS_SECONDS);
+ goto failure;
+ }
+ if (Z_LVAL_P(maxStalenessSeconds) > INT32_MAX) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"maxStalenessSeconds\" integer field to be <= %" PRId32, ZSTR_VAL(php_phongo_readpreference_ce->name), INT32_MAX);
+ goto failure;
+ }
+ }
+
+ mongoc_read_prefs_set_max_staleness_seconds(intern->read_preference, Z_LVAL_P(maxStalenessSeconds));
+ } else {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"maxStalenessSeconds\" field to be integer", ZSTR_VAL(php_phongo_readpreference_ce->name));
+ goto failure;
+ }
+ }
+
+ if ((hedge = zend_hash_str_find(props, "hedge", sizeof("hedge") - 1))) {
+ if (Z_TYPE_P(hedge) == IS_ARRAY || Z_TYPE_P(hedge) == IS_OBJECT) {
+ bson_t* hedge_doc = bson_new();
+
+ if (mongoc_read_prefs_get_mode(intern->read_preference) == MONGOC_READ_PRIMARY) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"hedge\" field to not be present with \"primary\" mode", ZSTR_VAL(php_phongo_readpreference_ce->name));
+ bson_destroy(hedge_doc);
+ goto failure;
+ }
+
+ php_phongo_zval_to_bson(hedge, PHONGO_BSON_NONE, hedge_doc, NULL);
+
+ if (EG(exception)) {
+ bson_destroy(hedge_doc);
+ goto failure;
+ }
+
+ mongoc_read_prefs_set_hedge(intern->read_preference, hedge_doc);
+ bson_destroy(hedge_doc);
+ } else {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"hedge\" field to be an array or object", ZSTR_VAL(php_phongo_readpreference_ce->name));
+ goto failure;
+ }
+ }
+
+ if (!mongoc_read_prefs_is_valid(intern->read_preference)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Read preference is not valid");
+ goto failure;
+ }
+
+ return true;
+
+failure:
+ mongoc_read_prefs_destroy(intern->read_preference);
+ intern->read_preference = NULL;
+ return false;
+} /* }}} */
+
+static const char* php_phongo_readpreference_get_mode_string(mongoc_read_mode_t mode) /* {{{ */
+{
+ switch (mode) {
+ case MONGOC_READ_PRIMARY:
+ return PHONGO_READ_PRIMARY;
+ case MONGOC_READ_PRIMARY_PREFERRED:
+ return PHONGO_READ_PRIMARY_PREFERRED;
+ case MONGOC_READ_SECONDARY:
+ return PHONGO_READ_SECONDARY;
+ case MONGOC_READ_SECONDARY_PREFERRED:
+ return PHONGO_READ_SECONDARY_PREFERRED;
+ case MONGOC_READ_NEAREST:
+ return PHONGO_READ_NEAREST;
+ default:
+ /* Should never happen, but if it does: exception */
+ phongo_throw_exception(PHONGO_ERROR_LOGIC, "Mode '%d' should never have been passed to php_phongo_readpreference_get_mode_string, please file a bug report", mode);
+ break;
+ }
+
+ return NULL;
+} /* }}} */
+
+/* {{{ proto void MongoDB\Driver\ReadPreference::__construct(int|string $mode[, array $tagSets = array()[, array $options = array()]])
+ Constructs a new ReadPreference */
+static PHP_METHOD(ReadPreference, __construct)
+{
+ zend_error_handling error_handling;
+ php_phongo_readpreference_t* intern;
+ zval* mode;
+ zval* tagSets = NULL;
+ zval* options = NULL;
+
+ intern = Z_READPREFERENCE_OBJ_P(getThis());
+
+ /* Separate the tagSets zval, since we may end up modifying it in
+ * php_phongo_read_preference_prep_tagsets() below. */
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|a/!a!", &mode, &tagSets, &options) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ if (Z_TYPE_P(mode) == IS_LONG) {
+ switch (Z_LVAL_P(mode)) {
+ case MONGOC_READ_PRIMARY:
+ case MONGOC_READ_SECONDARY:
+ case MONGOC_READ_PRIMARY_PREFERRED:
+ case MONGOC_READ_SECONDARY_PREFERRED:
+ case MONGOC_READ_NEAREST:
+ intern->read_preference = mongoc_read_prefs_new(Z_LVAL_P(mode));
+ break;
+ default:
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Invalid mode: %" PHONGO_LONG_FORMAT, Z_LVAL_P(mode));
+ return;
+ }
+ } else if (Z_TYPE_P(mode) == IS_STRING) {
+ if (strcasecmp(Z_STRVAL_P(mode), PHONGO_READ_PRIMARY) == 0) {
+ intern->read_preference = mongoc_read_prefs_new(MONGOC_READ_PRIMARY);
+ } else if (strcasecmp(Z_STRVAL_P(mode), PHONGO_READ_PRIMARY_PREFERRED) == 0) {
+ intern->read_preference = mongoc_read_prefs_new(MONGOC_READ_PRIMARY_PREFERRED);
+ } else if (strcasecmp(Z_STRVAL_P(mode), PHONGO_READ_SECONDARY) == 0) {
+ intern->read_preference = mongoc_read_prefs_new(MONGOC_READ_SECONDARY);
+ } else if (strcasecmp(Z_STRVAL_P(mode), PHONGO_READ_SECONDARY_PREFERRED) == 0) {
+ intern->read_preference = mongoc_read_prefs_new(MONGOC_READ_SECONDARY_PREFERRED);
+ } else if (strcasecmp(Z_STRVAL_P(mode), PHONGO_READ_NEAREST) == 0) {
+ intern->read_preference = mongoc_read_prefs_new(MONGOC_READ_NEAREST);
+ } else {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Invalid mode: '%s'", Z_STRVAL_P(mode));
+ return;
+ }
+ } else {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected mode to be integer or string, %s given", PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(mode));
+ return;
+ }
+
+ if (tagSets) {
+ bson_t* tags = bson_new();
+
+ php_phongo_read_preference_prep_tagsets(tagSets);
+ php_phongo_zval_to_bson(tagSets, PHONGO_BSON_NONE, (bson_t*) tags, NULL);
+
+ if (!php_phongo_read_preference_tags_are_valid(tags)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "tagSets must be an array of zero or more documents");
+ bson_destroy(tags);
+ return;
+ }
+
+ if (!bson_empty(tags) && (mongoc_read_prefs_get_mode(intern->read_preference) == MONGOC_READ_PRIMARY)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "tagSets may not be used with primary mode");
+ bson_destroy(tags);
+ return;
+ }
+
+ mongoc_read_prefs_set_tags(intern->read_preference, tags);
+ bson_destroy(tags);
+ }
+
+ if (options && php_array_exists(options, "maxStalenessSeconds")) {
+ zend_long maxStalenessSeconds = php_array_fetchc_long(options, "maxStalenessSeconds");
+
+ if (maxStalenessSeconds != MONGOC_NO_MAX_STALENESS) {
+ if (maxStalenessSeconds < MONGOC_SMALLEST_MAX_STALENESS_SECONDS) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected maxStalenessSeconds to be >= %d, %" PHONGO_LONG_FORMAT " given", MONGOC_SMALLEST_MAX_STALENESS_SECONDS, maxStalenessSeconds);
+ return;
+ }
+ if (maxStalenessSeconds > INT32_MAX) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected maxStalenessSeconds to be <= %" PRId32 ", %" PHONGO_LONG_FORMAT " given", INT32_MAX, maxStalenessSeconds);
+ return;
+ }
+ if (mongoc_read_prefs_get_mode(intern->read_preference) == MONGOC_READ_PRIMARY) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "maxStalenessSeconds may not be used with primary mode");
+ return;
+ }
+ }
+
+ mongoc_read_prefs_set_max_staleness_seconds(intern->read_preference, maxStalenessSeconds);
+ }
+
+ if (options && php_array_exists(options, "hedge")) {
+ zval* hedge = php_array_fetchc(options, "hedge");
+
+ if (Z_TYPE_P(hedge) == IS_ARRAY || Z_TYPE_P(hedge) == IS_OBJECT) {
+ bson_t* hedge_doc = bson_new();
+
+ if (mongoc_read_prefs_get_mode(intern->read_preference) == MONGOC_READ_PRIMARY) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "hedge may not be used with primary mode");
+ bson_destroy(hedge_doc);
+ return;
+ }
+
+ php_phongo_zval_to_bson(hedge, PHONGO_BSON_NONE, hedge_doc, NULL);
+
+ if (EG(exception)) {
+ bson_destroy(hedge_doc);
+ return;
+ }
+
+ mongoc_read_prefs_set_hedge(intern->read_preference, hedge_doc);
+ bson_destroy(hedge_doc);
+ } else {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"hedge\" field to be an array or object", ZSTR_VAL(php_phongo_readpreference_ce->name));
+ return;
+ }
+ }
+
+ if (!mongoc_read_prefs_is_valid(intern->read_preference)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Read preference is not valid");
+ return;
+ }
+} /* }}} */
+
+/* {{{ proto MongoDB\Driver\ReadPreference MongoDB\Driver\ReadPreference::__set_state(array $properties)
+*/
+static PHP_METHOD(ReadPreference, __set_state)
+{
+ zend_error_handling error_handling;
+ php_phongo_readpreference_t* intern;
+ HashTable* props;
+ zval* array;
+
+ /* Separate the zval, since we may end up modifying the "tags" element in
+ * php_phongo_read_preference_prep_tagsets(), which is called from
+ * php_phongo_readpreference_init_from_hash. */
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/", &array) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ object_init_ex(return_value, php_phongo_readpreference_ce);
+
+ intern = Z_READPREFERENCE_OBJ_P(return_value);
+ props = Z_ARRVAL_P(array);
+
+ php_phongo_readpreference_init_from_hash(intern, props);
+} /* }}} */
+
+/* {{{ proto array|null MongoDB\Driver\ReadPreference::getHedge()
+ Returns the ReadPreference hedge document */
+static PHP_METHOD(ReadPreference, getHedge)
+{
+ zend_error_handling error_handling;
+ php_phongo_readpreference_t* intern;
+ const bson_t* hedge;
+
+ intern = Z_READPREFERENCE_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ hedge = mongoc_read_prefs_get_hedge(intern->read_preference);
+
+ if (!bson_empty0(hedge)) {
+ php_phongo_bson_state state;
+
+ PHONGO_BSON_INIT_STATE(state);
+
+ if (!php_phongo_bson_to_zval_ex(bson_get_data(hedge), hedge->len, &state)) {
+ zval_ptr_dtor(&state.zchild);
+ return;
+ }
+
+ RETURN_ZVAL(&state.zchild, 0, 1);
+ } else {
+ RETURN_NULL();
+ }
+} /* }}} */
+
+/* {{{ proto integer MongoDB\Driver\ReadPreference::getMaxStalenessSeconds()
+ Returns the ReadPreference maxStalenessSeconds value */
+static PHP_METHOD(ReadPreference, getMaxStalenessSeconds)
+{
+ zend_error_handling error_handling;
+ php_phongo_readpreference_t* intern;
+
+ intern = Z_READPREFERENCE_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ RETURN_LONG(mongoc_read_prefs_get_max_staleness_seconds(intern->read_preference));
+} /* }}} */
+
+/* {{{ proto integer MongoDB\Driver\ReadPreference::getMode()
+ Returns the ReadPreference mode */
+static PHP_METHOD(ReadPreference, getMode)
+{
+ zend_error_handling error_handling;
+ php_phongo_readpreference_t* intern;
+
+ intern = Z_READPREFERENCE_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ RETURN_LONG(mongoc_read_prefs_get_mode(intern->read_preference));
+} /* }}} */
+
+/* {{{ proto string MongoDB\Driver\ReadPreference::getModeString()
+ Returns the ReadPreference mode as string */
+static PHP_METHOD(ReadPreference, getModeString)
+{
+ zend_error_handling error_handling;
+ php_phongo_readpreference_t* intern;
+ const char* mode_string;
+
+ intern = Z_READPREFERENCE_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ mode_string = php_phongo_readpreference_get_mode_string(mongoc_read_prefs_get_mode(intern->read_preference));
+ if (!mode_string) {
+ /* Exception already thrown */
+ return;
+ }
+
+ RETURN_STRING(mode_string);
+} /* }}} */
+
+/* {{{ proto array MongoDB\Driver\ReadPreference::getTagSets()
+ Returns the ReadPreference tag sets */
+static PHP_METHOD(ReadPreference, getTagSets)
+{
+ zend_error_handling error_handling;
+ php_phongo_readpreference_t* intern;
+ const bson_t* tags;
+
+ intern = Z_READPREFERENCE_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ tags = mongoc_read_prefs_get_tags(intern->read_preference);
+
+ if (tags->len) {
+ php_phongo_bson_state state;
+
+ PHONGO_BSON_INIT_DEBUG_STATE(state);
+
+ if (!php_phongo_bson_to_zval_ex(bson_get_data(tags), tags->len, &state)) {
+ zval_ptr_dtor(&state.zchild);
+ return;
+ }
+
+ RETURN_ZVAL(&state.zchild, 0, 1);
+ } else {
+ RETURN_NULL();
+ }
+} /* }}} */
+
+static HashTable* php_phongo_readpreference_get_properties_hash(phongo_compat_object_handler_type* object, bool is_temp) /* {{{ */
+{
+ php_phongo_readpreference_t* intern;
+ HashTable* props;
+ const char* modeString = NULL;
+ const bson_t* tags;
+ const bson_t* hedge;
+ mongoc_read_mode_t mode;
+
+ intern = Z_OBJ_READPREFERENCE(PHONGO_COMPAT_GET_OBJ(object));
+
+ PHONGO_GET_PROPERTY_HASH_INIT_PROPS(is_temp, intern, props, 4);
+
+ if (!intern->read_preference) {
+ return props;
+ }
+
+ tags = mongoc_read_prefs_get_tags(intern->read_preference);
+ mode = mongoc_read_prefs_get_mode(intern->read_preference);
+ modeString = php_phongo_readpreference_get_mode_string(mode);
+ hedge = mongoc_read_prefs_get_hedge(intern->read_preference);
+
+ if (modeString) {
+ zval z_mode;
+
+ ZVAL_STRING(&z_mode, modeString);
+ zend_hash_str_update(props, "mode", sizeof("mode") - 1, &z_mode);
+ }
+
+ if (!bson_empty0(tags)) {
+ php_phongo_bson_state state;
+
+ /* Use PHONGO_TYPEMAP_NATIVE_ARRAY for the root type since tags is an
+ * array; however, inner documents and arrays can use the default. */
+ PHONGO_BSON_INIT_STATE(state);
+ state.map.root_type = PHONGO_TYPEMAP_NATIVE_ARRAY;
+
+ if (!php_phongo_bson_to_zval_ex(bson_get_data(tags), tags->len, &state)) {
+ zval_ptr_dtor(&state.zchild);
+ goto done;
+ }
+
+ zend_hash_str_update(props, "tags", sizeof("tags") - 1, &state.zchild);
+ }
+
+ if (mongoc_read_prefs_get_max_staleness_seconds(intern->read_preference) != MONGOC_NO_MAX_STALENESS) {
+ /* Note: valid values for maxStalesnessSeconds will not exceed the range
+ * of 32-bit signed integers, so conditional encoding is not necessary. */
+ long maxStalenessSeconds = mongoc_read_prefs_get_max_staleness_seconds(intern->read_preference);
+ zval z_max_ss;
+
+ ZVAL_LONG(&z_max_ss, maxStalenessSeconds);
+ zend_hash_str_update(props, "maxStalenessSeconds", sizeof("maxStalenessSeconds") - 1, &z_max_ss);
+ }
+
+ if (!bson_empty0(hedge)) {
+ php_phongo_bson_state state;
+
+ PHONGO_BSON_INIT_STATE(state);
+
+ if (!php_phongo_bson_to_zval_ex(bson_get_data(hedge), hedge->len, &state)) {
+ zval_ptr_dtor(&state.zchild);
+ goto done;
+ }
+
+ zend_hash_str_update(props, "hedge", sizeof("hedge") - 1, &state.zchild);
+ }
+
+done:
+ return props;
+} /* }}} */
+
+/* {{{ proto array MongoDB\Driver\ReadPreference::bsonSerialize()
+*/
+static PHP_METHOD(ReadPreference, bsonSerialize)
+{
+ zend_error_handling error_handling;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ ZVAL_ARR(return_value, php_phongo_readpreference_get_properties_hash(PHONGO_COMPAT_OBJ_P(getThis()), true));
+ convert_to_object(return_value);
+} /* }}} */
+
+/* {{{ proto string MongoDB\Driver\ReadPreference::serialize()
+*/
+static PHP_METHOD(ReadPreference, serialize)
+{
+ zend_error_handling error_handling;
+ php_phongo_readpreference_t* intern;
+ zval retval;
+ php_serialize_data_t var_hash;
+ smart_str buf = { 0 };
+ const char* modeString = NULL;
+ const bson_t* tags;
+ const bson_t* hedge;
+ int64_t maxStalenessSeconds;
+ mongoc_read_mode_t mode;
+
+ intern = Z_READPREFERENCE_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ if (!intern->read_preference) {
+ return;
+ }
+
+ tags = mongoc_read_prefs_get_tags(intern->read_preference);
+ mode = mongoc_read_prefs_get_mode(intern->read_preference);
+ modeString = php_phongo_readpreference_get_mode_string(mode);
+ maxStalenessSeconds = mongoc_read_prefs_get_max_staleness_seconds(intern->read_preference);
+ hedge = mongoc_read_prefs_get_hedge(intern->read_preference);
+
+ array_init_size(&retval, 4);
+
+ if (modeString) {
+ ADD_ASSOC_STRING(&retval, "mode", modeString);
+ }
+
+ if (!bson_empty0(tags)) {
+ php_phongo_bson_state state;
+
+ PHONGO_BSON_INIT_DEBUG_STATE(state);
+
+ if (!php_phongo_bson_to_zval_ex(bson_get_data(tags), tags->len, &state)) {
+ zval_ptr_dtor(&state.zchild);
+ return;
+ }
+
+ ADD_ASSOC_ZVAL_EX(&retval, "tags", &state.zchild);
+ }
+
+ if (maxStalenessSeconds != MONGOC_NO_MAX_STALENESS) {
+ ADD_ASSOC_LONG_EX(&retval, "maxStalenessSeconds", maxStalenessSeconds);
+ }
+
+ if (!bson_empty0(hedge)) {
+ php_phongo_bson_state state;
+
+ PHONGO_BSON_INIT_STATE(state);
+
+ if (!php_phongo_bson_to_zval_ex(bson_get_data(hedge), hedge->len, &state)) {
+ zval_ptr_dtor(&state.zchild);
+ return;
+ }
+
+ ADD_ASSOC_ZVAL_EX(&retval, "hedge", &state.zchild);
+ }
+
+ PHP_VAR_SERIALIZE_INIT(var_hash);
+ php_var_serialize(&buf, &retval, &var_hash);
+ smart_str_0(&buf);
+ PHP_VAR_SERIALIZE_DESTROY(var_hash);
+
+ PHONGO_RETVAL_SMART_STR(buf);
+
+ smart_str_free(&buf);
+ zval_ptr_dtor(&retval);
+} /* }}} */
+
+/* {{{ proto void MongoDB\Driver\ReadPreference::unserialize(string $serialized)
+*/
+static PHP_METHOD(ReadPreference, unserialize)
+{
+ zend_error_handling error_handling;
+ php_phongo_readpreference_t* intern;
+ char* serialized;
+ size_t serialized_len;
+ zval props;
+ php_unserialize_data_t var_hash;
+
+ intern = Z_READPREFERENCE_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &serialized, &serialized_len) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ if (!serialized_len) {
+ return;
+ }
+
+ PHP_VAR_UNSERIALIZE_INIT(var_hash);
+ if (!php_var_unserialize(&props, (const unsigned char**) &serialized, (unsigned char*) serialized + serialized_len, &var_hash)) {
+ zval_ptr_dtor(&props);
+ phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "%s unserialization failed", ZSTR_VAL(php_phongo_readpreference_ce->name));
+
+ PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+ return;
+ }
+ PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+
+ php_phongo_readpreference_init_from_hash(intern, HASH_OF(&props));
+ zval_ptr_dtor(&props);
+} /* }}} */
+
+/* {{{ proto array MongoDB\Driver\ReadPreference::__serialize()
+*/
+static PHP_METHOD(ReadPreference, __serialize)
+{
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ RETURN_ARR(php_phongo_readpreference_get_properties_hash(PHONGO_COMPAT_OBJ_P(getThis()), true));
+} /* }}} */
+
+/* {{{ proto void MongoDB\Driver\ReadPreference::__unserialize(array $data)
+*/
+static PHP_METHOD(ReadPreference, __unserialize)
+{
+ zval* data;
+
+ PHONGO_PARSE_PARAMETERS_START(1, 1)
+ Z_PARAM_ARRAY(data)
+ PHONGO_PARSE_PARAMETERS_END();
+
+ php_phongo_readpreference_init_from_hash(Z_READPREFERENCE_OBJ_P(getThis()), Z_ARRVAL_P(data));
+} /* }}} */
+
+/* {{{ MongoDB\Driver\ReadPreference function entries */
+ZEND_BEGIN_ARG_INFO_EX(ai_ReadPreference___construct, 0, 0, 1)
+ ZEND_ARG_INFO(0, mode)
+ ZEND_ARG_ARRAY_INFO(0, tagSets, 1)
+ ZEND_ARG_ARRAY_INFO(0, options, 1)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_ReadPreference___set_state, 0, 0, 1)
+ ZEND_ARG_ARRAY_INFO(0, properties, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_ReadPreference___unserialize, 0, 0, 1)
+ ZEND_ARG_ARRAY_INFO(0, data, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_ReadPreference_unserialize, 0, 0, 1)
+ ZEND_ARG_INFO(0, serialized)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_ReadPreference_void, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry php_phongo_readpreference_me[] = {
+ /* clang-format off */
+ PHP_ME(ReadPreference, __construct, ai_ReadPreference___construct, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(ReadPreference, __serialize, ai_ReadPreference_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(ReadPreference, __set_state, ai_ReadPreference___set_state, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+ PHP_ME(ReadPreference, __unserialize, ai_ReadPreference___unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(ReadPreference, getHedge, ai_ReadPreference_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(ReadPreference, getMaxStalenessSeconds, ai_ReadPreference_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(ReadPreference, getMode, ai_ReadPreference_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(ReadPreference, getModeString, ai_ReadPreference_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(ReadPreference, getTagSets, ai_ReadPreference_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(ReadPreference, bsonSerialize, ai_ReadPreference_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(ReadPreference, serialize, ai_ReadPreference_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(ReadPreference, unserialize, ai_ReadPreference_unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_FE_END
+ /* clang-format on */
+};
+/* }}} */
+
+/* {{{ MongoDB\Driver\ReadPreference object handlers */
+static zend_object_handlers php_phongo_handler_readpreference;
+
+static void php_phongo_readpreference_free_object(zend_object* object) /* {{{ */
+{
+ php_phongo_readpreference_t* intern = Z_OBJ_READPREFERENCE(object);
+
+ zend_object_std_dtor(&intern->std);
+
+ if (intern->properties) {
+ zend_hash_destroy(intern->properties);
+ FREE_HASHTABLE(intern->properties);
+ }
+
+ if (intern->read_preference) {
+ mongoc_read_prefs_destroy(intern->read_preference);
+ }
+} /* }}} */
+
+static zend_object* php_phongo_readpreference_create_object(zend_class_entry* class_type) /* {{{ */
+{
+ php_phongo_readpreference_t* intern = zend_object_alloc(sizeof(php_phongo_readpreference_t), class_type);
+
+ zend_object_std_init(&intern->std, class_type);
+ object_properties_init(&intern->std, class_type);
+
+ intern->std.handlers = &php_phongo_handler_readpreference;
+
+ return &intern->std;
+} /* }}} */
+
+static HashTable* php_phongo_readpreference_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
+{
+ *is_temp = 1;
+ return php_phongo_readpreference_get_properties_hash(object, true);
+} /* }}} */
+
+static HashTable* php_phongo_readpreference_get_properties(phongo_compat_object_handler_type* object) /* {{{ */
+{
+ return php_phongo_readpreference_get_properties_hash(object, false);
+} /* }}} */
+/* }}} */
+
+void php_phongo_readpreference_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver", "ReadPreference", php_phongo_readpreference_me);
+ php_phongo_readpreference_ce = zend_register_internal_class(&ce);
+ php_phongo_readpreference_ce->create_object = php_phongo_readpreference_create_object;
+ PHONGO_CE_FINAL(php_phongo_readpreference_ce);
+
+ zend_class_implements(php_phongo_readpreference_ce, 1, php_phongo_serializable_ce);
+ zend_class_implements(php_phongo_readpreference_ce, 1, zend_ce_serializable);
+
+ memcpy(&php_phongo_handler_readpreference, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
+ php_phongo_handler_readpreference.get_debug_info = php_phongo_readpreference_get_debug_info;
+ php_phongo_handler_readpreference.get_properties = php_phongo_readpreference_get_properties;
+ php_phongo_handler_readpreference.free_obj = php_phongo_readpreference_free_object;
+ php_phongo_handler_readpreference.offset = XtOffsetOf(php_phongo_readpreference_t, std);
+
+ zend_declare_class_constant_long(php_phongo_readpreference_ce, ZEND_STRL("RP_PRIMARY"), MONGOC_READ_PRIMARY);
+ zend_declare_class_constant_long(php_phongo_readpreference_ce, ZEND_STRL("RP_PRIMARY_PREFERRED"), MONGOC_READ_PRIMARY_PREFERRED);
+ zend_declare_class_constant_long(php_phongo_readpreference_ce, ZEND_STRL("RP_SECONDARY"), MONGOC_READ_SECONDARY);
+ zend_declare_class_constant_long(php_phongo_readpreference_ce, ZEND_STRL("RP_SECONDARY_PREFERRED"), MONGOC_READ_SECONDARY_PREFERRED);
+ zend_declare_class_constant_long(php_phongo_readpreference_ce, ZEND_STRL("RP_NEAREST"), MONGOC_READ_NEAREST);
+ zend_declare_class_constant_long(php_phongo_readpreference_ce, ZEND_STRL("NO_MAX_STALENESS"), MONGOC_NO_MAX_STALENESS);
+ zend_declare_class_constant_long(php_phongo_readpreference_ce, ZEND_STRL("SMALLEST_MAX_STALENESS_SECONDS"), MONGOC_SMALLEST_MAX_STALENESS_SECONDS);
+
+ zend_declare_class_constant_string(php_phongo_readpreference_ce, ZEND_STRL("PRIMARY"), PHONGO_READ_PRIMARY);
+ zend_declare_class_constant_string(php_phongo_readpreference_ce, ZEND_STRL("PRIMARY_PREFERRED"), PHONGO_READ_PRIMARY_PREFERRED);
+ zend_declare_class_constant_string(php_phongo_readpreference_ce, ZEND_STRL("SECONDARY"), PHONGO_READ_SECONDARY);
+ zend_declare_class_constant_string(php_phongo_readpreference_ce, ZEND_STRL("SECONDARY_PREFERRED"), PHONGO_READ_SECONDARY_PREFERRED);
+ zend_declare_class_constant_string(php_phongo_readpreference_ce, ZEND_STRL("NEAREST"), PHONGO_READ_NEAREST);
+} /* }}} */
+
+void phongo_readpreference_init(zval* return_value, const mongoc_read_prefs_t* read_prefs) /* {{{ */
+{
+ php_phongo_readpreference_t* intern;
+
+ object_init_ex(return_value, php_phongo_readpreference_ce);
+
+ intern = Z_READPREFERENCE_OBJ_P(return_value);
+ intern->read_preference = mongoc_read_prefs_copy(read_prefs);
+}
+/* }}} */
+
+const mongoc_read_prefs_t* phongo_read_preference_from_zval(zval* zread_preference) /* {{{ */
+{
+ if (zread_preference) {
+ php_phongo_readpreference_t* intern = Z_READPREFERENCE_OBJ_P(zread_preference);
+
+ if (intern) {
+ return intern->read_preference;
+ }
+ }
+
+ return NULL;
+} /* }}} */
+/* }}} */
+
+/* Prepare tagSets for BSON encoding by converting each array in the set to an
+ * object. This ensures that empty arrays will serialize as empty documents.
+ *
+ * php_phongo_read_preference_tags_are_valid() handles actual validation of the
+ * tag set structure. */
+void php_phongo_read_preference_prep_tagsets(zval* tagSets) /* {{{ */
+{
+ HashTable* ht_data;
+ zval* tagSet;
+
+ if (Z_TYPE_P(tagSets) != IS_ARRAY) {
+ return;
+ }
+
+ ht_data = HASH_OF(tagSets);
+
+ ZEND_HASH_FOREACH_VAL_IND(ht_data, tagSet)
+ {
+ ZVAL_DEREF(tagSet);
+ if (Z_TYPE_P(tagSet) == IS_ARRAY) {
+ SEPARATE_ZVAL_NOREF(tagSet);
+ convert_to_object(tagSet);
+ }
+ }
+ ZEND_HASH_FOREACH_END();
+} /* }}} */
+
+/* Checks if tags is valid to set on a mongoc_read_prefs_t. It may be null or an
+ * array of one or more documents. */
+bool php_phongo_read_preference_tags_are_valid(const bson_t* tags) /* {{{ */
+{
+ bson_iter_t iter;
+
+ if (bson_empty0(tags)) {
+ return true;
+ }
+
+ if (!bson_iter_init(&iter, tags)) {
+ return false;
+ }
+
+ while (bson_iter_next(&iter)) {
+ if (!BSON_ITER_HOLDS_DOCUMENT(&iter)) {
+ return false;
+ }
+ }
+
+ return true;
+} /* }}} */
diff --git a/mongodb-1.13.0/src/MongoDB/ReadPreference.h b/mongodb-1.13.0/src/MongoDB/ReadPreference.h
new file mode 100644
index 00000000..9ede1819
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/ReadPreference.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2022-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PHONGO_READPREFERENCE_H
+#define PHONGO_READPREFERENCE_H
+
+#include "bson/bson.h"
+#include "mongoc/mongoc.h"
+
+#include <php.h>
+
+void phongo_readpreference_init(zval* return_value, const mongoc_read_prefs_t* read_prefs);
+
+const mongoc_read_prefs_t* phongo_read_preference_from_zval(zval* zread_preference);
+
+void php_phongo_read_preference_prep_tagsets(zval* tagSets);
+bool php_phongo_read_preference_tags_are_valid(const bson_t* tags);
+
+#endif /* PHONGO_READPREFERENCE_H */
diff --git a/mongodb-1.13.0/src/MongoDB/Server.c b/mongodb-1.13.0/src/MongoDB/Server.c
new file mode 100644
index 00000000..63624c15
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/Server.c
@@ -0,0 +1,846 @@
+/*
+ * Copyright 2014-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bson/bson.h"
+#include "mongoc/mongoc.h"
+
+#include <php.h>
+#include <Zend/zend_interfaces.h>
+
+#include "php_phongo.h"
+#include "phongo_bson_encode.h"
+#include "phongo_client.h"
+#include "phongo_error.h"
+#include "phongo_execute.h"
+#include "phongo_util.h"
+
+#include "MongoDB/Server.h"
+#include "MongoDB/ServerDescription.h"
+
+zend_class_entry* php_phongo_server_ce;
+
+/* {{{ proto MongoDB\Driver\Cursor MongoDB\Driver\Server::executeCommand(string $db, MongoDB\Driver\Command $command[, array $options = null]))
+ Executes a Command on this Server */
+static PHP_METHOD(Server, executeCommand)
+{
+ zend_error_handling error_handling;
+ php_phongo_server_t* intern;
+ char* db;
+ size_t db_len;
+ zval* command;
+ zval* options = NULL;
+ bool free_options = false;
+
+ intern = Z_SERVER_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "sO|z!", &db, &db_len, &command, php_phongo_command_ce, &options) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ options = php_phongo_prep_legacy_option(options, "readPreference", &free_options);
+
+ /* If the Server was created in a different process, reset the client so
+ * that cursors created by this process can be differentiated and its
+ * session pool is cleared. */
+ PHONGO_RESET_CLIENT_IF_PID_DIFFERS(intern, Z_MANAGER_OBJ_P(&intern->manager));
+
+ phongo_execute_command(&intern->manager, PHONGO_COMMAND_RAW, db, command, options, intern->server_id, return_value);
+
+ if (free_options) {
+ php_phongo_prep_legacy_option_free(options);
+ }
+} /* }}} */
+
+/* {{{ proto MongoDB\Driver\Cursor MongoDB\Driver\Server::executeReadCommand(string $db, MongoDB\Driver\Command $command[, array $options = null]))
+ Executes a ReadCommand on this Server */
+static PHP_METHOD(Server, executeReadCommand)
+{
+ zend_error_handling error_handling;
+ php_phongo_server_t* intern;
+ char* db;
+ size_t db_len;
+ zval* command;
+ zval* options = NULL;
+
+ intern = Z_SERVER_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "sO|a!", &db, &db_len, &command, php_phongo_command_ce, &options) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ /* If the Server was created in a different process, reset the client so
+ * that cursors created by this process can be differentiated and its
+ * session pool is cleared. */
+ PHONGO_RESET_CLIENT_IF_PID_DIFFERS(intern, Z_MANAGER_OBJ_P(&intern->manager));
+
+ phongo_execute_command(&intern->manager, PHONGO_COMMAND_READ, db, command, options, intern->server_id, return_value);
+} /* }}} */
+
+/* {{{ proto MongoDB\Driver\Cursor MongoDB\Driver\Server::executeWriteCommand(string $db, MongoDB\Driver\Command $command[, array $options = null]))
+ Executes a WriteCommand on this Server */
+static PHP_METHOD(Server, executeWriteCommand)
+{
+ zend_error_handling error_handling;
+ php_phongo_server_t* intern;
+ char* db;
+ size_t db_len;
+ zval* command;
+ zval* options = NULL;
+
+ intern = Z_SERVER_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "sO|a!", &db, &db_len, &command, php_phongo_command_ce, &options) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ /* If the Server was created in a different process, reset the client so
+ * that cursors created by this process can be differentiated. and its
+ * session pool is cleared. */
+ PHONGO_RESET_CLIENT_IF_PID_DIFFERS(intern, Z_MANAGER_OBJ_P(&intern->manager));
+
+ phongo_execute_command(&intern->manager, PHONGO_COMMAND_WRITE, db, command, options, intern->server_id, return_value);
+} /* }}} */
+
+/* {{{ proto MongoDB\Driver\Cursor MongoDB\Driver\Server::executeReadWriteCommand(string $db, MongoDB\Driver\Command $command[, array $options = null]))
+ Executes a ReadWriteCommand on this Server */
+static PHP_METHOD(Server, executeReadWriteCommand)
+{
+ zend_error_handling error_handling;
+ php_phongo_server_t* intern;
+ char* db;
+ size_t db_len;
+ zval* command;
+ zval* options = NULL;
+
+ intern = Z_SERVER_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "sO|a!", &db, &db_len, &command, php_phongo_command_ce, &options) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ /* If the Server was created in a different process, reset the client so
+ * that cursors created by this process can be differentiated and its
+ * session pool is cleared. */
+ PHONGO_RESET_CLIENT_IF_PID_DIFFERS(intern, Z_MANAGER_OBJ_P(&intern->manager));
+
+ phongo_execute_command(&intern->manager, PHONGO_COMMAND_READ_WRITE, db, command, options, intern->server_id, return_value);
+} /* }}} */
+
+/* {{{ proto MongoDB\Driver\Cursor MongoDB\Driver\Server::executeQuery(string $namespace, MongoDB\Driver\Query $query[, array $options = null]))
+ Executes a Query on this Server */
+static PHP_METHOD(Server, executeQuery)
+{
+ zend_error_handling error_handling;
+ php_phongo_server_t* intern;
+ char* namespace;
+ size_t namespace_len;
+ zval* query;
+ zval* options = NULL;
+ bool free_options = false;
+
+ intern = Z_SERVER_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "sO|z!", &namespace, &namespace_len, &query, php_phongo_query_ce, &options) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ options = php_phongo_prep_legacy_option(options, "readPreference", &free_options);
+
+ /* If the Server was created in a different process, reset the client so
+ * that cursors created by this process can be differentiated and its
+ * session pool is cleared. */
+ PHONGO_RESET_CLIENT_IF_PID_DIFFERS(intern, Z_MANAGER_OBJ_P(&intern->manager));
+
+ phongo_execute_query(&intern->manager, namespace, query, options, intern->server_id, return_value);
+
+ if (free_options) {
+ php_phongo_prep_legacy_option_free(options);
+ }
+} /* }}} */
+
+/* {{{ proto MongoDB\Driver\WriteResult MongoDB\Driver\Server::executeBulkWrite(string $namespace, MongoDB\Driver\BulkWrite $zbulk[, array $options = null])
+ Executes a BulkWrite (i.e. any number of insert, update, and delete ops) on
+ this Server */
+static PHP_METHOD(Server, executeBulkWrite)
+{
+ zend_error_handling error_handling;
+ php_phongo_server_t* intern;
+ char* namespace;
+ size_t namespace_len;
+ zval* zbulk;
+ php_phongo_bulkwrite_t* bulk;
+ zval* options = NULL;
+ bool free_options = false;
+
+ intern = Z_SERVER_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "sO|z!", &namespace, &namespace_len, &zbulk, php_phongo_bulkwrite_ce, &options, php_phongo_writeconcern_ce) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ bulk = Z_BULKWRITE_OBJ_P(zbulk);
+
+ options = php_phongo_prep_legacy_option(options, "writeConcern", &free_options);
+
+ /* If the Server was created in a different process, reset the client so
+ * that its session pool is cleared. */
+ PHONGO_RESET_CLIENT_IF_PID_DIFFERS(intern, Z_MANAGER_OBJ_P(&intern->manager));
+
+ phongo_execute_bulk_write(&intern->manager, namespace, bulk, options, intern->server_id, return_value);
+
+ if (free_options) {
+ php_phongo_prep_legacy_option_free(options);
+ }
+} /* }}} */
+
+/* {{{ proto string MongoDB\Driver\Server::getHost()
+ Returns the hostname for this Server */
+static PHP_METHOD(Server, getHost)
+{
+ zend_error_handling error_handling;
+ php_phongo_server_t* intern;
+ mongoc_server_description_t* sd;
+
+ intern = Z_SERVER_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ if ((sd = mongoc_client_get_server_description(Z_MANAGER_OBJ_P(&intern->manager)->client, intern->server_id))) {
+ RETVAL_STRING(mongoc_server_description_host(sd)->host);
+ mongoc_server_description_destroy(sd);
+ return;
+ }
+
+ phongo_throw_exception(PHONGO_ERROR_RUNTIME, "Failed to get server description");
+} /* }}} */
+
+/* {{{ proto array MongoDB\Driver\Server::getTags()
+ Returns the currently configured tags for this Server */
+static PHP_METHOD(Server, getTags)
+{
+ zend_error_handling error_handling;
+ php_phongo_server_t* intern;
+ mongoc_server_description_t* sd;
+
+ intern = Z_SERVER_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ if ((sd = mongoc_client_get_server_description(Z_MANAGER_OBJ_P(&intern->manager)->client, intern->server_id))) {
+ const bson_t* hello_response = mongoc_server_description_hello_response(sd);
+ bson_iter_t iter;
+
+ if (bson_iter_init_find(&iter, hello_response, "tags") && BSON_ITER_HOLDS_DOCUMENT(&iter)) {
+ const uint8_t* bytes;
+ uint32_t len;
+ php_phongo_bson_state state;
+
+ PHONGO_BSON_INIT_DEBUG_STATE(state);
+ bson_iter_document(&iter, &len, &bytes);
+
+ if (!php_phongo_bson_to_zval_ex(bytes, len, &state)) {
+ /* Exception should already have been thrown */
+ zval_ptr_dtor(&state.zchild);
+ mongoc_server_description_destroy(sd);
+ return;
+ }
+
+ mongoc_server_description_destroy(sd);
+
+ RETURN_ZVAL(&state.zchild, 0, 1);
+ }
+
+ array_init(return_value);
+ mongoc_server_description_destroy(sd);
+ return;
+ }
+
+ phongo_throw_exception(PHONGO_ERROR_RUNTIME, "Failed to get server description");
+} /* }}} */
+
+/* {{{ proto array MongoDB\Driver\Server::getInfo()
+ Returns the last hello response for this Server or, in the case of a load
+ balancer, the initial handshake response. */
+static PHP_METHOD(Server, getInfo)
+{
+ php_phongo_server_t* intern;
+ mongoc_client_t* client;
+ mongoc_server_description_t* sd;
+ mongoc_server_description_t* handshake_sd = NULL;
+ const bson_t* hello_response;
+ php_phongo_bson_state state;
+
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ intern = Z_SERVER_OBJ_P(getThis());
+ client = Z_MANAGER_OBJ_P(&intern->manager)->client;
+
+ if (!(sd = mongoc_client_get_server_description(client, intern->server_id))) {
+ phongo_throw_exception(PHONGO_ERROR_RUNTIME, "Failed to get server description");
+ return;
+ }
+
+ hello_response = mongoc_server_description_hello_response(sd);
+
+ /* If the server description is a load balancer, its hello_response will be
+ * empty. Instead, report the hello_response from the handshake description
+ * (i.e. backing server). */
+ if (!strcmp(mongoc_server_description_type(sd), php_phongo_server_description_type_map[PHONGO_SERVER_LOAD_BALANCER].name)) {
+ bson_error_t error = { 0 };
+
+ if (!(handshake_sd = mongoc_client_get_handshake_description(client, intern->server_id, NULL, &error))) {
+ phongo_throw_exception(PHONGO_ERROR_RUNTIME, "Failed to get handshake server description: %s", error.message);
+ goto cleanup;
+ }
+
+ hello_response = mongoc_server_description_hello_response(handshake_sd);
+ }
+
+ PHONGO_BSON_INIT_DEBUG_STATE(state);
+
+ if (!php_phongo_bson_to_zval_ex(bson_get_data(hello_response), hello_response->len, &state)) {
+ /* Exception should already have been thrown */
+ zval_ptr_dtor(&state.zchild);
+ goto cleanup;
+ }
+
+ RETVAL_ZVAL(&state.zchild, 0, 1);
+
+cleanup:
+ if (handshake_sd) {
+ mongoc_server_description_destroy(handshake_sd);
+ }
+
+ mongoc_server_description_destroy(sd);
+} /* }}} */
+
+/* {{{ proto integer|null MongoDB\Driver\Server::getLatency()
+ Returns the measured latency (i.e. round trip time in milliseconds) for
+ this Server, or null if unset. */
+static PHP_METHOD(Server, getLatency)
+{
+ php_phongo_server_t* intern;
+ mongoc_server_description_t* sd;
+
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ intern = Z_SERVER_OBJ_P(getThis());
+
+ if (!(sd = mongoc_client_get_server_description(Z_MANAGER_OBJ_P(&intern->manager)->client, intern->server_id))) {
+ phongo_throw_exception(PHONGO_ERROR_RUNTIME, "Failed to get server description");
+ return;
+ }
+
+ /* TODO: Use MONGOC_RTT_UNSET once it is added to libmongoc's public API (CDRIVER-4176) */
+ if (mongoc_server_description_round_trip_time(sd) == -1) {
+ RETVAL_NULL();
+ } else {
+ RETVAL_LONG((zend_long) mongoc_server_description_round_trip_time(sd));
+ }
+
+ mongoc_server_description_destroy(sd);
+} /* }}} */
+
+/* {{{ proto integer MongoDB\Driver\Server::getPort()
+ Returns the port for this Server */
+static PHP_METHOD(Server, getPort)
+{
+ zend_error_handling error_handling;
+ php_phongo_server_t* intern;
+ mongoc_server_description_t* sd;
+
+ intern = Z_SERVER_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ if ((sd = mongoc_client_get_server_description(Z_MANAGER_OBJ_P(&intern->manager)->client, intern->server_id))) {
+ RETVAL_LONG(mongoc_server_description_host(sd)->port);
+ mongoc_server_description_destroy(sd);
+ return;
+ }
+
+ phongo_throw_exception(PHONGO_ERROR_RUNTIME, "Failed to get server description");
+} /* }}} */
+
+/* {{{ proto MongoDB\Driver\ServerDescription MongoDB\Driver\Server::getServerDescription()
+ Returns the server description for this Server */
+static PHP_METHOD(Server, getServerDescription)
+{
+ mongoc_server_description_t* server_description;
+ php_phongo_server_t* intern = Z_SERVER_OBJ_P(getThis());
+
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ server_description = mongoc_client_get_server_description(Z_MANAGER_OBJ_P(&intern->manager)->client, intern->server_id);
+
+ /* Avoid making another copy in phongo_serverdescription_init */
+ phongo_serverdescription_init_ex(return_value, server_description, false);
+} /* }}} */
+
+/* {{{ proto integer MongoDB\Driver\Server::getType()
+ Returns the node type of this Server */
+static PHP_METHOD(Server, getType)
+{
+ zend_error_handling error_handling;
+ php_phongo_server_t* intern;
+ mongoc_server_description_t* sd;
+
+ intern = Z_SERVER_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ if ((sd = mongoc_client_get_server_description(Z_MANAGER_OBJ_P(&intern->manager)->client, intern->server_id))) {
+ RETVAL_LONG(php_phongo_server_description_type(sd));
+ mongoc_server_description_destroy(sd);
+ return;
+ }
+
+ phongo_throw_exception(PHONGO_ERROR_RUNTIME, "Failed to get server description");
+} /* }}} */
+
+/* {{{ proto boolean MongoDB\Driver\Server::isPrimary()
+ Returns whether this Server is a primary member of a replica set */
+static PHP_METHOD(Server, isPrimary)
+{
+ zend_error_handling error_handling;
+ php_phongo_server_t* intern;
+ mongoc_server_description_t* sd;
+
+ intern = Z_SERVER_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ if ((sd = mongoc_client_get_server_description(Z_MANAGER_OBJ_P(&intern->manager)->client, intern->server_id))) {
+ RETVAL_BOOL(!strcmp(mongoc_server_description_type(sd), php_phongo_server_description_type_map[PHONGO_SERVER_RS_PRIMARY].name));
+ mongoc_server_description_destroy(sd);
+ return;
+ }
+
+ phongo_throw_exception(PHONGO_ERROR_RUNTIME, "Failed to get server description");
+} /* }}} */
+
+/* {{{ proto boolean MongoDB\Driver\Server::isSecondary()
+ Returns whether this Server is a secondary member of a replica set */
+static PHP_METHOD(Server, isSecondary)
+{
+ zend_error_handling error_handling;
+ php_phongo_server_t* intern;
+ mongoc_server_description_t* sd;
+
+ intern = Z_SERVER_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ if ((sd = mongoc_client_get_server_description(Z_MANAGER_OBJ_P(&intern->manager)->client, intern->server_id))) {
+ RETVAL_BOOL(!strcmp(mongoc_server_description_type(sd), php_phongo_server_description_type_map[PHONGO_SERVER_RS_SECONDARY].name));
+ mongoc_server_description_destroy(sd);
+ return;
+ }
+
+ phongo_throw_exception(PHONGO_ERROR_RUNTIME, "Failed to get server description");
+} /* }}} */
+
+/* {{{ proto boolean MongoDB\Driver\Server::isArbiter()
+ Returns whether this Server is an arbiter member of a replica set */
+static PHP_METHOD(Server, isArbiter)
+{
+ zend_error_handling error_handling;
+ php_phongo_server_t* intern;
+ mongoc_server_description_t* sd;
+
+ intern = Z_SERVER_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ if ((sd = mongoc_client_get_server_description(Z_MANAGER_OBJ_P(&intern->manager)->client, intern->server_id))) {
+ RETVAL_BOOL(!strcmp(mongoc_server_description_type(sd), php_phongo_server_description_type_map[PHONGO_SERVER_RS_ARBITER].name));
+ mongoc_server_description_destroy(sd);
+ return;
+ }
+
+ phongo_throw_exception(PHONGO_ERROR_RUNTIME, "Failed to get server description");
+} /* }}} */
+
+/* {{{ proto boolean MongoDB\Driver\Server::isHidden()
+ Returns whether this Server is a hidden member of a replica set */
+static PHP_METHOD(Server, isHidden)
+{
+ zend_error_handling error_handling;
+ php_phongo_server_t* intern;
+ mongoc_server_description_t* sd;
+
+ intern = Z_SERVER_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ if ((sd = mongoc_client_get_server_description(Z_MANAGER_OBJ_P(&intern->manager)->client, intern->server_id))) {
+ bson_iter_t iter;
+
+ RETVAL_BOOL(bson_iter_init_find_case(&iter, mongoc_server_description_hello_response(sd), "hidden") && bson_iter_as_bool(&iter));
+ mongoc_server_description_destroy(sd);
+ return;
+ }
+
+ phongo_throw_exception(PHONGO_ERROR_RUNTIME, "Failed to get server description");
+} /* }}} */
+
+/* {{{ proto boolean MongoDB\Driver\Server::isPassive()
+ Returns whether this Server is a passive member of a replica set */
+static PHP_METHOD(Server, isPassive)
+{
+ zend_error_handling error_handling;
+ php_phongo_server_t* intern;
+ mongoc_server_description_t* sd;
+
+ intern = Z_SERVER_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ if ((sd = mongoc_client_get_server_description(Z_MANAGER_OBJ_P(&intern->manager)->client, intern->server_id))) {
+ bson_iter_t iter;
+
+ RETVAL_BOOL(bson_iter_init_find_case(&iter, mongoc_server_description_hello_response(sd), "passive") && bson_iter_as_bool(&iter));
+ mongoc_server_description_destroy(sd);
+ return;
+ }
+
+ phongo_throw_exception(PHONGO_ERROR_RUNTIME, "Failed to get server description");
+} /* }}} */
+
+/* {{{ MongoDB\Driver\Server function entries */
+ZEND_BEGIN_ARG_INFO_EX(ai_Server_executeCommand, 0, 0, 2)
+ ZEND_ARG_INFO(0, db)
+ ZEND_ARG_OBJ_INFO(0, command, MongoDB\\Driver\\Command, 0)
+ ZEND_ARG_INFO(0, options)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_Server_executeRWCommand, 0, 0, 2)
+ ZEND_ARG_INFO(0, db)
+ ZEND_ARG_OBJ_INFO(0, command, MongoDB\\Driver\\Command, 0)
+ ZEND_ARG_ARRAY_INFO(0, options, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_Server_executeQuery, 0, 0, 2)
+ ZEND_ARG_INFO(0, namespace)
+ ZEND_ARG_OBJ_INFO(0, zquery, MongoDB\\Driver\\Query, 0)
+ ZEND_ARG_INFO(0, options)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_Server_executeBulkWrite, 0, 0, 2)
+ ZEND_ARG_INFO(0, namespace)
+ ZEND_ARG_OBJ_INFO(0, zbulk, MongoDB\\Driver\\BulkWrite, 0)
+ ZEND_ARG_INFO(0, options)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_Server_void, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry php_phongo_server_me[] = {
+ /* clang-format off */
+ PHP_ME(Server, executeCommand, ai_Server_executeCommand, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Server, executeReadCommand, ai_Server_executeRWCommand, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Server, executeWriteCommand, ai_Server_executeRWCommand, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Server, executeReadWriteCommand, ai_Server_executeRWCommand, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Server, executeQuery, ai_Server_executeQuery, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Server, executeBulkWrite, ai_Server_executeBulkWrite, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Server, getHost, ai_Server_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Server, getTags, ai_Server_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Server, getInfo, ai_Server_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Server, getLatency, ai_Server_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Server, getPort, ai_Server_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Server, getServerDescription, ai_Server_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Server, getType, ai_Server_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Server, isPrimary, ai_Server_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Server, isSecondary, ai_Server_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Server, isArbiter, ai_Server_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Server, isHidden, ai_Server_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Server, isPassive, ai_Server_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ ZEND_NAMED_ME(__construct, PHP_FN(MongoDB_disabled___construct), ai_Server_void, ZEND_ACC_PRIVATE | ZEND_ACC_FINAL)
+ ZEND_NAMED_ME(__wakeup, PHP_FN(MongoDB_disabled___wakeup), ai_Server_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_FE_END
+ /* clang-format on */
+};
+/* }}} */
+
+/* {{{ MongoDB\Driver\Server object handlers */
+static zend_object_handlers php_phongo_handler_server;
+
+static int php_phongo_server_compare_objects(zval* o1, zval* o2) /* {{{ */
+{
+ php_phongo_server_t* intern1;
+ php_phongo_server_t* intern2;
+ mongoc_server_description_t *sd1, *sd2;
+ int retval = 0;
+
+ ZEND_COMPARE_OBJECTS_FALLBACK(o1, o2);
+
+ intern1 = Z_SERVER_OBJ_P(o1);
+ intern2 = Z_SERVER_OBJ_P(o2);
+
+ sd1 = mongoc_client_get_server_description(Z_MANAGER_OBJ_P(&intern1->manager)->client, intern1->server_id);
+ sd2 = mongoc_client_get_server_description(Z_MANAGER_OBJ_P(&intern2->manager)->client, intern2->server_id);
+
+ if (sd1 && sd2) {
+ retval = strcasecmp(mongoc_server_description_host(sd1)->host_and_port, mongoc_server_description_host(sd2)->host_and_port);
+ } else {
+ phongo_throw_exception(PHONGO_ERROR_RUNTIME, "Failed to get server description(s)");
+ }
+
+ if (sd1) {
+ mongoc_server_description_destroy(sd1);
+ }
+
+ if (sd2) {
+ mongoc_server_description_destroy(sd2);
+ }
+
+ return retval;
+} /* }}} */
+
+static void php_phongo_server_free_object(zend_object* object) /* {{{ */
+{
+ php_phongo_server_t* intern = Z_OBJ_SERVER(object);
+
+ zend_object_std_dtor(&intern->std);
+
+ if (!Z_ISUNDEF(intern->manager)) {
+ zval_ptr_dtor(&intern->manager);
+ }
+} /* }}} */
+
+static zend_object* php_phongo_server_create_object(zend_class_entry* class_type) /* {{{ */
+{
+ php_phongo_server_t* intern = zend_object_alloc(sizeof(php_phongo_server_t), class_type);
+
+ zend_object_std_init(&intern->std, class_type);
+ object_properties_init(&intern->std, class_type);
+
+ PHONGO_SET_CREATED_BY_PID(intern);
+
+ intern->std.handlers = &php_phongo_handler_server;
+
+ return &intern->std;
+} /* }}} */
+
+static HashTable* php_phongo_server_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
+{
+ php_phongo_server_t* intern = NULL;
+ zval retval = ZVAL_STATIC_INIT;
+ mongoc_client_t* client;
+ mongoc_server_description_t* sd;
+
+ *is_temp = 1;
+ intern = Z_OBJ_SERVER(PHONGO_COMPAT_GET_OBJ(object));
+ client = Z_MANAGER_OBJ_P(&intern->manager)->client;
+
+ if (!(sd = mongoc_client_get_server_description(client, intern->server_id))) {
+ phongo_throw_exception(PHONGO_ERROR_RUNTIME, "Failed to get server description");
+ return NULL;
+ }
+
+ php_phongo_server_to_zval(&retval, client, sd);
+ mongoc_server_description_destroy(sd);
+
+ return Z_ARRVAL(retval);
+} /* }}} */
+/* }}} */
+
+void php_phongo_server_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver", "Server", php_phongo_server_me);
+ php_phongo_server_ce = zend_register_internal_class(&ce);
+ php_phongo_server_ce->create_object = php_phongo_server_create_object;
+ PHONGO_CE_FINAL(php_phongo_server_ce);
+ PHONGO_CE_DISABLE_SERIALIZATION(php_phongo_server_ce);
+
+ memcpy(&php_phongo_handler_server, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
+ PHONGO_COMPAT_SET_COMPARE_OBJECTS_HANDLER(server);
+ php_phongo_handler_server.get_debug_info = php_phongo_server_get_debug_info;
+ php_phongo_handler_server.free_obj = php_phongo_server_free_object;
+ php_phongo_handler_server.offset = XtOffsetOf(php_phongo_server_t, std);
+
+ zend_declare_class_constant_long(php_phongo_server_ce, ZEND_STRL("TYPE_UNKNOWN"), PHONGO_SERVER_UNKNOWN);
+ zend_declare_class_constant_long(php_phongo_server_ce, ZEND_STRL("TYPE_STANDALONE"), PHONGO_SERVER_STANDALONE);
+ zend_declare_class_constant_long(php_phongo_server_ce, ZEND_STRL("TYPE_MONGOS"), PHONGO_SERVER_MONGOS);
+ zend_declare_class_constant_long(php_phongo_server_ce, ZEND_STRL("TYPE_POSSIBLE_PRIMARY"), PHONGO_SERVER_POSSIBLE_PRIMARY);
+ zend_declare_class_constant_long(php_phongo_server_ce, ZEND_STRL("TYPE_RS_PRIMARY"), PHONGO_SERVER_RS_PRIMARY);
+ zend_declare_class_constant_long(php_phongo_server_ce, ZEND_STRL("TYPE_RS_SECONDARY"), PHONGO_SERVER_RS_SECONDARY);
+ zend_declare_class_constant_long(php_phongo_server_ce, ZEND_STRL("TYPE_RS_ARBITER"), PHONGO_SERVER_RS_ARBITER);
+ zend_declare_class_constant_long(php_phongo_server_ce, ZEND_STRL("TYPE_RS_OTHER"), PHONGO_SERVER_RS_OTHER);
+ zend_declare_class_constant_long(php_phongo_server_ce, ZEND_STRL("TYPE_RS_GHOST"), PHONGO_SERVER_RS_GHOST);
+ zend_declare_class_constant_long(php_phongo_server_ce, ZEND_STRL("TYPE_LOAD_BALANCER"), PHONGO_SERVER_LOAD_BALANCER);
+} /* }}} */
+
+void phongo_server_init(zval* return_value, zval* manager, uint32_t server_id) /* {{{ */
+{
+ php_phongo_server_t* server;
+
+ object_init_ex(return_value, php_phongo_server_ce);
+
+ server = Z_SERVER_OBJ_P(return_value);
+ server->server_id = server_id;
+
+ ZVAL_ZVAL(&server->manager, manager, 1, 0);
+}
+/* }}} */
+
+bool php_phongo_server_to_zval(zval* retval, mongoc_client_t* client, mongoc_server_description_t* sd) /* {{{ */
+{
+ mongoc_host_list_t* host = mongoc_server_description_host(sd);
+ const bson_t* hello_response = mongoc_server_description_hello_response(sd);
+ bson_iter_t iter;
+
+ array_init(retval);
+
+ ADD_ASSOC_STRING(retval, "host", host->host);
+ ADD_ASSOC_LONG_EX(retval, "port", host->port);
+ ADD_ASSOC_LONG_EX(retval, "type", php_phongo_server_description_type(sd));
+ ADD_ASSOC_BOOL_EX(retval, "is_primary", !strcmp(mongoc_server_description_type(sd), php_phongo_server_description_type_map[PHONGO_SERVER_RS_PRIMARY].name));
+ ADD_ASSOC_BOOL_EX(retval, "is_secondary", !strcmp(mongoc_server_description_type(sd), php_phongo_server_description_type_map[PHONGO_SERVER_RS_SECONDARY].name));
+ ADD_ASSOC_BOOL_EX(retval, "is_arbiter", !strcmp(mongoc_server_description_type(sd), php_phongo_server_description_type_map[PHONGO_SERVER_RS_ARBITER].name));
+ ADD_ASSOC_BOOL_EX(retval, "is_hidden", bson_iter_init_find_case(&iter, hello_response, "hidden") && bson_iter_as_bool(&iter));
+ ADD_ASSOC_BOOL_EX(retval, "is_passive", bson_iter_init_find_case(&iter, hello_response, "passive") && bson_iter_as_bool(&iter));
+
+ if (bson_iter_init_find(&iter, hello_response, "tags") && BSON_ITER_HOLDS_DOCUMENT(&iter)) {
+ const uint8_t* bytes;
+ uint32_t len;
+ php_phongo_bson_state state;
+
+ PHONGO_BSON_INIT_DEBUG_STATE(state);
+ bson_iter_document(&iter, &len, &bytes);
+ if (!php_phongo_bson_to_zval_ex(bytes, len, &state)) {
+ /* Exception already thrown */
+ zval_ptr_dtor(&state.zchild);
+ return false;
+ }
+
+ ADD_ASSOC_ZVAL_EX(retval, "tags", &state.zchild);
+ }
+
+ /* If the server description is a load balancer, its hello_response will be
+ * empty. Instead, report the hello_response from the handshake description
+ * (i.e. backing server). */
+ if (!strcmp(mongoc_server_description_type(sd), php_phongo_server_description_type_map[PHONGO_SERVER_LOAD_BALANCER].name)) {
+ const bson_t* handshake_response;
+ mongoc_server_description_t* handshake_sd;
+ bson_error_t error = { 0 };
+ php_phongo_bson_state state;
+
+ if (!(handshake_sd = mongoc_client_get_handshake_description(client, mongoc_server_description_id(sd), NULL, &error))) {
+ phongo_throw_exception(PHONGO_ERROR_RUNTIME, "Failed to get handshake server description: %s", error.message);
+ return false;
+ }
+
+ PHONGO_BSON_INIT_DEBUG_STATE(state);
+ handshake_response = mongoc_server_description_hello_response(handshake_sd);
+
+ if (!php_phongo_bson_to_zval_ex(bson_get_data(handshake_response), handshake_response->len, &state)) {
+ /* Exception already thrown */
+ mongoc_server_description_destroy(handshake_sd);
+ zval_ptr_dtor(&state.zchild);
+ return false;
+ }
+
+ ADD_ASSOC_ZVAL_EX(retval, "last_hello_response", &state.zchild);
+ mongoc_server_description_destroy(handshake_sd);
+ } else {
+ php_phongo_bson_state state;
+
+ PHONGO_BSON_INIT_DEBUG_STATE(state);
+
+ if (!php_phongo_bson_to_zval_ex(bson_get_data(hello_response), hello_response->len, &state)) {
+ /* Exception already thrown */
+ zval_ptr_dtor(&state.zchild);
+ return false;
+ }
+
+ ADD_ASSOC_ZVAL_EX(retval, "last_hello_response", &state.zchild);
+ }
+
+ /* TODO: Use MONGOC_RTT_UNSET once it is added to libmongoc's public API (CDRIVER-4176) */
+ if (mongoc_server_description_round_trip_time(sd) == -1) {
+ ADD_ASSOC_NULL_EX(retval, "round_trip_time");
+ } else {
+ ADD_ASSOC_LONG_EX(retval, "round_trip_time", (zend_long) mongoc_server_description_round_trip_time(sd));
+ }
+
+ return true;
+} /* }}} */
diff --git a/mongodb-1.13.0/src/MongoDB/Server.h b/mongodb-1.13.0/src/MongoDB/Server.h
new file mode 100644
index 00000000..4214d496
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/Server.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2022-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PHONGO_SERVER_H
+#define PHONGO_SERVER_H
+
+#include "mongoc/mongoc.h"
+
+#include <php.h>
+
+void phongo_server_init(zval* return_value, zval* manager, uint32_t server_id);
+
+bool php_phongo_server_to_zval(zval* retval, mongoc_client_t* client, mongoc_server_description_t* sd);
+
+#endif /* PHONGO_SERVER_H */
diff --git a/mongodb-1.13.0/src/MongoDB/ServerApi.c b/mongodb-1.13.0/src/MongoDB/ServerApi.c
new file mode 100644
index 00000000..94ea2da5
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/ServerApi.c
@@ -0,0 +1,390 @@
+/*
+ * Copyright 2021-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mongoc/mongoc.h"
+
+#include <php.h>
+#include <zend_smart_str.h>
+#include <ext/standard/php_var.h>
+#include <Zend/zend_interfaces.h>
+
+#include "php_phongo.h"
+#include "phongo_error.h"
+
+zend_class_entry* php_phongo_serverapi_ce;
+
+static bool php_phongo_serverapi_create_libmongoc_object(mongoc_server_api_t** server_api, zend_string* version, bool strict_set, bool strict, bool deprecation_errors_set, bool deprecation_errors) /* {{{ */
+{
+ mongoc_server_api_version_t server_api_version;
+
+ if (!mongoc_server_api_version_from_string(ZSTR_VAL(version), &server_api_version)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Server API version \"%s\" is not supported in this driver version", ZSTR_VAL(version));
+ return false;
+ }
+
+ if (*server_api) {
+ phongo_throw_exception(PHONGO_ERROR_LOGIC, "Server API object already initialized. Please file a bug report as this should not happen.");
+ return false;
+ }
+
+ *server_api = mongoc_server_api_new(server_api_version);
+
+ if (strict_set) {
+ mongoc_server_api_strict(*server_api, strict);
+ }
+
+ if (deprecation_errors_set) {
+ mongoc_server_api_deprecation_errors(*server_api, deprecation_errors);
+ }
+
+ return true;
+} /* }}} */
+
+/* Initialize the object from a HashTable and return whether it was successful.
+ * An exception will be thrown on error. */
+static bool php_phongo_serverapi_init_from_hash(php_phongo_serverapi_t* intern, HashTable* props) /* {{{ */
+{
+ zval* version;
+ zval* strict;
+ zval* deprecation_errors;
+
+ version = zend_hash_str_find(props, ZEND_STRL("version"));
+ if (!version || Z_TYPE_P(version) != IS_STRING) {
+ // Exception
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"version\" field to be string", ZSTR_VAL(php_phongo_serverapi_ce->name));
+ return false;
+ }
+
+ if ((strict = zend_hash_str_find(props, ZEND_STRL("strict"))) && !ZVAL_IS_NULL(strict)) {
+ if (Z_TYPE_P(strict) != IS_TRUE && Z_TYPE_P(strict) != IS_FALSE) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"strict\" field to be bool or null", ZSTR_VAL(php_phongo_serverapi_ce->name));
+ return false;
+ }
+ }
+
+ if ((deprecation_errors = zend_hash_str_find(props, ZEND_STRL("deprecationErrors"))) && !ZVAL_IS_NULL(deprecation_errors)) {
+ if (Z_TYPE_P(deprecation_errors) != IS_TRUE && Z_TYPE_P(deprecation_errors) != IS_FALSE) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"deprecationErrors\" field to be bool or null", ZSTR_VAL(php_phongo_serverapi_ce->name));
+ return false;
+ }
+ }
+
+ return php_phongo_serverapi_create_libmongoc_object(
+ &intern->server_api,
+ Z_STR_P(version),
+ strict && !ZVAL_IS_NULL(strict),
+ strict && zval_is_true(strict),
+ deprecation_errors && !ZVAL_IS_NULL(deprecation_errors),
+ deprecation_errors && zval_is_true(deprecation_errors));
+} /* }}} */
+
+/* {{{ proto void MongoDB\Driver\ServerApi::__construct(string $version, [?bool $strict], [?bool $deprecationErrors])
+ Constructs a new ServerApi object */
+static PHP_METHOD(ServerApi, __construct)
+{
+ php_phongo_serverapi_t* intern;
+ zend_string* version;
+ zend_bool strict = 0;
+ zend_bool strict_null = 1;
+ zend_bool deprecation_errors = 0;
+ zend_bool deprecation_errors_null = 1;
+
+ intern = Z_SERVERAPI_OBJ_P(getThis());
+
+ PHONGO_PARSE_PARAMETERS_START(1, 3)
+ Z_PARAM_STR(version)
+ Z_PARAM_OPTIONAL
+ Z_PARAM_BOOL_EX(strict, strict_null, 1, 0)
+ Z_PARAM_BOOL_EX(deprecation_errors, deprecation_errors_null, 1, 0)
+ PHONGO_PARSE_PARAMETERS_END();
+
+ // Will throw on failure
+ php_phongo_serverapi_create_libmongoc_object(
+ &intern->server_api,
+ version,
+ (bool) !strict_null,
+ (bool) strict,
+ (bool) !deprecation_errors_null,
+ (bool) deprecation_errors);
+} /* }}} */
+
+/* {{{ proto MongoDB\Driver\ServerApi MongoDB\Driver\ServerApi::__set_state(array $properties)
+*/
+static PHP_METHOD(ServerApi, __set_state)
+{
+ php_phongo_serverapi_t* intern;
+ HashTable* props;
+ zval* array;
+
+ PHONGO_PARSE_PARAMETERS_START(1, 1)
+ Z_PARAM_ARRAY(array)
+ PHONGO_PARSE_PARAMETERS_END();
+
+ object_init_ex(return_value, php_phongo_serverapi_ce);
+
+ intern = Z_SERVERAPI_OBJ_P(return_value);
+ props = Z_ARRVAL_P(array);
+
+ php_phongo_serverapi_init_from_hash(intern, props);
+} /* }}} */
+
+static HashTable* php_phongo_serverapi_get_properties_hash(phongo_compat_object_handler_type* object, bool is_temp, bool include_null) /* {{{ */
+{
+ php_phongo_serverapi_t* intern;
+ HashTable* props;
+ zval version, strict, deprecation_errors;
+ bool is_set;
+
+ intern = Z_OBJ_SERVERAPI(PHONGO_COMPAT_GET_OBJ(object));
+
+ PHONGO_GET_PROPERTY_HASH_INIT_PROPS(is_temp, intern, props, 1);
+
+ ZVAL_STRING(&version, mongoc_server_api_version_to_string(mongoc_server_api_get_version(intern->server_api)));
+ zend_hash_str_add(props, "version", sizeof("version") - 1, &version);
+
+ is_set = mongoc_optional_is_set(mongoc_server_api_get_strict(intern->server_api));
+ if (is_set) {
+ ZVAL_BOOL(&strict, mongoc_optional_value(mongoc_server_api_get_strict(intern->server_api)));
+ } else {
+ ZVAL_NULL(&strict);
+ }
+
+ if (include_null || is_set) {
+ zend_hash_str_add(props, "strict", sizeof("strict") - 1, &strict);
+ }
+
+ is_set = mongoc_optional_is_set(mongoc_server_api_get_deprecation_errors(intern->server_api));
+ if (is_set) {
+ ZVAL_BOOL(&deprecation_errors, mongoc_optional_value(mongoc_server_api_get_deprecation_errors(intern->server_api)));
+ } else {
+ ZVAL_NULL(&deprecation_errors);
+ }
+
+ if (include_null || is_set) {
+ zend_hash_str_add(props, "deprecationErrors", sizeof("deprecationErrors") - 1, &deprecation_errors);
+ }
+
+ return props;
+} /* }}} */
+
+/* {{{ proto array MongoDB\Driver\ServerApi::bsonSerialize()
+*/
+static PHP_METHOD(ServerApi, bsonSerialize)
+{
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ ZVAL_ARR(return_value, php_phongo_serverapi_get_properties_hash(PHONGO_COMPAT_OBJ_P(getThis()), true, false));
+ convert_to_object(return_value);
+} /* }}} */
+
+/* {{{ proto string MongoDB\Driver\ServerApi::serialize()
+*/
+static PHP_METHOD(ServerApi, serialize)
+{
+ php_phongo_serverapi_t* intern;
+ zval retval;
+ php_serialize_data_t var_hash;
+ smart_str buf = { 0 };
+
+ intern = Z_SERVERAPI_OBJ_P(getThis());
+
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ array_init_size(&retval, 3);
+
+ ADD_ASSOC_STRING(&retval, "version", mongoc_server_api_version_to_string(mongoc_server_api_get_version(intern->server_api)));
+
+ if (mongoc_optional_is_set(mongoc_server_api_get_strict(intern->server_api))) {
+ ADD_ASSOC_BOOL_EX(&retval, "strict", mongoc_optional_value(mongoc_server_api_get_strict(intern->server_api)));
+ } else {
+ ADD_ASSOC_NULL_EX(&retval, "strict");
+ }
+
+ if (mongoc_optional_is_set(mongoc_server_api_get_deprecation_errors(intern->server_api))) {
+ ADD_ASSOC_BOOL_EX(&retval, "deprecationErrors", mongoc_optional_value(mongoc_server_api_get_deprecation_errors(intern->server_api)));
+ } else {
+ ADD_ASSOC_NULL_EX(&retval, "deprecationErrors");
+ }
+
+ PHP_VAR_SERIALIZE_INIT(var_hash);
+ php_var_serialize(&buf, &retval, &var_hash);
+ smart_str_0(&buf);
+ PHP_VAR_SERIALIZE_DESTROY(var_hash);
+
+ PHONGO_RETVAL_SMART_STR(buf);
+
+ smart_str_free(&buf);
+ zval_ptr_dtor(&retval);
+} /* }}} */
+
+/* {{{ proto void MongoDB\Driver\ServerApi::unserialize(string $serialized)
+*/
+static PHP_METHOD(ServerApi, unserialize)
+{
+ php_phongo_serverapi_t* intern;
+ char* serialized;
+ size_t serialized_len;
+ zval props;
+ php_unserialize_data_t var_hash;
+
+ intern = Z_SERVERAPI_OBJ_P(getThis());
+
+ PHONGO_PARSE_PARAMETERS_START(1, 1)
+ Z_PARAM_STRING(serialized, serialized_len)
+ PHONGO_PARSE_PARAMETERS_END();
+
+ if (!serialized_len) {
+ return;
+ }
+
+ PHP_VAR_UNSERIALIZE_INIT(var_hash);
+ if (!php_var_unserialize(&props, (const unsigned char**) &serialized, (unsigned char*) serialized + serialized_len, &var_hash)) {
+ zval_ptr_dtor(&props);
+ phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "%s unserialization failed", ZSTR_VAL(php_phongo_serverapi_ce->name));
+
+ PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+ return;
+ }
+ PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+
+ php_phongo_serverapi_init_from_hash(intern, HASH_OF(&props));
+ zval_ptr_dtor(&props);
+} /* }}} */
+
+/* {{{ proto array MongoDB\Driver\ServerApi::__serialize()
+*/
+static PHP_METHOD(ServerApi, __serialize)
+{
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ RETURN_ARR(php_phongo_serverapi_get_properties_hash(PHONGO_COMPAT_OBJ_P(getThis()), true, true));
+} /* }}} */
+
+/* {{{ proto void MongoDB\Driver\ServerApi::__unserialize(array $data)
+*/
+static PHP_METHOD(ServerApi, __unserialize)
+{
+ zval* data;
+
+ PHONGO_PARSE_PARAMETERS_START(1, 1)
+ Z_PARAM_ARRAY(data)
+ PHONGO_PARSE_PARAMETERS_END();
+
+ php_phongo_serverapi_init_from_hash(Z_SERVERAPI_OBJ_P(getThis()), Z_ARRVAL_P(data));
+} /* }}} */
+
+/* {{{ MongoDB\Driver\ServerApi function entries */
+ZEND_BEGIN_ARG_INFO_EX(ai_ServerApi___construct, 0, 0, 1)
+ ZEND_ARG_TYPE_INFO(0, version, IS_STRING, 0)
+ ZEND_ARG_TYPE_INFO(0, strict, _IS_BOOL, 1)
+ ZEND_ARG_TYPE_INFO(0, deprecationErrors, _IS_BOOL, 1)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_ServerApi___set_state, 0, 0, 1)
+ ZEND_ARG_ARRAY_INFO(0, properties, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_ServerApi___unserialize, 0, 0, 1)
+ ZEND_ARG_ARRAY_INFO(0, data, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_ServerApi_unserialize, 0, 0, 1)
+#if PHP_VERSION_ID >= 80000
+ ZEND_ARG_TYPE_INFO(0, serialized, IS_STRING, 0)
+#else
+ ZEND_ARG_INFO(0, serialized)
+#endif
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_ServerApi_void, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry php_phongo_serverapi_me[] = {
+ /* clang-format off */
+ PHP_ME(ServerApi, __construct, ai_ServerApi___construct, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(ServerApi, __serialize, ai_ServerApi_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(ServerApi, __set_state, ai_ServerApi___set_state, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+ PHP_ME(ServerApi, __unserialize, ai_ServerApi___unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(ServerApi, bsonSerialize, ai_ServerApi_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(ServerApi, serialize, ai_ServerApi_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(ServerApi, unserialize, ai_ServerApi_unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_FE_END
+ /* clang-format on */
+};
+/* }}} */
+
+/* {{{ MongoDB\Driver\ServerApi object handlers */
+static zend_object_handlers php_phongo_handler_serverapi;
+
+static void php_phongo_serverapi_free_object(zend_object* object) /* {{{ */
+{
+ php_phongo_serverapi_t* intern = Z_OBJ_SERVERAPI(object);
+
+ zend_object_std_dtor(&intern->std);
+
+ if (intern->properties) {
+ zend_hash_destroy(intern->properties);
+ FREE_HASHTABLE(intern->properties);
+ }
+
+ if (intern->server_api) {
+ mongoc_server_api_destroy(intern->server_api);
+ }
+}
+
+static zend_object* php_phongo_serverapi_create_object(zend_class_entry* class_type) /* {{{ */
+{
+ php_phongo_serverapi_t* intern = zend_object_alloc(sizeof(php_phongo_serverapi_t), class_type);
+
+ zend_object_std_init(&intern->std, class_type);
+ object_properties_init(&intern->std, class_type);
+
+ intern->std.handlers = &php_phongo_handler_serverapi;
+
+ return &intern->std;
+} /* }}} */
+
+static HashTable* php_phongo_serverapi_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
+{
+ *is_temp = 1;
+ return php_phongo_serverapi_get_properties_hash(object, true, true);
+} /* }}} */
+
+static HashTable* php_phongo_serverapi_get_properties(phongo_compat_object_handler_type* object) /* {{{ */
+{
+ return php_phongo_serverapi_get_properties_hash(object, false, true);
+} /* }}} */
+
+void php_phongo_serverapi_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver", "ServerApi", php_phongo_serverapi_me);
+ php_phongo_serverapi_ce = zend_register_internal_class(&ce);
+ php_phongo_serverapi_ce->create_object = php_phongo_serverapi_create_object;
+ PHONGO_CE_FINAL(php_phongo_serverapi_ce);
+
+ zend_class_implements(php_phongo_serverapi_ce, 1, php_phongo_serializable_ce);
+ zend_class_implements(php_phongo_serverapi_ce, 1, zend_ce_serializable);
+
+ memcpy(&php_phongo_handler_serverapi, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
+ php_phongo_handler_serverapi.get_debug_info = php_phongo_serverapi_get_debug_info;
+ php_phongo_handler_serverapi.get_properties = php_phongo_serverapi_get_properties;
+ php_phongo_handler_serverapi.free_obj = php_phongo_serverapi_free_object;
+ php_phongo_handler_serverapi.offset = XtOffsetOf(php_phongo_serverapi_t, std);
+
+ zend_declare_class_constant_stringl(php_phongo_serverapi_ce, ZEND_STRL("V1"), ZEND_STRL("1"));
+} /* }}} */
diff --git a/mongodb-1.13.0/src/MongoDB/ServerDescription.c b/mongodb-1.13.0/src/MongoDB/ServerDescription.c
new file mode 100644
index 00000000..d9ff1fd5
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/ServerDescription.c
@@ -0,0 +1,356 @@
+/*
+ * Copyright 2021-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bson/bson.h"
+#include "mongoc/mongoc.h"
+
+#include <php.h>
+#include <zend_smart_str.h>
+#include <ext/standard/php_var.h>
+#include <Zend/zend_interfaces.h>
+
+#include "php_phongo.h"
+#include "phongo_error.h"
+
+#include "MongoDB/ServerDescription.h"
+
+zend_class_entry* php_phongo_serverdescription_ce;
+
+/* Note: these constants are derived from mongoc_server_description_type, since
+ * since mongoc_server_description_type_t is private. */
+#define PHONGO_SERVER_TYPE_UNKNOWN "Unknown"
+#define PHONGO_SERVER_TYPE_STANDALONE "Standalone"
+#define PHONGO_SERVER_TYPE_MONGOS "Mongos"
+#define PHONGO_SERVER_TYPE_POSSIBLE_PRIMARY "PossiblePrimary"
+#define PHONGO_SERVER_TYPE_RS_PRIMARY "RSPrimary"
+#define PHONGO_SERVER_TYPE_RS_SECONDARY "RSSecondary"
+#define PHONGO_SERVER_TYPE_RS_ARBITER "RSArbiter"
+#define PHONGO_SERVER_TYPE_RS_OTHER "RSOther"
+#define PHONGO_SERVER_TYPE_RS_GHOST "RSGhost"
+#define PHONGO_SERVER_TYPE_LOAD_BALANCER "LoadBalancer"
+
+php_phongo_server_description_type_map_t
+ php_phongo_server_description_type_map[PHONGO_SERVER_DESCRIPTION_TYPES] = {
+ { PHONGO_SERVER_UNKNOWN, PHONGO_SERVER_TYPE_UNKNOWN },
+ { PHONGO_SERVER_STANDALONE, PHONGO_SERVER_TYPE_STANDALONE },
+ { PHONGO_SERVER_MONGOS, PHONGO_SERVER_TYPE_MONGOS },
+ { PHONGO_SERVER_POSSIBLE_PRIMARY, PHONGO_SERVER_TYPE_POSSIBLE_PRIMARY },
+ { PHONGO_SERVER_RS_PRIMARY, PHONGO_SERVER_TYPE_RS_PRIMARY },
+ { PHONGO_SERVER_RS_SECONDARY, PHONGO_SERVER_TYPE_RS_SECONDARY },
+ { PHONGO_SERVER_RS_ARBITER, PHONGO_SERVER_TYPE_RS_ARBITER },
+ { PHONGO_SERVER_RS_OTHER, PHONGO_SERVER_TYPE_RS_OTHER },
+ { PHONGO_SERVER_RS_GHOST, PHONGO_SERVER_TYPE_RS_GHOST },
+ { PHONGO_SERVER_LOAD_BALANCER, PHONGO_SERVER_TYPE_LOAD_BALANCER },
+ };
+
+/* {{{ proto array MongoDB\Driver\ServerDescription::getHelloResponse()
+ Returns the most recent "hello" response */
+static PHP_METHOD(ServerDescription, getHelloResponse)
+{
+ php_phongo_serverdescription_t* intern;
+ const bson_t* helloResponse;
+ php_phongo_bson_state state;
+
+ intern = Z_SERVERDESCRIPTION_OBJ_P(getThis());
+
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ /* Note: the hello response will be empty for load balancers since they are
+ * not monitored. Unlike Server::getInfo(), we do not attempt to fetch the
+ * corresponding handshake description, as that would require holding a
+ * reference to the libmongoc client (and likely a Manager object) on the
+ * ServerDescription and TopologyDescription classes. */
+ helloResponse = mongoc_server_description_hello_response(intern->server_description);
+
+ PHONGO_BSON_INIT_DEBUG_STATE(state);
+
+ if (!php_phongo_bson_to_zval_ex(bson_get_data(helloResponse), helloResponse->len, &state)) {
+ /* Exception should already have been thrown */
+ zval_ptr_dtor(&state.zchild);
+ return;
+ }
+
+ RETURN_ZVAL(&state.zchild, 0, 1);
+} /* }}} */
+
+/* {{{ proto string MongoDB\Driver\ServerDescription::getHost()
+ Returns the server's hostname */
+static PHP_METHOD(ServerDescription, getHost)
+{
+ php_phongo_serverdescription_t* intern;
+
+ intern = Z_SERVERDESCRIPTION_OBJ_P(getThis());
+
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ RETVAL_STRING(mongoc_server_description_host(intern->server_description)->host);
+} /* }}} */
+
+/* {{{ proto integer MongoDB\Driver\ServerDescription::getLastUpdateTime()
+ Returns the server's last update time, in microseconds */
+static PHP_METHOD(ServerDescription, getLastUpdateTime)
+{
+ php_phongo_serverdescription_t* intern;
+ int64_t last_update_time;
+
+ intern = Z_SERVERDESCRIPTION_OBJ_P(getThis());
+
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ last_update_time = mongoc_server_description_last_update_time(intern->server_description);
+
+#if SIZEOF_ZEND_LONG == 4
+ if (last_update_time > INT32_MAX || last_update_time < INT32_MIN) {
+ zend_error(E_WARNING, "Truncating 64-bit value for lastUpdateTime");
+ }
+#endif
+
+ RETVAL_LONG(last_update_time);
+} /* }}} */
+
+/* {{{ proto integer MongoDB\Driver\ServerDescription::getPort()
+ Returns the server's port */
+static PHP_METHOD(ServerDescription, getPort)
+{
+ php_phongo_serverdescription_t* intern;
+
+ intern = Z_SERVERDESCRIPTION_OBJ_P(getThis());
+
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ RETVAL_LONG(mongoc_server_description_host(intern->server_description)->port);
+} /* }}} */
+
+/* {{{ proto integer MongoDB\Driver\ServerDescription::getRoundTripTime()
+ Returns the server's round trip time, in milliseconds */
+static PHP_METHOD(ServerDescription, getRoundTripTime)
+{
+ php_phongo_serverdescription_t* intern;
+
+ intern = Z_SERVERDESCRIPTION_OBJ_P(getThis());
+
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ /* TODO: Use MONGOC_RTT_UNSET once it is added to libmongoc's public API (CDRIVER-4176) */
+ if (mongoc_server_description_round_trip_time(intern->server_description) == -1) {
+ RETVAL_NULL();
+ } else {
+ RETVAL_LONG((zend_long) mongoc_server_description_round_trip_time(intern->server_description));
+ }
+} /* }}} */
+
+/* {{{ proto string MongoDB\Driver\ServerDescription::getType()
+ Returns the server's node type */
+static PHP_METHOD(ServerDescription, getType)
+{
+ php_phongo_serverdescription_t* intern;
+
+ intern = Z_SERVERDESCRIPTION_OBJ_P(getThis());
+
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ RETVAL_STRING(mongoc_server_description_type(intern->server_description));
+} /* }}} */
+
+/* {{{ MongoDB\Driver\ServerDescription function entries */
+ZEND_BEGIN_ARG_INFO_EX(ai_ServerDescription_void, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry php_phongo_serverdescription_me[] = {
+ /* clang-format off */
+ PHP_ME(ServerDescription, getHelloResponse, ai_ServerDescription_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(ServerDescription, getHost, ai_ServerDescription_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(ServerDescription, getLastUpdateTime, ai_ServerDescription_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(ServerDescription, getPort, ai_ServerDescription_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(ServerDescription, getRoundTripTime, ai_ServerDescription_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(ServerDescription, getType, ai_ServerDescription_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ ZEND_NAMED_ME(__construct, PHP_FN(MongoDB_disabled___construct), ai_ServerDescription_void, ZEND_ACC_PRIVATE | ZEND_ACC_FINAL)
+ PHP_FE_END
+ /* clang-format on */
+};
+/* }}} */
+
+/* {{{ MongoDB\Driver\ServerDescription object handlers */
+static zend_object_handlers php_phongo_handler_serverdescription;
+
+static void php_phongo_serverdescription_free_object(zend_object* object) /* {{{ */
+{
+ php_phongo_serverdescription_t* intern = Z_OBJ_SERVERDESCRIPTION(object);
+
+ zend_object_std_dtor(&intern->std);
+
+ if (intern->properties) {
+ zend_hash_destroy(intern->properties);
+ FREE_HASHTABLE(intern->properties);
+ }
+
+ if (intern->server_description) {
+ mongoc_server_description_destroy(intern->server_description);
+ }
+}
+
+static zend_object* php_phongo_serverdescription_create_object(zend_class_entry* class_type) /* {{{ */
+{
+ php_phongo_serverdescription_t* intern = zend_object_alloc(sizeof(php_phongo_serverdescription_t), class_type);
+
+ zend_object_std_init(&intern->std, class_type);
+ object_properties_init(&intern->std, class_type);
+
+ intern->std.handlers = &php_phongo_handler_serverdescription;
+
+ return &intern->std;
+} /* }}} */
+
+HashTable* php_phongo_serverdescription_get_properties_hash(phongo_compat_object_handler_type* object, bool is_debug) /* {{{ */
+{
+ php_phongo_serverdescription_t* intern = NULL;
+ HashTable* props;
+
+ intern = Z_OBJ_SERVERDESCRIPTION(PHONGO_COMPAT_GET_OBJ(object));
+
+ PHONGO_GET_PROPERTY_HASH_INIT_PROPS(is_debug, intern, props, 6);
+
+ if (!intern->server_description) {
+ return props;
+ }
+
+ {
+ zval host, port, type;
+ mongoc_host_list_t* host_list = mongoc_server_description_host(intern->server_description);
+
+ ZVAL_STRING(&host, host_list->host);
+ zend_hash_str_update(props, "host", sizeof("host") - 1, &host);
+
+ ZVAL_LONG(&port, host_list->port);
+ zend_hash_str_update(props, "port", sizeof("port") - 1, &port);
+
+ ZVAL_STRING(&type, mongoc_server_description_type(intern->server_description));
+ zend_hash_str_update(props, "type", sizeof("type") - 1, &type);
+ }
+
+ {
+ const bson_t* hello_response = mongoc_server_description_hello_response(intern->server_description);
+ php_phongo_bson_state state;
+
+ PHONGO_BSON_INIT_DEBUG_STATE(state);
+
+ if (!php_phongo_bson_to_zval_ex(bson_get_data(hello_response), hello_response->len, &state)) {
+ zval_ptr_dtor(&state.zchild);
+ goto done;
+ }
+ zend_hash_str_update(props, "hello_response", sizeof("hello_response") - 1, &state.zchild);
+ }
+
+ {
+ int64_t last_update_time;
+ zval z_last_update_time;
+
+ last_update_time = mongoc_server_description_last_update_time(intern->server_description);
+
+#if SIZEOF_ZEND_LONG == 4
+ if (last_update_time > INT32_MAX || last_update_time < INT32_MIN) {
+ ZVAL_INT64_STRING(&z_last_update_time, last_update_time);
+ } else {
+ ZVAL_LONG(&z_last_update_time, last_update_time);
+ }
+#else
+ ZVAL_LONG(&z_last_update_time, last_update_time);
+#endif
+
+ zend_hash_str_update(props, "last_update_time", sizeof("last_update_time") - 1, &z_last_update_time);
+ }
+
+ {
+ zval round_trip_time;
+
+ /* TODO: Use MONGOC_RTT_UNSET once it is added to libmongoc's public API (CDRIVER-4176) */
+ if (mongoc_server_description_round_trip_time(intern->server_description) == -1) {
+ ZVAL_NULL(&round_trip_time);
+ } else {
+ ZVAL_LONG(&round_trip_time, (zend_long) mongoc_server_description_round_trip_time(intern->server_description));
+ }
+
+ zend_hash_str_update(props, "round_trip_time", sizeof("round_trip_time") - 1, &round_trip_time);
+ }
+
+done:
+ return props;
+} /* }}} */
+
+static HashTable* php_phongo_serverdescription_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
+{
+ *is_temp = 1;
+ return php_phongo_serverdescription_get_properties_hash(object, true);
+} /* }}} */
+
+static HashTable* php_phongo_serverdescription_get_properties(phongo_compat_object_handler_type* object) /* {{{ */
+{
+ return php_phongo_serverdescription_get_properties_hash(object, false);
+} /* }}} */
+/* }}} */
+
+void php_phongo_serverdescription_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver", "ServerDescription", php_phongo_serverdescription_me);
+ php_phongo_serverdescription_ce = zend_register_internal_class(&ce);
+ php_phongo_serverdescription_ce->create_object = php_phongo_serverdescription_create_object;
+ PHONGO_CE_FINAL(php_phongo_serverdescription_ce);
+ PHONGO_CE_DISABLE_SERIALIZATION(php_phongo_serverdescription_ce);
+
+ memcpy(&php_phongo_handler_serverdescription, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
+ php_phongo_handler_serverdescription.get_debug_info = php_phongo_serverdescription_get_debug_info;
+ php_phongo_handler_serverdescription.get_properties = php_phongo_serverdescription_get_properties;
+ php_phongo_handler_serverdescription.free_obj = php_phongo_serverdescription_free_object;
+ php_phongo_handler_serverdescription.offset = XtOffsetOf(php_phongo_serverdescription_t, std);
+
+ zend_declare_class_constant_string(php_phongo_serverdescription_ce, ZEND_STRL("TYPE_UNKNOWN"), PHONGO_SERVER_TYPE_UNKNOWN);
+ zend_declare_class_constant_string(php_phongo_serverdescription_ce, ZEND_STRL("TYPE_STANDALONE"), PHONGO_SERVER_TYPE_STANDALONE);
+ zend_declare_class_constant_string(php_phongo_serverdescription_ce, ZEND_STRL("TYPE_MONGOS"), PHONGO_SERVER_TYPE_MONGOS);
+ zend_declare_class_constant_string(php_phongo_serverdescription_ce, ZEND_STRL("TYPE_POSSIBLE_PRIMARY"), PHONGO_SERVER_TYPE_POSSIBLE_PRIMARY);
+ zend_declare_class_constant_string(php_phongo_serverdescription_ce, ZEND_STRL("TYPE_RS_PRIMARY"), PHONGO_SERVER_TYPE_RS_PRIMARY);
+ zend_declare_class_constant_string(php_phongo_serverdescription_ce, ZEND_STRL("TYPE_RS_SECONDARY"), PHONGO_SERVER_TYPE_RS_SECONDARY);
+ zend_declare_class_constant_string(php_phongo_serverdescription_ce, ZEND_STRL("TYPE_RS_ARBITER"), PHONGO_SERVER_TYPE_RS_ARBITER);
+ zend_declare_class_constant_string(php_phongo_serverdescription_ce, ZEND_STRL("TYPE_RS_OTHER"), PHONGO_SERVER_TYPE_RS_OTHER);
+ zend_declare_class_constant_string(php_phongo_serverdescription_ce, ZEND_STRL("TYPE_RS_GHOST"), PHONGO_SERVER_TYPE_RS_GHOST);
+ zend_declare_class_constant_string(php_phongo_serverdescription_ce, ZEND_STRL("TYPE_LOAD_BALANCER"), PHONGO_SERVER_TYPE_LOAD_BALANCER);
+} /* }}} */
+
+void phongo_serverdescription_init_ex(zval* return_value, mongoc_server_description_t* server_description, bool copy) /* {{{ */
+{
+ php_phongo_serverdescription_t* intern;
+
+ object_init_ex(return_value, php_phongo_serverdescription_ce);
+
+ intern = Z_SERVERDESCRIPTION_OBJ_P(return_value);
+ intern->server_description = copy ? mongoc_server_description_new_copy(server_description) : server_description;
+}
+/* }}} */
+
+php_phongo_server_description_type_t php_phongo_server_description_type(mongoc_server_description_t* sd)
+{
+ const char* name = mongoc_server_description_type(sd);
+ int i;
+
+ for (i = 0; i < PHONGO_SERVER_DESCRIPTION_TYPES; i++) {
+ if (!strcmp(name, php_phongo_server_description_type_map[i].name)) {
+ return php_phongo_server_description_type_map[i].type;
+ }
+ }
+
+ return PHONGO_SERVER_UNKNOWN;
+}
diff --git a/mongodb-1.13.0/src/MongoDB/ServerDescription.h b/mongodb-1.13.0/src/MongoDB/ServerDescription.h
new file mode 100644
index 00000000..a23679ed
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/ServerDescription.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2022-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PHONGO_SERVERDESCRIPTION_H
+#define PHONGO_SERVERDESCRIPTION_H
+
+#include "mongoc/mongoc.h"
+
+#include <php.h>
+
+/* This enum is necessary since mongoc_server_description_type_t is private and
+ * we need to translate strings returned by mongoc_server_description_type() to
+ * Server integer constants. */
+typedef enum {
+ PHONGO_SERVER_UNKNOWN = 0,
+ PHONGO_SERVER_STANDALONE = 1,
+ PHONGO_SERVER_MONGOS = 2,
+ PHONGO_SERVER_POSSIBLE_PRIMARY = 3,
+ PHONGO_SERVER_RS_PRIMARY = 4,
+ PHONGO_SERVER_RS_SECONDARY = 5,
+ PHONGO_SERVER_RS_ARBITER = 6,
+ PHONGO_SERVER_RS_OTHER = 7,
+ PHONGO_SERVER_RS_GHOST = 8,
+ PHONGO_SERVER_LOAD_BALANCER = 9,
+ PHONGO_SERVER_DESCRIPTION_TYPES = 10,
+} php_phongo_server_description_type_t;
+
+typedef struct {
+ php_phongo_server_description_type_t type;
+ const char* name;
+} php_phongo_server_description_type_map_t;
+
+extern php_phongo_server_description_type_map_t php_phongo_server_description_type_map[];
+
+void phongo_serverdescription_init_ex(zval* return_value, mongoc_server_description_t* sd, bool copy);
+#define phongo_serverdescription_init(r, sd) phongo_serverdescription_init_ex((r), (sd), true)
+
+php_phongo_server_description_type_t php_phongo_server_description_type(mongoc_server_description_t* sd);
+
+#endif /* PHONGO_SERVERDESCRIPTION_H */
diff --git a/mongodb-1.13.0/src/MongoDB/Session.c b/mongodb-1.13.0/src/MongoDB/Session.c
new file mode 100644
index 00000000..c8a64711
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/Session.c
@@ -0,0 +1,851 @@
+/*
+ * Copyright 2017-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bson/bson.h"
+#include "mongoc/mongoc.h"
+
+#include <php.h>
+#include <Zend/zend_interfaces.h>
+
+#include "php_array_api.h"
+
+#include "php_phongo.h"
+#include "phongo_bson_encode.h"
+#include "phongo_client.h"
+#include "phongo_error.h"
+
+#include "MongoDB/ReadConcern.h"
+#include "MongoDB/ReadPreference.h"
+#include "MongoDB/Server.h"
+#include "MongoDB/Session.h"
+#include "MongoDB/WriteConcern.h"
+
+zend_class_entry* php_phongo_session_ce;
+
+#define PHONGO_TRANSACTION_NONE "none"
+#define PHONGO_TRANSACTION_STARTING "starting"
+#define PHONGO_TRANSACTION_IN_PROGRESS "in_progress"
+#define PHONGO_TRANSACTION_COMMITTED "committed"
+#define PHONGO_TRANSACTION_ABORTED "aborted"
+
+#define SESSION_CHECK_LIVELINESS(i, m) \
+ if (!(i)->client_session) { \
+ phongo_throw_exception( \
+ PHONGO_ERROR_LOGIC, \
+ "Cannot call '%s', as the session has already been ended.", \
+ (m)); \
+ return; \
+ }
+
+static bool php_phongo_session_get_timestamp_parts(zval* obj, uint32_t* timestamp, uint32_t* increment)
+{
+ bool retval = false;
+ zval ztimestamp = ZVAL_STATIC_INIT;
+ zval zincrement = ZVAL_STATIC_INIT;
+
+ zend_call_method_with_0_params(PHONGO_COMPAT_OBJ_P(obj), NULL, NULL, "getTimestamp", &ztimestamp);
+
+ if (Z_ISUNDEF(ztimestamp) || EG(exception)) {
+ goto cleanup;
+ }
+
+ zend_call_method_with_0_params(PHONGO_COMPAT_OBJ_P(obj), NULL, NULL, "getIncrement", &zincrement);
+
+ if (Z_ISUNDEF(zincrement) || EG(exception)) {
+ goto cleanup;
+ }
+
+ *timestamp = Z_LVAL(ztimestamp);
+ *increment = Z_LVAL(zincrement);
+
+ retval = true;
+
+cleanup:
+ if (!Z_ISUNDEF(ztimestamp)) {
+ zval_ptr_dtor(&ztimestamp);
+ }
+
+ if (!Z_ISUNDEF(zincrement)) {
+ zval_ptr_dtor(&zincrement);
+ }
+
+ return retval;
+}
+
+static const char* php_phongo_get_transaction_state_string(mongoc_transaction_state_t state)
+{
+ switch (state) {
+ case MONGOC_TRANSACTION_NONE:
+ return PHONGO_TRANSACTION_NONE;
+ case MONGOC_TRANSACTION_STARTING:
+ return PHONGO_TRANSACTION_STARTING;
+ case MONGOC_TRANSACTION_IN_PROGRESS:
+ return PHONGO_TRANSACTION_IN_PROGRESS;
+ case MONGOC_TRANSACTION_COMMITTED:
+ return PHONGO_TRANSACTION_COMMITTED;
+ case MONGOC_TRANSACTION_ABORTED:
+ return PHONGO_TRANSACTION_ABORTED;
+ default:
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Invalid transaction state %d given", (int) state);
+ return NULL;
+ }
+}
+
+static void php_phongo_transaction_options_to_zval(mongoc_client_session_t* cs, zval* retval)
+{
+ mongoc_transaction_opt_t* opts;
+ int64_t max_commit_time_ms;
+ const mongoc_read_concern_t* read_concern;
+ const mongoc_read_prefs_t* read_preference;
+ const mongoc_write_concern_t* write_concern;
+
+ if (!cs) {
+ ZVAL_NULL(retval);
+ return;
+ }
+
+ opts = mongoc_session_opts_get_transaction_opts(cs);
+
+ if (!opts) {
+ ZVAL_NULL(retval);
+ return;
+ }
+
+ max_commit_time_ms = mongoc_transaction_opts_get_max_commit_time_ms(opts);
+ read_concern = mongoc_transaction_opts_get_read_concern(opts);
+ read_preference = mongoc_transaction_opts_get_read_prefs(opts);
+ write_concern = mongoc_transaction_opts_get_write_concern(opts);
+
+ array_init_size(retval, 4);
+
+ if (max_commit_time_ms) {
+ ADD_ASSOC_LONG_EX(retval, "maxCommitTimeMS", max_commit_time_ms);
+ }
+
+ if (!mongoc_read_concern_is_default(read_concern)) {
+ zval zread_concern;
+
+ phongo_readconcern_init(&zread_concern, read_concern);
+ ADD_ASSOC_ZVAL_EX(retval, "readConcern", &zread_concern);
+ }
+
+ if (read_preference) {
+ zval zread_preference;
+
+ phongo_readpreference_init(&zread_preference, read_preference);
+ ADD_ASSOC_ZVAL_EX(retval, "readPreference", &zread_preference);
+ }
+
+ if (!mongoc_write_concern_is_default(write_concern)) {
+ zval zwrite_concern;
+
+ phongo_writeconcern_init(&zwrite_concern, write_concern);
+ ADD_ASSOC_ZVAL_EX(retval, "writeConcern", &zwrite_concern);
+ }
+
+ mongoc_transaction_opts_destroy(opts);
+}
+
+/* {{{ proto void MongoDB\Driver\Session::advanceClusterTime(array|object $clusterTime)
+ Advances the cluster time for this Session */
+static PHP_METHOD(Session, advanceClusterTime)
+{
+ zend_error_handling error_handling;
+ php_phongo_session_t* intern;
+ zval* zcluster_time;
+ bson_t cluster_time = BSON_INITIALIZER;
+
+ intern = Z_SESSION_OBJ_P(getThis());
+ SESSION_CHECK_LIVELINESS(intern, "advanceClusterTime")
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "A", &zcluster_time) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ php_phongo_zval_to_bson(zcluster_time, PHONGO_BSON_NONE, &cluster_time, NULL);
+
+ /* An exception may be thrown during BSON conversion */
+ if (EG(exception)) {
+ goto cleanup;
+ }
+
+ mongoc_client_session_advance_cluster_time(intern->client_session, &cluster_time);
+
+cleanup:
+ bson_destroy(&cluster_time);
+} /* }}} */
+
+/* {{{ proto void MongoDB\Driver\Session::advanceOperationTime(MongoDB\BSON\TimestampInterface $timestamp)
+ Advances the operation time for this Session */
+static PHP_METHOD(Session, advanceOperationTime)
+{
+ zend_error_handling error_handling;
+ php_phongo_session_t* intern;
+ zval* ztimestamp;
+ uint32_t timestamp = 0;
+ uint32_t increment = 0;
+
+ intern = Z_SESSION_OBJ_P(getThis());
+ SESSION_CHECK_LIVELINESS(intern, "advanceOperationTime")
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &ztimestamp, php_phongo_timestamp_interface_ce) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ if (!php_phongo_session_get_timestamp_parts(ztimestamp, &timestamp, &increment)) {
+ return;
+ }
+
+ mongoc_client_session_advance_operation_time(intern->client_session, timestamp, increment);
+} /* }}} */
+
+/* {{{ proto object|null MongoDB\Driver\Session::getClusterTime()
+ Returns the cluster time for this Session */
+static PHP_METHOD(Session, getClusterTime)
+{
+ zend_error_handling error_handling;
+ php_phongo_session_t* intern;
+ const bson_t* cluster_time;
+ php_phongo_bson_state state;
+
+ PHONGO_BSON_INIT_STATE(state);
+
+ intern = Z_SESSION_OBJ_P(getThis());
+ SESSION_CHECK_LIVELINESS(intern, "getClusterTime")
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ cluster_time = mongoc_client_session_get_cluster_time(intern->client_session);
+
+ if (!cluster_time) {
+ RETURN_NULL();
+ }
+
+ if (!php_phongo_bson_to_zval_ex(bson_get_data(cluster_time), cluster_time->len, &state)) {
+ /* Exception should already have been thrown */
+ zval_ptr_dtor(&state.zchild);
+ return;
+ }
+
+ RETURN_ZVAL(&state.zchild, 0, 1);
+} /* }}} */
+
+/* {{{ proto object MongoDB\Driver\Session::getLogicalSessionId()
+ Returns the logical session ID for this Session */
+static PHP_METHOD(Session, getLogicalSessionId)
+{
+ zend_error_handling error_handling;
+ php_phongo_session_t* intern;
+ const bson_t* lsid;
+ php_phongo_bson_state state;
+
+ PHONGO_BSON_INIT_STATE(state);
+
+ intern = Z_SESSION_OBJ_P(getThis());
+ SESSION_CHECK_LIVELINESS(intern, "getLogicalSessionId")
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ lsid = mongoc_client_session_get_lsid(intern->client_session);
+
+ if (!php_phongo_bson_to_zval_ex(bson_get_data(lsid), lsid->len, &state)) {
+ /* Exception should already have been thrown */
+ zval_ptr_dtor(&state.zchild);
+ return;
+ }
+
+ RETURN_ZVAL(&state.zchild, 0, 1);
+} /* }}} */
+
+/* {{{ proto MongoDB\BSON\Timestamp|null MongoDB\Driver\Session::getOperationTime()
+ Returns the operation time for this Session */
+static PHP_METHOD(Session, getOperationTime)
+{
+ zend_error_handling error_handling;
+ php_phongo_session_t* intern;
+ uint32_t timestamp, increment;
+
+ intern = Z_SESSION_OBJ_P(getThis());
+ SESSION_CHECK_LIVELINESS(intern, "getOperationTime")
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ mongoc_client_session_get_operation_time(intern->client_session, &timestamp, &increment);
+
+ /* mongoc_client_session_get_operation_time() returns 0 for both parts if
+ * the session has not been used. According to the causal consistency spec,
+ * the operation time for an unused session is null. */
+ if (timestamp == 0 && increment == 0) {
+ RETURN_NULL();
+ }
+
+ php_phongo_bson_new_timestamp_from_increment_and_timestamp(return_value, increment, timestamp);
+} /* }}} */
+
+/* {{{ proto MongoDB\Driver\Server|null MongoDB\Driver\Session::getServer()
+ Returns the server this session is pinned to */
+static PHP_METHOD(Session, getServer)
+{
+ zend_error_handling error_handling;
+ php_phongo_session_t* intern;
+ uint32_t server_id = 0;
+
+ intern = Z_SESSION_OBJ_P(getThis());
+ SESSION_CHECK_LIVELINESS(intern, "getServer")
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ server_id = mongoc_client_session_get_server_id(intern->client_session);
+
+ /* For sessions without a pinned server, 0 is returned. */
+ if (!server_id) {
+ RETURN_NULL();
+ }
+
+ phongo_server_init(return_value, &intern->manager, server_id);
+} /* }}} */
+
+/* {{{ proto array|null MongoDB\Driver\Session::getTransactionOptions()
+ Returns options for the currently running transaction */
+static PHP_METHOD(Session, getTransactionOptions)
+{
+ zend_error_handling error_handling;
+ php_phongo_session_t* intern;
+
+ intern = Z_SESSION_OBJ_P(getThis());
+ SESSION_CHECK_LIVELINESS(intern, "getTransactionOptions")
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ php_phongo_transaction_options_to_zval(intern->client_session, return_value);
+} /* }}} */
+
+/* {{{ proto string MongoDB\Driver\Session::getTransactionState()
+ Returns the current transaction state for this session */
+static PHP_METHOD(Session, getTransactionState)
+{
+ zend_error_handling error_handling;
+ php_phongo_session_t* intern;
+ const char* state;
+
+ intern = Z_SESSION_OBJ_P(getThis());
+ SESSION_CHECK_LIVELINESS(intern, "getTransactionState")
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ state = php_phongo_get_transaction_state_string(mongoc_client_session_get_transaction_state(intern->client_session));
+ if (!state) {
+ /* Exception already thrown */
+ return;
+ }
+
+ RETURN_STRING(state);
+} /* }}} */
+
+/* Creates a opts structure from an array optionally containing an RP, RC,
+ * WC object, and/or maxCommitTimeMS int. Returns NULL if no options were found,
+ * or there was an invalid option. If there was an invalid option or structure,
+ * an exception will be thrown too. */
+mongoc_transaction_opt_t* php_mongodb_session_parse_transaction_options(zval* options)
+{
+ mongoc_transaction_opt_t* opts = NULL;
+
+ if (php_array_existsc(options, "maxCommitTimeMS")) {
+ int64_t max_commit_time_ms = php_array_fetchc_long(options, "maxCommitTimeMS");
+
+ if (max_commit_time_ms < 0) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"maxCommitTimeMS\" option to be >= 0, %" PRId64 " given", max_commit_time_ms);
+ /* Freeing opts is not needed here, as it can't be set yet. The
+ * code is here to keep it consistent with the others in case more
+ * options are added before this one. */
+ if (opts) {
+ mongoc_transaction_opts_destroy(opts);
+ }
+ return NULL;
+ }
+
+ if (max_commit_time_ms > UINT32_MAX) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"maxCommitTimeMS\" option to be <= %" PRIu32 ", %" PRId64 " given", UINT32_MAX, max_commit_time_ms);
+ /* Freeing opts is not needed here, as it can't be set yet. The
+ * code is here to keep it consistent with the others in case more
+ * options are added before this one. */
+ if (opts) {
+ mongoc_transaction_opts_destroy(opts);
+ }
+ return NULL;
+ }
+
+ if (!opts) {
+ opts = mongoc_transaction_opts_new();
+ }
+
+ mongoc_transaction_opts_set_max_commit_time_ms(opts, max_commit_time_ms);
+ }
+
+ if (php_array_existsc(options, "readConcern")) {
+ zval* read_concern = php_array_fetchc(options, "readConcern");
+
+ if (Z_TYPE_P(read_concern) != IS_OBJECT || !instanceof_function(Z_OBJCE_P(read_concern), php_phongo_readconcern_ce)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"readConcern\" option to be %s, %s given", ZSTR_VAL(php_phongo_readconcern_ce->name), PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(read_concern));
+ if (opts) {
+ mongoc_transaction_opts_destroy(opts);
+ }
+ return NULL;
+ }
+
+ if (!opts) {
+ opts = mongoc_transaction_opts_new();
+ }
+
+ mongoc_transaction_opts_set_read_concern(opts, phongo_read_concern_from_zval(read_concern));
+ }
+
+ if (php_array_existsc(options, "readPreference")) {
+ zval* read_preference = php_array_fetchc(options, "readPreference");
+
+ if (Z_TYPE_P(read_preference) != IS_OBJECT || !instanceof_function(Z_OBJCE_P(read_preference), php_phongo_readpreference_ce)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"readPreference\" option to be %s, %s given", ZSTR_VAL(php_phongo_readpreference_ce->name), PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(read_preference));
+ if (opts) {
+ mongoc_transaction_opts_destroy(opts);
+ }
+ return NULL;
+ }
+
+ if (!opts) {
+ opts = mongoc_transaction_opts_new();
+ }
+
+ mongoc_transaction_opts_set_read_prefs(opts, phongo_read_preference_from_zval(read_preference));
+ }
+
+ if (php_array_existsc(options, "writeConcern")) {
+ zval* write_concern = php_array_fetchc(options, "writeConcern");
+
+ if (Z_TYPE_P(write_concern) != IS_OBJECT || !instanceof_function(Z_OBJCE_P(write_concern), php_phongo_writeconcern_ce)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"writeConcern\" option to be %s, %s given", ZSTR_VAL(php_phongo_writeconcern_ce->name), PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(write_concern));
+ if (opts) {
+ mongoc_transaction_opts_destroy(opts);
+ }
+ return NULL;
+ }
+
+ if (!opts) {
+ opts = mongoc_transaction_opts_new();
+ }
+
+ mongoc_transaction_opts_set_write_concern(opts, phongo_write_concern_from_zval(write_concern));
+ }
+
+ return opts;
+}
+
+/* {{{ proto void MongoDB\Driver\Session::startTransaction([array $options = null])
+ Starts a new transaction */
+static PHP_METHOD(Session, startTransaction)
+{
+ zend_error_handling error_handling;
+ php_phongo_session_t* intern;
+ zval* options = NULL;
+ mongoc_transaction_opt_t* txn_options = NULL;
+ bson_error_t error;
+
+ intern = Z_SESSION_OBJ_P(getThis());
+ SESSION_CHECK_LIVELINESS(intern, "startTransaction")
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "|a!", &options) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ if (options) {
+ txn_options = php_mongodb_session_parse_transaction_options(options);
+ }
+ if (EG(exception)) {
+ return;
+ }
+
+ if (!mongoc_client_session_start_transaction(intern->client_session, txn_options, &error)) {
+ phongo_throw_exception_from_bson_error_t(&error);
+ }
+
+ if (txn_options) {
+ mongoc_transaction_opts_destroy(txn_options);
+ }
+} /* }}} */
+
+/* {{{ proto void MongoDB\Driver\Session::commitTransaction(void)
+ Commits an existing transaction */
+static PHP_METHOD(Session, commitTransaction)
+{
+ zend_error_handling error_handling;
+ php_phongo_session_t* intern;
+ bson_error_t error;
+ bson_t reply;
+
+ intern = Z_SESSION_OBJ_P(getThis());
+ SESSION_CHECK_LIVELINESS(intern, "commitTransaction")
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ if (!mongoc_client_session_commit_transaction(intern->client_session, &reply, &error)) {
+ phongo_throw_exception_from_bson_error_t_and_reply(&error, &reply);
+ }
+
+ bson_destroy(&reply);
+} /* }}} */
+
+/* {{{ proto void MongoDB\Driver\Session::abortTransaction(void)
+ Aborts (rolls back) an existing transaction */
+static PHP_METHOD(Session, abortTransaction)
+{
+ zend_error_handling error_handling;
+ php_phongo_session_t* intern;
+ bson_error_t error;
+
+ intern = Z_SESSION_OBJ_P(getThis());
+ SESSION_CHECK_LIVELINESS(intern, "abortTransaction")
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ if (!mongoc_client_session_abort_transaction(intern->client_session, &error)) {
+ phongo_throw_exception_from_bson_error_t(&error);
+ }
+} /* }}} */
+
+/* {{{ proto void MongoDB\Driver\Session::endSession(void)
+ Ends the session, and a running transaction if active */
+static PHP_METHOD(Session, endSession)
+{
+ zend_error_handling error_handling;
+ php_phongo_session_t* intern;
+
+ intern = Z_SESSION_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ mongoc_client_session_destroy(intern->client_session);
+ intern->client_session = NULL;
+} /* }}} */
+
+/* {{{ proto bool MongoDB\Driver\Session::isDirty()
+ Returns whether the session is dirty (i.e. was used with a command that
+ encountered a network error) and will be discarded when returned to the
+ server session pool. */
+static PHP_METHOD(Session, isDirty)
+{
+ php_phongo_session_t* intern = Z_SESSION_OBJ_P(getThis());
+
+ SESSION_CHECK_LIVELINESS(intern, "isDirty")
+
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ RETVAL_BOOL(mongoc_client_session_get_dirty(intern->client_session));
+} /* }}} */
+
+/* {{{ proto void MongoDB\Driver\Session::isInTransaction(void)
+ Returns whether a multi-document transaction is in progress */
+static PHP_METHOD(Session, isInTransaction)
+{
+ zend_error_handling error_handling;
+ php_phongo_session_t* intern;
+
+ intern = Z_SESSION_OBJ_P(getThis());
+ SESSION_CHECK_LIVELINESS(intern, "isInTransaction")
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ RETURN_BOOL(mongoc_client_session_in_transaction(intern->client_session));
+} /* }}} */
+
+/* {{{ MongoDB\Driver\Session function entries */
+ZEND_BEGIN_ARG_INFO_EX(ai_Session_advanceClusterTime, 0, 0, 1)
+ ZEND_ARG_INFO(0, clusterTime)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_Session_advanceOperationTime, 0, 0, 1)
+ ZEND_ARG_INFO(0, timestamp)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_Session_startTransaction, 0, 0, 0)
+ ZEND_ARG_ARRAY_INFO(0, options, 1)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_Session_void, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry php_phongo_session_me[] = {
+ /* clang-format off */
+ PHP_ME(Session, abortTransaction, ai_Session_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Session, advanceClusterTime, ai_Session_advanceClusterTime, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Session, advanceOperationTime, ai_Session_advanceOperationTime, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Session, commitTransaction, ai_Session_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Session, endSession, ai_Session_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Session, getClusterTime, ai_Session_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Session, getLogicalSessionId, ai_Session_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Session, getOperationTime, ai_Session_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Session, getServer, ai_Session_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Session, getTransactionOptions, ai_Session_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Session, getTransactionState, ai_Session_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Session, isDirty, ai_Session_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Session, isInTransaction, ai_Session_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(Session, startTransaction, ai_Session_startTransaction, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ ZEND_NAMED_ME(__construct, PHP_FN(MongoDB_disabled___construct), ai_Session_void, ZEND_ACC_PRIVATE | ZEND_ACC_FINAL)
+ ZEND_NAMED_ME(__wakeup, PHP_FN(MongoDB_disabled___wakeup), ai_Session_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_FE_END
+ /* clang-format on */
+};
+/* }}} */
+
+/* {{{ MongoDB\Driver\Session object handlers */
+static zend_object_handlers php_phongo_handler_session;
+
+static void php_phongo_session_free_object(zend_object* object) /* {{{ */
+{
+ php_phongo_session_t* intern = Z_OBJ_SESSION(object);
+
+ zend_object_std_dtor(&intern->std);
+
+ /* If this Session was created in a different process, reset the client so
+ * that its session pool is cleared and mongoc_client_session_destroy will
+ * destroy the corresponding server session rather than return it to the
+ * now-empty pool. This will ensure that we do not re-use a server session
+ * (i.e. LSID) created by a parent process. */
+ PHONGO_RESET_CLIENT_IF_PID_DIFFERS(intern, Z_MANAGER_OBJ_P(&intern->manager));
+
+ if (intern->client_session) {
+ mongoc_client_session_destroy(intern->client_session);
+ }
+
+ if (!Z_ISUNDEF(intern->manager)) {
+ zval_ptr_dtor(&intern->manager);
+ }
+} /* }}} */
+
+static zend_object* php_phongo_session_create_object(zend_class_entry* class_type) /* {{{ */
+{
+ php_phongo_session_t* intern = zend_object_alloc(sizeof(php_phongo_session_t), class_type);
+
+ zend_object_std_init(&intern->std, class_type);
+ object_properties_init(&intern->std, class_type);
+
+ PHONGO_SET_CREATED_BY_PID(intern);
+
+ intern->std.handlers = &php_phongo_handler_session;
+
+ return &intern->std;
+} /* }}} */
+
+static HashTable* php_phongo_session_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
+{
+ php_phongo_session_t* intern = NULL;
+ zval retval = ZVAL_STATIC_INIT;
+
+ *is_temp = 1;
+ intern = Z_OBJ_SESSION(PHONGO_COMPAT_GET_OBJ(object));
+
+ array_init(&retval);
+
+ if (!intern->client_session) {
+ ADD_ASSOC_BOOL_EX(&retval, "ended", true);
+
+ goto done;
+ }
+
+ {
+ const bson_t* lsid = mongoc_client_session_get_lsid(intern->client_session);
+ php_phongo_bson_state state;
+
+ PHONGO_BSON_INIT_DEBUG_STATE(state);
+
+ if (!php_phongo_bson_to_zval_ex(bson_get_data(lsid), lsid->len, &state)) {
+ zval_ptr_dtor(&state.zchild);
+ goto done;
+ }
+
+ ADD_ASSOC_ZVAL_EX(&retval, "logicalSessionId", &state.zchild);
+ }
+
+ {
+ const bson_t* cluster_time = mongoc_client_session_get_cluster_time(intern->client_session);
+
+ if (cluster_time) {
+ php_phongo_bson_state state;
+
+ PHONGO_BSON_INIT_DEBUG_STATE(state);
+
+ if (!php_phongo_bson_to_zval_ex(bson_get_data(cluster_time), cluster_time->len, &state)) {
+ zval_ptr_dtor(&state.zchild);
+ goto done;
+ }
+
+ ADD_ASSOC_ZVAL_EX(&retval, "clusterTime", &state.zchild);
+ } else {
+ ADD_ASSOC_NULL_EX(&retval, "clusterTime");
+ }
+ }
+
+ {
+ const mongoc_session_opt_t* cs_opts = mongoc_client_session_get_opts(intern->client_session);
+ ADD_ASSOC_BOOL_EX(&retval, "causalConsistency", mongoc_session_opts_get_causal_consistency(cs_opts));
+ ADD_ASSOC_BOOL_EX(&retval, "snapshot", mongoc_session_opts_get_snapshot(cs_opts));
+ }
+
+ {
+ uint32_t timestamp, increment;
+
+ mongoc_client_session_get_operation_time(intern->client_session, &timestamp, &increment);
+
+ if (timestamp && increment) {
+ zval ztimestamp;
+
+ php_phongo_bson_new_timestamp_from_increment_and_timestamp(&ztimestamp, increment, timestamp);
+ ADD_ASSOC_ZVAL_EX(&retval, "operationTime", &ztimestamp);
+ } else {
+ ADD_ASSOC_NULL_EX(&retval, "operationTime");
+ }
+ }
+
+ {
+ uint32_t server_id = mongoc_client_session_get_server_id(intern->client_session);
+
+ if (server_id) {
+ zval server;
+
+ phongo_server_init(&server, &intern->manager, server_id);
+ ADD_ASSOC_ZVAL_EX(&retval, "server", &server);
+ } else {
+ ADD_ASSOC_NULL_EX(&retval, "server");
+ }
+ }
+
+ ADD_ASSOC_BOOL_EX(&retval, "dirty", mongoc_client_session_get_dirty(intern->client_session));
+ ADD_ASSOC_BOOL_EX(&retval, "inTransaction", mongoc_client_session_in_transaction(intern->client_session));
+
+ {
+ const char* state = php_phongo_get_transaction_state_string(mongoc_client_session_get_transaction_state(intern->client_session));
+
+ if (!state) {
+ /* Exception should already have been thrown */
+ goto done;
+ }
+
+ ADD_ASSOC_STRING(&retval, "transactionState", state);
+ }
+
+ {
+ zval txn_opts;
+
+ php_phongo_transaction_options_to_zval(intern->client_session, &txn_opts);
+ ADD_ASSOC_ZVAL_EX(&retval, "transactionOptions", &txn_opts);
+ }
+
+done:
+ return Z_ARRVAL(retval);
+} /* }}} */
+/* }}} */
+
+void php_phongo_session_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver", "Session", php_phongo_session_me);
+ php_phongo_session_ce = zend_register_internal_class(&ce);
+ php_phongo_session_ce->create_object = php_phongo_session_create_object;
+ PHONGO_CE_FINAL(php_phongo_session_ce);
+ PHONGO_CE_DISABLE_SERIALIZATION(php_phongo_session_ce);
+
+ memcpy(&php_phongo_handler_session, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
+ php_phongo_handler_session.get_debug_info = php_phongo_session_get_debug_info;
+ php_phongo_handler_session.free_obj = php_phongo_session_free_object;
+ php_phongo_handler_session.offset = XtOffsetOf(php_phongo_session_t, std);
+
+ zend_declare_class_constant_string(php_phongo_session_ce, ZEND_STRL("TRANSACTION_NONE"), PHONGO_TRANSACTION_NONE);
+ zend_declare_class_constant_string(php_phongo_session_ce, ZEND_STRL("TRANSACTION_STARTING"), PHONGO_TRANSACTION_STARTING);
+ zend_declare_class_constant_string(php_phongo_session_ce, ZEND_STRL("TRANSACTION_IN_PROGRESS"), PHONGO_TRANSACTION_IN_PROGRESS);
+ zend_declare_class_constant_string(php_phongo_session_ce, ZEND_STRL("TRANSACTION_COMMITTED"), PHONGO_TRANSACTION_COMMITTED);
+ zend_declare_class_constant_string(php_phongo_session_ce, ZEND_STRL("TRANSACTION_ABORTED"), PHONGO_TRANSACTION_ABORTED);
+} /* }}} */
+
+void phongo_session_init(zval* return_value, zval* manager, mongoc_client_session_t* client_session) /* {{{ */
+{
+ php_phongo_session_t* session;
+
+ object_init_ex(return_value, php_phongo_session_ce);
+
+ session = Z_SESSION_OBJ_P(return_value);
+ session->client_session = client_session;
+
+ ZVAL_ZVAL(&session->manager, manager, 1, 0);
+}
+/* }}} */
diff --git a/mongodb-1.13.0/src/MongoDB/Session.h b/mongodb-1.13.0/src/MongoDB/Session.h
new file mode 100644
index 00000000..9162ffb7
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/Session.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2017-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PHP_MONGODB_DRIVER_SESSION_H
+#define PHP_MONGODB_DRIVER_SESSION_H
+
+#include "mongoc/mongoc.h"
+
+#include <php.h>
+
+mongoc_transaction_opt_t* php_mongodb_session_parse_transaction_options(zval* txnOptions);
+
+void phongo_session_init(zval* return_value, zval* manager, mongoc_client_session_t* client_session);
+
+#endif /* PHP_MONGODB_DRIVER_SESSION_H */
diff --git a/mongodb-1.13.0/src/MongoDB/TopologyDescription.c b/mongodb-1.13.0/src/MongoDB/TopologyDescription.c
new file mode 100644
index 00000000..a87c4554
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/TopologyDescription.c
@@ -0,0 +1,247 @@
+/*
+ * Copyright 2021-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mongoc/mongoc.h"
+
+#include <php.h>
+#include <zend_smart_str.h>
+#include <ext/standard/php_var.h>
+#include <Zend/zend_interfaces.h>
+
+#include "php_phongo.h"
+#include "phongo_error.h"
+
+#include "MongoDB/ReadPreference.h"
+#include "MongoDB/ServerDescription.h"
+#include "MongoDB/TopologyDescription.h"
+
+zend_class_entry* php_phongo_topologydescription_ce;
+
+/* Note: these constants are derived from _mongoc_topology_description_type,
+ * since mongoc_topology_description_t is private. */
+#define PHONGO_TOPOLOGY_UNKNOWN "Unknown"
+#define PHONGO_TOPOLOGY_SINGLE "Single"
+#define PHONGO_TOPOLOGY_SHARDED "Sharded"
+#define PHONGO_TOPOLOGY_REPLICA_SET_NO_PRIMARY "ReplicaSetNoPrimary"
+#define PHONGO_TOPOLOGY_REPLICA_SET_WITH_PRIMARY "ReplicaSetWithPrimary"
+#define PHONGO_TOPOLOGY_LOAD_BALANCED "LoadBalanced"
+
+/* {{{ proto array MongoDB\Driver\TopologyDescription::getServers()
+ Returns an array of ServerDescription objects for all known servers in the topology */
+static PHP_METHOD(TopologyDescription, getServers)
+{
+ php_phongo_topologydescription_t* intern;
+ mongoc_server_description_t** sds;
+ size_t i, n = 0;
+
+ intern = Z_TOPOLOGYDESCRIPTION_OBJ_P(getThis());
+
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ sds = mongoc_topology_description_get_servers(intern->topology_description, &n);
+
+ array_init_size(return_value, n);
+
+ for (i = 0; i < n; i++) {
+ zval sd;
+ phongo_serverdescription_init(&sd, sds[i]);
+ add_next_index_zval(return_value, &sd);
+ }
+
+ mongoc_server_descriptions_destroy_all(sds, n);
+} /* }}} */
+
+/* {{{ proto boolean MongoDB\Driver\TopologyDescription::hasReadableServer([MongoDB\Driver\ReadPreference $readPreference])
+ Returns whether the topology has a readable server available */
+static PHP_METHOD(TopologyDescription, hasReadableServer)
+{
+ php_phongo_topologydescription_t* intern;
+ const mongoc_read_prefs_t* read_preference = NULL;
+ zval* z_read_preference = NULL;
+
+ intern = Z_TOPOLOGYDESCRIPTION_OBJ_P(getThis());
+
+ PHONGO_PARSE_PARAMETERS_START(0, 1)
+ Z_PARAM_OPTIONAL
+ Z_PARAM_OBJECT_OF_CLASS(z_read_preference, php_phongo_readpreference_ce)
+ PHONGO_PARSE_PARAMETERS_END();
+
+ if (z_read_preference) {
+ read_preference = phongo_read_preference_from_zval(z_read_preference);
+ }
+
+ RETVAL_BOOL(mongoc_topology_description_has_readable_server(intern->topology_description, read_preference));
+} /* }}} */
+
+/* {{{ proto boolean MongoDB\Driver\TopologyDescription::hasWritableServer()
+ Returns whether the topology has a writable server available */
+static PHP_METHOD(TopologyDescription, hasWritableServer)
+{
+ php_phongo_topologydescription_t* intern = Z_TOPOLOGYDESCRIPTION_OBJ_P(getThis());
+
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ RETVAL_BOOL(mongoc_topology_description_has_writable_server(intern->topology_description));
+} /* }}} */
+
+/* {{{ proto string MongoDB\Driver\TopologyDescription::getType()
+ Returns the topology type */
+static PHP_METHOD(TopologyDescription, getType)
+{
+ php_phongo_topologydescription_t* intern = Z_TOPOLOGYDESCRIPTION_OBJ_P(getThis());
+
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ RETVAL_STRING(mongoc_topology_description_type(intern->topology_description));
+} /* }}} */
+
+/* {{{ MongoDB\Driver\TopologyDescription function entries */
+/* clang-format off */
+ZEND_BEGIN_ARG_INFO_EX(ai_TopologyDescription_hasReadableServer, 0, 0, 0)
+ ZEND_ARG_OBJ_INFO(0, readPreference, MongoDB\\Driver\\ReadPreference, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_TopologyDescription_void, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry php_phongo_topologydescription_me[] = {
+ PHP_ME(TopologyDescription, getServers, ai_TopologyDescription_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(TopologyDescription, hasReadableServer, ai_TopologyDescription_hasReadableServer, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(TopologyDescription, hasWritableServer, ai_TopologyDescription_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(TopologyDescription, getType, ai_TopologyDescription_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ ZEND_NAMED_ME(__construct, PHP_FN(MongoDB_disabled___construct), ai_TopologyDescription_void, ZEND_ACC_PRIVATE | ZEND_ACC_FINAL)
+ PHP_FE_END
+};
+/* clang-format on */
+/* }}} */
+
+/* {{{ MongoDB\Driver\TopologyDescription object handlers */
+static zend_object_handlers php_phongo_handler_topologydescription;
+
+static void php_phongo_topologydescription_free_object(zend_object* object) /* {{{ */
+{
+ php_phongo_topologydescription_t* intern = Z_OBJ_TOPOLOGYDESCRIPTION(object);
+
+ zend_object_std_dtor(&intern->std);
+
+ if (intern->properties) {
+ zend_hash_destroy(intern->properties);
+ FREE_HASHTABLE(intern->properties);
+ }
+
+ if (intern->topology_description) {
+ mongoc_topology_description_destroy(intern->topology_description);
+ }
+}
+
+static zend_object* php_phongo_topologydescription_create_object(zend_class_entry* class_type) /* {{{ */
+{
+ php_phongo_topologydescription_t* intern = zend_object_alloc(sizeof(php_phongo_topologydescription_t), class_type);
+
+ zend_object_std_init(&intern->std, class_type);
+ object_properties_init(&intern->std, class_type);
+
+ intern->std.handlers = &php_phongo_handler_topologydescription;
+
+ return &intern->std;
+} /* }}} */
+
+HashTable* php_phongo_topologydescription_get_properties_hash(phongo_compat_object_handler_type* object, bool is_debug) /* {{{ */
+{
+ php_phongo_topologydescription_t* intern = NULL;
+ HashTable* props;
+
+ intern = Z_OBJ_TOPOLOGYDESCRIPTION(PHONGO_COMPAT_GET_OBJ(object));
+
+ PHONGO_GET_PROPERTY_HASH_INIT_PROPS(is_debug, intern, props, 2);
+
+ if (!intern->topology_description) {
+ return props;
+ }
+
+ {
+ zval servers;
+ size_t i, n = 0;
+ mongoc_server_description_t** sds = mongoc_topology_description_get_servers(intern->topology_description, &n);
+
+ array_init_size(&servers, n);
+
+ for (i = 0; i < n; i++) {
+ zval sd;
+ phongo_serverdescription_init(&sd, sds[i]);
+ add_next_index_zval(&servers, &sd);
+ }
+
+ zend_hash_str_update(props, "servers", sizeof("servers") - 1, &servers);
+ mongoc_server_descriptions_destroy_all(sds, n);
+ }
+
+ {
+ zval type;
+
+ ZVAL_STRING(&type, mongoc_topology_description_type(intern->topology_description));
+ zend_hash_str_update(props, "type", sizeof("type") - 1, &type);
+ }
+
+ return props;
+} /* }}} */
+
+static HashTable* php_phongo_topologydescription_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
+{
+ *is_temp = 1;
+ return php_phongo_topologydescription_get_properties_hash(object, true);
+} /* }}} */
+
+static HashTable* php_phongo_topologydescription_get_properties(phongo_compat_object_handler_type* object) /* {{{ */
+{
+ return php_phongo_topologydescription_get_properties_hash(object, false);
+} /* }}} */
+/* }}} */
+
+void php_phongo_topologydescription_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver", "TopologyDescription", php_phongo_topologydescription_me);
+ php_phongo_topologydescription_ce = zend_register_internal_class(&ce);
+ php_phongo_topologydescription_ce->create_object = php_phongo_topologydescription_create_object;
+ PHONGO_CE_FINAL(php_phongo_topologydescription_ce);
+ PHONGO_CE_DISABLE_SERIALIZATION(php_phongo_topologydescription_ce);
+
+ memcpy(&php_phongo_handler_topologydescription, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
+ php_phongo_handler_topologydescription.get_debug_info = php_phongo_topologydescription_get_debug_info;
+ php_phongo_handler_topologydescription.get_properties = php_phongo_topologydescription_get_properties;
+ php_phongo_handler_topologydescription.free_obj = php_phongo_topologydescription_free_object;
+ php_phongo_handler_topologydescription.offset = XtOffsetOf(php_phongo_topologydescription_t, std);
+
+ zend_declare_class_constant_string(php_phongo_topologydescription_ce, ZEND_STRL("TYPE_UNKNOWN"), PHONGO_TOPOLOGY_UNKNOWN);
+ zend_declare_class_constant_string(php_phongo_topologydescription_ce, ZEND_STRL("TYPE_SINGLE"), PHONGO_TOPOLOGY_SINGLE);
+ zend_declare_class_constant_string(php_phongo_topologydescription_ce, ZEND_STRL("TYPE_SHARDED"), PHONGO_TOPOLOGY_SHARDED);
+ zend_declare_class_constant_string(php_phongo_topologydescription_ce, ZEND_STRL("TYPE_REPLICA_SET_NO_PRIMARY"), PHONGO_TOPOLOGY_REPLICA_SET_NO_PRIMARY);
+ zend_declare_class_constant_string(php_phongo_topologydescription_ce, ZEND_STRL("TYPE_REPLICA_SET_WITH_PRIMARY"), PHONGO_TOPOLOGY_REPLICA_SET_WITH_PRIMARY);
+ zend_declare_class_constant_string(php_phongo_topologydescription_ce, ZEND_STRL("TYPE_LOAD_BALANCED"), PHONGO_TOPOLOGY_LOAD_BALANCED);
+} /* }}} */
+
+void phongo_topologydescription_init(zval* return_value, mongoc_topology_description_t* topology_description) /* {{{ */
+{
+ php_phongo_topologydescription_t* intern;
+
+ object_init_ex(return_value, php_phongo_topologydescription_ce);
+
+ intern = Z_TOPOLOGYDESCRIPTION_OBJ_P(return_value);
+ intern->topology_description = mongoc_topology_description_new_copy(topology_description);
+}
+/* }}} */
diff --git a/mongodb-1.13.0/src/MongoDB/TopologyDescription.h b/mongodb-1.13.0/src/MongoDB/TopologyDescription.h
new file mode 100644
index 00000000..2e5af369
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/TopologyDescription.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2022-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PHONGO_TOPOLOGYDESCRIPTION_H
+#define PHONGO_TOPOLOGYDESCRIPTION_H
+
+#include "mongoc/mongoc.h"
+
+#include <php.h>
+
+void phongo_topologydescription_init(zval* return_value, mongoc_topology_description_t* topology_description);
+
+#endif /* PHONGO_TOPOLOGYDESCRIPTION_H */
diff --git a/mongodb-1.13.0/src/MongoDB/WriteConcern.c b/mongodb-1.13.0/src/MongoDB/WriteConcern.c
new file mode 100644
index 00000000..10eebd14
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/WriteConcern.c
@@ -0,0 +1,671 @@
+/*
+ * Copyright 2014-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mongoc/mongoc.h"
+
+#include <php.h>
+#include <zend_smart_str.h>
+#include <ext/standard/php_var.h>
+#include <Zend/zend_interfaces.h>
+
+#include "php_phongo.h"
+#include "phongo_error.h"
+#include "phongo_util.h"
+
+#include "MongoDB/WriteConcern.h"
+
+zend_class_entry* php_phongo_writeconcern_ce;
+
+/* Initialize the object from a HashTable and return whether it was successful.
+ * An exception will be thrown on error. */
+static bool php_phongo_writeconcern_init_from_hash(php_phongo_writeconcern_t* intern, HashTable* props) /* {{{ */
+{
+ zval *w, *wtimeout, *j;
+
+ intern->write_concern = mongoc_write_concern_new();
+
+ if ((w = zend_hash_str_find(props, "w", sizeof("w") - 1))) {
+ if (Z_TYPE_P(w) == IS_LONG) {
+ if (Z_LVAL_P(w) < -3) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"w\" integer field to be >= -3", ZSTR_VAL(php_phongo_writeconcern_ce->name));
+ goto failure;
+ }
+ mongoc_write_concern_set_w(intern->write_concern, Z_LVAL_P(w));
+ } else if (Z_TYPE_P(w) == IS_STRING) {
+ if (strcmp(Z_STRVAL_P(w), PHONGO_WRITE_CONCERN_W_MAJORITY) == 0) {
+ mongoc_write_concern_set_w(intern->write_concern, MONGOC_WRITE_CONCERN_W_MAJORITY);
+ } else {
+ mongoc_write_concern_set_wtag(intern->write_concern, Z_STRVAL_P(w));
+ }
+ } else {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"w\" field to be integer or string", ZSTR_VAL(php_phongo_writeconcern_ce->name));
+ goto failure;
+ }
+ }
+
+ if ((wtimeout = zend_hash_str_find(props, "wtimeout", sizeof("wtimeout") - 1))) {
+ if (Z_TYPE_P(wtimeout) == IS_LONG) {
+ if (Z_LVAL_P(wtimeout) < 0) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"wtimeout\" integer field to be >= 0", ZSTR_VAL(php_phongo_writeconcern_ce->name));
+ goto failure;
+ }
+
+ mongoc_write_concern_set_wtimeout_int64(intern->write_concern, (int64_t) Z_LVAL_P(wtimeout));
+ } else if (Z_TYPE_P(wtimeout) == IS_STRING) {
+ int64_t timeout;
+
+ if (!php_phongo_parse_int64(&timeout, Z_STRVAL_P(wtimeout), Z_STRLEN_P(wtimeout))) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Error parsing \"%s\" as 64-bit value for %s initialization", Z_STRVAL_P(wtimeout), ZSTR_VAL(php_phongo_writeconcern_ce->name));
+ return false;
+ }
+
+ mongoc_write_concern_set_wtimeout_int64(intern->write_concern, timeout);
+ } else {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"wtimeout\" field to be integer or string", ZSTR_VAL(php_phongo_writeconcern_ce->name));
+ goto failure;
+ }
+ }
+
+ if ((j = zend_hash_str_find(props, "j", sizeof("j") - 1))) {
+ if (Z_TYPE_P(j) == IS_TRUE || Z_TYPE_P(j) == IS_FALSE) {
+ if (zend_is_true(j) && (mongoc_write_concern_get_w(intern->write_concern) == MONGOC_WRITE_CONCERN_W_UNACKNOWLEDGED || mongoc_write_concern_get_w(intern->write_concern) == MONGOC_WRITE_CONCERN_W_ERRORS_IGNORED)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Cannot enable journaling when using w = 0");
+ goto failure;
+ }
+
+ mongoc_write_concern_set_journal(intern->write_concern, zend_is_true(j));
+ } else {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s initialization requires \"j\" field to be boolean", ZSTR_VAL(php_phongo_writeconcern_ce->name));
+ goto failure;
+ }
+ }
+
+ if (!mongoc_write_concern_is_valid(intern->write_concern)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Write concern is not valid");
+ goto failure;
+ }
+
+ return true;
+
+failure:
+ mongoc_write_concern_destroy(intern->write_concern);
+ intern->write_concern = NULL;
+ return false;
+} /* }}} */
+
+/* {{{ proto void MongoDB\Driver\WriteConcern::__construct(integer|string $w[, integer $wtimeout[, boolean $journal]])
+ Constructs a new WriteConcern */
+static PHP_METHOD(WriteConcern, __construct)
+{
+ zend_error_handling error_handling;
+ php_phongo_writeconcern_t* intern;
+ zval * w, *journal;
+ zend_long wtimeout = 0;
+
+ intern = Z_WRITECONCERN_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|lz", &w, &wtimeout, &journal) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ intern->write_concern = mongoc_write_concern_new();
+
+ if (Z_TYPE_P(w) == IS_LONG) {
+ if (Z_LVAL_P(w) < -3) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected w to be >= -3, %ld given", Z_LVAL_P(w));
+ return;
+ }
+ mongoc_write_concern_set_w(intern->write_concern, Z_LVAL_P(w));
+ } else if (Z_TYPE_P(w) == IS_STRING) {
+ if (strcmp(Z_STRVAL_P(w), PHONGO_WRITE_CONCERN_W_MAJORITY) == 0) {
+ mongoc_write_concern_set_w(intern->write_concern, MONGOC_WRITE_CONCERN_W_MAJORITY);
+ } else {
+ mongoc_write_concern_set_wtag(intern->write_concern, Z_STRVAL_P(w));
+ }
+ } else {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected w to be integer or string, %s given", PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(w));
+ return;
+ }
+
+ switch (ZEND_NUM_ARGS()) {
+ case 3:
+ if (Z_TYPE_P(journal) != IS_NULL) {
+ if (zend_is_true(journal) && (mongoc_write_concern_get_w(intern->write_concern) == MONGOC_WRITE_CONCERN_W_UNACKNOWLEDGED || mongoc_write_concern_get_w(intern->write_concern) == MONGOC_WRITE_CONCERN_W_ERRORS_IGNORED)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Cannot enable journaling when using w = 0");
+ return;
+ }
+
+ mongoc_write_concern_set_journal(intern->write_concern, zend_is_true(journal));
+ }
+ PHONGO_BREAK_INTENTIONALLY_MISSING
+
+ case 2:
+ if (wtimeout < 0) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected wtimeout to be >= 0, %" PHONGO_LONG_FORMAT " given", wtimeout);
+ return;
+ }
+
+ mongoc_write_concern_set_wtimeout_int64(intern->write_concern, (int64_t) wtimeout);
+ }
+
+ if (!mongoc_write_concern_is_valid(intern->write_concern)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Write concern is not valid");
+ return;
+ }
+} /* }}} */
+
+/* {{{ proto MongoDB\Driver\WriteConcern MongoDB\Driver\WriteConcern::__set_state(array $properties)
+*/
+static PHP_METHOD(WriteConcern, __set_state)
+{
+ zend_error_handling error_handling;
+ php_phongo_writeconcern_t* intern;
+ HashTable* props;
+ zval* array;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &array) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ object_init_ex(return_value, php_phongo_writeconcern_ce);
+
+ intern = Z_WRITECONCERN_OBJ_P(return_value);
+ props = Z_ARRVAL_P(array);
+
+ php_phongo_writeconcern_init_from_hash(intern, props);
+} /* }}} */
+
+/* {{{ proto string|integer|null MongoDB\Driver\WriteConcern::getW()
+ Returns the WriteConcern "w" option */
+static PHP_METHOD(WriteConcern, getW)
+{
+ zend_error_handling error_handling;
+ php_phongo_writeconcern_t* intern;
+ const char* wtag;
+
+ intern = Z_WRITECONCERN_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ wtag = mongoc_write_concern_get_wtag(intern->write_concern);
+
+ if (wtag) {
+ RETURN_STRING(wtag);
+ }
+
+ if (mongoc_write_concern_get_wmajority(intern->write_concern)) {
+ RETURN_STRING(PHONGO_WRITE_CONCERN_W_MAJORITY);
+ }
+
+ if (mongoc_write_concern_get_w(intern->write_concern) != MONGOC_WRITE_CONCERN_W_DEFAULT) {
+ RETURN_LONG(mongoc_write_concern_get_w(intern->write_concern));
+ }
+
+ RETURN_NULL();
+} /* }}} */
+
+/* {{{ proto integer MongoDB\Driver\WriteConcern::getWtimeout()
+ Returns the WriteConcern "wtimeout" option */
+static PHP_METHOD(WriteConcern, getWtimeout)
+{
+ zend_error_handling error_handling;
+ php_phongo_writeconcern_t* intern;
+ int64_t wtimeout;
+
+ intern = Z_WRITECONCERN_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ wtimeout = mongoc_write_concern_get_wtimeout_int64(intern->write_concern);
+
+#if SIZEOF_ZEND_LONG == 4
+ if (wtimeout > INT32_MAX || wtimeout < INT32_MIN) {
+ zend_error(E_WARNING, "Truncating 64-bit value for wTimeoutMS");
+ }
+#endif
+
+ RETURN_LONG(wtimeout);
+} /* }}} */
+
+/* {{{ proto null|boolean MongoDB\Driver\WriteConcern::getJournal()
+ Returns the WriteConcern "journal" option */
+static PHP_METHOD(WriteConcern, getJournal)
+{
+ zend_error_handling error_handling;
+ php_phongo_writeconcern_t* intern;
+
+ intern = Z_WRITECONCERN_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ if (mongoc_write_concern_journal_is_set(intern->write_concern)) {
+ RETURN_BOOL(mongoc_write_concern_get_journal(intern->write_concern));
+ }
+
+ RETURN_NULL();
+} /* }}} */
+
+/* {{{ proto boolean MongoDB\Driver\WriteConcern::isDefault()
+ Returns whether the write concern has not been modified (i.e. from a Manager
+ with no write concern URI options). */
+static PHP_METHOD(WriteConcern, isDefault)
+{
+ zend_error_handling error_handling;
+ php_phongo_writeconcern_t* intern;
+
+ intern = Z_WRITECONCERN_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ RETURN_BOOL(mongoc_write_concern_is_default(intern->write_concern));
+} /* }}} */
+
+static HashTable* php_phongo_writeconcern_get_properties_hash(phongo_compat_object_handler_type* object, bool is_temp, bool is_bson, bool is_serialize) /* {{{ */
+{
+ php_phongo_writeconcern_t* intern;
+ HashTable* props;
+ const char* wtag;
+ int32_t w;
+ int64_t wtimeout;
+
+ intern = Z_OBJ_WRITECONCERN(PHONGO_COMPAT_GET_OBJ(object));
+
+ PHONGO_GET_PROPERTY_HASH_INIT_PROPS(is_temp, intern, props, 4);
+
+ if (!intern->write_concern) {
+ return props;
+ }
+
+ wtag = mongoc_write_concern_get_wtag(intern->write_concern);
+ w = mongoc_write_concern_get_w(intern->write_concern);
+ wtimeout = mongoc_write_concern_get_wtimeout_int64(intern->write_concern);
+
+ {
+ zval z_w;
+
+ if (wtag) {
+ ZVAL_STRING(&z_w, wtag);
+ zend_hash_str_update(props, "w", sizeof("w") - 1, &z_w);
+ } else if (mongoc_write_concern_get_wmajority(intern->write_concern)) {
+ ZVAL_STRING(&z_w, PHONGO_WRITE_CONCERN_W_MAJORITY);
+ zend_hash_str_update(props, "w", sizeof("w") - 1, &z_w);
+ } else if (w != MONGOC_WRITE_CONCERN_W_DEFAULT) {
+ ZVAL_LONG(&z_w, w);
+ zend_hash_str_update(props, "w", sizeof("w") - 1, &z_w);
+ }
+
+ if (mongoc_write_concern_journal_is_set(intern->write_concern)) {
+ zval z_j;
+
+ ZVAL_BOOL(&z_j, mongoc_write_concern_get_journal(intern->write_concern));
+ zend_hash_str_update(props, "j", sizeof("j") - 1, &z_j);
+ }
+
+ if (wtimeout != 0) {
+ zval z_wtimeout;
+
+ if (is_bson) {
+ ZVAL_INT64(&z_wtimeout, wtimeout);
+ } else if (is_serialize) {
+ if (wtimeout > INT32_MAX || wtimeout < INT32_MIN) {
+ ZVAL_INT64_STRING(&z_wtimeout, wtimeout);
+ } else {
+ ZVAL_LONG(&z_wtimeout, wtimeout);
+ }
+ } else {
+#if SIZEOF_ZEND_LONG == 4
+ if (wtimeout > INT32_MAX || wtimeout < INT32_MIN) {
+ ZVAL_INT64_STRING(&z_wtimeout, wtimeout);
+ } else {
+ ZVAL_LONG(&z_wtimeout, wtimeout);
+ }
+#else
+ ZVAL_LONG(&z_wtimeout, wtimeout);
+#endif
+ }
+
+ zend_hash_str_update(props, "wtimeout", sizeof("wtimeout") - 1, &z_wtimeout);
+ }
+ }
+
+ return props;
+} /* }}} */
+
+/* {{{ proto array MongoDB\Driver\WriteConcern::bsonSerialize()
+*/
+static PHP_METHOD(WriteConcern, bsonSerialize)
+{
+ zend_error_handling error_handling;
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ ZVAL_ARR(return_value, php_phongo_writeconcern_get_properties_hash(PHONGO_COMPAT_OBJ_P(getThis()), true, true, false));
+ convert_to_object(return_value);
+} /* }}} */
+
+/* {{{ proto string MongoDB\Driver\WriteConcern::serialize()
+*/
+static PHP_METHOD(WriteConcern, serialize)
+{
+ zend_error_handling error_handling;
+ php_phongo_writeconcern_t* intern;
+ zval retval;
+ php_serialize_data_t var_hash;
+ smart_str buf = { 0 };
+ const char* wtag;
+ int32_t w;
+ int64_t wtimeout;
+
+ intern = Z_WRITECONCERN_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ if (!intern->write_concern) {
+ return;
+ }
+
+ wtag = mongoc_write_concern_get_wtag(intern->write_concern);
+ w = mongoc_write_concern_get_w(intern->write_concern);
+ wtimeout = mongoc_write_concern_get_wtimeout_int64(intern->write_concern);
+
+ array_init_size(&retval, 3);
+
+ if (wtag) {
+ ADD_ASSOC_STRING(&retval, "w", wtag);
+ } else if (mongoc_write_concern_get_wmajority(intern->write_concern)) {
+ ADD_ASSOC_STRING(&retval, "w", PHONGO_WRITE_CONCERN_W_MAJORITY);
+ } else if (w != MONGOC_WRITE_CONCERN_W_DEFAULT) {
+ ADD_ASSOC_LONG_EX(&retval, "w", w);
+ }
+
+ if (mongoc_write_concern_journal_is_set(intern->write_concern)) {
+ ADD_ASSOC_BOOL_EX(&retval, "j", mongoc_write_concern_get_journal(intern->write_concern));
+ }
+
+ if (wtimeout != 0) {
+ if (wtimeout > INT32_MAX || wtimeout < INT32_MIN) {
+ ADD_ASSOC_INT64_AS_STRING(&retval, "wtimeout", wtimeout);
+ } else {
+ ADD_ASSOC_LONG_EX(&retval, "wtimeout", wtimeout);
+ }
+ }
+
+ PHP_VAR_SERIALIZE_INIT(var_hash);
+ php_var_serialize(&buf, &retval, &var_hash);
+ smart_str_0(&buf);
+ PHP_VAR_SERIALIZE_DESTROY(var_hash);
+
+ PHONGO_RETVAL_SMART_STR(buf);
+
+ smart_str_free(&buf);
+ zval_ptr_dtor(&retval);
+} /* }}} */
+
+/* {{{ proto void MongoDB\Driver\WriteConcern::unserialize(string $serialized)
+*/
+static PHP_METHOD(WriteConcern, unserialize)
+{
+ zend_error_handling error_handling;
+ php_phongo_writeconcern_t* intern;
+ char* serialized;
+ size_t serialized_len;
+ zval props;
+ php_unserialize_data_t var_hash;
+
+ intern = Z_WRITECONCERN_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &serialized, &serialized_len) == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ if (!serialized_len) {
+ return;
+ }
+
+ PHP_VAR_UNSERIALIZE_INIT(var_hash);
+ if (!php_var_unserialize(&props, (const unsigned char**) &serialized, (unsigned char*) serialized + serialized_len, &var_hash)) {
+ zval_ptr_dtor(&props);
+ phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "%s unserialization failed", ZSTR_VAL(php_phongo_writeconcern_ce->name));
+
+ PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+ return;
+ }
+ PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+
+ php_phongo_writeconcern_init_from_hash(intern, HASH_OF(&props));
+ zval_ptr_dtor(&props);
+} /* }}} */
+
+/* {{{ proto array MongoDB\Driver\WriteConcern::__serialize()
+*/
+static PHP_METHOD(WriteConcern, __serialize)
+{
+ PHONGO_PARSE_PARAMETERS_NONE();
+
+ RETURN_ARR(php_phongo_writeconcern_get_properties_hash(PHONGO_COMPAT_OBJ_P(getThis()), true, false, true));
+} /* }}} */
+
+/* {{{ proto void MongoDB\Driver\WriteConcern::__unserialize(array $data)
+*/
+static PHP_METHOD(WriteConcern, __unserialize)
+{
+ zval* data;
+
+ PHONGO_PARSE_PARAMETERS_START(1, 1)
+ Z_PARAM_ARRAY(data)
+ PHONGO_PARSE_PARAMETERS_END();
+
+ php_phongo_writeconcern_init_from_hash(Z_WRITECONCERN_OBJ_P(getThis()), Z_ARRVAL_P(data));
+} /* }}} */
+
+/* {{{ MongoDB\Driver\WriteConcern function entries */
+ZEND_BEGIN_ARG_INFO_EX(ai_WriteConcern___construct, 0, 0, 1)
+ ZEND_ARG_INFO(0, w)
+ ZEND_ARG_INFO(0, wtimeout)
+ ZEND_ARG_INFO(0, journal)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_WriteConcern___set_state, 0, 0, 1)
+ ZEND_ARG_ARRAY_INFO(0, properties, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_WriteConcern___unserialize, 0, 0, 1)
+ ZEND_ARG_ARRAY_INFO(0, data, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_WriteConcern_unserialize, 0, 0, 1)
+ ZEND_ARG_INFO(0, serialized)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(ai_WriteConcern_void, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry php_phongo_writeconcern_me[] = {
+ /* clang-format off */
+ PHP_ME(WriteConcern, __construct, ai_WriteConcern___construct, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(WriteConcern, __serialize, ai_WriteConcern_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(WriteConcern, __set_state, ai_WriteConcern___set_state, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+ PHP_ME(WriteConcern, __unserialize, ai_WriteConcern___unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(WriteConcern, getW, ai_WriteConcern_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(WriteConcern, getWtimeout, ai_WriteConcern_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(WriteConcern, getJournal, ai_WriteConcern_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(WriteConcern, isDefault, ai_WriteConcern_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(WriteConcern, bsonSerialize, ai_WriteConcern_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(WriteConcern, serialize, ai_WriteConcern_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(WriteConcern, unserialize, ai_WriteConcern_unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_FE_END
+ /* clang-format on */
+};
+/* }}} */
+
+/* {{{ MongoDB\Driver\WriteConcern object handlers */
+static zend_object_handlers php_phongo_handler_writeconcern;
+
+static void php_phongo_writeconcern_free_object(zend_object* object) /* {{{ */
+{
+ php_phongo_writeconcern_t* intern = Z_OBJ_WRITECONCERN(object);
+
+ zend_object_std_dtor(&intern->std);
+
+ if (intern->properties) {
+ zend_hash_destroy(intern->properties);
+ FREE_HASHTABLE(intern->properties);
+ }
+
+ if (intern->write_concern) {
+ mongoc_write_concern_destroy(intern->write_concern);
+ }
+} /* }}} */
+
+static zend_object* php_phongo_writeconcern_create_object(zend_class_entry* class_type) /* {{{ */
+{
+ php_phongo_writeconcern_t* intern = zend_object_alloc(sizeof(php_phongo_writeconcern_t), class_type);
+
+ zend_object_std_init(&intern->std, class_type);
+ object_properties_init(&intern->std, class_type);
+
+ intern->std.handlers = &php_phongo_handler_writeconcern;
+
+ return &intern->std;
+} /* }}} */
+
+static HashTable* php_phongo_writeconcern_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
+{
+ *is_temp = 1;
+ return php_phongo_writeconcern_get_properties_hash(object, true, false, false);
+} /* }}} */
+
+static HashTable* php_phongo_writeconcern_get_properties(phongo_compat_object_handler_type* object) /* {{{ */
+{
+ return php_phongo_writeconcern_get_properties_hash(object, false, false, false);
+} /* }}} */
+
+void php_phongo_writeconcern_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver", "WriteConcern", php_phongo_writeconcern_me);
+ php_phongo_writeconcern_ce = zend_register_internal_class(&ce);
+ php_phongo_writeconcern_ce->create_object = php_phongo_writeconcern_create_object;
+ PHONGO_CE_FINAL(php_phongo_writeconcern_ce);
+
+ zend_class_implements(php_phongo_writeconcern_ce, 1, php_phongo_serializable_ce);
+ zend_class_implements(php_phongo_writeconcern_ce, 1, zend_ce_serializable);
+
+ memcpy(&php_phongo_handler_writeconcern, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
+ php_phongo_handler_writeconcern.get_debug_info = php_phongo_writeconcern_get_debug_info;
+ php_phongo_handler_writeconcern.get_properties = php_phongo_writeconcern_get_properties;
+ php_phongo_handler_writeconcern.free_obj = php_phongo_writeconcern_free_object;
+ php_phongo_handler_writeconcern.offset = XtOffsetOf(php_phongo_writeconcern_t, std);
+
+ zend_declare_class_constant_stringl(php_phongo_writeconcern_ce, ZEND_STRL("MAJORITY"), ZEND_STRL(PHONGO_WRITE_CONCERN_W_MAJORITY));
+} /* }}} */
+
+void phongo_writeconcern_init(zval* return_value, const mongoc_write_concern_t* write_concern) /* {{{ */
+{
+ php_phongo_writeconcern_t* intern;
+
+ object_init_ex(return_value, php_phongo_writeconcern_ce);
+
+ intern = Z_WRITECONCERN_OBJ_P(return_value);
+ intern->write_concern = mongoc_write_concern_copy(write_concern);
+}
+/* }}} */
+
+const mongoc_write_concern_t* phongo_write_concern_from_zval(zval* zwrite_concern) /* {{{ */
+{
+ if (zwrite_concern) {
+ php_phongo_writeconcern_t* intern = Z_WRITECONCERN_OBJ_P(zwrite_concern);
+
+ if (intern) {
+ return intern->write_concern;
+ }
+ }
+
+ return NULL;
+} /* }}} */
+
+void php_phongo_write_concern_to_zval(zval* retval, const mongoc_write_concern_t* write_concern) /* {{{ */
+{
+ const char* wtag = mongoc_write_concern_get_wtag(write_concern);
+ const int32_t w = mongoc_write_concern_get_w(write_concern);
+ const int64_t wtimeout = mongoc_write_concern_get_wtimeout_int64(write_concern);
+
+ array_init_size(retval, 4);
+
+ if (wtag) {
+ ADD_ASSOC_STRING(retval, "w", wtag);
+ } else if (mongoc_write_concern_get_wmajority(write_concern)) {
+ ADD_ASSOC_STRING(retval, "w", PHONGO_WRITE_CONCERN_W_MAJORITY);
+ } else if (w != MONGOC_WRITE_CONCERN_W_DEFAULT) {
+ ADD_ASSOC_LONG_EX(retval, "w", w);
+ }
+
+ if (mongoc_write_concern_journal_is_set(write_concern)) {
+ ADD_ASSOC_BOOL_EX(retval, "j", mongoc_write_concern_get_journal(write_concern));
+ }
+
+ if (wtimeout != 0) {
+#if SIZEOF_ZEND_LONG == 4
+ if (wtimeout > INT32_MAX || wtimeout < INT32_MIN) {
+ ADD_ASSOC_INT64_AS_STRING(retval, "wtimeout", wtimeout);
+ } else {
+ ADD_ASSOC_LONG_EX(retval, "wtimeout", wtimeout);
+ }
+#else
+ ADD_ASSOC_LONG_EX(retval, "wtimeout", wtimeout);
+#endif
+ }
+} /* }}} */
diff --git a/mongodb-1.13.0/src/MongoDB/WriteConcern.h b/mongodb-1.13.0/src/MongoDB/WriteConcern.h
new file mode 100644
index 00000000..7ae865fb
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/WriteConcern.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2022-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PHONGO_WRITECONCERN_H
+#define PHONGO_WRITECONCERN_H
+
+#include "mongoc/mongoc.h"
+
+#include <php.h>
+
+#define PHONGO_WRITE_CONCERN_W_MAJORITY "majority"
+
+void phongo_writeconcern_init(zval* return_value, const mongoc_write_concern_t* write_concern);
+
+const mongoc_write_concern_t* phongo_write_concern_from_zval(zval* zwrite_concern);
+
+void php_phongo_write_concern_to_zval(zval* retval, const mongoc_write_concern_t* write_concern);
+
+#endif /* PHONGO_WRITECONCERN_H */
diff --git a/mongodb-1.13.0/src/MongoDB/WriteConcernError.c b/mongodb-1.13.0/src/MongoDB/WriteConcernError.c
new file mode 100644
index 00000000..afc8a71b
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/WriteConcernError.c
@@ -0,0 +1,208 @@
+/*
+ * Copyright 2014-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bson/bson.h"
+
+#include <php.h>
+#include <Zend/zend_interfaces.h>
+
+#include "php_phongo.h"
+#include "phongo_error.h"
+
+#include "MongoDB/WriteConcernError.h"
+
+zend_class_entry* php_phongo_writeconcernerror_ce;
+
+/* {{{ proto integer MongoDB\Driver\WriteConcernError::getCode()
+ Returns the MongoDB error code */
+static PHP_METHOD(WriteConcernError, getCode)
+{
+ zend_error_handling error_handling;
+ php_phongo_writeconcernerror_t* intern;
+
+ intern = Z_WRITECONCERNERROR_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ RETURN_LONG(intern->code);
+} /* }}} */
+
+/* {{{ proto object|null MongoDB\Driver\WriteConcernError::getInfo()
+ Returns additional metadata for the error */
+static PHP_METHOD(WriteConcernError, getInfo)
+{
+ zend_error_handling error_handling;
+ php_phongo_writeconcernerror_t* intern;
+
+ intern = Z_WRITECONCERNERROR_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ if (!Z_ISUNDEF(intern->info)) {
+ RETURN_ZVAL(&intern->info, 1, 0);
+ }
+} /* }}} */
+
+/* {{{ proto string MongoDB\Driver\WriteConcernError::getMessage()
+ Returns the actual error message from the server */
+static PHP_METHOD(WriteConcernError, getMessage)
+{
+ zend_error_handling error_handling;
+ php_phongo_writeconcernerror_t* intern;
+
+ intern = Z_WRITECONCERNERROR_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ RETURN_STRING(intern->message);
+} /* }}} */
+
+/* {{{ MongoDB\Driver\WriteConcernError function entries */
+ZEND_BEGIN_ARG_INFO_EX(ai_WriteConcernError_void, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry php_phongo_writeconcernerror_me[] = {
+ /* clang-format off */
+ PHP_ME(WriteConcernError, getCode, ai_WriteConcernError_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(WriteConcernError, getInfo, ai_WriteConcernError_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(WriteConcernError, getMessage, ai_WriteConcernError_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ ZEND_NAMED_ME(__construct, PHP_FN(MongoDB_disabled___construct), ai_WriteConcernError_void, ZEND_ACC_PRIVATE | ZEND_ACC_FINAL)
+ ZEND_NAMED_ME(__wakeup, PHP_FN(MongoDB_disabled___wakeup), ai_WriteConcernError_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_FE_END
+ /* clang-format on */
+};
+/* }}} */
+
+/* {{{ MongoDB\Driver\WriteConcernError object handlers */
+static zend_object_handlers php_phongo_handler_writeconcernerror;
+
+static void php_phongo_writeconcernerror_free_object(zend_object* object) /* {{{ */
+{
+ php_phongo_writeconcernerror_t* intern = Z_OBJ_WRITECONCERNERROR(object);
+
+ zend_object_std_dtor(&intern->std);
+
+ if (intern->message) {
+ efree(intern->message);
+ }
+
+ if (!Z_ISUNDEF(intern->info)) {
+ zval_ptr_dtor(&intern->info);
+ }
+} /* }}} */
+
+static zend_object* php_phongo_writeconcernerror_create_object(zend_class_entry* class_type) /* {{{ */
+{
+ php_phongo_writeconcernerror_t* intern = zend_object_alloc(sizeof(php_phongo_writeconcernerror_t), class_type);
+
+ zend_object_std_init(&intern->std, class_type);
+ object_properties_init(&intern->std, class_type);
+
+ intern->std.handlers = &php_phongo_handler_writeconcernerror;
+
+ return &intern->std;
+} /* }}} */
+
+static HashTable* php_phongo_writeconcernerror_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
+{
+ php_phongo_writeconcernerror_t* intern;
+ zval retval = ZVAL_STATIC_INIT;
+
+ *is_temp = 1;
+ intern = Z_OBJ_WRITECONCERNERROR(PHONGO_COMPAT_GET_OBJ(object));
+
+ array_init_size(&retval, 3);
+ ADD_ASSOC_STRING(&retval, "message", intern->message);
+ ADD_ASSOC_LONG_EX(&retval, "code", intern->code);
+ if (!Z_ISUNDEF(intern->info)) {
+ Z_ADDREF(intern->info);
+ ADD_ASSOC_ZVAL_EX(&retval, "info", &intern->info);
+ } else {
+ ADD_ASSOC_NULL_EX(&retval, "info");
+ }
+
+ return Z_ARRVAL(retval);
+} /* }}} */
+/* }}} */
+
+void php_phongo_writeconcernerror_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver", "WriteConcernError", php_phongo_writeconcernerror_me);
+ php_phongo_writeconcernerror_ce = zend_register_internal_class(&ce);
+ php_phongo_writeconcernerror_ce->create_object = php_phongo_writeconcernerror_create_object;
+ PHONGO_CE_FINAL(php_phongo_writeconcernerror_ce);
+ PHONGO_CE_DISABLE_SERIALIZATION(php_phongo_writeconcernerror_ce);
+
+ memcpy(&php_phongo_handler_writeconcernerror, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
+ php_phongo_handler_writeconcernerror.get_debug_info = php_phongo_writeconcernerror_get_debug_info;
+ php_phongo_handler_writeconcernerror.free_obj = php_phongo_writeconcernerror_free_object;
+ php_phongo_handler_writeconcernerror.offset = XtOffsetOf(php_phongo_writeconcernerror_t, std);
+} /* }}} */
+
+zend_bool phongo_writeconcernerror_init(zval* return_value, bson_t* bson) /* {{{ */
+{
+ bson_iter_t iter;
+ php_phongo_writeconcernerror_t* intern;
+
+ object_init_ex(return_value, php_phongo_writeconcernerror_ce);
+
+ intern = Z_WRITECONCERNERROR_OBJ_P(return_value);
+ intern->code = 0;
+
+ if (bson_iter_init_find(&iter, bson, "code") && BSON_ITER_HOLDS_INT32(&iter)) {
+ intern->code = bson_iter_int32(&iter);
+ }
+
+ if (bson_iter_init_find(&iter, bson, "errmsg") && BSON_ITER_HOLDS_UTF8(&iter)) {
+ uint32_t errmsg_len;
+ const char* err_msg = bson_iter_utf8(&iter, &errmsg_len);
+
+ intern->message = estrndup(err_msg, errmsg_len);
+ }
+
+ if (bson_iter_init_find(&iter, bson, "errInfo") && BSON_ITER_HOLDS_DOCUMENT(&iter)) {
+ uint32_t len;
+ const uint8_t* data = NULL;
+
+ bson_iter_document(&iter, &len, &data);
+
+ if (!php_phongo_bson_to_zval(data, len, &intern->info)) {
+ zval_ptr_dtor(&intern->info);
+ ZVAL_UNDEF(&intern->info);
+
+ return false;
+ }
+ }
+
+ return true;
+} /* }}} */
diff --git a/mongodb-1.13.0/src/MongoDB/WriteConcernError.h b/mongodb-1.13.0/src/MongoDB/WriteConcernError.h
new file mode 100644
index 00000000..f5f632bf
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/WriteConcernError.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2022-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PHONGO_WRITECONCERNERROR_H
+#define PHONGO_WRITECONCERNERROR_H
+
+#include "bson/bson.h"
+
+#include <php.h>
+
+zend_bool phongo_writeconcernerror_init(zval* return_value, bson_t* bson);
+
+#endif /* PHONGO_WRITECONCERNERROR_H */
diff --git a/mongodb-1.13.0/src/MongoDB/WriteError.c b/mongodb-1.13.0/src/MongoDB/WriteError.c
new file mode 100644
index 00000000..e5fed4ab
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/WriteError.c
@@ -0,0 +1,235 @@
+/*
+ * Copyright 2014-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bson/bson.h"
+
+#include <php.h>
+#include <Zend/zend_interfaces.h>
+
+#include "php_phongo.h"
+#include "phongo_error.h"
+
+#include "MongoDB/WriteError.h"
+
+zend_class_entry* php_phongo_writeerror_ce;
+
+/* {{{ proto integer MongoDB\Driver\WriteError::getCode()
+ Returns the MongoDB error code */
+static PHP_METHOD(WriteError, getCode)
+{
+ zend_error_handling error_handling;
+ php_phongo_writeerror_t* intern;
+
+ intern = Z_WRITEERROR_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ RETURN_LONG(intern->code);
+} /* }}} */
+
+/* {{{ proto integer MongoDB\Driver\WriteError::getIndex()
+ Returns the index of the operation in the BulkWrite to which this WriteError
+ corresponds. */
+static PHP_METHOD(WriteError, getIndex)
+{
+ zend_error_handling error_handling;
+ php_phongo_writeerror_t* intern;
+
+ intern = Z_WRITEERROR_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ RETURN_LONG(intern->index);
+} /* }}} */
+
+/* {{{ proto string MongoDB\Driver\WriteError::getMessage()
+ Returns the actual error message from the server */
+static PHP_METHOD(WriteError, getMessage)
+{
+ zend_error_handling error_handling;
+ php_phongo_writeerror_t* intern;
+
+ intern = Z_WRITEERROR_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ RETURN_STRING(intern->message);
+} /* }}} */
+
+/* {{{ proto object|null MongoDB\Driver\WriteError::getInfo()
+ Returns additional metadata for the error */
+static PHP_METHOD(WriteError, getInfo)
+{
+ zend_error_handling error_handling;
+ php_phongo_writeerror_t* intern;
+
+ intern = Z_WRITEERROR_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ if (!Z_ISUNDEF(intern->info)) {
+ RETURN_ZVAL(&intern->info, 1, 0);
+ }
+} /* }}} */
+
+/* {{{ MongoDB\Driver\WriteError function entries */
+ZEND_BEGIN_ARG_INFO_EX(ai_WriteError_void, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry php_phongo_writeerror_me[] = {
+ /* clang-format off */
+ PHP_ME(WriteError, getCode, ai_WriteError_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(WriteError, getIndex, ai_WriteError_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(WriteError, getMessage, ai_WriteError_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(WriteError, getInfo, ai_WriteError_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ ZEND_NAMED_ME(__construct, PHP_FN(MongoDB_disabled___construct), ai_WriteError_void, ZEND_ACC_PRIVATE | ZEND_ACC_FINAL)
+ ZEND_NAMED_ME(__wakeup, PHP_FN(MongoDB_disabled___wakeup), ai_WriteError_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_FE_END
+ /* clang-format on */
+};
+/* }}} */
+
+/* {{{ MongoDB\Driver\WriteError object handlers */
+static zend_object_handlers php_phongo_handler_writeerror;
+
+static void php_phongo_writeerror_free_object(zend_object* object) /* {{{ */
+{
+ php_phongo_writeerror_t* intern = Z_OBJ_WRITEERROR(object);
+
+ zend_object_std_dtor(&intern->std);
+
+ if (intern->message) {
+ efree(intern->message);
+ }
+
+ if (!Z_ISUNDEF(intern->info)) {
+ zval_ptr_dtor(&intern->info);
+ }
+} /* }}} */
+
+static zend_object* php_phongo_writeerror_create_object(zend_class_entry* class_type) /* {{{ */
+{
+ php_phongo_writeerror_t* intern = zend_object_alloc(sizeof(php_phongo_writeerror_t), class_type);
+
+ zend_object_std_init(&intern->std, class_type);
+ object_properties_init(&intern->std, class_type);
+
+ intern->std.handlers = &php_phongo_handler_writeerror;
+
+ return &intern->std;
+} /* }}} */
+
+static HashTable* php_phongo_writeerror_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
+{
+ php_phongo_writeerror_t* intern;
+ zval retval = ZVAL_STATIC_INIT;
+
+ *is_temp = 1;
+ intern = Z_OBJ_WRITEERROR(PHONGO_COMPAT_GET_OBJ(object));
+
+ array_init_size(&retval, 3);
+ ADD_ASSOC_STRING(&retval, "message", intern->message);
+ ADD_ASSOC_LONG_EX(&retval, "code", intern->code);
+ ADD_ASSOC_LONG_EX(&retval, "index", intern->index);
+ if (!Z_ISUNDEF(intern->info)) {
+ Z_ADDREF(intern->info);
+ ADD_ASSOC_ZVAL_EX(&retval, "info", &intern->info);
+ } else {
+ ADD_ASSOC_NULL_EX(&retval, "info");
+ }
+
+ return Z_ARRVAL(retval);
+} /* }}} */
+/* }}} */
+
+void php_phongo_writeerror_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver", "WriteError", php_phongo_writeerror_me);
+ php_phongo_writeerror_ce = zend_register_internal_class(&ce);
+ php_phongo_writeerror_ce->create_object = php_phongo_writeerror_create_object;
+ PHONGO_CE_FINAL(php_phongo_writeerror_ce);
+ PHONGO_CE_DISABLE_SERIALIZATION(php_phongo_writeerror_ce);
+
+ memcpy(&php_phongo_handler_writeerror, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
+ php_phongo_handler_writeerror.get_debug_info = php_phongo_writeerror_get_debug_info;
+ php_phongo_handler_writeerror.free_obj = php_phongo_writeerror_free_object;
+ php_phongo_handler_writeerror.offset = XtOffsetOf(php_phongo_writeerror_t, std);
+} /* }}} */
+
+zend_bool phongo_writeerror_init(zval* return_value, bson_t* bson) /* {{{ */
+{
+ bson_iter_t iter;
+ php_phongo_writeerror_t* intern;
+
+ object_init_ex(return_value, php_phongo_writeerror_ce);
+
+ intern = Z_WRITEERROR_OBJ_P(return_value);
+ intern->code = 0;
+ intern->index = 0;
+
+ if (bson_iter_init_find(&iter, bson, "code") && BSON_ITER_HOLDS_INT32(&iter)) {
+ intern->code = bson_iter_int32(&iter);
+ }
+
+ if (bson_iter_init_find(&iter, bson, "errmsg") && BSON_ITER_HOLDS_UTF8(&iter)) {
+ uint32_t errmsg_len;
+ const char* err_msg = bson_iter_utf8(&iter, &errmsg_len);
+
+ intern->message = estrndup(err_msg, errmsg_len);
+ }
+
+ if (bson_iter_init_find(&iter, bson, "errInfo") && BSON_ITER_HOLDS_DOCUMENT(&iter)) {
+ uint32_t len;
+ const uint8_t* data = NULL;
+
+ bson_iter_document(&iter, &len, &data);
+
+ if (!php_phongo_bson_to_zval(data, len, &intern->info)) {
+ zval_ptr_dtor(&intern->info);
+ ZVAL_UNDEF(&intern->info);
+
+ return false;
+ }
+ }
+
+ if (bson_iter_init_find(&iter, bson, "index") && BSON_ITER_HOLDS_INT32(&iter)) {
+ intern->index = bson_iter_int32(&iter);
+ }
+
+ return true;
+} /* }}} */
diff --git a/mongodb-1.13.0/src/MongoDB/WriteError.h b/mongodb-1.13.0/src/MongoDB/WriteError.h
new file mode 100644
index 00000000..b2334f98
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/WriteError.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2022-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PHONGO_WRITEERROR_H
+#define PHONGO_WRITEERROR_H
+
+#include "bson/bson.h"
+
+#include <php.h>
+
+zend_bool phongo_writeerror_init(zval* return_value, bson_t* bson);
+
+#endif /* PHONGO_WRITEERROR_H */
diff --git a/mongodb-1.13.0/src/MongoDB/WriteResult.c b/mongodb-1.13.0/src/MongoDB/WriteResult.c
new file mode 100644
index 00000000..759fa0b6
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/WriteResult.c
@@ -0,0 +1,493 @@
+/*
+ * Copyright 2014-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bson/bson.h"
+#include "mongoc/mongoc.h"
+
+#include <php.h>
+#include <Zend/zend_interfaces.h>
+
+#include "php_array_api.h"
+
+#include "php_phongo.h"
+#include "phongo_error.h"
+
+#include "MongoDB/Server.h"
+#include "MongoDB/WriteConcern.h"
+#include "MongoDB/WriteConcernError.h"
+#include "MongoDB/WriteError.h"
+
+#define PHONGO_WRITERESULT_RETURN_LONG_FROM_BSON_INT32(iter, bson, key) \
+ if (bson_iter_init_find((iter), (bson), (key)) && BSON_ITER_HOLDS_INT32((iter))) { \
+ RETURN_LONG(bson_iter_int32((iter))); \
+ }
+
+zend_class_entry* php_phongo_writeresult_ce;
+
+static bool php_phongo_writeresult_get_writeconcernerror(php_phongo_writeresult_t* intern, zval* return_value) /* {{{ */
+{
+ bson_iter_t iter, child;
+ zval writeconcernerror;
+
+ ZVAL_NULL(return_value);
+
+ if (bson_iter_init_find(&iter, intern->reply, "writeConcernErrors") && BSON_ITER_HOLDS_ARRAY(&iter) && bson_iter_recurse(&iter, &child)) {
+ while (bson_iter_next(&child)) {
+ bson_t cbson;
+ uint32_t len;
+ const uint8_t* data;
+
+ if (!BSON_ITER_HOLDS_DOCUMENT(&child)) {
+ continue;
+ }
+
+ bson_iter_document(&child, &len, &data);
+
+ if (!bson_init_static(&cbson, data, len)) {
+ continue;
+ }
+
+ if (!phongo_writeconcernerror_init(&writeconcernerror, &cbson)) {
+ zval_ptr_dtor(&writeconcernerror);
+ return false;
+ }
+
+ ZVAL_ZVAL(return_value, &writeconcernerror, 1, 1);
+
+ return true;
+ }
+ }
+
+ return true;
+} /* }}} */
+
+static bool php_phongo_writeresult_get_writeerrors(php_phongo_writeresult_t* intern, zval* return_value) /* {{{ */
+{
+ bson_iter_t iter, child;
+
+ array_init(return_value);
+
+ if (bson_iter_init_find(&iter, intern->reply, "writeErrors") && BSON_ITER_HOLDS_ARRAY(&iter) && bson_iter_recurse(&iter, &child)) {
+ while (bson_iter_next(&child)) {
+ bson_t cbson;
+ uint32_t len;
+ const uint8_t* data;
+ zval writeerror;
+
+ if (!BSON_ITER_HOLDS_DOCUMENT(&child)) {
+ continue;
+ }
+
+ bson_iter_document(&child, &len, &data);
+
+ if (!bson_init_static(&cbson, data, len)) {
+ continue;
+ }
+
+ if (!phongo_writeerror_init(&writeerror, &cbson)) {
+ zval_ptr_dtor(&writeerror);
+ continue;
+ }
+
+ add_next_index_zval(return_value, &writeerror);
+ }
+ }
+
+ return true;
+} /* }}} */
+
+/* {{{ proto integer|null MongoDB\Driver\WriteResult::getInsertedCount()
+ Returns the number of documents that were inserted */
+static PHP_METHOD(WriteResult, getInsertedCount)
+{
+ zend_error_handling error_handling;
+ bson_iter_t iter;
+ php_phongo_writeresult_t* intern;
+
+ intern = Z_WRITERESULT_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ PHONGO_WRITERESULT_RETURN_LONG_FROM_BSON_INT32(&iter, intern->reply, "nInserted");
+} /* }}} */
+
+/* {{{ proto integer|null MongoDB\Driver\WriteResult::getMatchedCount()
+ Returns the number of documents that matched the update criteria */
+static PHP_METHOD(WriteResult, getMatchedCount)
+{
+ zend_error_handling error_handling;
+ bson_iter_t iter;
+ php_phongo_writeresult_t* intern;
+
+ intern = Z_WRITERESULT_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ PHONGO_WRITERESULT_RETURN_LONG_FROM_BSON_INT32(&iter, intern->reply, "nMatched");
+} /* }}} */
+
+/* {{{ proto integer|null MongoDB\Driver\WriteResult::getModifiedCount()
+ Returns the number of documents that were actually modified by an update */
+static PHP_METHOD(WriteResult, getModifiedCount)
+{
+ zend_error_handling error_handling;
+ bson_iter_t iter;
+ php_phongo_writeresult_t* intern;
+
+ intern = Z_WRITERESULT_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ PHONGO_WRITERESULT_RETURN_LONG_FROM_BSON_INT32(&iter, intern->reply, "nModified");
+} /* }}} */
+
+/* {{{ proto integer|null MongoDB\Driver\WriteResult::getDeletedCount()
+ Returns the number of documents that were deleted */
+static PHP_METHOD(WriteResult, getDeletedCount)
+{
+ zend_error_handling error_handling;
+ bson_iter_t iter;
+ php_phongo_writeresult_t* intern;
+
+ intern = Z_WRITERESULT_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ PHONGO_WRITERESULT_RETURN_LONG_FROM_BSON_INT32(&iter, intern->reply, "nRemoved");
+} /* }}} */
+
+/* {{{ proto integer|null MongoDB\Driver\WriteResult::getUpsertedCount()
+ Returns the number of documents that were upserted */
+static PHP_METHOD(WriteResult, getUpsertedCount)
+{
+ zend_error_handling error_handling;
+ bson_iter_t iter;
+ php_phongo_writeresult_t* intern;
+
+ intern = Z_WRITERESULT_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ PHONGO_WRITERESULT_RETURN_LONG_FROM_BSON_INT32(&iter, intern->reply, "nUpserted");
+} /* }}} */
+
+/* {{{ proto MongoDB\Driver\Server MongoDB\Driver\WriteResult::getServer()
+ Returns the Server from which the result originated */
+static PHP_METHOD(WriteResult, getServer)
+{
+ zend_error_handling error_handling;
+ php_phongo_writeresult_t* intern;
+
+ intern = Z_WRITERESULT_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ phongo_server_init(return_value, &intern->manager, intern->server_id);
+} /* }}} */
+
+/* {{{ proto array MongoDB\Driver\WriteResult::getUpsertedIds()
+ Returns the identifiers generated by the server for upsert operations. */
+static PHP_METHOD(WriteResult, getUpsertedIds)
+{
+ zend_error_handling error_handling;
+ bson_iter_t iter, child;
+ php_phongo_writeresult_t* intern;
+
+ intern = Z_WRITERESULT_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ array_init(return_value);
+
+ if (bson_iter_init_find(&iter, intern->reply, "upserted") && BSON_ITER_HOLDS_ARRAY(&iter) && bson_iter_recurse(&iter, &child)) {
+ while (bson_iter_next(&child)) {
+ uint32_t data_len;
+ const uint8_t* data = NULL;
+ php_phongo_bson_state state;
+
+ /* Use PHONGO_TYPEMAP_NATIVE_ARRAY for the root type so we can
+ * easily access the "index" and "_id" fields. */
+ PHONGO_BSON_INIT_STATE(state);
+ state.map.root_type = PHONGO_TYPEMAP_NATIVE_ARRAY;
+
+ if (!BSON_ITER_HOLDS_DOCUMENT(&child)) {
+ continue;
+ }
+
+ bson_iter_document(&child, &data_len, &data);
+
+ if (php_phongo_bson_to_zval_ex(data, data_len, &state)) {
+ zval* zid = php_array_fetchc(&state.zchild, "_id");
+ add_index_zval(return_value, php_array_fetchc_long(&state.zchild, "index"), zid);
+ zval_add_ref(zid);
+ }
+
+ zval_ptr_dtor(&state.zchild);
+ }
+ }
+} /* }}} */
+
+/* {{{ proto WriteConcernError MongoDB\Driver\WriteResult::getWriteConcernError()
+ Return any write concern error that occurred */
+static PHP_METHOD(WriteResult, getWriteConcernError)
+{
+ zend_error_handling error_handling;
+ php_phongo_writeresult_t* intern;
+
+ intern = Z_WRITERESULT_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ php_phongo_writeresult_get_writeconcernerror(intern, return_value);
+} /* }}} */
+
+/* {{{ proto WriteError[] MongoDB\Driver\WriteResult::getWriteErrors()
+ Returns any write errors that occurred */
+static PHP_METHOD(WriteResult, getWriteErrors)
+{
+ zend_error_handling error_handling;
+ php_phongo_writeresult_t* intern;
+
+ intern = Z_WRITERESULT_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ php_phongo_writeresult_get_writeerrors(intern, return_value);
+} /* }}} */
+
+/* {{{ proto boolean MongoDB\Driver\WriteResult::isAcknowledged()
+ Returns whether the write operation was acknowledged (based on the write
+ concern). */
+static PHP_METHOD(WriteResult, isAcknowledged)
+{
+ zend_error_handling error_handling;
+ php_phongo_writeresult_t* intern;
+
+ intern = Z_WRITERESULT_OBJ_P(getThis());
+
+ zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling);
+ if (zend_parse_parameters_none() == FAILURE) {
+ zend_restore_error_handling(&error_handling);
+ return;
+ }
+ zend_restore_error_handling(&error_handling);
+
+ RETURN_BOOL(mongoc_write_concern_is_acknowledged(intern->write_concern));
+} /* }}} */
+
+/* {{{ MongoDB\Driver\WriteResult function entries */
+ZEND_BEGIN_ARG_INFO_EX(ai_WriteResult_void, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry php_phongo_writeresult_me[] = {
+ /* clang-format off */
+ PHP_ME(WriteResult, getInsertedCount, ai_WriteResult_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(WriteResult, getMatchedCount, ai_WriteResult_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(WriteResult, getModifiedCount, ai_WriteResult_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(WriteResult, getDeletedCount, ai_WriteResult_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(WriteResult, getUpsertedCount, ai_WriteResult_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(WriteResult, getServer, ai_WriteResult_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(WriteResult, getUpsertedIds, ai_WriteResult_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(WriteResult, getWriteConcernError, ai_WriteResult_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(WriteResult, getWriteErrors, ai_WriteResult_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_ME(WriteResult, isAcknowledged, ai_WriteResult_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ ZEND_NAMED_ME(__construct, PHP_FN(MongoDB_disabled___construct), ai_WriteResult_void, ZEND_ACC_PRIVATE | ZEND_ACC_FINAL)
+ ZEND_NAMED_ME(__wakeup, PHP_FN(MongoDB_disabled___wakeup), ai_WriteResult_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
+ PHP_FE_END
+ /* clang-format on */
+};
+/* }}} */
+
+/* {{{ MongoDB\Driver\WriteResult object handlers */
+static zend_object_handlers php_phongo_handler_writeresult;
+
+static void php_phongo_writeresult_free_object(zend_object* object) /* {{{ */
+{
+ php_phongo_writeresult_t* intern = Z_OBJ_WRITERESULT(object);
+
+ zend_object_std_dtor(&intern->std);
+
+ if (intern->reply) {
+ bson_destroy(intern->reply);
+ }
+
+ if (intern->write_concern) {
+ mongoc_write_concern_destroy(intern->write_concern);
+ }
+
+ if (!Z_ISUNDEF(intern->manager)) {
+ zval_ptr_dtor(&intern->manager);
+ }
+} /* }}} */
+
+static zend_object* php_phongo_writeresult_create_object(zend_class_entry* class_type) /* {{{ */
+{
+ php_phongo_writeresult_t* intern = zend_object_alloc(sizeof(php_phongo_writeresult_t), class_type);
+
+ zend_object_std_init(&intern->std, class_type);
+ object_properties_init(&intern->std, class_type);
+
+ intern->std.handlers = &php_phongo_handler_writeresult;
+
+ return &intern->std;
+} /* }}} */
+
+static HashTable* php_phongo_writeresult_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */
+{
+ php_phongo_writeresult_t* intern;
+ zval retval = ZVAL_STATIC_INIT;
+ bson_iter_t iter;
+
+ intern = Z_OBJ_WRITERESULT(PHONGO_COMPAT_GET_OBJ(object));
+ *is_temp = 1;
+ array_init_size(&retval, 9);
+
+#define PHONGO_WRITERESULT_SCP(field) \
+ if (bson_iter_init_find(&iter, intern->reply, (field)) && BSON_ITER_HOLDS_INT32(&iter)) { \
+ ADD_ASSOC_LONG_EX(&retval, (field), bson_iter_int32(&iter)); \
+ } else { \
+ ADD_ASSOC_NULL_EX(&retval, (field)); \
+ }
+
+ PHONGO_WRITERESULT_SCP("nInserted");
+ PHONGO_WRITERESULT_SCP("nMatched");
+ PHONGO_WRITERESULT_SCP("nModified");
+ PHONGO_WRITERESULT_SCP("nRemoved");
+ PHONGO_WRITERESULT_SCP("nUpserted");
+#undef PHONGO_WRITERESULT_SCP
+
+ if (bson_iter_init_find(&iter, intern->reply, "upserted") && BSON_ITER_HOLDS_ARRAY(&iter)) {
+ uint32_t len;
+ const uint8_t* data;
+ php_phongo_bson_state state;
+
+ PHONGO_BSON_INIT_DEBUG_STATE(state);
+ bson_iter_array(&iter, &len, &data);
+ if (!php_phongo_bson_to_zval_ex(data, len, &state)) {
+ zval_ptr_dtor(&state.zchild);
+ goto done;
+ }
+
+ ADD_ASSOC_ZVAL_EX(&retval, "upsertedIds", &state.zchild);
+ } else {
+ zval upsertedIds;
+ array_init(&upsertedIds);
+ ADD_ASSOC_ZVAL_EX(&retval, "upsertedIds", &upsertedIds);
+ }
+
+ {
+ zval writeerrors;
+
+ php_phongo_writeresult_get_writeerrors(intern, &writeerrors);
+ ADD_ASSOC_ZVAL_EX(&retval, "writeErrors", &writeerrors);
+ }
+
+ {
+ zval writeconcernerror;
+
+ php_phongo_writeresult_get_writeconcernerror(intern, &writeconcernerror);
+ ADD_ASSOC_ZVAL_EX(&retval, "writeConcernError", &writeconcernerror);
+ }
+
+ if (intern->write_concern) {
+ zval write_concern;
+
+ phongo_writeconcern_init(&write_concern, intern->write_concern);
+ ADD_ASSOC_ZVAL_EX(&retval, "writeConcern", &write_concern);
+ } else {
+ ADD_ASSOC_NULL_EX(&retval, "writeConcern");
+ }
+
+done:
+ return Z_ARRVAL(retval);
+} /* }}} */
+/* }}} */
+
+void php_phongo_writeresult_init_ce(INIT_FUNC_ARGS) /* {{{ */
+{
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver", "WriteResult", php_phongo_writeresult_me);
+ php_phongo_writeresult_ce = zend_register_internal_class(&ce);
+ php_phongo_writeresult_ce->create_object = php_phongo_writeresult_create_object;
+ PHONGO_CE_FINAL(php_phongo_writeresult_ce);
+ PHONGO_CE_DISABLE_SERIALIZATION(php_phongo_writeresult_ce);
+
+ memcpy(&php_phongo_handler_writeresult, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
+ php_phongo_handler_writeresult.get_debug_info = php_phongo_writeresult_get_debug_info;
+ php_phongo_handler_writeresult.free_obj = php_phongo_writeresult_free_object;
+ php_phongo_handler_writeresult.offset = XtOffsetOf(php_phongo_writeresult_t, std);
+} /* }}} */
+
+php_phongo_writeresult_t* phongo_writeresult_init(zval* return_value, bson_t* reply, zval* manager, uint32_t server_id) /* {{{ */
+{
+ php_phongo_writeresult_t* writeresult;
+
+ object_init_ex(return_value, php_phongo_writeresult_ce);
+
+ writeresult = Z_WRITERESULT_OBJ_P(return_value);
+ writeresult->reply = bson_copy(reply);
+ writeresult->server_id = server_id;
+
+ ZVAL_ZVAL(&writeresult->manager, manager, 1, 0);
+
+ return writeresult;
+} /* }}} */
diff --git a/mongodb-1.13.0/src/MongoDB/WriteResult.h b/mongodb-1.13.0/src/MongoDB/WriteResult.h
new file mode 100644
index 00000000..1a7acd9f
--- /dev/null
+++ b/mongodb-1.13.0/src/MongoDB/WriteResult.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2022-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PHONGO_WRITERESULT_H
+#define PHONGO_WRITERESULT_H
+
+#include "bson/bson.h"
+
+#include <php.h>
+
+php_phongo_writeresult_t* phongo_writeresult_init(zval* return_value, bson_t* reply, zval* manager, uint32_t server_id);
+
+#endif /* PHONGO_WRITERESULT_H */
diff --git a/mongodb-1.12.0/src/contrib/php_array_api.h b/mongodb-1.13.0/src/contrib/php_array_api.h
similarity index 100%
rename from mongodb-1.12.0/src/contrib/php_array_api.h
rename to mongodb-1.13.0/src/contrib/php_array_api.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/common/common-b64-private.h b/mongodb-1.13.0/src/libmongoc/src/common/common-b64-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/common/common-b64-private.h
rename to mongodb-1.13.0/src/libmongoc/src/common/common-b64-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/common/common-b64.c b/mongodb-1.13.0/src/libmongoc/src/common/common-b64.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/common/common-b64.c
rename to mongodb-1.13.0/src/libmongoc/src/common/common-b64.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/common/common-config.h b/mongodb-1.13.0/src/libmongoc/src/common/common-config.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/common/common-config.h
rename to mongodb-1.13.0/src/libmongoc/src/common/common-config.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/common/common-config.h.in b/mongodb-1.13.0/src/libmongoc/src/common/common-config.h.in
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/common/common-config.h.in
rename to mongodb-1.13.0/src/libmongoc/src/common/common-config.h.in
diff --git a/mongodb-1.12.0/src/libmongoc/src/common/common-macros-private.h b/mongodb-1.13.0/src/libmongoc/src/common/common-macros-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/common/common-macros-private.h
rename to mongodb-1.13.0/src/libmongoc/src/common/common-macros-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/common/common-md5-private.h b/mongodb-1.13.0/src/libmongoc/src/common/common-md5-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/common/common-md5-private.h
rename to mongodb-1.13.0/src/libmongoc/src/common/common-md5-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/common/common-md5.c b/mongodb-1.13.0/src/libmongoc/src/common/common-md5.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/common/common-md5.c
rename to mongodb-1.13.0/src/libmongoc/src/common/common-md5.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/common/common-prelude.h b/mongodb-1.13.0/src/libmongoc/src/common/common-prelude.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/common/common-prelude.h
rename to mongodb-1.13.0/src/libmongoc/src/common/common-prelude.h
diff --git a/mongodb-1.13.0/src/libmongoc/src/common/common-thread-private.h b/mongodb-1.13.0/src/libmongoc/src/common/common-thread-private.h
new file mode 100644
index 00000000..c0740520
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongoc/src/common/common-thread-private.h
@@ -0,0 +1,183 @@
+/*
+ * Copyright 2013-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "common-prelude.h"
+#include "common-config.h"
+#include "common-macros-private.h"
+
+#ifndef COMMON_THREAD_PRIVATE_H
+#define COMMON_THREAD_PRIVATE_H
+
+#define BSON_INSIDE
+#include "bson/bson-compat.h"
+#include "bson/bson-config.h"
+#include "bson/bson-macros.h"
+#undef BSON_INSIDE
+
+BSON_BEGIN_DECLS
+
+#if defined(BSON_OS_UNIX)
+#include <pthread.h>
+
+#define BSON_ONCE_FUN(n) void n (void)
+#define BSON_ONCE_RETURN return
+#define BSON_ONCE_INIT PTHREAD_ONCE_INIT
+#define bson_once pthread_once
+#define bson_once_t pthread_once_t
+#define bson_thread_t pthread_t
+#define BSON_THREAD_FUN(_function_name, _arg_name) \
+ void *(_function_name) (void *(_arg_name))
+#define BSON_THREAD_FUN_TYPE(_function_name) void *(*(_function_name)) (void *)
+#define BSON_THREAD_RETURN return NULL
+
+/* this macro can be defined as a as a build configuration option
+ * with -DENABLE_DEBUG_ASSERTIONS=ON. its purpose is to allow for functions
+ * that require a mutex to be locked on entry to assert that the mutex
+ * is actually locked.
+ * this can prevent bugs where a caller forgets to lock the mutex. */
+
+#ifndef MONGOC_ENABLE_DEBUG_ASSERTIONS
+
+#define bson_mutex_destroy pthread_mutex_destroy
+#define bson_mutex_init(_n) pthread_mutex_init ((_n), NULL)
+#define bson_mutex_lock pthread_mutex_lock
+#define bson_mutex_t pthread_mutex_t
+#define bson_mutex_unlock pthread_mutex_unlock
+
+#else
+typedef struct {
+ pthread_t lock_owner;
+ pthread_mutex_t wrapped_mutex;
+ bool valid_tid;
+} bson_mutex_t;
+
+#define bson_mutex_destroy(mutex) \
+ do { \
+ pthread_mutex_destroy (&(mutex)->wrapped_mutex); \
+ } while (0);
+
+#define bson_mutex_init(mutex) \
+ do { \
+ pthread_mutex_init (&(mutex)->wrapped_mutex, NULL); \
+ (mutex)->valid_tid = false; \
+ } while (0);
+
+#define bson_mutex_lock(mutex) \
+ do { \
+ pthread_mutex_lock (&(mutex)->wrapped_mutex); \
+ (mutex)->lock_owner = pthread_self (); \
+ (mutex)->valid_tid = true; \
+ } while (0);
+
+#define bson_mutex_unlock(mutex) \
+ do { \
+ (mutex)->valid_tid = false; \
+ pthread_mutex_unlock (&(mutex)->wrapped_mutex); \
+ } while (0);
+
+#endif
+
+#else
+#include <process.h>
+#define BSON_ONCE_FUN(n) \
+ BOOL CALLBACK n (PINIT_ONCE _ignored_a, PVOID _ignored_b, PVOID *_ignored_c)
+#define BSON_ONCE_INIT INIT_ONCE_STATIC_INIT
+#define BSON_ONCE_RETURN return true
+#define bson_mutex_destroy DeleteCriticalSection
+#define bson_mutex_init InitializeCriticalSection
+#define bson_mutex_lock EnterCriticalSection
+#define bson_mutex_t CRITICAL_SECTION
+#define bson_mutex_unlock LeaveCriticalSection
+#define bson_once(o, c) InitOnceExecuteOnce (o, c, NULL, NULL)
+#define bson_once_t INIT_ONCE
+#define bson_thread_t HANDLE
+#define BSON_THREAD_FUN(_function_name, _arg_name) \
+ unsigned (__stdcall _function_name) (void *(_arg_name))
+#define BSON_THREAD_FUN_TYPE(_function_name) \
+ unsigned(__stdcall * _function_name) (void *)
+#define BSON_THREAD_RETURN return 0
+#endif
+
+/* Functions that require definitions get the common prefix (_mongoc for
+ * libmongoc or _bson for libbson) to avoid duplicate symbols when linking both
+ * libbson and libmongoc statically. */
+int COMMON_PREFIX (thread_join) (bson_thread_t thread);
+int COMMON_PREFIX (thread_create) (bson_thread_t *thread,
+ BSON_THREAD_FUN_TYPE (func),
+ void *arg);
+
+#if defined(MONGOC_ENABLE_DEBUG_ASSERTIONS) && defined(BSON_OS_UNIX)
+bool COMMON_PREFIX (mutex_is_locked) (bson_mutex_t *mutex);
+#endif
+
+/**
+ * @brief A shared mutex (a read-write lock)
+ *
+ * A shared mutex can be locked in 'shared' mode or 'exclusive' mode. Only one
+ * thread may hold exclusive mode at a time. Any number of threads may hold
+ * the lock in shared mode simultaneously. No thread can hold in exclusive mode
+ * while another thread holds in shared mode, and vice-versa.
+ */
+typedef struct bson_shared_mutex_t {
+ BSON_IF_WINDOWS (SRWLOCK native;)
+ BSON_IF_POSIX (pthread_rwlock_t native;)
+} bson_shared_mutex_t;
+
+static BSON_INLINE void
+bson_shared_mutex_init (bson_shared_mutex_t *mtx)
+{
+ BSON_IF_WINDOWS (InitializeSRWLock (&mtx->native));
+ BSON_IF_POSIX (pthread_rwlock_init (&mtx->native, NULL));
+}
+
+static BSON_INLINE void
+bson_shared_mutex_destroy (bson_shared_mutex_t *mtx)
+{
+ BSON_IF_WINDOWS ((void) mtx;)
+ BSON_IF_POSIX (pthread_rwlock_destroy (&mtx->native);)
+}
+
+static BSON_INLINE void
+bson_shared_mutex_lock_shared (bson_shared_mutex_t *mtx)
+{
+ BSON_IF_WINDOWS (AcquireSRWLockShared (&mtx->native);)
+ BSON_IF_POSIX (pthread_rwlock_rdlock (&mtx->native);)
+}
+
+static BSON_INLINE void
+bson_shared_mutex_lock (bson_shared_mutex_t *mtx)
+{
+ BSON_IF_WINDOWS (AcquireSRWLockExclusive (&mtx->native);)
+ BSON_IF_POSIX (pthread_rwlock_wrlock (&mtx->native);)
+}
+
+static BSON_INLINE void
+bson_shared_mutex_unlock (bson_shared_mutex_t *mtx)
+{
+ BSON_IF_WINDOWS (ReleaseSRWLockExclusive (&mtx->native);)
+ BSON_IF_POSIX (pthread_rwlock_unlock (&mtx->native);)
+}
+
+static BSON_INLINE void
+bson_shared_mutex_unlock_shared (bson_shared_mutex_t *mtx)
+{
+ BSON_IF_WINDOWS (ReleaseSRWLockShared (&mtx->native);)
+ BSON_IF_POSIX (pthread_rwlock_unlock (&mtx->native);)
+}
+
+BSON_END_DECLS
+
+#endif /* COMMON_THREAD_PRIVATE_H */
diff --git a/mongodb-1.12.0/src/libmongoc/src/common/common-thread.c b/mongodb-1.13.0/src/libmongoc/src/common/common-thread.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/common/common-thread.c
rename to mongodb-1.13.0/src/libmongoc/src/common/common-thread.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/kms-message/src/hexlify.c b/mongodb-1.13.0/src/libmongoc/src/kms-message/src/hexlify.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/kms-message/src/hexlify.c
rename to mongodb-1.13.0/src/libmongoc/src/kms-message/src/hexlify.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/kms-message/src/hexlify.h b/mongodb-1.13.0/src/libmongoc/src/kms-message/src/hexlify.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/kms-message/src/hexlify.h
rename to mongodb-1.13.0/src/libmongoc/src/kms-message/src/hexlify.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_b64.c b/mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_b64.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_b64.c
rename to mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_b64.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_caller_identity_request.c b/mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_caller_identity_request.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_caller_identity_request.c
rename to mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_caller_identity_request.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_crypto.h b/mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_crypto.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_crypto.h
rename to mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_crypto.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_crypto_apple.c b/mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_crypto_apple.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_crypto_apple.c
rename to mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_crypto_apple.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_crypto_libcrypto.c b/mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_crypto_libcrypto.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_crypto_libcrypto.c
rename to mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_crypto_libcrypto.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_crypto_none.c b/mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_crypto_none.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_crypto_none.c
rename to mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_crypto_none.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_crypto_windows.c b/mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_crypto_windows.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_crypto_windows.c
rename to mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_crypto_windows.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_decrypt_request.c b/mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_decrypt_request.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_decrypt_request.c
rename to mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_decrypt_request.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_encrypt_request.c b/mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_encrypt_request.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_encrypt_request.c
rename to mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_encrypt_request.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_kv_list.c b/mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_kv_list.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_kv_list.c
rename to mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_kv_list.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_kv_list.h b/mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_kv_list.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_kv_list.h
rename to mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_kv_list.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_message.c b/mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_message.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_message.c
rename to mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_message.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_message/kms_b64.h b/mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_message/kms_b64.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_message/kms_b64.h
rename to mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_message/kms_b64.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_message/kms_caller_identity_request.h b/mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_message/kms_caller_identity_request.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_message/kms_caller_identity_request.h
rename to mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_message/kms_caller_identity_request.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_message/kms_decrypt_request.h b/mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_message/kms_decrypt_request.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_message/kms_decrypt_request.h
rename to mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_message/kms_decrypt_request.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_message/kms_encrypt_request.h b/mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_message/kms_encrypt_request.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_message/kms_encrypt_request.h
rename to mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_message/kms_encrypt_request.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_message/kms_message.h b/mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_message/kms_message.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_message/kms_message.h
rename to mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_message/kms_message.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_message/kms_message_defines.h b/mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_message/kms_message_defines.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_message/kms_message_defines.h
rename to mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_message/kms_message_defines.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_message/kms_request.h b/mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_message/kms_request.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_message/kms_request.h
rename to mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_message/kms_request.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_message/kms_request_opt.h b/mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_message/kms_request_opt.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_message/kms_request_opt.h
rename to mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_message/kms_request_opt.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_message/kms_response.h b/mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_message/kms_response.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_message/kms_response.h
rename to mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_message/kms_response.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_message/kms_response_parser.h b/mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_message/kms_response_parser.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_message/kms_response_parser.h
rename to mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_message/kms_response_parser.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_message_private.h b/mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_message_private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_message_private.h
rename to mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_message_private.h
diff --git a/mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_port.c b/mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_port.c
new file mode 100644
index 00000000..af9ea822
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_port.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2020-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "kms_port.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#if defined(_WIN32)
+char *
+kms_strndup (const char *src, size_t len)
+{
+ char *dst = (char *) malloc (len + 1);
+ if (!dst) {
+ return 0;
+ }
+
+ memcpy (dst, src, len);
+ dst[len] = '\0';
+
+ return dst;
+}
+#endif
\ No newline at end of file
diff --git a/mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_port.h b/mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_port.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_port.h
rename to mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_port.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_request.c b/mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_request.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_request.c
rename to mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_request.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_request_opt.c b/mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_request_opt.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_request_opt.c
rename to mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_request_opt.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_request_opt_private.h b/mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_request_opt_private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_request_opt_private.h
rename to mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_request_opt_private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_request_str.c b/mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_request_str.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_request_str.c
rename to mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_request_str.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_request_str.h b/mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_request_str.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_request_str.h
rename to mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_request_str.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_response.c b/mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_response.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_response.c
rename to mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_response.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_response_parser.c b/mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_response_parser.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/kms-message/src/kms_response_parser.c
rename to mongodb-1.13.0/src/libmongoc/src/kms-message/src/kms_response_parser.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/kms-message/src/sort.c b/mongodb-1.13.0/src/libmongoc/src/kms-message/src/sort.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/kms-message/src/sort.c
rename to mongodb-1.13.0/src/libmongoc/src/kms-message/src/sort.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/kms-message/src/sort.h b/mongodb-1.13.0/src/libmongoc/src/kms-message/src/sort.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/kms-message/src/sort.h
rename to mongodb-1.13.0/src/libmongoc/src/kms-message/src/sort.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bcon.c b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bcon.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bcon.c
rename to mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bcon.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bcon.h b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bcon.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bcon.h
rename to mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bcon.h
diff --git a/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-atomic.c b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-atomic.c
new file mode 100644
index 00000000..0531c9fb
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-atomic.c
@@ -0,0 +1,260 @@
+/*
+ * Copyright 2014 MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include "bson-atomic.h"
+
+#ifdef BSON_OS_UNIX
+/* For sched_yield() */
+#include <sched.h>
+#endif
+
+int32_t
+bson_atomic_int_add (volatile int32_t *p, int32_t n)
+{
+ return n + bson_atomic_int32_fetch_add (p, n, bson_memory_order_seq_cst);
+}
+
+int64_t
+bson_atomic_int64_add (volatile int64_t *p, int64_t n)
+{
+ return n + bson_atomic_int64_fetch_add (p, n, bson_memory_order_seq_cst);
+}
+
+void
+bson_thrd_yield (void)
+{
+ BSON_IF_WINDOWS (SwitchToThread ();)
+ BSON_IF_POSIX (sched_yield ();)
+}
+
+void
+bson_memory_barrier (void)
+{
+ bson_atomic_thread_fence ();
+}
+
+/**
+ * Some platforms do not support compiler intrinsics for atomic operations.
+ * We emulate that here using a spin lock and regular arithmetic operations
+ */
+static int8_t gEmulAtomicLock = 0;
+
+static void
+_lock_emul_atomic ()
+{
+ int i;
+ if (bson_atomic_int8_compare_exchange_weak (
+ &gEmulAtomicLock, 0, 1, bson_memory_order_acquire) == 0) {
+ /* Successfully took the spinlock */
+ return;
+ }
+ /* Failed. Try taking ten more times, then begin sleeping. */
+ for (i = 0; i < 10; ++i) {
+ if (bson_atomic_int8_compare_exchange_weak (
+ &gEmulAtomicLock, 0, 1, bson_memory_order_acquire) == 0) {
+ /* Succeeded in taking the lock */
+ return;
+ }
+ }
+ /* Still don't have the lock. Spin and yield */
+ while (bson_atomic_int8_compare_exchange_weak (
+ &gEmulAtomicLock, 0, 1, bson_memory_order_acquire) != 0) {
+ bson_thrd_yield ();
+ }
+}
+
+static void
+_unlock_emul_atomic ()
+{
+ int64_t rv = bson_atomic_int8_exchange (
+ &gEmulAtomicLock, 0, bson_memory_order_release);
+ BSON_ASSERT (rv == 1 && "Released atomic lock while not holding it");
+}
+
+int64_t
+_bson_emul_atomic_int64_fetch_add (volatile int64_t *p,
+ int64_t n,
+ enum bson_memory_order _unused)
+{
+ int64_t ret;
+ _lock_emul_atomic ();
+ ret = *p;
+ *p += n;
+ _unlock_emul_atomic ();
+ return ret;
+}
+
+int64_t
+_bson_emul_atomic_int64_exchange (volatile int64_t *p,
+ int64_t n,
+ enum bson_memory_order _unused)
+{
+ int64_t ret;
+ _lock_emul_atomic ();
+ ret = *p;
+ *p = n;
+ _unlock_emul_atomic ();
+ return ret;
+}
+
+int64_t
+_bson_emul_atomic_int64_compare_exchange_strong (volatile int64_t *p,
+ int64_t expect_value,
+ int64_t new_value,
+ enum bson_memory_order _unused)
+{
+ int64_t ret;
+ _lock_emul_atomic ();
+ ret = *p;
+ if (ret == expect_value) {
+ *p = new_value;
+ }
+ _unlock_emul_atomic ();
+ return ret;
+}
+
+int64_t
+_bson_emul_atomic_int64_compare_exchange_weak (volatile int64_t *p,
+ int64_t expect_value,
+ int64_t new_value,
+ enum bson_memory_order order)
+{
+ /* We're emulating. We can't do a weak version. */
+ return _bson_emul_atomic_int64_compare_exchange_strong (
+ p, expect_value, new_value, order);
+}
+
+
+int32_t
+_bson_emul_atomic_int32_fetch_add (volatile int32_t *p,
+ int32_t n,
+ enum bson_memory_order _unused)
+{
+ int32_t ret;
+ _lock_emul_atomic ();
+ ret = *p;
+ *p += n;
+ _unlock_emul_atomic ();
+ return ret;
+}
+
+int32_t
+_bson_emul_atomic_int32_exchange (volatile int32_t *p,
+ int32_t n,
+ enum bson_memory_order _unused)
+{
+ int32_t ret;
+ _lock_emul_atomic ();
+ ret = *p;
+ *p = n;
+ _unlock_emul_atomic ();
+ return ret;
+}
+
+int32_t
+_bson_emul_atomic_int32_compare_exchange_strong (volatile int32_t *p,
+ int32_t expect_value,
+ int32_t new_value,
+ enum bson_memory_order _unused)
+{
+ int32_t ret;
+ _lock_emul_atomic ();
+ ret = *p;
+ if (ret == expect_value) {
+ *p = new_value;
+ }
+ _unlock_emul_atomic ();
+ return ret;
+}
+
+int32_t
+_bson_emul_atomic_int32_compare_exchange_weak (volatile int32_t *p,
+ int32_t expect_value,
+ int32_t new_value,
+ enum bson_memory_order order)
+{
+ /* We're emulating. We can't do a weak version. */
+ return _bson_emul_atomic_int32_compare_exchange_strong (
+ p, expect_value, new_value, order);
+}
+
+
+int
+_bson_emul_atomic_int_fetch_add (volatile int *p,
+ int n,
+ enum bson_memory_order _unused)
+{
+ int ret;
+ _lock_emul_atomic ();
+ ret = *p;
+ *p += n;
+ _unlock_emul_atomic ();
+ return ret;
+}
+
+int
+_bson_emul_atomic_int_exchange (volatile int *p,
+ int n,
+ enum bson_memory_order _unused)
+{
+ int ret;
+ _lock_emul_atomic ();
+ ret = *p;
+ *p = n;
+ _unlock_emul_atomic ();
+ return ret;
+}
+
+int
+_bson_emul_atomic_int_compare_exchange_strong (volatile int *p,
+ int expect_value,
+ int new_value,
+ enum bson_memory_order _unused)
+{
+ int ret;
+ _lock_emul_atomic ();
+ ret = *p;
+ if (ret == expect_value) {
+ *p = new_value;
+ }
+ _unlock_emul_atomic ();
+ return ret;
+}
+
+int
+_bson_emul_atomic_int_compare_exchange_weak (volatile int *p,
+ int expect_value,
+ int new_value,
+ enum bson_memory_order order)
+{
+ /* We're emulating. We can't do a weak version. */
+ return _bson_emul_atomic_int_compare_exchange_strong (
+ p, expect_value, new_value, order);
+}
+
+void *
+_bson_emul_atomic_ptr_exchange (void *volatile *p,
+ void *n,
+ enum bson_memory_order _unused)
+{
+ void *ret;
+ _lock_emul_atomic ();
+ ret = *p;
+ *p = n;
+ _unlock_emul_atomic ();
+ return ret;
+}
diff --git a/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-atomic.h b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-atomic.h
new file mode 100644
index 00000000..845fe342
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-atomic.h
@@ -0,0 +1,774 @@
+/*
+ * Copyright 2013-2014 MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bson-prelude.h"
+
+
+#ifndef BSON_ATOMIC_H
+#define BSON_ATOMIC_H
+
+
+#include "bson-config.h"
+#include "bson-compat.h"
+#include "bson-macros.h"
+
+#ifdef _MSC_VER
+#include <intrin.h>
+#endif
+
+
+BSON_BEGIN_DECLS
+
+enum bson_memory_order {
+ bson_memory_order_seq_cst,
+ bson_memory_order_acquire,
+ bson_memory_order_release,
+ bson_memory_order_relaxed,
+ bson_memory_order_acq_rel,
+ bson_memory_order_consume,
+};
+
+#if defined(_M_ARM) /* MSVC memorder atomics are only avail on ARM */
+#define MSVC_MEMORDER_SUFFIX(X) X
+#else
+#define MSVC_MEMORDER_SUFFIX(X)
+#endif
+
+#if defined(USE_LEGACY_GCC_ATOMICS) || (!defined(__clang__) && __GNUC__ == 4)
+#define BSON_USE_LEGACY_GCC_ATOMICS
+#else
+#undef BSON_USE_LEGACY_GCC_ATOMICS
+#endif
+
+/* Not all GCC-like compilers support the current __atomic built-ins. Older
+ * GCC (pre-5) used different built-ins named with the __sync prefix. When
+ * compiling with such older GCC versions, it is necessary to use the applicable
+ * functions, which requires redefining BSON_IF_GNU_LIKE and defining the
+ * additional BSON_IF_GNU_LEGACY_ATOMICS macro here. */
+#ifdef BSON_USE_LEGACY_GCC_ATOMICS
+#undef BSON_IF_GNU_LIKE
+#define BSON_IF_GNU_LIKE(...)
+#define BSON_IF_GNU_LEGACY_ATOMICS(...) __VA_ARGS__
+#else
+#define BSON_IF_GNU_LEGACY_ATOMICS(...)
+#endif
+
+/* CDRIVER-4229 zSeries with gcc 4.8.4 produces illegal instructions for int and
+ * int32 atomic intrinsics. */
+#if defined(__s390__) || defined(__s390x__) || defined(__zarch__)
+#define BSON_EMULATE_INT32
+#define BSON_EMULATE_INT
+#endif
+
+/* CDRIVER-4264 Contrary to documentation, VS 2013 targeting x86 does not
+ * correctly/consistently provide _InterlockedPointerExchange. */
+#if defined(_MSC_VER) && _MSC_VER < 1900 && defined(_M_IX86)
+#define BSON_EMULATE_PTR
+#endif
+
+#define DEF_ATOMIC_OP( \
+ MSVC_Intrinsic, GNU_Intrinsic, GNU_Legacy_Intrinsic, Order, ...) \
+ do { \
+ switch (Order) { \
+ case bson_memory_order_acq_rel: \
+ BSON_IF_MSVC (return MSVC_Intrinsic (__VA_ARGS__);) \
+ BSON_IF_GNU_LIKE ( \
+ return GNU_Intrinsic (__VA_ARGS__, __ATOMIC_ACQ_REL);) \
+ BSON_IF_GNU_LEGACY_ATOMICS ( \
+ return GNU_Legacy_Intrinsic (__VA_ARGS__);) \
+ case bson_memory_order_seq_cst: \
+ BSON_IF_MSVC (return MSVC_Intrinsic (__VA_ARGS__);) \
+ BSON_IF_GNU_LIKE ( \
+ return GNU_Intrinsic (__VA_ARGS__, __ATOMIC_SEQ_CST);) \
+ BSON_IF_GNU_LEGACY_ATOMICS ( \
+ return GNU_Legacy_Intrinsic (__VA_ARGS__);) \
+ case bson_memory_order_acquire: \
+ BSON_IF_MSVC ( \
+ return BSON_CONCAT (MSVC_Intrinsic, \
+ MSVC_MEMORDER_SUFFIX (_acq)) (__VA_ARGS__);) \
+ BSON_IF_GNU_LIKE ( \
+ return GNU_Intrinsic (__VA_ARGS__, __ATOMIC_ACQUIRE);) \
+ BSON_IF_GNU_LEGACY_ATOMICS ( \
+ return GNU_Legacy_Intrinsic (__VA_ARGS__);) \
+ case bson_memory_order_consume: \
+ BSON_IF_MSVC ( \
+ return BSON_CONCAT (MSVC_Intrinsic, \
+ MSVC_MEMORDER_SUFFIX (_acq)) (__VA_ARGS__);) \
+ BSON_IF_GNU_LIKE ( \
+ return GNU_Intrinsic (__VA_ARGS__, __ATOMIC_CONSUME);) \
+ BSON_IF_GNU_LEGACY_ATOMICS ( \
+ return GNU_Legacy_Intrinsic (__VA_ARGS__);) \
+ case bson_memory_order_release: \
+ BSON_IF_MSVC ( \
+ return BSON_CONCAT (MSVC_Intrinsic, \
+ MSVC_MEMORDER_SUFFIX (_rel)) (__VA_ARGS__);) \
+ BSON_IF_GNU_LIKE ( \
+ return GNU_Intrinsic (__VA_ARGS__, __ATOMIC_RELEASE);) \
+ BSON_IF_GNU_LEGACY_ATOMICS ( \
+ return GNU_Legacy_Intrinsic (__VA_ARGS__);) \
+ case bson_memory_order_relaxed: \
+ BSON_IF_MSVC ( \
+ return BSON_CONCAT (MSVC_Intrinsic, \
+ MSVC_MEMORDER_SUFFIX (_nf)) (__VA_ARGS__);) \
+ BSON_IF_GNU_LIKE ( \
+ return GNU_Intrinsic (__VA_ARGS__, __ATOMIC_RELAXED);) \
+ BSON_IF_GNU_LEGACY_ATOMICS ( \
+ return GNU_Legacy_Intrinsic (__VA_ARGS__);) \
+ default: \
+ BSON_UNREACHABLE ("Invalid bson_memory_order value"); \
+ } \
+ } while (0)
+
+
+#define DEF_ATOMIC_CMPEXCH_STRONG( \
+ VCSuffix1, VCSuffix2, GNU_MemOrder, Ptr, ExpectActualVar, NewValue) \
+ do { \
+ BSON_IF_MSVC (ExpectActualVar = BSON_CONCAT3 ( \
+ _InterlockedCompareExchange, VCSuffix1, VCSuffix2) ( \
+ Ptr, NewValue, ExpectActualVar);) \
+ BSON_IF_GNU_LIKE ( \
+ (void) __atomic_compare_exchange_n (Ptr, \
+ &ExpectActualVar, \
+ NewValue, \
+ false, /* Not weak */ \
+ GNU_MemOrder, \
+ GNU_MemOrder);) \
+ BSON_IF_GNU_LEGACY_ATOMICS ( \
+ __typeof__ (ExpectActualVar) _val; \
+ _val = __sync_val_compare_and_swap (Ptr, ExpectActualVar, NewValue); \
+ ExpectActualVar = _val;) \
+ } while (0)
+
+
+#define DEF_ATOMIC_CMPEXCH_WEAK( \
+ VCSuffix1, VCSuffix2, GNU_MemOrder, Ptr, ExpectActualVar, NewValue) \
+ do { \
+ BSON_IF_MSVC (ExpectActualVar = BSON_CONCAT3 ( \
+ _InterlockedCompareExchange, VCSuffix1, VCSuffix2) ( \
+ Ptr, NewValue, ExpectActualVar);) \
+ BSON_IF_GNU_LIKE ( \
+ (void) __atomic_compare_exchange_n (Ptr, \
+ &ExpectActualVar, \
+ NewValue, \
+ true, /* Yes weak */ \
+ GNU_MemOrder, \
+ GNU_MemOrder);) \
+ BSON_IF_GNU_LEGACY_ATOMICS ( \
+ __typeof__ (ExpectActualVar) _val; \
+ _val = __sync_val_compare_and_swap (Ptr, ExpectActualVar, NewValue); \
+ ExpectActualVar = _val;) \
+ } while (0)
+
+
+#define DECL_ATOMIC_INTEGRAL(NamePart, Type, VCIntrinSuffix) \
+ static BSON_INLINE Type bson_atomic_##NamePart##_fetch_add ( \
+ Type volatile *a, Type addend, enum bson_memory_order ord) \
+ { \
+ DEF_ATOMIC_OP (BSON_CONCAT (_InterlockedExchangeAdd, VCIntrinSuffix), \
+ __atomic_fetch_add, \
+ __sync_fetch_and_add, \
+ ord, \
+ a, \
+ addend); \
+ } \
+ \
+ static BSON_INLINE Type bson_atomic_##NamePart##_fetch_sub ( \
+ Type volatile *a, Type subtrahend, enum bson_memory_order ord) \
+ { \
+ /* MSVC doesn't have a subtract intrinsic, so just reuse addition */ \
+ BSON_IF_MSVC ( \
+ return bson_atomic_##NamePart##_fetch_add (a, -subtrahend, ord);) \
+ BSON_IF_GNU_LIKE ( \
+ DEF_ATOMIC_OP (~, __atomic_fetch_sub, ~, ord, a, subtrahend);) \
+ BSON_IF_GNU_LEGACY_ATOMICS ( \
+ DEF_ATOMIC_OP (~, ~, __sync_fetch_and_sub, ord, a, subtrahend);) \
+ } \
+ \
+ static BSON_INLINE Type bson_atomic_##NamePart##_fetch ( \
+ Type volatile const *a, enum bson_memory_order order) \
+ { \
+ /* MSVC doesn't have a load intrinsic, so just add zero */ \
+ BSON_IF_MSVC (return bson_atomic_##NamePart##_fetch_add ( \
+ (Type volatile *) a, 0, order);) \
+ /* GNU doesn't want RELEASE order for the fetch operation, so we can't \
+ * just use DEF_ATOMIC_OP. */ \
+ BSON_IF_GNU_LIKE (switch (order) { \
+ case bson_memory_order_release: /* Fall back to seqcst */ \
+ case bson_memory_order_acq_rel: /* Fall back to seqcst */ \
+ case bson_memory_order_seq_cst: \
+ return __atomic_load_n (a, __ATOMIC_SEQ_CST); \
+ case bson_memory_order_acquire: \
+ return __atomic_load_n (a, __ATOMIC_ACQUIRE); \
+ case bson_memory_order_consume: \
+ return __atomic_load_n (a, __ATOMIC_CONSUME); \
+ case bson_memory_order_relaxed: \
+ return __atomic_load_n (a, __ATOMIC_RELAXED); \
+ default: \
+ BSON_UNREACHABLE ("Invalid bson_memory_order value"); \
+ }) \
+ BSON_IF_GNU_LEGACY_ATOMICS ({ \
+ __sync_synchronize (); \
+ return *a; \
+ }) \
+ } \
+ \
+ static BSON_INLINE Type bson_atomic_##NamePart##_exchange ( \
+ Type volatile *a, Type value, enum bson_memory_order ord) \
+ { \
+ BSON_IF_MSVC ( \
+ DEF_ATOMIC_OP (BSON_CONCAT (_InterlockedExchange, VCIntrinSuffix), \
+ ~, \
+ ~, \
+ ord, \
+ a, \
+ value);) \
+ /* GNU doesn't want CONSUME order for the exchange operation, so we \
+ * cannot use DEF_ATOMIC_OP. */ \
+ BSON_IF_GNU_LIKE (switch (ord) { \
+ case bson_memory_order_acq_rel: \
+ return __atomic_exchange_n (a, value, __ATOMIC_ACQ_REL); \
+ case bson_memory_order_release: \
+ return __atomic_exchange_n (a, value, __ATOMIC_RELEASE); \
+ case bson_memory_order_seq_cst: \
+ return __atomic_exchange_n (a, value, __ATOMIC_SEQ_CST); \
+ case bson_memory_order_consume: /* Fall back to acquire */ \
+ case bson_memory_order_acquire: \
+ return __atomic_exchange_n (a, value, __ATOMIC_ACQUIRE); \
+ case bson_memory_order_relaxed: \
+ return __atomic_exchange_n (a, value, __ATOMIC_RELAXED); \
+ default: \
+ BSON_UNREACHABLE ("Invalid bson_memory_order value"); \
+ }) \
+ BSON_IF_GNU_LEGACY_ATOMICS ( \
+ return __sync_val_compare_and_swap (a, *a, value);) \
+ } \
+ \
+ static BSON_INLINE Type bson_atomic_##NamePart##_compare_exchange_strong ( \
+ Type volatile *a, \
+ Type expect, \
+ Type new_value, \
+ enum bson_memory_order ord) \
+ { \
+ Type actual = expect; \
+ switch (ord) { \
+ case bson_memory_order_release: \
+ case bson_memory_order_acq_rel: \
+ case bson_memory_order_seq_cst: \
+ DEF_ATOMIC_CMPEXCH_STRONG ( \
+ VCIntrinSuffix, , __ATOMIC_SEQ_CST, a, actual, new_value); \
+ break; \
+ case bson_memory_order_acquire: \
+ DEF_ATOMIC_CMPEXCH_STRONG (VCIntrinSuffix, \
+ MSVC_MEMORDER_SUFFIX (_acq), \
+ __ATOMIC_ACQUIRE, \
+ a, \
+ actual, \
+ new_value); \
+ break; \
+ case bson_memory_order_consume: \
+ DEF_ATOMIC_CMPEXCH_STRONG (VCIntrinSuffix, \
+ MSVC_MEMORDER_SUFFIX (_acq), \
+ __ATOMIC_CONSUME, \
+ a, \
+ actual, \
+ new_value); \
+ break; \
+ case bson_memory_order_relaxed: \
+ DEF_ATOMIC_CMPEXCH_STRONG (VCIntrinSuffix, \
+ MSVC_MEMORDER_SUFFIX (_nf), \
+ __ATOMIC_RELAXED, \
+ a, \
+ actual, \
+ new_value); \
+ break; \
+ default: \
+ BSON_UNREACHABLE ("Invalid bson_memory_order value"); \
+ } \
+ return actual; \
+ } \
+ \
+ static BSON_INLINE Type bson_atomic_##NamePart##_compare_exchange_weak ( \
+ Type volatile *a, \
+ Type expect, \
+ Type new_value, \
+ enum bson_memory_order ord) \
+ { \
+ Type actual = expect; \
+ switch (ord) { \
+ case bson_memory_order_release: \
+ case bson_memory_order_acq_rel: \
+ case bson_memory_order_seq_cst: \
+ DEF_ATOMIC_CMPEXCH_WEAK ( \
+ VCIntrinSuffix, , __ATOMIC_SEQ_CST, a, actual, new_value); \
+ break; \
+ case bson_memory_order_acquire: \
+ DEF_ATOMIC_CMPEXCH_WEAK (VCIntrinSuffix, \
+ MSVC_MEMORDER_SUFFIX (_acq), \
+ __ATOMIC_ACQUIRE, \
+ a, \
+ actual, \
+ new_value); \
+ break; \
+ case bson_memory_order_consume: \
+ DEF_ATOMIC_CMPEXCH_WEAK (VCIntrinSuffix, \
+ MSVC_MEMORDER_SUFFIX (_acq), \
+ __ATOMIC_CONSUME, \
+ a, \
+ actual, \
+ new_value); \
+ break; \
+ case bson_memory_order_relaxed: \
+ DEF_ATOMIC_CMPEXCH_WEAK (VCIntrinSuffix, \
+ MSVC_MEMORDER_SUFFIX (_nf), \
+ __ATOMIC_RELAXED, \
+ a, \
+ actual, \
+ new_value); \
+ break; \
+ default: \
+ BSON_UNREACHABLE ("Invalid bson_memory_order value"); \
+ } \
+ return actual; \
+ }
+
+#define DECL_ATOMIC_STDINT(Name, VCSuffix) \
+ DECL_ATOMIC_INTEGRAL (Name, Name##_t, VCSuffix)
+
+#if defined(_MSC_VER) || defined(BSON_USE_LEGACY_GCC_ATOMICS)
+/* MSVC and GCC require built-in types (not typedefs) for their atomic
+ * intrinsics. */
+#if defined(_MSC_VER)
+#define DECL_ATOMIC_INTEGRAL_INT8 char
+#define DECL_ATOMIC_INTEGRAL_INT32 long
+#define DECL_ATOMIC_INTEGRAL_INT long
+#else
+#define DECL_ATOMIC_INTEGRAL_INT8 signed char
+#define DECL_ATOMIC_INTEGRAL_INT32 int
+#define DECL_ATOMIC_INTEGRAL_INT int
+#endif
+DECL_ATOMIC_INTEGRAL (int8, DECL_ATOMIC_INTEGRAL_INT8, 8)
+DECL_ATOMIC_INTEGRAL (int16, short, 16)
+#if !defined(BSON_EMULATE_INT32)
+DECL_ATOMIC_INTEGRAL (int32, DECL_ATOMIC_INTEGRAL_INT32, )
+#endif
+#if !defined(BSON_EMULATE_INT)
+DECL_ATOMIC_INTEGRAL (int, DECL_ATOMIC_INTEGRAL_INT, )
+#endif
+#else
+/* Other compilers that we support provide generic intrinsics */
+DECL_ATOMIC_STDINT (int8, 8)
+DECL_ATOMIC_STDINT (int16, 16)
+#if !defined(BSON_EMULATE_INT32)
+DECL_ATOMIC_STDINT (int32, )
+#endif
+#if !defined(BSON_EMULATE_INT)
+DECL_ATOMIC_INTEGRAL (int, int, )
+#endif
+#endif
+
+BSON_EXPORT (int64_t)
+_bson_emul_atomic_int64_fetch_add (int64_t volatile *val,
+ int64_t v,
+ enum bson_memory_order);
+BSON_EXPORT (int64_t)
+_bson_emul_atomic_int64_exchange (int64_t volatile *val,
+ int64_t v,
+ enum bson_memory_order);
+BSON_EXPORT (int64_t)
+_bson_emul_atomic_int64_compare_exchange_strong (int64_t volatile *val,
+ int64_t expect_value,
+ int64_t new_value,
+ enum bson_memory_order);
+
+BSON_EXPORT (int64_t)
+_bson_emul_atomic_int64_compare_exchange_weak (int64_t volatile *val,
+ int64_t expect_value,
+ int64_t new_value,
+ enum bson_memory_order);
+
+BSON_EXPORT (int32_t)
+_bson_emul_atomic_int32_fetch_add (int32_t volatile *val,
+ int32_t v,
+ enum bson_memory_order);
+BSON_EXPORT (int32_t)
+_bson_emul_atomic_int32_exchange (int32_t volatile *val,
+ int32_t v,
+ enum bson_memory_order);
+BSON_EXPORT (int32_t)
+_bson_emul_atomic_int32_compare_exchange_strong (int32_t volatile *val,
+ int32_t expect_value,
+ int32_t new_value,
+ enum bson_memory_order);
+
+BSON_EXPORT (int32_t)
+_bson_emul_atomic_int32_compare_exchange_weak (int32_t volatile *val,
+ int32_t expect_value,
+ int32_t new_value,
+ enum bson_memory_order);
+
+BSON_EXPORT (int)
+_bson_emul_atomic_int_fetch_add (int volatile *val,
+ int v,
+ enum bson_memory_order);
+BSON_EXPORT (int)
+_bson_emul_atomic_int_exchange (int volatile *val,
+ int v,
+ enum bson_memory_order);
+BSON_EXPORT (int)
+_bson_emul_atomic_int_compare_exchange_strong (int volatile *val,
+ int expect_value,
+ int new_value,
+ enum bson_memory_order);
+
+BSON_EXPORT (int)
+_bson_emul_atomic_int_compare_exchange_weak (int volatile *val,
+ int expect_value,
+ int new_value,
+ enum bson_memory_order);
+
+BSON_EXPORT (void *)
+_bson_emul_atomic_ptr_exchange (void *volatile *val,
+ void *v,
+ enum bson_memory_order);
+
+BSON_EXPORT (void)
+bson_thrd_yield (void);
+
+#if (defined(_MSC_VER) && !defined(_M_IX86)) || (defined(__LP64__) && __LP64__)
+/* (64-bit intrinsics are only available in x64) */
+#ifdef _MSC_VER
+DECL_ATOMIC_INTEGRAL (int64, __int64, 64)
+#else
+DECL_ATOMIC_STDINT (int64, 64)
+#endif
+#else
+static BSON_INLINE int64_t
+bson_atomic_int64_fetch (const int64_t volatile *val,
+ enum bson_memory_order order)
+{
+ return _bson_emul_atomic_int64_fetch_add (
+ (int64_t volatile *) val, 0, order);
+}
+
+static BSON_INLINE int64_t
+bson_atomic_int64_fetch_add (int64_t volatile *val,
+ int64_t v,
+ enum bson_memory_order order)
+{
+ return _bson_emul_atomic_int64_fetch_add (val, v, order);
+}
+
+static BSON_INLINE int64_t
+bson_atomic_int64_fetch_sub (int64_t volatile *val,
+ int64_t v,
+ enum bson_memory_order order)
+{
+ return _bson_emul_atomic_int64_fetch_add (val, -v, order);
+}
+
+static BSON_INLINE int64_t
+bson_atomic_int64_exchange (int64_t volatile *val,
+ int64_t v,
+ enum bson_memory_order order)
+{
+ return _bson_emul_atomic_int64_exchange (val, v, order);
+}
+
+static BSON_INLINE int64_t
+bson_atomic_int64_compare_exchange_strong (int64_t volatile *val,
+ int64_t expect_value,
+ int64_t new_value,
+ enum bson_memory_order order)
+{
+ return _bson_emul_atomic_int64_compare_exchange_strong (
+ val, expect_value, new_value, order);
+}
+
+static BSON_INLINE int64_t
+bson_atomic_int64_compare_exchange_weak (int64_t volatile *val,
+ int64_t expect_value,
+ int64_t new_value,
+ enum bson_memory_order order)
+{
+ return _bson_emul_atomic_int64_compare_exchange_weak (
+ val, expect_value, new_value, order);
+}
+#endif
+
+#if defined(BSON_EMULATE_INT32)
+static BSON_INLINE int32_t
+bson_atomic_int32_fetch (const int32_t volatile *val,
+ enum bson_memory_order order)
+{
+ return _bson_emul_atomic_int32_fetch_add (
+ (int32_t volatile *) val, 0, order);
+}
+
+static BSON_INLINE int32_t
+bson_atomic_int32_fetch_add (int32_t volatile *val,
+ int32_t v,
+ enum bson_memory_order order)
+{
+ return _bson_emul_atomic_int32_fetch_add (val, v, order);
+}
+
+static BSON_INLINE int32_t
+bson_atomic_int32_fetch_sub (int32_t volatile *val,
+ int32_t v,
+ enum bson_memory_order order)
+{
+ return _bson_emul_atomic_int32_fetch_add (val, -v, order);
+}
+
+static BSON_INLINE int32_t
+bson_atomic_int32_exchange (int32_t volatile *val,
+ int32_t v,
+ enum bson_memory_order order)
+{
+ return _bson_emul_atomic_int32_exchange (val, v, order);
+}
+
+static BSON_INLINE int32_t
+bson_atomic_int32_compare_exchange_strong (int32_t volatile *val,
+ int32_t expect_value,
+ int32_t new_value,
+ enum bson_memory_order order)
+{
+ return _bson_emul_atomic_int32_compare_exchange_strong (
+ val, expect_value, new_value, order);
+}
+
+static BSON_INLINE int32_t
+bson_atomic_int32_compare_exchange_weak (int32_t volatile *val,
+ int32_t expect_value,
+ int32_t new_value,
+ enum bson_memory_order order)
+{
+ return _bson_emul_atomic_int32_compare_exchange_weak (
+ val, expect_value, new_value, order);
+}
+#endif /* BSON_EMULATE_INT32 */
+
+#if defined(BSON_EMULATE_INT)
+static BSON_INLINE int
+bson_atomic_int_fetch (const int volatile *val, enum bson_memory_order order)
+{
+ return _bson_emul_atomic_int_fetch_add ((int volatile *) val, 0, order);
+}
+
+static BSON_INLINE int
+bson_atomic_int_fetch_add (int volatile *val,
+ int v,
+ enum bson_memory_order order)
+{
+ return _bson_emul_atomic_int_fetch_add (val, v, order);
+}
+
+static BSON_INLINE int
+bson_atomic_int_fetch_sub (int volatile *val,
+ int v,
+ enum bson_memory_order order)
+{
+ return _bson_emul_atomic_int_fetch_add (val, -v, order);
+}
+
+static BSON_INLINE int
+bson_atomic_int_exchange (int volatile *val,
+ int v,
+ enum bson_memory_order order)
+{
+ return _bson_emul_atomic_int_exchange (val, v, order);
+}
+
+static BSON_INLINE int
+bson_atomic_int_compare_exchange_strong (int volatile *val,
+ int expect_value,
+ int new_value,
+ enum bson_memory_order order)
+{
+ return _bson_emul_atomic_int_compare_exchange_strong (
+ val, expect_value, new_value, order);
+}
+
+static BSON_INLINE int
+bson_atomic_int_compare_exchange_weak (int volatile *val,
+ int expect_value,
+ int new_value,
+ enum bson_memory_order order)
+{
+ return _bson_emul_atomic_int_compare_exchange_weak (
+ val, expect_value, new_value, order);
+}
+#endif /* BSON_EMULATE_INT */
+
+static BSON_INLINE void *
+bson_atomic_ptr_exchange (void *volatile *ptr,
+ void *new_value,
+ enum bson_memory_order ord)
+{
+#if defined(BSON_EMULATE_PTR)
+ return _bson_emul_atomic_ptr_exchange (ptr, new_value, ord);
+#elif defined(BSON_USE_LEGACY_GCC_ATOMICS)
+ /* The older __sync_val_compare_and_swap also takes oldval */
+ DEF_ATOMIC_OP (_InterlockedExchangePointer,
+ ,
+ __sync_val_compare_and_swap,
+ ord,
+ ptr,
+ *ptr,
+ new_value);
+#else
+ DEF_ATOMIC_OP (
+ _InterlockedExchangePointer, __atomic_exchange_n, , ord, ptr, new_value);
+#endif
+}
+
+static BSON_INLINE void *
+bson_atomic_ptr_compare_exchange_strong (void *volatile *ptr,
+ void *expect,
+ void *new_value,
+ enum bson_memory_order ord)
+{
+ switch (ord) {
+ case bson_memory_order_release:
+ case bson_memory_order_acq_rel:
+ case bson_memory_order_seq_cst:
+ DEF_ATOMIC_CMPEXCH_STRONG (
+ Pointer, , __ATOMIC_SEQ_CST, ptr, expect, new_value);
+ return expect;
+ case bson_memory_order_relaxed:
+ DEF_ATOMIC_CMPEXCH_STRONG (Pointer,
+ MSVC_MEMORDER_SUFFIX (_nf),
+ __ATOMIC_RELAXED,
+ ptr,
+ expect,
+ new_value);
+ return expect;
+ case bson_memory_order_consume:
+ DEF_ATOMIC_CMPEXCH_STRONG (Pointer,
+ MSVC_MEMORDER_SUFFIX (_acq),
+ __ATOMIC_CONSUME,
+ ptr,
+ expect,
+ new_value);
+ return expect;
+ case bson_memory_order_acquire:
+ DEF_ATOMIC_CMPEXCH_STRONG (Pointer,
+ MSVC_MEMORDER_SUFFIX (_acq),
+ __ATOMIC_ACQUIRE,
+ ptr,
+ expect,
+ new_value);
+ return expect;
+ default:
+ BSON_UNREACHABLE ("Invalid bson_memory_order value");
+ }
+}
+
+
+static BSON_INLINE void *
+bson_atomic_ptr_compare_exchange_weak (void *volatile *ptr,
+ void *expect,
+ void *new_value,
+ enum bson_memory_order ord)
+{
+ switch (ord) {
+ case bson_memory_order_release:
+ case bson_memory_order_acq_rel:
+ case bson_memory_order_seq_cst:
+ DEF_ATOMIC_CMPEXCH_WEAK (
+ Pointer, , __ATOMIC_SEQ_CST, ptr, expect, new_value);
+ return expect;
+ case bson_memory_order_relaxed:
+ DEF_ATOMIC_CMPEXCH_WEAK (Pointer,
+ MSVC_MEMORDER_SUFFIX (_nf),
+ __ATOMIC_RELAXED,
+ ptr,
+ expect,
+ new_value);
+ return expect;
+ case bson_memory_order_consume:
+ DEF_ATOMIC_CMPEXCH_WEAK (Pointer,
+ MSVC_MEMORDER_SUFFIX (_acq),
+ __ATOMIC_CONSUME,
+ ptr,
+ expect,
+ new_value);
+ return expect;
+ case bson_memory_order_acquire:
+ DEF_ATOMIC_CMPEXCH_WEAK (Pointer,
+ MSVC_MEMORDER_SUFFIX (_acq),
+ __ATOMIC_ACQUIRE,
+ ptr,
+ expect,
+ new_value);
+ return expect;
+ default:
+ BSON_UNREACHABLE ("Invalid bson_memory_order value");
+ }
+}
+
+
+static BSON_INLINE void *
+bson_atomic_ptr_fetch (void *volatile const *ptr, enum bson_memory_order ord)
+{
+ return bson_atomic_ptr_compare_exchange_strong (
+ (void *volatile *) ptr, NULL, NULL, ord);
+}
+
+#undef DECL_ATOMIC_STDINT
+#undef DECL_ATOMIC_INTEGRAL
+#undef DEF_ATOMIC_OP
+#undef DEF_ATOMIC_CMPEXCH_STRONG
+#undef DEF_ATOMIC_CMPEXCH_WEAK
+#undef MSVC_MEMORDER_SUFFIX
+
+/**
+ * @brief Generate a full-fence memory barrier at the call site.
+ */
+static BSON_INLINE void
+bson_atomic_thread_fence (void)
+{
+ BSON_IF_MSVC (MemoryBarrier ();)
+ BSON_IF_GNU_LIKE (__sync_synchronize ();)
+ BSON_IF_GNU_LEGACY_ATOMICS (__sync_synchronize ();)
+}
+
+#ifdef BSON_USE_LEGACY_GCC_ATOMICS
+#undef BSON_IF_GNU_LIKE
+#define BSON_IF_GNU_LIKE(...) __VA_ARGS__
+#endif
+#undef BSON_IF_GNU_LEGACY_ATOMICS
+#undef BSON_USE_LEGACY_GCC_ATOMICS
+
+BSON_GNUC_DEPRECATED_FOR ("bson_atomic_thread_fence")
+BSON_EXPORT (void) bson_memory_barrier (void);
+
+BSON_GNUC_DEPRECATED_FOR ("bson_atomic_int_fetch_add")
+BSON_EXPORT (int32_t) bson_atomic_int_add (volatile int32_t *p, int32_t n);
+
+BSON_GNUC_DEPRECATED_FOR ("bson_atomic_int64_fetch_add")
+BSON_EXPORT (int64_t) bson_atomic_int64_add (volatile int64_t *p, int64_t n);
+
+
+#undef BSON_EMULATE_PTR
+#undef BSON_EMULATE_INT32
+#undef BSON_EMULATE_INT
+
+BSON_END_DECLS
+
+
+#endif /* BSON_ATOMIC_H */
diff --git a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-clock.c b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-clock.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-clock.c
rename to mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-clock.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-clock.h b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-clock.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-clock.h
rename to mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-clock.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-compat.h b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-compat.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-compat.h
rename to mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-compat.h
diff --git a/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-config.h b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-config.h
new file mode 100644
index 00000000..fbfa8325
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-config.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2018-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if !defined(BSON_INSIDE) && !defined(BSON_COMPILATION)
+#error "Only <bson/bson.h> can be included directly."
+#endif
+
+#ifndef BSON_CONFIG_H
+#define BSON_CONFIG_H
+
+/*
+ * Define to 1234 for Little Endian, 4321 for Big Endian.
+ */
+#define BSON_BYTE_ORDER 1234
+
+
+/*
+ * Define to 1 if you have stdbool.h
+ */
+#define BSON_HAVE_STDBOOL_H 1
+#if BSON_HAVE_STDBOOL_H != 1
+# undef BSON_HAVE_STDBOOL_H
+#endif
+
+
+/*
+ * Define to 1 for POSIX-like systems, 2 for Windows.
+ */
+#define BSON_OS 1
+
+
+/*
+ * Define to 1 if you have clock_gettime() available.
+ */
+#define BSON_HAVE_CLOCK_GETTIME 1
+#if BSON_HAVE_CLOCK_GETTIME != 1
+# undef BSON_HAVE_CLOCK_GETTIME
+#endif
+
+
+/*
+ * Define to 1 if you have strings.h available on your platform.
+ */
+#define BSON_HAVE_STRINGS_H 1
+#if BSON_HAVE_STRINGS_H != 1
+# undef BSON_HAVE_STRINGS_H
+#endif
+
+
+/*
+ * Define to 1 if you have strnlen available on your platform.
+ */
+#define BSON_HAVE_STRNLEN 1
+#if BSON_HAVE_STRNLEN != 1
+# undef BSON_HAVE_STRNLEN
+#endif
+
+
+/*
+ * Define to 1 if you have snprintf available on your platform.
+ */
+#define BSON_HAVE_SNPRINTF 1
+#if BSON_HAVE_SNPRINTF != 1
+# undef BSON_HAVE_SNPRINTF
+#endif
+
+
+/*
+ * Define to 1 if you have gmtime_r available on your platform.
+ */
+#define BSON_HAVE_GMTIME_R 1
+#if BSON_HAVE_GMTIME_R != 1
+# undef BSON_HAVE_GMTIME_R
+#endif
+
+
+/*
+ * Define to 1 if you have struct timespec available on your platform.
+ */
+#define BSON_HAVE_TIMESPEC 1
+#if BSON_HAVE_TIMESPEC != 1
+# undef BSON_HAVE_TIMESPEC
+#endif
+
+
+/*
+ * Define to 1 if you want extra aligned types in libbson
+ */
+#define BSON_EXTRA_ALIGN 0
+#if BSON_EXTRA_ALIGN != 1
+# undef BSON_EXTRA_ALIGN
+#endif
+
+
+/*
+ * Define to 1 if you have rand_r available on your platform.
+ */
+#define BSON_HAVE_RAND_R 1
+#if BSON_HAVE_RAND_R != 1
+# undef BSON_HAVE_RAND_R
+#endif
+
+
+/*
+ * Define to 1 if you have strlcpy available on your platform.
+ */
+#define BSON_HAVE_STRLCPY 0
+#if BSON_HAVE_STRLCPY != 1
+# undef BSON_HAVE_STRLCPY
+#endif
+
+#endif /* BSON_CONFIG_H */
diff --git a/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-config.h.in b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-config.h.in
new file mode 100644
index 00000000..2849d020
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-config.h.in
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2018-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if !defined(BSON_INSIDE) && !defined(BSON_COMPILATION)
+#error "Only <bson/bson.h> can be included directly."
+#endif
+
+#ifndef BSON_CONFIG_H
+#define BSON_CONFIG_H
+
+/*
+ * Define to 1234 for Little Endian, 4321 for Big Endian.
+ */
+#define BSON_BYTE_ORDER @BSON_BYTE_ORDER@
+
+
+/*
+ * Define to 1 if you have stdbool.h
+ */
+#define BSON_HAVE_STDBOOL_H @BSON_HAVE_STDBOOL_H@
+#if BSON_HAVE_STDBOOL_H != 1
+# undef BSON_HAVE_STDBOOL_H
+#endif
+
+
+/*
+ * Define to 1 for POSIX-like systems, 2 for Windows.
+ */
+#define BSON_OS @BSON_OS@
+
+
+/*
+ * Define to 1 if you have clock_gettime() available.
+ */
+#define BSON_HAVE_CLOCK_GETTIME @BSON_HAVE_CLOCK_GETTIME@
+#if BSON_HAVE_CLOCK_GETTIME != 1
+# undef BSON_HAVE_CLOCK_GETTIME
+#endif
+
+
+/*
+ * Define to 1 if you have strings.h available on your platform.
+ */
+#define BSON_HAVE_STRINGS_H @BSON_HAVE_STRINGS_H@
+#if BSON_HAVE_STRINGS_H != 1
+# undef BSON_HAVE_STRINGS_H
+#endif
+
+
+/*
+ * Define to 1 if you have strnlen available on your platform.
+ */
+#define BSON_HAVE_STRNLEN @BSON_HAVE_STRNLEN@
+#if BSON_HAVE_STRNLEN != 1
+# undef BSON_HAVE_STRNLEN
+#endif
+
+
+/*
+ * Define to 1 if you have snprintf available on your platform.
+ */
+#define BSON_HAVE_SNPRINTF @BSON_HAVE_SNPRINTF@
+#if BSON_HAVE_SNPRINTF != 1
+# undef BSON_HAVE_SNPRINTF
+#endif
+
+
+/*
+ * Define to 1 if you have gmtime_r available on your platform.
+ */
+#define BSON_HAVE_GMTIME_R @BSON_HAVE_GMTIME_R@
+#if BSON_HAVE_GMTIME_R != 1
+# undef BSON_HAVE_GMTIME_R
+#endif
+
+
+/*
+ * Define to 1 if you have struct timespec available on your platform.
+ */
+#define BSON_HAVE_TIMESPEC @BSON_HAVE_TIMESPEC@
+#if BSON_HAVE_TIMESPEC != 1
+# undef BSON_HAVE_TIMESPEC
+#endif
+
+
+/*
+ * Define to 1 if you want extra aligned types in libbson
+ */
+#define BSON_EXTRA_ALIGN @BSON_EXTRA_ALIGN@
+#if BSON_EXTRA_ALIGN != 1
+# undef BSON_EXTRA_ALIGN
+#endif
+
+
+/*
+ * Define to 1 if you have rand_r available on your platform.
+ */
+#define BSON_HAVE_RAND_R @BSON_HAVE_RAND_R@
+#if BSON_HAVE_RAND_R != 1
+# undef BSON_HAVE_RAND_R
+#endif
+
+
+/*
+ * Define to 1 if you have strlcpy available on your platform.
+ */
+#define BSON_HAVE_STRLCPY @BSON_HAVE_STRLCPY@
+#if BSON_HAVE_STRLCPY != 1
+# undef BSON_HAVE_STRLCPY
+#endif
+
+#endif /* BSON_CONFIG_H */
diff --git a/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-context-private.h b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-context-private.h
new file mode 100644
index 00000000..c88c87cc
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-context-private.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2014 MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bson-prelude.h"
+
+
+#ifndef BSON_CONTEXT_PRIVATE_H
+#define BSON_CONTEXT_PRIVATE_H
+
+
+#include "bson-context.h"
+#include "common-thread-private.h"
+
+
+BSON_BEGIN_DECLS
+
+
+enum {
+ BSON_OID_RANDOMESS_OFFSET = 4,
+ BSON_OID_RANDOMNESS_SIZE = 5,
+ BSON_OID_SEQ32_OFFSET = 9,
+ BSON_OID_SEQ32_SIZE = 3,
+ BSON_OID_SEQ64_OFFSET = 4,
+ BSON_OID_SEQ64_SIZE = 8
+};
+
+struct _bson_context_t {
+ /* flags are defined in bson_context_flags_t */
+ int flags;
+ uint32_t seq32;
+ uint64_t seq64;
+ uint8_t randomness[BSON_OID_RANDOMNESS_SIZE];
+ uint64_t pid;
+};
+
+/**
+ * @brief Insert the context's randomness data into the given OID
+ *
+ * @param context A context for some random data
+ * @param oid The OID to update.
+ */
+void
+_bson_context_set_oid_rand (bson_context_t *context, bson_oid_t *oid);
+
+/**
+ * @brief Insert the context's sequence counter into the given OID. Increments
+ * the context's sequence counter.
+ *
+ * @param context The context with the counter to get+update
+ * @param oid The OID to modify
+ */
+void
+_bson_context_set_oid_seq32 (bson_context_t *context, bson_oid_t *oid);
+
+/**
+ * @brief Write a 64-bit counter from the given context into the OID. Increments
+ * the context's sequence counter.
+ *
+ * @param context The context with the counter to get+update
+ * @param oid The OID to modify
+ *
+ * @note Only used by the deprecated @ref bson_oid_init_sequence
+ */
+void
+_bson_context_set_oid_seq64 (bson_context_t *context, bson_oid_t *oid);
+
+
+BSON_END_DECLS
+
+
+#endif /* BSON_CONTEXT_PRIVATE_H */
diff --git a/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-context.c b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-context.c
new file mode 100644
index 00000000..862a80a9
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-context.c
@@ -0,0 +1,380 @@
+/*
+ * Copyright 2013 MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bson-compat.h"
+
+#include <limits.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "bson-atomic.h"
+#include "bson-clock.h"
+#include "bson-context.h"
+#include "bson-context-private.h"
+#include "bson-memory.h"
+#include "common-thread-private.h"
+
+
+#ifndef HOST_NAME_MAX
+#define HOST_NAME_MAX 256
+#endif
+
+
+/*
+ * Globals.
+ */
+static bson_context_t gContextDefault;
+
+static BSON_INLINE uint64_t
+_bson_getpid (void)
+{
+ uint64_t pid;
+#ifdef BSON_OS_WIN32
+ DWORD real_pid;
+
+ real_pid = GetCurrentProcessId ();
+ pid = (real_pid & 0xFFFF) ^ ((real_pid >> 16) & 0xFFFF);
+#else
+ pid = (uint64_t) getpid ();
+#endif
+
+ return pid;
+}
+
+
+void
+_bson_context_set_oid_seq32 (bson_context_t *context, /* IN */
+ bson_oid_t *oid) /* OUT */
+{
+ uint32_t seq = (uint32_t) bson_atomic_int32_fetch_add (
+ (int32_t *) &context->seq32, 1, bson_memory_order_seq_cst);
+ seq = BSON_UINT32_TO_BE (seq);
+ memcpy (&oid->bytes[BSON_OID_SEQ32_OFFSET],
+ ((uint8_t *) &seq) + 1,
+ BSON_OID_SEQ32_SIZE);
+}
+
+
+void
+_bson_context_set_oid_seq64 (bson_context_t *context, /* IN */
+ bson_oid_t *oid) /* OUT */
+{
+ uint64_t seq = (uint64_t) bson_atomic_int64_fetch_add (
+ (int64_t *) &context->seq64, 1, bson_memory_order_seq_cst);
+
+ seq = BSON_UINT64_TO_BE (seq);
+ memcpy (&oid->bytes[BSON_OID_SEQ64_OFFSET], &seq, BSON_OID_SEQ64_SIZE);
+}
+
+/*
+ * --------------------------------------------------------------------------
+ *
+ * _bson_context_get_hostname
+ *
+ * Gets the hostname of the machine, logs a warning on failure. "out"
+ * must be an array of HOST_NAME_MAX bytes.
+ *
+ * --------------------------------------------------------------------------
+ */
+static void
+_bson_context_get_hostname (char out[HOST_NAME_MAX])
+{
+ if (gethostname (out, HOST_NAME_MAX) != 0) {
+ if (errno == ENAMETOOLONG) {
+ fprintf (stderr,
+ "hostname exceeds %d characters, truncating.",
+ HOST_NAME_MAX);
+ } else {
+ fprintf (stderr, "unable to get hostname: %d", errno);
+ }
+ }
+ out[HOST_NAME_MAX - 1] = '\0';
+}
+
+
+/*** ========================================
+ * The below SipHash implementation is based on the original public-domain
+ * reference implementation from Jean-Philippe Aumasson and DJB
+ * (https://github.com/veorq/SipHash).
+ */
+
+/* in-place rotate a 64bit number */
+void
+_bson_rotl_u64 (uint64_t *p, int nbits)
+{
+ *p = (*p << nbits) | (*p >> (64 - nbits));
+}
+
+/* Write the little-endian representation of 'val' into 'out' */
+void
+_u64_into_u8x8_le (uint8_t out[8], uint64_t val)
+{
+ val = BSON_UINT64_TO_LE (val);
+ memcpy (out, &val, sizeof val);
+}
+
+/* Read a little-endian representation of a 64bit number from 'in' */
+uint64_t
+_u8x8_le_to_u64 (const uint8_t in[8])
+{
+ uint64_t r;
+ memcpy (&r, in, sizeof r);
+ return BSON_UINT64_FROM_LE (r);
+}
+
+/* Perform one SipHash round */
+void
+_sip_round (uint64_t *v0, uint64_t *v1, uint64_t *v2, uint64_t *v3)
+{
+ *v0 += *v1;
+ _bson_rotl_u64 (v1, 13);
+ *v1 ^= *v0;
+ _bson_rotl_u64 (v0, 32);
+ *v2 += *v3;
+ _bson_rotl_u64 (v3, 16);
+ *v3 ^= *v2;
+ *v0 += *v3;
+ _bson_rotl_u64 (v3, 21);
+ *v3 ^= *v0;
+ *v2 += *v1;
+ _bson_rotl_u64 (v1, 17);
+ *v1 ^= *v2;
+ _bson_rotl_u64 (v2, 32);
+}
+
+void
+_siphash (const void *in,
+ const size_t inlen,
+ const uint64_t key[2],
+ uint64_t digest[2])
+{
+ const unsigned char *ni = (const unsigned char *) in;
+ const unsigned char *kk = (const unsigned char *) key;
+ uint8_t digest_buf[16] = {0};
+
+ const int C_ROUNDS = 2;
+ const int D_ROUNDS = 4;
+
+ uint64_t v0 = UINT64_C (0x736f6d6570736575);
+ uint64_t v1 = UINT64_C (0x646f72616e646f6d);
+ uint64_t v2 = UINT64_C (0x6c7967656e657261);
+ uint64_t v3 = UINT64_C (0x7465646279746573);
+ uint64_t k0 = _u8x8_le_to_u64 (kk);
+ uint64_t k1 = _u8x8_le_to_u64 (kk + 8);
+ uint64_t m;
+ int i;
+ const unsigned char *end = ni + inlen - (inlen % sizeof (uint64_t));
+ const int left = inlen & 7;
+ uint64_t b = ((uint64_t) inlen) << 56;
+ v3 ^= k1;
+ v2 ^= k0;
+ v1 ^= k1;
+ v0 ^= k0;
+
+ v1 ^= 0xee;
+
+ for (; ni != end; ni += 8) {
+ m = _u8x8_le_to_u64 (ni);
+ v3 ^= m;
+
+ for (i = 0; i < C_ROUNDS; ++i)
+ _sip_round (&v0, &v1, &v2, &v3);
+
+ v0 ^= m;
+ }
+
+ switch (left) {
+ case 7:
+ b |= ((uint64_t) ni[6]) << 48;
+ /* FALLTHRU */
+ case 6:
+ b |= ((uint64_t) ni[5]) << 40;
+ /* FALLTHRU */
+ case 5:
+ b |= ((uint64_t) ni[4]) << 32;
+ /* FALLTHRU */
+ case 4:
+ b |= ((uint64_t) ni[3]) << 24;
+ /* FALLTHRU */
+ case 3:
+ b |= ((uint64_t) ni[2]) << 16;
+ /* FALLTHRU */
+ case 2:
+ b |= ((uint64_t) ni[1]) << 8;
+ /* FALLTHRU */
+ case 1:
+ b |= ((uint64_t) ni[0]);
+ break;
+ default:
+ BSON_UNREACHABLE ("Invalid remainder during SipHash");
+ case 0:
+ break;
+ }
+
+ v3 ^= b;
+
+ for (i = 0; i < C_ROUNDS; ++i)
+ _sip_round (&v0, &v1, &v2, &v3);
+
+ v0 ^= b;
+
+ v2 ^= 0xee;
+
+ for (i = 0; i < D_ROUNDS; ++i)
+ _sip_round (&v0, &v1, &v2, &v3);
+
+ b = v0 ^ v1 ^ v2 ^ v3;
+ _u64_into_u8x8_le (digest_buf, b);
+
+ v1 ^= 0xdd;
+
+ for (i = 0; i < D_ROUNDS; ++i)
+ _sip_round (&v0, &v1, &v2, &v3);
+
+ b = v0 ^ v1 ^ v2 ^ v3;
+ _u64_into_u8x8_le (digest_buf + 8, b);
+
+ memcpy (digest, digest_buf, sizeof digest_buf);
+}
+
+/*
+ * The seed consists of the following hashed together:
+ * - current time (with microsecond resolution)
+ * - current pid
+ * - current hostname
+ * - The init-call counter
+ */
+struct _init_rand_params {
+ struct timeval time;
+ uint64_t pid;
+ char hostname[HOST_NAME_MAX];
+ int64_t rand_call_counter;
+};
+
+static void
+_bson_context_init_random (bson_context_t *context, bool init_seq)
+{
+ /* Keep an atomic counter of this function being called. This is used to add
+ * additional input to the random hash, ensuring no two calls in a single
+ * process will receive identical hash inputs, even occurring at the same
+ * microsecond. */
+ static int64_t s_rand_call_counter = INT64_MIN;
+
+ /* The message digest of the random params */
+ uint64_t digest[2] = {0};
+ uint64_t key[2] = {0};
+ /* The randomness parameters */
+ struct _init_rand_params rand_params;
+
+ /* Init each part of the randomness source: */
+ memset (&rand_params, 0, sizeof rand_params);
+ bson_gettimeofday (&rand_params.time);
+ rand_params.pid = _bson_getpid ();
+ _bson_context_get_hostname (rand_params.hostname);
+ rand_params.rand_call_counter = bson_atomic_int64_fetch_add (
+ &s_rand_call_counter, 1, bson_memory_order_seq_cst);
+
+ /* Generate a SipHash key. We do not care about secrecy or determinism, only
+ * uniqueness. */
+ memcpy (key, &rand_params, sizeof key);
+ key[1] = ~key[0];
+
+ /* Hash the param struct */
+ _siphash (&rand_params, sizeof rand_params, key, digest);
+
+ /** Initialize the rand and sequence counters with our random digest */
+ memcpy (context->randomness, digest, sizeof context->randomness);
+ if (init_seq) {
+ memcpy (&context->seq32, digest + 1, sizeof context->seq32);
+ memcpy (&context->seq64, digest + 1, sizeof context->seq64);
+ /* Chop off some initial bits for nicer counter behavior. This allows the
+ * low digit to start at a zero, and prevents immediately wrapping the
+ * counter in subsequent calls to set_oid_seq. */
+ context->seq32 &= ~UINT32_C (0xf0000f);
+ context->seq64 &= ~UINT64_C (0xf0000f);
+ }
+
+ /* Remember the PID we saw here. This may change in case of fork() */
+ context->pid = rand_params.pid;
+}
+
+static void
+_bson_context_init (bson_context_t *context, bson_context_flags_t flags)
+{
+ context->flags = (int) flags;
+ _bson_context_init_random (context, true /* Init counters */);
+}
+
+
+void
+_bson_context_set_oid_rand (bson_context_t *context, bson_oid_t *oid)
+{
+ BSON_ASSERT (context);
+ BSON_ASSERT (oid);
+
+ if (context->flags & BSON_CONTEXT_DISABLE_PID_CACHE) {
+ /* User has requested that we check if our PID has changed. This can occur
+ * after a call to fork() */
+ uint64_t now_pid = _bson_getpid ();
+ if (now_pid != context->pid) {
+ _bson_context_init_random (
+ context, false /* Do not update the sequence counters */);
+ }
+ }
+ /* Copy the stored randomness into the OID */
+ memcpy (oid->bytes + BSON_OID_RANDOMESS_OFFSET,
+ &context->randomness,
+ BSON_OID_RANDOMNESS_SIZE);
+}
+
+
+bson_context_t *
+bson_context_new (bson_context_flags_t flags)
+{
+ bson_context_t *context;
+
+ context = bson_malloc0 (sizeof *context);
+ _bson_context_init (context, flags);
+
+ return context;
+}
+
+
+void
+bson_context_destroy (bson_context_t *context) /* IN */
+{
+ bson_free (context);
+}
+
+
+static BSON_ONCE_FUN (_bson_context_init_default)
+{
+ _bson_context_init (&gContextDefault, BSON_CONTEXT_DISABLE_PID_CACHE);
+ BSON_ONCE_RETURN;
+}
+
+
+bson_context_t *
+bson_context_get_default (void)
+{
+ static bson_once_t once = BSON_ONCE_INIT;
+
+ bson_once (&once, _bson_context_init_default);
+
+ return &gContextDefault;
+}
diff --git a/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-context.h b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-context.h
new file mode 100644
index 00000000..3098ce60
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-context.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2013 MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bson-prelude.h"
+
+
+#ifndef BSON_CONTEXT_H
+#define BSON_CONTEXT_H
+
+
+#include "bson-macros.h"
+#include "bson-types.h"
+
+
+BSON_BEGIN_DECLS
+
+
+/**
+ * @brief Initialize a new context with the given flags
+ *
+ * @param flags Flags used to configure the behavior of the context. For most
+ * cases, this should be BSON_CONTEXT_NONE.
+ *
+ * @return A newly allocated context. Must be freed with bson_context_destroy()
+ *
+ * @note If you expect your pid to change without notice, such as from an
+ * unexpected call to fork(), then specify BSON_CONTEXT_DISABLE_PID_CACHE in
+ * `flags`.
+ */
+BSON_EXPORT (bson_context_t *)
+bson_context_new (bson_context_flags_t flags);
+
+/**
+ * @brief Destroy and free a bson_context_t created by bson_context_new()
+ */
+BSON_EXPORT (void)
+bson_context_destroy (bson_context_t *context);
+
+/**
+ * @brief Obtain a pointer to the application-default bson_context_t
+ *
+ * @note This context_t MUST NOT be passed to bson_context_destroy()
+ */
+BSON_EXPORT (bson_context_t *)
+bson_context_get_default (void);
+
+
+BSON_END_DECLS
+
+
+#endif /* BSON_CONTEXT_H */
diff --git a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-decimal128.c b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-decimal128.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-decimal128.c
rename to mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-decimal128.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-decimal128.h b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-decimal128.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-decimal128.h
rename to mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-decimal128.h
diff --git a/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-endian.h b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-endian.h
new file mode 100644
index 00000000..1acb5479
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-endian.h
@@ -0,0 +1,227 @@
+/*
+ * Copyright 2013 MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bson-prelude.h"
+
+
+#ifndef BSON_ENDIAN_H
+#define BSON_ENDIAN_H
+
+
+#if defined(__sun)
+#include <sys/byteorder.h>
+#endif
+
+#include "bson-config.h"
+#include "bson-macros.h"
+#include "bson-compat.h"
+
+
+BSON_BEGIN_DECLS
+
+
+#define BSON_BIG_ENDIAN 4321
+#define BSON_LITTLE_ENDIAN 1234
+
+
+#if defined(__sun)
+#define BSON_UINT16_SWAP_LE_BE(v) BSWAP_16 ((uint16_t) v)
+#define BSON_UINT32_SWAP_LE_BE(v) BSWAP_32 ((uint32_t) v)
+#define BSON_UINT64_SWAP_LE_BE(v) BSWAP_64 ((uint64_t) v)
+#elif defined(__clang__) && defined(__clang_major__) && \
+ defined(__clang_minor__) && (__clang_major__ >= 3) && \
+ (__clang_minor__ >= 1)
+#if __has_builtin(__builtin_bswap16)
+#define BSON_UINT16_SWAP_LE_BE(v) __builtin_bswap16 (v)
+#endif
+#if __has_builtin(__builtin_bswap32)
+#define BSON_UINT32_SWAP_LE_BE(v) __builtin_bswap32 (v)
+#endif
+#if __has_builtin(__builtin_bswap64)
+#define BSON_UINT64_SWAP_LE_BE(v) __builtin_bswap64 (v)
+#endif
+#elif defined(__GNUC__) && (__GNUC__ >= 4)
+#if __GNUC__ > 4 || (defined(__GNUC_MINOR__) && __GNUC_MINOR__ >= 3)
+#define BSON_UINT32_SWAP_LE_BE(v) __builtin_bswap32 ((uint32_t) v)
+#define BSON_UINT64_SWAP_LE_BE(v) __builtin_bswap64 ((uint64_t) v)
+#endif
+#if __GNUC__ > 4 || (defined(__GNUC_MINOR__) && __GNUC_MINOR__ >= 8)
+#define BSON_UINT16_SWAP_LE_BE(v) __builtin_bswap16 ((uint32_t) v)
+#endif
+#endif
+
+
+#ifndef BSON_UINT16_SWAP_LE_BE
+#define BSON_UINT16_SWAP_LE_BE(v) __bson_uint16_swap_slow ((uint16_t) v)
+#endif
+
+
+#ifndef BSON_UINT32_SWAP_LE_BE
+#define BSON_UINT32_SWAP_LE_BE(v) __bson_uint32_swap_slow ((uint32_t) v)
+#endif
+
+
+#ifndef BSON_UINT64_SWAP_LE_BE
+#define BSON_UINT64_SWAP_LE_BE(v) __bson_uint64_swap_slow ((uint64_t) v)
+#endif
+
+
+#if BSON_BYTE_ORDER == BSON_LITTLE_ENDIAN
+#define BSON_UINT16_FROM_LE(v) ((uint16_t) v)
+#define BSON_UINT16_TO_LE(v) ((uint16_t) v)
+#define BSON_UINT16_FROM_BE(v) BSON_UINT16_SWAP_LE_BE (v)
+#define BSON_UINT16_TO_BE(v) BSON_UINT16_SWAP_LE_BE (v)
+#define BSON_UINT32_FROM_LE(v) ((uint32_t) v)
+#define BSON_UINT32_TO_LE(v) ((uint32_t) v)
+#define BSON_UINT32_FROM_BE(v) BSON_UINT32_SWAP_LE_BE (v)
+#define BSON_UINT32_TO_BE(v) BSON_UINT32_SWAP_LE_BE (v)
+#define BSON_UINT64_FROM_LE(v) ((uint64_t) v)
+#define BSON_UINT64_TO_LE(v) ((uint64_t) v)
+#define BSON_UINT64_FROM_BE(v) BSON_UINT64_SWAP_LE_BE (v)
+#define BSON_UINT64_TO_BE(v) BSON_UINT64_SWAP_LE_BE (v)
+#define BSON_DOUBLE_FROM_LE(v) ((double) v)
+#define BSON_DOUBLE_TO_LE(v) ((double) v)
+#elif BSON_BYTE_ORDER == BSON_BIG_ENDIAN
+#define BSON_UINT16_FROM_LE(v) BSON_UINT16_SWAP_LE_BE (v)
+#define BSON_UINT16_TO_LE(v) BSON_UINT16_SWAP_LE_BE (v)
+#define BSON_UINT16_FROM_BE(v) ((uint16_t) v)
+#define BSON_UINT16_TO_BE(v) ((uint16_t) v)
+#define BSON_UINT32_FROM_LE(v) BSON_UINT32_SWAP_LE_BE (v)
+#define BSON_UINT32_TO_LE(v) BSON_UINT32_SWAP_LE_BE (v)
+#define BSON_UINT32_FROM_BE(v) ((uint32_t) v)
+#define BSON_UINT32_TO_BE(v) ((uint32_t) v)
+#define BSON_UINT64_FROM_LE(v) BSON_UINT64_SWAP_LE_BE (v)
+#define BSON_UINT64_TO_LE(v) BSON_UINT64_SWAP_LE_BE (v)
+#define BSON_UINT64_FROM_BE(v) ((uint64_t) v)
+#define BSON_UINT64_TO_BE(v) ((uint64_t) v)
+#define BSON_DOUBLE_FROM_LE(v) (__bson_double_swap_slow (v))
+#define BSON_DOUBLE_TO_LE(v) (__bson_double_swap_slow (v))
+#else
+#error "The endianness of target architecture is unknown."
+#endif
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * __bson_uint16_swap_slow --
+ *
+ * Fallback endianness conversion for 16-bit integers.
+ *
+ * Returns:
+ * The endian swapped version.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+static BSON_INLINE uint16_t
+__bson_uint16_swap_slow (uint16_t v) /* IN */
+{
+ return (uint16_t) ((v & 0x00FF) << 8) | (uint16_t) ((v & 0xFF00) >> 8);
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * __bson_uint32_swap_slow --
+ *
+ * Fallback endianness conversion for 32-bit integers.
+ *
+ * Returns:
+ * The endian swapped version.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+static BSON_INLINE uint32_t
+__bson_uint32_swap_slow (uint32_t v) /* IN */
+{
+ return ((v & 0x000000FFU) << 24) | ((v & 0x0000FF00U) << 8) |
+ ((v & 0x00FF0000U) >> 8) | ((v & 0xFF000000U) >> 24);
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * __bson_uint64_swap_slow --
+ *
+ * Fallback endianness conversion for 64-bit integers.
+ *
+ * Returns:
+ * The endian swapped version.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+static BSON_INLINE uint64_t
+__bson_uint64_swap_slow (uint64_t v) /* IN */
+{
+ return ((v & 0x00000000000000FFULL) << 56) |
+ ((v & 0x000000000000FF00ULL) << 40) |
+ ((v & 0x0000000000FF0000ULL) << 24) |
+ ((v & 0x00000000FF000000ULL) << 8) |
+ ((v & 0x000000FF00000000ULL) >> 8) |
+ ((v & 0x0000FF0000000000ULL) >> 24) |
+ ((v & 0x00FF000000000000ULL) >> 40) |
+ ((v & 0xFF00000000000000ULL) >> 56);
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * __bson_double_swap_slow --
+ *
+ * Fallback endianness conversion for double floating point.
+ *
+ * Returns:
+ * The endian swapped version.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+BSON_STATIC_ASSERT2 (sizeof_uint64_t, sizeof (double) == sizeof (uint64_t));
+
+static BSON_INLINE double
+__bson_double_swap_slow (double v) /* IN */
+{
+ uint64_t uv;
+
+ memcpy (&uv, &v, sizeof (v));
+ uv = BSON_UINT64_SWAP_LE_BE (uv);
+ memcpy (&v, &uv, sizeof (v));
+
+ return v;
+}
+
+BSON_END_DECLS
+
+
+#endif /* BSON_ENDIAN_H */
diff --git a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-error.c b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-error.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-error.c
rename to mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-error.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-error.h b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-error.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-error.h
rename to mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-error.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-iso8601-private.h b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-iso8601-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-iso8601-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-iso8601-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-iso8601.c b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-iso8601.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-iso8601.c
rename to mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-iso8601.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-iter.c b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-iter.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-iter.c
rename to mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-iter.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-iter.h b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-iter.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-iter.h
rename to mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-iter.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-json-private.h b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-json-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-json-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-json-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-json.c b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-json.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-json.c
rename to mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-json.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-json.h b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-json.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-json.h
rename to mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-json.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-keys.c b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-keys.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-keys.c
rename to mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-keys.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-keys.h b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-keys.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-keys.h
rename to mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-keys.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-macros.h b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-macros.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-macros.h
rename to mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-macros.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-md5.c b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-md5.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-md5.c
rename to mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-md5.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-md5.h b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-md5.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-md5.h
rename to mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-md5.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-memory.c b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-memory.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-memory.c
rename to mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-memory.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-memory.h b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-memory.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-memory.h
rename to mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-memory.h
diff --git a/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-oid.c b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-oid.c
new file mode 100644
index 00000000..513d0626
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-oid.c
@@ -0,0 +1,293 @@
+/*
+ * Copyright 2013 MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bson-compat.h"
+
+#include <limits.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "bson-context-private.h"
+#include "bson-oid.h"
+#include "bson-string.h"
+
+
+/*
+ * This table contains an array of two character pairs for every possible
+ * uint8_t. It is used as a lookup table when encoding a bson_oid_t
+ * to hex formatted ASCII. Performing two characters at a time roughly
+ * reduces the number of operations by one-half.
+ */
+static const uint16_t gHexCharPairs[] = {
+#if BSON_BYTE_ORDER == BSON_BIG_ENDIAN
+ 12336, 12337, 12338, 12339, 12340, 12341, 12342, 12343, 12344, 12345, 12385,
+ 12386, 12387, 12388, 12389, 12390, 12592, 12593, 12594, 12595, 12596, 12597,
+ 12598, 12599, 12600, 12601, 12641, 12642, 12643, 12644, 12645, 12646, 12848,
+ 12849, 12850, 12851, 12852, 12853, 12854, 12855, 12856, 12857, 12897, 12898,
+ 12899, 12900, 12901, 12902, 13104, 13105, 13106, 13107, 13108, 13109, 13110,
+ 13111, 13112, 13113, 13153, 13154, 13155, 13156, 13157, 13158, 13360, 13361,
+ 13362, 13363, 13364, 13365, 13366, 13367, 13368, 13369, 13409, 13410, 13411,
+ 13412, 13413, 13414, 13616, 13617, 13618, 13619, 13620, 13621, 13622, 13623,
+ 13624, 13625, 13665, 13666, 13667, 13668, 13669, 13670, 13872, 13873, 13874,
+ 13875, 13876, 13877, 13878, 13879, 13880, 13881, 13921, 13922, 13923, 13924,
+ 13925, 13926, 14128, 14129, 14130, 14131, 14132, 14133, 14134, 14135, 14136,
+ 14137, 14177, 14178, 14179, 14180, 14181, 14182, 14384, 14385, 14386, 14387,
+ 14388, 14389, 14390, 14391, 14392, 14393, 14433, 14434, 14435, 14436, 14437,
+ 14438, 14640, 14641, 14642, 14643, 14644, 14645, 14646, 14647, 14648, 14649,
+ 14689, 14690, 14691, 14692, 14693, 14694, 24880, 24881, 24882, 24883, 24884,
+ 24885, 24886, 24887, 24888, 24889, 24929, 24930, 24931, 24932, 24933, 24934,
+ 25136, 25137, 25138, 25139, 25140, 25141, 25142, 25143, 25144, 25145, 25185,
+ 25186, 25187, 25188, 25189, 25190, 25392, 25393, 25394, 25395, 25396, 25397,
+ 25398, 25399, 25400, 25401, 25441, 25442, 25443, 25444, 25445, 25446, 25648,
+ 25649, 25650, 25651, 25652, 25653, 25654, 25655, 25656, 25657, 25697, 25698,
+ 25699, 25700, 25701, 25702, 25904, 25905, 25906, 25907, 25908, 25909, 25910,
+ 25911, 25912, 25913, 25953, 25954, 25955, 25956, 25957, 25958, 26160, 26161,
+ 26162, 26163, 26164, 26165, 26166, 26167, 26168, 26169, 26209, 26210, 26211,
+ 26212, 26213, 26214
+#else
+ 12336, 12592, 12848, 13104, 13360, 13616, 13872, 14128, 14384, 14640, 24880,
+ 25136, 25392, 25648, 25904, 26160, 12337, 12593, 12849, 13105, 13361, 13617,
+ 13873, 14129, 14385, 14641, 24881, 25137, 25393, 25649, 25905, 26161, 12338,
+ 12594, 12850, 13106, 13362, 13618, 13874, 14130, 14386, 14642, 24882, 25138,
+ 25394, 25650, 25906, 26162, 12339, 12595, 12851, 13107, 13363, 13619, 13875,
+ 14131, 14387, 14643, 24883, 25139, 25395, 25651, 25907, 26163, 12340, 12596,
+ 12852, 13108, 13364, 13620, 13876, 14132, 14388, 14644, 24884, 25140, 25396,
+ 25652, 25908, 26164, 12341, 12597, 12853, 13109, 13365, 13621, 13877, 14133,
+ 14389, 14645, 24885, 25141, 25397, 25653, 25909, 26165, 12342, 12598, 12854,
+ 13110, 13366, 13622, 13878, 14134, 14390, 14646, 24886, 25142, 25398, 25654,
+ 25910, 26166, 12343, 12599, 12855, 13111, 13367, 13623, 13879, 14135, 14391,
+ 14647, 24887, 25143, 25399, 25655, 25911, 26167, 12344, 12600, 12856, 13112,
+ 13368, 13624, 13880, 14136, 14392, 14648, 24888, 25144, 25400, 25656, 25912,
+ 26168, 12345, 12601, 12857, 13113, 13369, 13625, 13881, 14137, 14393, 14649,
+ 24889, 25145, 25401, 25657, 25913, 26169, 12385, 12641, 12897, 13153, 13409,
+ 13665, 13921, 14177, 14433, 14689, 24929, 25185, 25441, 25697, 25953, 26209,
+ 12386, 12642, 12898, 13154, 13410, 13666, 13922, 14178, 14434, 14690, 24930,
+ 25186, 25442, 25698, 25954, 26210, 12387, 12643, 12899, 13155, 13411, 13667,
+ 13923, 14179, 14435, 14691, 24931, 25187, 25443, 25699, 25955, 26211, 12388,
+ 12644, 12900, 13156, 13412, 13668, 13924, 14180, 14436, 14692, 24932, 25188,
+ 25444, 25700, 25956, 26212, 12389, 12645, 12901, 13157, 13413, 13669, 13925,
+ 14181, 14437, 14693, 24933, 25189, 25445, 25701, 25957, 26213, 12390, 12646,
+ 12902, 13158, 13414, 13670, 13926, 14182, 14438, 14694, 24934, 25190, 25446,
+ 25702, 25958, 26214
+#endif
+};
+
+
+void
+bson_oid_init_sequence (bson_oid_t *oid, /* OUT */
+ bson_context_t *context) /* IN */
+{
+ uint32_t now = (uint32_t) (time (NULL));
+
+ if (!context) {
+ context = bson_context_get_default ();
+ }
+
+ now = BSON_UINT32_TO_BE (now);
+ memcpy (&oid->bytes[0], &now, sizeof (now));
+ _bson_context_set_oid_seq64 (context, oid);
+}
+
+
+void
+bson_oid_init (bson_oid_t *oid, /* OUT */
+ bson_context_t *context) /* IN */
+{
+ uint32_t now = (uint32_t) (time (NULL));
+
+ BSON_ASSERT (oid);
+
+ if (!context) {
+ context = bson_context_get_default ();
+ }
+
+ now = BSON_UINT32_TO_BE (now);
+ memcpy (&oid->bytes[0], &now, sizeof (now));
+ _bson_context_set_oid_rand (context, oid);
+ _bson_context_set_oid_seq32 (context, oid);
+}
+
+
+void
+bson_oid_init_from_data (bson_oid_t *oid, /* OUT */
+ const uint8_t *data) /* IN */
+{
+ BSON_ASSERT (oid);
+ BSON_ASSERT (data);
+
+ memcpy (oid, data, 12);
+}
+
+
+void
+bson_oid_init_from_string (bson_oid_t *oid, /* OUT */
+ const char *str) /* IN */
+{
+ BSON_ASSERT (oid);
+ BSON_ASSERT (str);
+
+ bson_oid_init_from_string_unsafe (oid, str);
+}
+
+
+time_t
+bson_oid_get_time_t (const bson_oid_t *oid) /* IN */
+{
+ BSON_ASSERT (oid);
+
+ return bson_oid_get_time_t_unsafe (oid);
+}
+
+
+void
+bson_oid_to_string (const bson_oid_t *oid, /* IN */
+ char str[BSON_ENSURE_ARRAY_PARAM_SIZE (25)]) /* OUT */
+{
+#if !defined(__i386__) && !defined(__x86_64__) && !defined(_M_IX86) && \
+ !defined(_M_X64)
+ BSON_ASSERT (oid);
+ BSON_ASSERT (str);
+
+ bson_snprintf (str,
+ 25,
+ "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
+ oid->bytes[0],
+ oid->bytes[1],
+ oid->bytes[2],
+ oid->bytes[3],
+ oid->bytes[4],
+ oid->bytes[5],
+ oid->bytes[6],
+ oid->bytes[7],
+ oid->bytes[8],
+ oid->bytes[9],
+ oid->bytes[10],
+ oid->bytes[11]);
+#else
+ uint16_t *dst;
+ uint8_t *id = (uint8_t *) oid;
+
+ BSON_ASSERT (oid);
+ BSON_ASSERT (str);
+
+ dst = (uint16_t *) (void *) str;
+ dst[0] = gHexCharPairs[id[0]];
+ dst[1] = gHexCharPairs[id[1]];
+ dst[2] = gHexCharPairs[id[2]];
+ dst[3] = gHexCharPairs[id[3]];
+ dst[4] = gHexCharPairs[id[4]];
+ dst[5] = gHexCharPairs[id[5]];
+ dst[6] = gHexCharPairs[id[6]];
+ dst[7] = gHexCharPairs[id[7]];
+ dst[8] = gHexCharPairs[id[8]];
+ dst[9] = gHexCharPairs[id[9]];
+ dst[10] = gHexCharPairs[id[10]];
+ dst[11] = gHexCharPairs[id[11]];
+ str[24] = '\0';
+#endif
+}
+
+
+uint32_t
+bson_oid_hash (const bson_oid_t *oid) /* IN */
+{
+ BSON_ASSERT (oid);
+
+ return bson_oid_hash_unsafe (oid);
+}
+
+
+int
+bson_oid_compare (const bson_oid_t *oid1, /* IN */
+ const bson_oid_t *oid2) /* IN */
+{
+ BSON_ASSERT (oid1);
+ BSON_ASSERT (oid2);
+
+ return bson_oid_compare_unsafe (oid1, oid2);
+}
+
+
+bool
+bson_oid_equal (const bson_oid_t *oid1, /* IN */
+ const bson_oid_t *oid2) /* IN */
+{
+ BSON_ASSERT (oid1);
+ BSON_ASSERT (oid2);
+
+ return bson_oid_equal_unsafe (oid1, oid2);
+}
+
+
+void
+bson_oid_copy (const bson_oid_t *src, /* IN */
+ bson_oid_t *dst) /* OUT */
+{
+ BSON_ASSERT (src);
+ BSON_ASSERT (dst);
+
+ bson_oid_copy_unsafe (src, dst);
+}
+
+
+bool
+bson_oid_is_valid (const char *str, /* IN */
+ size_t length) /* IN */
+{
+ size_t i;
+
+ BSON_ASSERT (str);
+
+ if ((length == 25) && (str[24] == '\0')) {
+ length = 24;
+ }
+
+ if (length == 24) {
+ for (i = 0; i < length; i++) {
+ switch (str[i]) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ break;
+ default:
+ return false;
+ }
+ }
+ return true;
+ }
+
+ return false;
+}
diff --git a/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-oid.h b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-oid.h
new file mode 100644
index 00000000..8586df8e
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-oid.h
@@ -0,0 +1,244 @@
+/*
+ * Copyright 2013 MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bson-prelude.h"
+
+
+#ifndef BSON_OID_H
+#define BSON_OID_H
+
+
+#include <time.h>
+
+#include "bson-context.h"
+#include "bson-macros.h"
+#include "bson-types.h"
+#include "bson-endian.h"
+
+
+BSON_BEGIN_DECLS
+
+
+BSON_EXPORT (int)
+bson_oid_compare (const bson_oid_t *oid1, const bson_oid_t *oid2);
+BSON_EXPORT (void)
+bson_oid_copy (const bson_oid_t *src, bson_oid_t *dst);
+BSON_EXPORT (bool)
+bson_oid_equal (const bson_oid_t *oid1, const bson_oid_t *oid2);
+BSON_EXPORT (bool)
+bson_oid_is_valid (const char *str, size_t length);
+BSON_EXPORT (time_t)
+bson_oid_get_time_t (const bson_oid_t *oid);
+BSON_EXPORT (uint32_t)
+bson_oid_hash (const bson_oid_t *oid);
+BSON_EXPORT (void)
+bson_oid_init (bson_oid_t *oid, bson_context_t *context);
+BSON_EXPORT (void)
+bson_oid_init_from_data (bson_oid_t *oid, const uint8_t *data);
+BSON_EXPORT (void)
+bson_oid_init_from_string (bson_oid_t *oid, const char *str);
+BSON_EXPORT (void)
+bson_oid_init_sequence (bson_oid_t *oid,
+ bson_context_t *context) BSON_GNUC_DEPRECATED;
+BSON_EXPORT (void)
+bson_oid_to_string (const bson_oid_t *oid, char str[25]);
+
+
+/**
+ * bson_oid_compare_unsafe:
+ * @oid1: A bson_oid_t.
+ * @oid2: A bson_oid_t.
+ *
+ * Performs a qsort() style comparison between @oid1 and @oid2.
+ *
+ * This function is meant to be as fast as possible and therefore performs
+ * no argument validation. That is the callers responsibility.
+ *
+ * Returns: An integer < 0 if @oid1 is less than @oid2. Zero if they are equal.
+ * An integer > 0 if @oid1 is greater than @oid2.
+ */
+static BSON_INLINE int
+bson_oid_compare_unsafe (const bson_oid_t *oid1, const bson_oid_t *oid2)
+{
+ return memcmp (oid1, oid2, sizeof *oid1);
+}
+
+
+/**
+ * bson_oid_equal_unsafe:
+ * @oid1: A bson_oid_t.
+ * @oid2: A bson_oid_t.
+ *
+ * Checks the equality of @oid1 and @oid2.
+ *
+ * This function is meant to be as fast as possible and therefore performs
+ * no checks for argument validity. That is the callers responsibility.
+ *
+ * Returns: true if @oid1 and @oid2 are equal; otherwise false.
+ */
+static BSON_INLINE bool
+bson_oid_equal_unsafe (const bson_oid_t *oid1, const bson_oid_t *oid2)
+{
+ return !memcmp (oid1, oid2, sizeof *oid1);
+}
+
+/**
+ * bson_oid_hash_unsafe:
+ * @oid: A bson_oid_t.
+ *
+ * This function performs a DJB style hash upon the bytes contained in @oid.
+ * The result is a hash key suitable for use in a hashtable.
+ *
+ * This function is meant to be as fast as possible and therefore performs no
+ * validation of arguments. The caller is responsible to ensure they are
+ * passing valid arguments.
+ *
+ * Returns: A uint32_t containing a hash code.
+ */
+static BSON_INLINE uint32_t
+bson_oid_hash_unsafe (const bson_oid_t *oid)
+{
+ uint32_t hash = 5381;
+ uint32_t i;
+
+ for (i = 0; i < sizeof oid->bytes; i++) {
+ hash = ((hash << 5) + hash) + oid->bytes[i];
+ }
+
+ return hash;
+}
+
+
+/**
+ * bson_oid_copy_unsafe:
+ * @src: A bson_oid_t to copy from.
+ * @dst: A bson_oid_t to copy into.
+ *
+ * Copies the contents of @src into @dst. This function is meant to be as
+ * fast as possible and therefore performs no argument checking. It is the
+ * callers responsibility to ensure they are passing valid data into the
+ * function.
+ */
+static BSON_INLINE void
+bson_oid_copy_unsafe (const bson_oid_t *src, bson_oid_t *dst)
+{
+ memcpy (dst, src, sizeof *src);
+}
+
+
+/**
+ * bson_oid_parse_hex_char:
+ * @hex: A character to parse to its integer value.
+ *
+ * This function contains a jump table to return the integer value for a
+ * character containing a hexadecimal value (0-9, a-f, A-F). If the character
+ * is not a hexadecimal character then zero is returned.
+ *
+ * Returns: An integer between 0 and 15.
+ */
+static BSON_INLINE uint8_t
+bson_oid_parse_hex_char (char hex)
+{
+ switch (hex) {
+ case '0':
+ return 0;
+ case '1':
+ return 1;
+ case '2':
+ return 2;
+ case '3':
+ return 3;
+ case '4':
+ return 4;
+ case '5':
+ return 5;
+ case '6':
+ return 6;
+ case '7':
+ return 7;
+ case '8':
+ return 8;
+ case '9':
+ return 9;
+ case 'a':
+ case 'A':
+ return 0xa;
+ case 'b':
+ case 'B':
+ return 0xb;
+ case 'c':
+ case 'C':
+ return 0xc;
+ case 'd':
+ case 'D':
+ return 0xd;
+ case 'e':
+ case 'E':
+ return 0xe;
+ case 'f':
+ case 'F':
+ return 0xf;
+ default:
+ return 0;
+ }
+}
+
+
+/**
+ * bson_oid_init_from_string_unsafe:
+ * @oid: A bson_oid_t to store the result.
+ * @str: A 24-character hexadecimal encoded string.
+ *
+ * Parses a string containing 24 hexadecimal encoded bytes into a bson_oid_t.
+ * This function is meant to be as fast as possible and inlined into your
+ * code. For that purpose, the function does not perform any sort of bounds
+ * checking and it is the callers responsibility to ensure they are passing
+ * valid input to the function.
+ */
+static BSON_INLINE void
+bson_oid_init_from_string_unsafe (bson_oid_t *oid, const char *str)
+{
+ int i;
+
+ for (i = 0; i < 12; i++) {
+ oid->bytes[i] = (uint8_t) ((bson_oid_parse_hex_char (str[2 * i]) << 4) |
+ (bson_oid_parse_hex_char (str[2 * i + 1])));
+ }
+}
+
+
+/**
+ * bson_oid_get_time_t_unsafe:
+ * @oid: A bson_oid_t.
+ *
+ * Fetches the time @oid was generated.
+ *
+ * Returns: A time_t containing the UNIX timestamp of generation.
+ */
+static BSON_INLINE time_t
+bson_oid_get_time_t_unsafe (const bson_oid_t *oid)
+{
+ uint32_t t;
+
+ memcpy (&t, oid, sizeof (t));
+ return BSON_UINT32_FROM_BE (t);
+}
+
+
+BSON_END_DECLS
+
+
+#endif /* BSON_OID_H */
diff --git a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-prelude.h b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-prelude.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-prelude.h
rename to mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-prelude.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-private.h b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-reader.c b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-reader.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-reader.c
rename to mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-reader.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-reader.h b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-reader.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-reader.h
rename to mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-reader.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-string.c b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-string.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-string.c
rename to mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-string.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-string.h b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-string.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-string.h
rename to mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-string.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-timegm-private.h b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-timegm-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-timegm-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-timegm-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-timegm.c b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-timegm.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-timegm.c
rename to mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-timegm.c
diff --git a/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-types.h b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-types.h
new file mode 100644
index 00000000..498d5432
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-types.h
@@ -0,0 +1,566 @@
+/*
+ * Copyright 2013 MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bson-prelude.h"
+
+
+#ifndef BSON_TYPES_H
+#define BSON_TYPES_H
+
+
+#include <stdlib.h>
+#include <sys/types.h>
+
+#include "bson-macros.h"
+#include "bson-config.h"
+#include "bson-compat.h"
+#include "bson-endian.h"
+
+BSON_BEGIN_DECLS
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * bson_unichar_t --
+ *
+ * bson_unichar_t provides an unsigned 32-bit type for containing
+ * unicode characters. When iterating UTF-8 sequences, this should
+ * be used to avoid losing the high-bits of non-ascii characters.
+ *
+ * See also:
+ * bson_string_append_unichar()
+ *
+ *--------------------------------------------------------------------------
+ */
+
+typedef uint32_t bson_unichar_t;
+
+
+/**
+ * @brief Flags configuring the creation of a bson_context_t
+ */
+typedef enum {
+ /** Use default options */
+ BSON_CONTEXT_NONE = 0,
+ /* Deprecated: Generating new OIDs from a bson_context_t is always
+ thread-safe */
+ BSON_CONTEXT_THREAD_SAFE = (1 << 0),
+ /* Deprecated: Does nothing and is ignored */
+ BSON_CONTEXT_DISABLE_HOST_CACHE = (1 << 1),
+ /* Call getpid() instead of remembering the result of getpid() when using the
+ context */
+ BSON_CONTEXT_DISABLE_PID_CACHE = (1 << 2),
+ /* Deprecated: Does nothing */
+ BSON_CONTEXT_USE_TASK_ID = (1 << 3),
+} bson_context_flags_t;
+
+
+/**
+ * bson_context_t:
+ *
+ * This structure manages context for the bson library. It handles
+ * configuration for thread-safety and other performance related requirements.
+ * Consumers will create a context and may use multiple under a variety of
+ * situations.
+ *
+ * If your program calls fork(), you should initialize a new bson_context_t
+ * using bson_context_init().
+ *
+ * If you are using threading, it is suggested that you use a bson_context_t
+ * per thread for best performance. Alternatively, you can initialize the
+ * bson_context_t with BSON_CONTEXT_THREAD_SAFE, although a performance penalty
+ * will be incurred.
+ *
+ * Many functions will require that you provide a bson_context_t such as OID
+ * generation.
+ *
+ * This structure is opaque in that you cannot see the contents of the
+ * structure. However, it is stack allocatable in that enough padding is
+ * provided in _bson_context_t to hold the structure.
+ */
+typedef struct _bson_context_t bson_context_t;
+
+/**
+ * bson_json_opts_t:
+ *
+ * This structure is used to pass options for serializing BSON into extended
+ * JSON to the respective serialization methods.
+ *
+ * max_len can be either a non-negative integer, or BSON_MAX_LEN_UNLIMITED to
+ * set no limit for serialization length.
+ */
+typedef struct _bson_json_opts_t bson_json_opts_t;
+
+
+/**
+ * bson_t:
+ *
+ * This structure manages a buffer whose contents are a properly formatted
+ * BSON document. You may perform various transforms on the BSON documents.
+ * Additionally, it can be iterated over using bson_iter_t.
+ *
+ * See bson_iter_init() for iterating the contents of a bson_t.
+ *
+ * When building a bson_t structure using the various append functions,
+ * memory allocations may occur. That is performed using power of two
+ * allocations and realloc().
+ *
+ * See http://bsonspec.org for the BSON document spec.
+ *
+ * This structure is meant to fit in two sequential 64-byte cachelines.
+ */
+#ifdef BSON_MEMCHECK
+BSON_ALIGNED_BEGIN (128) typedef struct _bson_t {
+ uint32_t flags; /* Internal flags for the bson_t. */
+ uint32_t len; /* Length of BSON data. */
+ char *canary; /* For valgrind check */
+ uint8_t padding[120 - sizeof (char *)];
+} bson_t BSON_ALIGNED_END (128);
+#else
+BSON_ALIGNED_BEGIN (128) typedef struct _bson_t {
+ uint32_t flags; /* Internal flags for the bson_t. */
+ uint32_t len; /* Length of BSON data. */
+ uint8_t padding[120]; /* Padding for stack allocation. */
+} bson_t BSON_ALIGNED_END (128);
+#endif
+
+/**
+ * BSON_INITIALIZER:
+ *
+ * This macro can be used to initialize a #bson_t structure on the stack
+ * without calling bson_init().
+ *
+ * |[
+ * bson_t b = BSON_INITIALIZER;
+ * ]|
+ */
+#ifdef BSON_MEMCHECK
+#define BSON_INITIALIZER \
+ { \
+ 3, 5, bson_malloc (1), {5}, \
+ }
+#else
+#define BSON_INITIALIZER \
+ { \
+ 3, 5, \
+ { \
+ 5 \
+ } \
+ }
+#endif
+
+
+BSON_STATIC_ASSERT2 (bson_t, sizeof (bson_t) == 128);
+
+
+/**
+ * bson_oid_t:
+ *
+ * This structure contains the binary form of a BSON Object Id as specified
+ * on http://bsonspec.org. If you would like the bson_oid_t in string form
+ * see bson_oid_to_string() or bson_oid_to_string_r().
+ */
+typedef struct {
+ uint8_t bytes[12];
+} bson_oid_t;
+
+BSON_STATIC_ASSERT2 (oid_t, sizeof (bson_oid_t) == 12);
+
+/**
+ * bson_decimal128_t:
+ *
+ * @high The high-order bytes of the decimal128. This field contains sign,
+ * combination bits, exponent, and part of the coefficient continuation.
+ * @low The low-order bytes of the decimal128. This field contains the second
+ * part of the coefficient continuation.
+ *
+ * This structure is a boxed type containing the value for the BSON decimal128
+ * type. The structure stores the 128 bits such that they correspond to the
+ * native format for the IEEE decimal128 type, if it is implemented.
+ **/
+typedef struct {
+#if BSON_BYTE_ORDER == BSON_LITTLE_ENDIAN
+ uint64_t low;
+ uint64_t high;
+#elif BSON_BYTE_ORDER == BSON_BIG_ENDIAN
+ uint64_t high;
+ uint64_t low;
+#endif
+} bson_decimal128_t;
+
+
+/**
+ * bson_validate_flags_t:
+ *
+ * This enumeration is used for validation of BSON documents. It allows
+ * selective control on what you wish to validate.
+ *
+ * %BSON_VALIDATE_NONE: No additional validation occurs.
+ * %BSON_VALIDATE_UTF8: Check that strings are valid UTF-8.
+ * %BSON_VALIDATE_DOLLAR_KEYS: Check that keys do not start with $.
+ * %BSON_VALIDATE_DOT_KEYS: Check that keys do not contain a period.
+ * %BSON_VALIDATE_UTF8_ALLOW_NULL: Allow NUL bytes in UTF-8 text.
+ * %BSON_VALIDATE_EMPTY_KEYS: Prohibit zero-length field names
+ */
+typedef enum {
+ BSON_VALIDATE_NONE = 0,
+ BSON_VALIDATE_UTF8 = (1 << 0),
+ BSON_VALIDATE_DOLLAR_KEYS = (1 << 1),
+ BSON_VALIDATE_DOT_KEYS = (1 << 2),
+ BSON_VALIDATE_UTF8_ALLOW_NULL = (1 << 3),
+ BSON_VALIDATE_EMPTY_KEYS = (1 << 4),
+} bson_validate_flags_t;
+
+
+/**
+ * bson_type_t:
+ *
+ * This enumeration contains all of the possible types within a BSON document.
+ * Use bson_iter_type() to fetch the type of a field while iterating over it.
+ */
+typedef enum {
+ BSON_TYPE_EOD = 0x00,
+ BSON_TYPE_DOUBLE = 0x01,
+ BSON_TYPE_UTF8 = 0x02,
+ BSON_TYPE_DOCUMENT = 0x03,
+ BSON_TYPE_ARRAY = 0x04,
+ BSON_TYPE_BINARY = 0x05,
+ BSON_TYPE_UNDEFINED = 0x06,
+ BSON_TYPE_OID = 0x07,
+ BSON_TYPE_BOOL = 0x08,
+ BSON_TYPE_DATE_TIME = 0x09,
+ BSON_TYPE_NULL = 0x0A,
+ BSON_TYPE_REGEX = 0x0B,
+ BSON_TYPE_DBPOINTER = 0x0C,
+ BSON_TYPE_CODE = 0x0D,
+ BSON_TYPE_SYMBOL = 0x0E,
+ BSON_TYPE_CODEWSCOPE = 0x0F,
+ BSON_TYPE_INT32 = 0x10,
+ BSON_TYPE_TIMESTAMP = 0x11,
+ BSON_TYPE_INT64 = 0x12,
+ BSON_TYPE_DECIMAL128 = 0x13,
+ BSON_TYPE_MAXKEY = 0x7F,
+ BSON_TYPE_MINKEY = 0xFF,
+} bson_type_t;
+
+
+/**
+ * bson_subtype_t:
+ *
+ * This enumeration contains the various subtypes that may be used in a binary
+ * field. See http://bsonspec.org for more information.
+ */
+typedef enum {
+ BSON_SUBTYPE_BINARY = 0x00,
+ BSON_SUBTYPE_FUNCTION = 0x01,
+ BSON_SUBTYPE_BINARY_DEPRECATED = 0x02,
+ BSON_SUBTYPE_UUID_DEPRECATED = 0x03,
+ BSON_SUBTYPE_UUID = 0x04,
+ BSON_SUBTYPE_MD5 = 0x05,
+ BSON_SUBTYPE_ENCRYPTED = 0x06,
+ BSON_SUBTYPE_COLUMN = 0x07,
+ BSON_SUBTYPE_USER = 0x80,
+} bson_subtype_t;
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * bson_value_t --
+ *
+ * A boxed type to contain various bson_type_t types.
+ *
+ * See also:
+ * bson_value_copy()
+ * bson_value_destroy()
+ *
+ *--------------------------------------------------------------------------
+ */
+
+BSON_ALIGNED_BEGIN (8)
+typedef struct _bson_value_t {
+ bson_type_t value_type;
+ int32_t padding;
+ union {
+ bson_oid_t v_oid;
+ int64_t v_int64;
+ int32_t v_int32;
+ int8_t v_int8;
+ double v_double;
+ bool v_bool;
+ int64_t v_datetime;
+ struct {
+ uint32_t timestamp;
+ uint32_t increment;
+ } v_timestamp;
+ struct {
+ char *str;
+ uint32_t len;
+ } v_utf8;
+ struct {
+ uint8_t *data;
+ uint32_t data_len;
+ } v_doc;
+ struct {
+ uint8_t *data;
+ uint32_t data_len;
+ bson_subtype_t subtype;
+ } v_binary;
+ struct {
+ char *regex;
+ char *options;
+ } v_regex;
+ struct {
+ char *collection;
+ uint32_t collection_len;
+ bson_oid_t oid;
+ } v_dbpointer;
+ struct {
+ char *code;
+ uint32_t code_len;
+ } v_code;
+ struct {
+ char *code;
+ uint8_t *scope_data;
+ uint32_t code_len;
+ uint32_t scope_len;
+ } v_codewscope;
+ struct {
+ char *symbol;
+ uint32_t len;
+ } v_symbol;
+ bson_decimal128_t v_decimal128;
+ } value;
+} bson_value_t BSON_ALIGNED_END (8);
+
+
+/**
+ * bson_iter_t:
+ *
+ * This structure manages iteration over a bson_t structure. It keeps track
+ * of the location of the current key and value within the buffer. Using the
+ * various functions to get the value of the iter will read from these
+ * locations.
+ *
+ * This structure is safe to discard on the stack. No cleanup is necessary
+ * after using it.
+ */
+BSON_ALIGNED_BEGIN (128)
+typedef struct {
+ const uint8_t *raw; /* The raw buffer being iterated. */
+ uint32_t len; /* The length of raw. */
+ uint32_t off; /* The offset within the buffer. */
+ uint32_t type; /* The offset of the type byte. */
+ uint32_t key; /* The offset of the key byte. */
+ uint32_t d1; /* The offset of the first data byte. */
+ uint32_t d2; /* The offset of the second data byte. */
+ uint32_t d3; /* The offset of the third data byte. */
+ uint32_t d4; /* The offset of the fourth data byte. */
+ uint32_t next_off; /* The offset of the next field. */
+ uint32_t err_off; /* The offset of the error. */
+ bson_value_t value; /* Internal value for various state. */
+} bson_iter_t BSON_ALIGNED_END (128);
+
+
+/**
+ * bson_reader_t:
+ *
+ * This structure is used to iterate over a sequence of BSON documents. It
+ * allows for them to be iterated with the possibility of no additional
+ * memory allocations under certain circumstances such as reading from an
+ * incoming mongo packet.
+ */
+
+BSON_ALIGNED_BEGIN (BSON_ALIGN_OF_PTR)
+typedef struct {
+ uint32_t type;
+ /*< private >*/
+} bson_reader_t BSON_ALIGNED_END (BSON_ALIGN_OF_PTR);
+
+
+/**
+ * bson_visitor_t:
+ *
+ * This structure contains a series of pointers that can be executed for
+ * each field of a BSON document based on the field type.
+ *
+ * For example, if an int32 field is found, visit_int32 will be called.
+ *
+ * When visiting each field using bson_iter_visit_all(), you may provide a
+ * data pointer that will be provided with each callback. This might be useful
+ * if you are marshaling to another language.
+ *
+ * You may pre-maturely stop the visitation of fields by returning true in your
+ * visitor. Returning false will continue visitation to further fields.
+ */
+BSON_ALIGNED_BEGIN (8)
+typedef struct {
+ /* run before / after descending into a document */
+ bool (*visit_before) (const bson_iter_t *iter, const char *key, void *data);
+ bool (*visit_after) (const bson_iter_t *iter, const char *key, void *data);
+ /* corrupt BSON, or unsupported type and visit_unsupported_type not set */
+ void (*visit_corrupt) (const bson_iter_t *iter, void *data);
+ /* normal bson field callbacks */
+ bool (*visit_double) (const bson_iter_t *iter,
+ const char *key,
+ double v_double,
+ void *data);
+ bool (*visit_utf8) (const bson_iter_t *iter,
+ const char *key,
+ size_t v_utf8_len,
+ const char *v_utf8,
+ void *data);
+ bool (*visit_document) (const bson_iter_t *iter,
+ const char *key,
+ const bson_t *v_document,
+ void *data);
+ bool (*visit_array) (const bson_iter_t *iter,
+ const char *key,
+ const bson_t *v_array,
+ void *data);
+ bool (*visit_binary) (const bson_iter_t *iter,
+ const char *key,
+ bson_subtype_t v_subtype,
+ size_t v_binary_len,
+ const uint8_t *v_binary,
+ void *data);
+ /* normal field with deprecated "Undefined" BSON type */
+ bool (*visit_undefined) (const bson_iter_t *iter,
+ const char *key,
+ void *data);
+ bool (*visit_oid) (const bson_iter_t *iter,
+ const char *key,
+ const bson_oid_t *v_oid,
+ void *data);
+ bool (*visit_bool) (const bson_iter_t *iter,
+ const char *key,
+ bool v_bool,
+ void *data);
+ bool (*visit_date_time) (const bson_iter_t *iter,
+ const char *key,
+ int64_t msec_since_epoch,
+ void *data);
+ bool (*visit_null) (const bson_iter_t *iter, const char *key, void *data);
+ bool (*visit_regex) (const bson_iter_t *iter,
+ const char *key,
+ const char *v_regex,
+ const char *v_options,
+ void *data);
+ bool (*visit_dbpointer) (const bson_iter_t *iter,
+ const char *key,
+ size_t v_collection_len,
+ const char *v_collection,
+ const bson_oid_t *v_oid,
+ void *data);
+ bool (*visit_code) (const bson_iter_t *iter,
+ const char *key,
+ size_t v_code_len,
+ const char *v_code,
+ void *data);
+ bool (*visit_symbol) (const bson_iter_t *iter,
+ const char *key,
+ size_t v_symbol_len,
+ const char *v_symbol,
+ void *data);
+ bool (*visit_codewscope) (const bson_iter_t *iter,
+ const char *key,
+ size_t v_code_len,
+ const char *v_code,
+ const bson_t *v_scope,
+ void *data);
+ bool (*visit_int32) (const bson_iter_t *iter,
+ const char *key,
+ int32_t v_int32,
+ void *data);
+ bool (*visit_timestamp) (const bson_iter_t *iter,
+ const char *key,
+ uint32_t v_timestamp,
+ uint32_t v_increment,
+ void *data);
+ bool (*visit_int64) (const bson_iter_t *iter,
+ const char *key,
+ int64_t v_int64,
+ void *data);
+ bool (*visit_maxkey) (const bson_iter_t *iter, const char *key, void *data);
+ bool (*visit_minkey) (const bson_iter_t *iter, const char *key, void *data);
+ /* if set, called instead of visit_corrupt when an apparently valid BSON
+ * includes an unrecognized field type (reading future version of BSON) */
+ void (*visit_unsupported_type) (const bson_iter_t *iter,
+ const char *key,
+ uint32_t type_code,
+ void *data);
+ bool (*visit_decimal128) (const bson_iter_t *iter,
+ const char *key,
+ const bson_decimal128_t *v_decimal128,
+ void *data);
+
+ void *padding[7];
+} bson_visitor_t BSON_ALIGNED_END (8);
+
+#define BSON_ERROR_BUFFER_SIZE 504
+
+BSON_ALIGNED_BEGIN (8)
+typedef struct _bson_error_t {
+ uint32_t domain;
+ uint32_t code;
+ char message[BSON_ERROR_BUFFER_SIZE];
+} bson_error_t BSON_ALIGNED_END (8);
+
+
+BSON_STATIC_ASSERT2 (error_t, sizeof (bson_error_t) == 512);
+
+
+/**
+ * bson_next_power_of_two:
+ * @v: A 32-bit unsigned integer of required bytes.
+ *
+ * Determines the next larger power of two for the value of @v
+ * in a constant number of operations.
+ *
+ * It is up to the caller to guarantee this will not overflow.
+ *
+ * Returns: The next power of 2 from @v.
+ */
+static BSON_INLINE size_t
+bson_next_power_of_two (size_t v)
+{
+ v--;
+ v |= v >> 1;
+ v |= v >> 2;
+ v |= v >> 4;
+ v |= v >> 8;
+ v |= v >> 16;
+#if BSON_WORD_SIZE == 64
+ v |= v >> 32;
+#endif
+ v++;
+
+ return v;
+}
+
+
+static BSON_INLINE bool
+bson_is_power_of_two (uint32_t v)
+{
+ return ((v != 0) && ((v & (v - 1)) == 0));
+}
+
+
+BSON_END_DECLS
+
+
+#endif /* BSON_TYPES_H */
diff --git a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-utf8.c b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-utf8.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-utf8.c
rename to mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-utf8.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-utf8.h b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-utf8.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-utf8.h
rename to mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-utf8.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-value.c b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-value.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-value.c
rename to mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-value.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-value.h b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-value.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-value.h
rename to mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-value.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-version-functions.c b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-version-functions.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-version-functions.c
rename to mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-version-functions.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-version-functions.h b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-version-functions.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-version-functions.h
rename to mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-version-functions.h
diff --git a/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-version.h b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-version.h
new file mode 100644
index 00000000..dec6ad95
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-version.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2013 MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#if !defined (BSON_INSIDE) && !defined (BSON_COMPILATION)
+#error "Only <bson/bson.h> can be included directly."
+#endif
+
+
+#ifndef BSON_VERSION_H
+#define BSON_VERSION_H
+
+
+/**
+ * BSON_MAJOR_VERSION:
+ *
+ * BSON major version component (e.g. 1 if %BSON_VERSION is 1.2.3)
+ */
+#define BSON_MAJOR_VERSION (1)
+
+
+/**
+ * BSON_MINOR_VERSION:
+ *
+ * BSON minor version component (e.g. 2 if %BSON_VERSION is 1.2.3)
+ */
+#define BSON_MINOR_VERSION (21)
+
+
+/**
+ * BSON_MICRO_VERSION:
+ *
+ * BSON micro version component (e.g. 3 if %BSON_VERSION is 1.2.3)
+ */
+#define BSON_MICRO_VERSION (1)
+
+
+/**
+ * BSON_PRERELEASE_VERSION:
+ *
+ * BSON prerelease version component (e.g. pre if %BSON_VERSION is 1.2.3-pre)
+ */
+#define BSON_PRERELEASE_VERSION ()
+
+/**
+ * BSON_VERSION:
+ *
+ * BSON version.
+ */
+#define BSON_VERSION (1.21.1)
+
+
+/**
+ * BSON_VERSION_S:
+ *
+ * BSON version, encoded as a string, useful for printing and
+ * concatenation.
+ */
+#define BSON_VERSION_S "1.21.1"
+
+
+/**
+ * BSON_VERSION_HEX:
+ *
+ * BSON version, encoded as an hexadecimal number, useful for
+ * integer comparisons.
+ */
+#define BSON_VERSION_HEX (BSON_MAJOR_VERSION << 24 | \
+ BSON_MINOR_VERSION << 16 | \
+ BSON_MICRO_VERSION << 8)
+
+
+/**
+ * BSON_CHECK_VERSION:
+ * @major: required major version
+ * @minor: required minor version
+ * @micro: required micro version
+ *
+ * Compile-time version checking. Evaluates to %TRUE if the version
+ * of BSON is greater than the required one.
+ */
+#define BSON_CHECK_VERSION(major,minor,micro) \
+ (BSON_MAJOR_VERSION > (major) || \
+ (BSON_MAJOR_VERSION == (major) && BSON_MINOR_VERSION > (minor)) || \
+ (BSON_MAJOR_VERSION == (major) && BSON_MINOR_VERSION == (minor) && \
+ BSON_MICRO_VERSION >= (micro)))
+
+#endif /* BSON_VERSION_H */
diff --git a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-version.h.in b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-version.h.in
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-version.h.in
rename to mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-version.h.in
diff --git a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-writer.c b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-writer.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-writer.c
rename to mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-writer.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-writer.h b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-writer.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson-writer.h
rename to mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson-writer.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson.c b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson.c
rename to mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson.h b/mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libbson/src/bson/bson.h
rename to mongodb-1.13.0/src/libmongoc/src/libbson/src/bson/bson.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libbson/src/jsonsl/jsonsl.c b/mongodb-1.13.0/src/libmongoc/src/libbson/src/jsonsl/jsonsl.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libbson/src/jsonsl/jsonsl.c
rename to mongodb-1.13.0/src/libmongoc/src/libbson/src/jsonsl/jsonsl.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libbson/src/jsonsl/jsonsl.h b/mongodb-1.13.0/src/libmongoc/src/libbson/src/jsonsl/jsonsl.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libbson/src/jsonsl/jsonsl.h
rename to mongodb-1.13.0/src/libmongoc/src/libbson/src/jsonsl/jsonsl.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-aggregate-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-aggregate-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-aggregate-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-aggregate-private.h
diff --git a/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-aggregate.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-aggregate.c
new file mode 100644
index 00000000..376ea2bc
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-aggregate.c
@@ -0,0 +1,316 @@
+/*
+ * Copyright 2019 MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include "mongoc-aggregate-private.h"
+#include "mongoc-client-private.h"
+#include "mongoc-cursor-private.h"
+#include "mongoc-read-prefs-private.h"
+#include "mongoc-server-stream-private.h"
+#include "mongoc-trace-private.h"
+#include "mongoc-util-private.h"
+
+
+/*--------------------------------------------------------------------------
+ *
+ * _has_write_key --
+ *
+ * Returns true if the aggregation pipeline's last stage is "$out"
+ * or "$merge"; otherwise returns false.
+ *
+ * Side effects:
+ * Advances @iter to the last element.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+bool
+_has_write_key (bson_iter_t *iter)
+{
+ bson_iter_t stage;
+ bson_iter_t next;
+
+ memcpy (&next, iter, sizeof (bson_iter_t));
+ if (!bson_iter_next (&next)) {
+ /* default to false when iter is emtpy */
+ return false;
+ }
+
+ while (bson_iter_next (iter)) {
+ if (!bson_iter_next (&next) && BSON_ITER_HOLDS_DOCUMENT (iter)) {
+ bson_iter_recurse (iter, &stage);
+ if (bson_iter_find (&stage, "$out")) {
+ return true;
+ }
+
+ bson_iter_recurse (iter, &stage);
+ if (bson_iter_find (&stage, "$merge")) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+
+/*--------------------------------------------------------------------------
+ *
+ * _make_agg_cmd --
+ *
+ * Constructs an aggregate command. If @ns does not include a collection
+ * name, 1 will be used in its place for the value of "aggregate" in the
+ * command document.
+ *
+ * Returns:
+ * true if successful; otherwise false and @error is set.
+ *
+ * Side effects:
+ * @command is always initialized.
+ * @error is set if there is a failure.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+static bool
+_make_agg_cmd (const char *ns,
+ const bson_t *pipeline,
+ mongoc_aggregate_opts_t *opts,
+ bson_t *command,
+ bson_error_t *err)
+{
+ const char *dot;
+ bson_iter_t iter;
+ bson_t child;
+ bool has_write_key;
+ bson_iter_t has_write_key_iter;
+
+ bson_init (command);
+
+ dot = strstr (ns, ".");
+
+ if (dot) {
+ /* Note: we're not validating that the collection name's length is one or
+ * more characters, as functions such as mongoc_client_get_collection also
+ * do not validate. */
+ BSON_APPEND_UTF8 (command, "aggregate", dot + 1);
+ } else {
+ BSON_APPEND_INT32 (command, "aggregate", 1);
+ }
+
+ /*
+ * The following will allow @pipeline to be either an array of
+ * items for the pipeline, or {"pipeline": [...]}.
+ */
+ if (bson_iter_init_find (&iter, pipeline, "pipeline") &&
+ BSON_ITER_HOLDS_ARRAY (&iter)) {
+ bson_iter_recurse (&iter, &has_write_key_iter);
+ if (!bson_append_iter (command, "pipeline", 8, &iter)) {
+ bson_set_error (err,
+ MONGOC_ERROR_COMMAND,
+ MONGOC_ERROR_COMMAND_INVALID_ARG,
+ "Failed to append \"pipeline\" to create command.");
+ return false;
+ }
+ } else {
+ BSON_APPEND_ARRAY (command, "pipeline", pipeline);
+ bson_iter_init (&has_write_key_iter, pipeline);
+ }
+
+ has_write_key = _has_write_key (&has_write_key_iter);
+ bson_append_document_begin (command, "cursor", 6, &child);
+ /* Ignore batchSize=0 for aggregates with $out or $merge */
+ if (opts->batchSize_is_set && !(has_write_key && opts->batchSize == 0)) {
+ BSON_APPEND_INT32 (&child, "batchSize", opts->batchSize);
+ }
+
+ bson_append_document_end (command, &child);
+ return true;
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_aggregate --
+ *
+ * Constructs a mongoc_cursor_t for an "aggregate" command.
+ *
+ * This function will always return a new mongoc_cursor_t that should
+ * be freed with mongoc_cursor_destroy().
+ *
+ * The cursor may fail once iterated upon, so check
+ * mongoc_cursor_error() if mongoc_cursor_next() returns false.
+ *
+ * See http://docs.mongodb.org/manual/aggregation/ for more
+ * information on how to build aggregation pipelines.
+ *
+ * Parameters:
+ * @ns: Namespace (or database name for database-level aggregation).
+ * @flags: Bitwise or of mongoc_query_flags_t or 0.
+ * @pipeline: A bson_t containing the pipeline request. @pipeline
+ * will be sent as an array type in the request.
+ * @opts: A bson_t containing aggregation options, such as
+ * bypassDocumentValidation (used with $out and $merge), maxTimeMS
+ * (declaring maximum server execution time) and explain (return
+ * information on the processing of the pipeline).
+ * @user_rp: Optional read preferences for the command.
+ * @default_rp: Default read preferences from the collection or database.
+ * @default_rc: Default read concern from the collection or database.
+ * @default_wc: Default write concern from the collection or database.
+ *
+ * Returns:
+ * A newly allocated mongoc_cursor_t that should be freed with
+ * mongoc_cursor_destroy().
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+mongoc_cursor_t *
+_mongoc_aggregate (mongoc_client_t *client,
+ const char *ns,
+ mongoc_query_flags_t flags,
+ const bson_t *pipeline,
+ const bson_t *opts,
+ const mongoc_read_prefs_t *user_rp,
+ const mongoc_read_prefs_t *default_rp,
+ const mongoc_read_concern_t *default_rc,
+ const mongoc_write_concern_t *default_wc)
+
+{
+ mongoc_server_stream_t *server_stream = NULL;
+ bool has_write_key;
+ bson_iter_t ar;
+ mongoc_cursor_t *cursor;
+ bson_iter_t iter;
+ bson_t command;
+ bson_t cursor_opts;
+ bool created_command;
+ bson_error_t create_cmd_err = {0};
+ mongoc_aggregate_opts_t aggregate_opts;
+ bson_error_t opts_err = {0};
+ bool parsed_opts;
+
+ ENTRY;
+
+ BSON_ASSERT (client);
+ BSON_ASSERT (ns);
+ BSON_ASSERT (pipeline);
+
+ bson_init (&cursor_opts);
+ _mongoc_cursor_flags_to_opts (flags, &cursor_opts, NULL);
+ if (opts) {
+ bson_concat (&cursor_opts /* destination */, opts /* source */);
+ }
+
+ parsed_opts =
+ _mongoc_aggregate_opts_parse (client, opts, &aggregate_opts, &opts_err);
+
+ if (parsed_opts) {
+ created_command = _make_agg_cmd (
+ ns, pipeline, &aggregate_opts, &command, &create_cmd_err);
+ } else {
+ created_command = false;
+ }
+
+ cursor = _mongoc_cursor_cmd_new (client,
+ ns,
+ created_command ? &command : NULL,
+ &cursor_opts,
+ user_rp,
+ default_rp,
+ default_rc);
+
+ if (created_command) {
+ bson_destroy (&command);
+ }
+ bson_destroy (&cursor_opts);
+
+ if (!parsed_opts) {
+ memcpy (&cursor->error, &opts_err, sizeof (bson_error_t));
+ GOTO (done);
+ }
+
+ if (!created_command) {
+ /* copy error back to cursor. */
+ memcpy (&cursor->error, &create_cmd_err, sizeof (bson_error_t));
+ GOTO (done);
+ }
+
+ if (mongoc_cursor_error (cursor, NULL)) {
+ GOTO (done);
+ }
+
+ if (!_mongoc_read_prefs_validate (cursor->read_prefs, &cursor->error)) {
+ GOTO (done);
+ }
+
+ /* pipeline could be like {pipeline: [{$out: 'test'}]} or [{$out: 'test'}] */
+ if (bson_iter_init_find (&iter, pipeline, "pipeline") &&
+ BSON_ITER_HOLDS_ARRAY (&iter) && bson_iter_recurse (&iter, &ar)) {
+ has_write_key = _has_write_key (&ar);
+ } else {
+ if (!bson_iter_init (&iter, pipeline)) {
+ bson_set_error (&cursor->error,
+ MONGOC_ERROR_BSON,
+ MONGOC_ERROR_BSON_INVALID,
+ "Pipeline is invalid BSON");
+ GOTO (done);
+ }
+ has_write_key = _has_write_key (&iter);
+ }
+
+ /* This has an important effect on server selection when
+ * readPreferences=secondary. Keep track of this fact for later use. */
+ cursor->is_aggr_with_write_stage = has_write_key;
+
+ /* server id isn't enough. ensure we're connected & know wire version */
+ server_stream = _mongoc_cursor_fetch_stream (cursor);
+ if (!server_stream) {
+ GOTO (done);
+ }
+
+ if (aggregate_opts.write_concern_owned && has_write_key &&
+ server_stream->sd->max_wire_version < WIRE_VERSION_CMD_WRITE_CONCERN) {
+ bson_set_error (
+ &cursor->error,
+ MONGOC_ERROR_COMMAND,
+ MONGOC_ERROR_PROTOCOL_BAD_WIRE_VERSION,
+ "\"aggregate\" with \"$out\" or \"$merge\" does not support "
+ "writeConcern with wire version %d, wire version %d is "
+ "required",
+ server_stream->sd->max_wire_version,
+ WIRE_VERSION_CMD_WRITE_CONCERN);
+ GOTO (done);
+ }
+
+ /* Only inherit WriteConcern when aggregate has $out or $merge */
+ if (!aggregate_opts.write_concern_owned && has_write_key) {
+ mongoc_write_concern_destroy (cursor->write_concern);
+ cursor->write_concern = mongoc_write_concern_copy (default_wc);
+ }
+
+done:
+ _mongoc_aggregate_opts_cleanup (&aggregate_opts);
+ mongoc_server_stream_cleanup (server_stream); /* null ok */
+
+ /* we always return the cursor, even if it fails; users can detect the
+ * failure on performing a cursor operation. see CDRIVER-880. */
+ RETURN (cursor);
+}
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-apm-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-apm-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-apm-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-apm-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-apm.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-apm.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-apm.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-apm.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-apm.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-apm.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-apm.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-apm.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-array-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-array-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-array-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-array-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-array.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-array.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-array.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-array.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-async-cmd-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-async-cmd-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-async-cmd-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-async-cmd-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-async-cmd.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-async-cmd.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-async-cmd.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-async-cmd.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-async-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-async-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-async-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-async-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-async.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-async.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-async.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-async.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-buffer-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-buffer-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-buffer-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-buffer-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-buffer.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-buffer.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-buffer.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-buffer.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-bulk-operation-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-bulk-operation-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-bulk-operation-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-bulk-operation-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-bulk-operation.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-bulk-operation.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-bulk-operation.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-bulk-operation.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-bulk-operation.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-bulk-operation.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-bulk-operation.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-bulk-operation.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-change-stream-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-change-stream-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-change-stream-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-change-stream-private.h
diff --git a/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-change-stream.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-change-stream.c
new file mode 100644
index 00000000..2daba263
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-change-stream.c
@@ -0,0 +1,669 @@
+/*
+ * Copyright 2017-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <bson/bson.h>
+#include "mongoc-cluster-private.h"
+#include "mongoc-change-stream-private.h"
+#include "mongoc-collection-private.h"
+#include "mongoc-client-private.h"
+#include "mongoc-client-session-private.h"
+#include "mongoc-cursor-private.h"
+#include "mongoc-database-private.h"
+#include "mongoc-error.h"
+#include "mongoc-error-private.h"
+
+#define CHANGE_STREAM_ERR(_str) \
+ bson_set_error (&stream->err, \
+ MONGOC_ERROR_CURSOR, \
+ MONGOC_ERROR_BSON, \
+ "Could not set " _str);
+
+/* the caller knows either a client or server error has occurred.
+ * `reply` contains the server reply or an empty document. */
+static bool
+_is_resumable_error (mongoc_change_stream_t *stream, const bson_t *reply)
+{
+ bson_error_t error = {0};
+
+ /* Change Streams Spec resumable criteria: "any error encountered which is
+ * not a server error (e.g. a timeout error or network error)" */
+ if (bson_empty (reply)) {
+ return true;
+ }
+
+ if (_mongoc_cmd_check_ok (reply, MONGOC_ERROR_API_VERSION_2, &error)) {
+ return true;
+ }
+
+ if (error.code == MONGOC_SERVER_ERR_CURSOR_NOT_FOUND) {
+ return true;
+ }
+
+ if (stream->max_wire_version >= WIRE_VERSION_4_4) {
+ return mongoc_error_has_label (reply, "ResumableChangeStreamError");
+ }
+
+ switch (error.code) {
+ case MONGOC_SERVER_ERR_HOSTUNREACHABLE:
+ case MONGOC_SERVER_ERR_HOSTNOTFOUND:
+ case MONGOC_SERVER_ERR_NETWORKTIMEOUT:
+ case MONGOC_SERVER_ERR_SHUTDOWNINPROGRESS:
+ case MONGOC_SERVER_ERR_PRIMARYSTEPPEDDOWN:
+ case MONGOC_SERVER_ERR_EXCEEDEDTIMELIMIT:
+ case MONGOC_SERVER_ERR_SOCKETEXCEPTION:
+ case MONGOC_SERVER_ERR_NOTPRIMARY:
+ case MONGOC_SERVER_ERR_INTERRUPTEDATSHUTDOWN:
+ case MONGOC_SERVER_ERR_INTERRUPTEDDUETOREPLSTATECHANGE:
+ case MONGOC_SERVER_ERR_NOTPRIMARYNOSECONDARYOK:
+ case MONGOC_SERVER_ERR_NOTPRIMARYORSECONDARY:
+ case MONGOC_SERVER_ERR_STALESHARDVERSION:
+ case MONGOC_SERVER_ERR_STALEEPOCH:
+ case MONGOC_SERVER_ERR_STALECONFIG:
+ case MONGOC_SERVER_ERR_RETRYCHANGESTREAM:
+ case MONGOC_SERVER_ERR_FAILEDTOSATISFYREADPREFERENCE:
+ return true;
+ default:
+ return false;
+ }
+}
+
+
+static void
+_set_resume_token (mongoc_change_stream_t *stream, const bson_t *resume_token)
+{
+ BSON_ASSERT (stream);
+ BSON_ASSERT (resume_token);
+
+ bson_destroy (&stream->resume_token);
+ bson_copy_to (resume_token, &stream->resume_token);
+}
+
+
+/* construct the aggregate command in cmd. looks like one of the following:
+ * for a collection change stream:
+ * { aggregate: collname, pipeline: [], cursor: { batchSize: x } }
+ * for a database change stream:
+ * { aggregate: 1, pipeline: [], cursor: { batchSize: x } }
+ * for a client change stream:
+ * { aggregate: 1, pipeline: [{$changeStream: {allChangesForCluster: true}}],
+ * cursor: { batchSize: x } }
+ */
+static void
+_make_command (mongoc_change_stream_t *stream, bson_t *command)
+{
+ bson_iter_t iter;
+ bson_t change_stream_stage; /* { $changeStream: <change_stream_doc> } */
+ bson_t change_stream_doc;
+ bson_t pipeline;
+ bson_t cursor_doc;
+
+ if (stream->change_stream_type == MONGOC_CHANGE_STREAM_COLLECTION) {
+ bson_append_utf8 (
+ command, "aggregate", 9, stream->coll, (int) strlen (stream->coll));
+ } else {
+ bson_append_int32 (command, "aggregate", 9, 1);
+ }
+
+ bson_append_array_begin (command, "pipeline", 8, &pipeline);
+
+ /* append the $changeStream stage. */
+ bson_append_document_begin (&pipeline, "0", 1, &change_stream_stage);
+ bson_append_document_begin (
+ &change_stream_stage, "$changeStream", 13, &change_stream_doc);
+ bson_concat (&change_stream_doc, stream->full_document);
+
+ if (stream->resumed) {
+ /* Change stream spec: Resume Process */
+ /* If there is a cached resumeToken: */
+ if (!bson_empty (&stream->resume_token)) {
+ /* If the ChangeStream was started with startAfter
+ and has yet to return a result document: */
+ if (!bson_empty (&stream->opts.startAfter) &&
+ !stream->has_returned_results) {
+ /* The driver MUST set startAfter to the cached resumeToken */
+ BSON_APPEND_DOCUMENT (
+ &change_stream_doc, "startAfter", &stream->resume_token);
+ } else {
+ /* The driver MUST set resumeAfter to the cached resumeToken */
+ BSON_APPEND_DOCUMENT (
+ &change_stream_doc, "resumeAfter", &stream->resume_token);
+ }
+ } else if (!_mongoc_timestamp_empty (&stream->operation_time) &&
+ stream->max_wire_version >= WIRE_VERSION_4_0) {
+ /* Else if there is no cached resumeToken and the ChangeStream
+ has a saved operation time and the max wire version is >= 7,
+ the driver MUST set startAtOperationTime */
+ _mongoc_timestamp_append (&stream->operation_time,
+ &change_stream_doc,
+ "startAtOperationTime");
+ }
+ } else {
+ /* Change streams spec: "startAtOperationTime, resumeAfter, and startAfter
+ * are all mutually exclusive; if any two are set, the server will return
+ * an error. Drivers MUST NOT throw a custom error, and MUST defer to the
+ * server error." */
+ if (!bson_empty (&stream->opts.resumeAfter)) {
+ BSON_APPEND_DOCUMENT (
+ &change_stream_doc, "resumeAfter", &stream->opts.resumeAfter);
+
+ /* Update the cached resume token */
+ _set_resume_token (stream, &stream->opts.resumeAfter);
+ }
+
+ if (!bson_empty (&stream->opts.startAfter)) {
+ BSON_APPEND_DOCUMENT (
+ &change_stream_doc, "startAfter", &stream->opts.startAfter);
+
+ /* Update the cached resume token (take precedence over resumeAfter) */
+ _set_resume_token (stream, &stream->opts.startAfter);
+ }
+
+ if (!_mongoc_timestamp_empty (&stream->operation_time)) {
+ _mongoc_timestamp_append (&stream->operation_time,
+ &change_stream_doc,
+ "startAtOperationTime");
+ }
+ }
+
+ if (stream->change_stream_type == MONGOC_CHANGE_STREAM_CLIENT) {
+ bson_append_bool (&change_stream_doc, "allChangesForCluster", 20, true);
+ }
+ bson_append_document_end (&change_stream_stage, &change_stream_doc);
+ bson_append_document_end (&pipeline, &change_stream_stage);
+
+ /* Append user pipeline if it exists */
+ if (bson_iter_init_find (&iter, &stream->pipeline_to_append, "pipeline") &&
+ BSON_ITER_HOLDS_ARRAY (&iter)) {
+ bson_iter_t child_iter;
+ uint32_t key_int = 1;
+ char buf[16];
+ const char *key_str;
+
+ BSON_ASSERT (bson_iter_recurse (&iter, &child_iter));
+ while (bson_iter_next (&child_iter)) {
+ /* the user pipeline may consist of invalid stages or non-documents.
+ * append anyway, and rely on the server error. */
+ size_t keyLen =
+ bson_uint32_to_string (key_int, &key_str, buf, sizeof (buf));
+ bson_append_value (
+ &pipeline, key_str, (int) keyLen, bson_iter_value (&child_iter));
+ ++key_int;
+ }
+ }
+
+ bson_append_array_end (command, &pipeline);
+
+ /* Add batch size if needed */
+ bson_append_document_begin (command, "cursor", 6, &cursor_doc);
+ if (stream->batch_size > 0) {
+ bson_append_int32 (&cursor_doc, "batchSize", 9, stream->batch_size);
+ }
+ bson_append_document_end (command, &cursor_doc);
+}
+
+/*---------------------------------------------------------------------------
+ *
+ * _make_cursor --
+ *
+ * Construct and send the aggregate command and create the resulting
+ * cursor. On error, stream->cursor remains NULL, otherwise it is
+ * created and must be destroyed.
+ *
+ * Return:
+ * False on error and sets stream->err.
+ *
+ *--------------------------------------------------------------------------
+ */
+static bool
+_make_cursor (mongoc_change_stream_t *stream)
+{
+ mongoc_client_session_t *cs = NULL;
+ bson_t command_opts;
+ bson_t command; /* { aggregate: "coll", pipeline: [], ... } */
+ bson_t reply;
+ bson_t getmore_opts = BSON_INITIALIZER;
+ bson_iter_t iter;
+ mongoc_server_stream_t *server_stream;
+
+ BSON_ASSERT (stream);
+ BSON_ASSERT (!stream->cursor);
+ bson_init (&command);
+ bson_copy_to (&(stream->opts.extra), &command_opts);
+
+ if (bson_iter_init_find (&iter, &command_opts, "sessionId")) {
+ if (!_mongoc_client_session_from_iter (
+ stream->client, &iter, &cs, &stream->err)) {
+ goto cleanup;
+ }
+ } else if (stream->implicit_session) {
+ /* If an implicit session was created before, and this cursor is now
+ * being recreated after resuming, then use the same session as before. */
+ cs = stream->implicit_session;
+ if (!mongoc_client_session_append (cs, &command_opts, &stream->err)) {
+ goto cleanup;
+ }
+ } else {
+ /* Create an implicit session. This session lsid must be the same for the
+ * agg command and the subsequent getMores. Thus, this implicit session is
+ * passed as if it were an explicit session to
+ * mongoc_client_read_command_with_opts and
+ * _mongoc_cursor_change_stream_new, but it is still implicit and its
+ * lifetime is owned by this change_stream_t. */
+ mongoc_session_opt_t *session_opts;
+ session_opts = mongoc_session_opts_new ();
+ mongoc_session_opts_set_causal_consistency (session_opts, false);
+ /* returns NULL if sessions aren't supported. ignore errors. */
+ cs = mongoc_client_start_session (stream->client, session_opts, NULL);
+ stream->implicit_session = cs;
+ mongoc_session_opts_destroy (session_opts);
+ if (cs &&
+ !mongoc_client_session_append (cs, &command_opts, &stream->err)) {
+ goto cleanup;
+ }
+ }
+
+ if (cs && !mongoc_client_session_append (cs, &getmore_opts, &stream->err)) {
+ goto cleanup;
+ }
+
+ server_stream =
+ mongoc_cluster_stream_for_reads (&stream->client->cluster,
+ stream->read_prefs,
+ cs,
+ &reply,
+ /* Not aggregate-with-write */ false,
+ &stream->err);
+ if (!server_stream) {
+ bson_destroy (&stream->err_doc);
+ bson_copy_to (&reply, &stream->err_doc);
+ bson_destroy (&reply);
+ goto cleanup;
+ }
+ bson_append_int32 (&command_opts, "serverId", 8, server_stream->sd->id);
+ bson_append_int32 (&getmore_opts, "serverId", 8, server_stream->sd->id);
+ stream->max_wire_version = server_stream->sd->max_wire_version;
+ mongoc_server_stream_cleanup (server_stream);
+
+ if (stream->read_concern && !bson_has_field (&command_opts, "readConcern")) {
+ mongoc_read_concern_append (stream->read_concern, &command_opts);
+ }
+
+ _make_command (stream, &command);
+
+ /* even though serverId has already been set, still pass the read prefs.
+ * they are necessary for OP_MSG if sending to a secondary. */
+ if (!mongoc_client_read_command_with_opts (stream->client,
+ stream->db,
+ &command,
+ stream->read_prefs,
+ &command_opts,
+ &reply,
+ &stream->err)) {
+ bson_destroy (&stream->err_doc);
+ bson_copy_to (&reply, &stream->err_doc);
+ bson_destroy (&reply);
+ goto cleanup;
+ }
+
+ bson_append_bool (
+ &getmore_opts, MONGOC_CURSOR_TAILABLE, MONGOC_CURSOR_TAILABLE_LEN, true);
+ bson_append_bool (&getmore_opts,
+ MONGOC_CURSOR_AWAIT_DATA,
+ MONGOC_CURSOR_AWAIT_DATA_LEN,
+ true);
+
+ /* maxTimeMS is only appended to getMores if these are set in cursor opts. */
+ if (stream->max_await_time_ms > 0) {
+ bson_append_int64 (&getmore_opts,
+ MONGOC_CURSOR_MAX_AWAIT_TIME_MS,
+ MONGOC_CURSOR_MAX_AWAIT_TIME_MS_LEN,
+ stream->max_await_time_ms);
+ }
+
+ if (stream->batch_size > 0) {
+ bson_append_int32 (&getmore_opts,
+ MONGOC_CURSOR_BATCH_SIZE,
+ MONGOC_CURSOR_BATCH_SIZE_LEN,
+ stream->batch_size);
+ }
+
+ /* steals reply. */
+ stream->cursor =
+ _mongoc_cursor_change_stream_new (stream->client, &reply, &getmore_opts);
+
+ if (mongoc_cursor_error (stream->cursor, NULL)) {
+ goto cleanup;
+ }
+
+ /* Change stream spec: "When aggregate or getMore returns: If an empty batch
+ * was returned and a postBatchResumeToken was included, cache it." */
+ if (_mongoc_cursor_change_stream_end_of_batch (stream->cursor) &&
+ _mongoc_cursor_change_stream_has_post_batch_resume_token (
+ stream->cursor)) {
+ _set_resume_token (
+ stream,
+ _mongoc_cursor_change_stream_get_post_batch_resume_token (
+ stream->cursor));
+ }
+
+ /* Change stream spec: startAtOperationTime */
+ if (bson_empty (&stream->opts.resumeAfter) &&
+ bson_empty (&stream->opts.startAfter) &&
+ _mongoc_timestamp_empty (&stream->operation_time) &&
+ stream->max_wire_version >= WIRE_VERSION_4_0 &&
+ bson_empty (&stream->resume_token) &&
+ bson_iter_init_find (
+ &iter,
+ _mongoc_cursor_change_stream_get_reply (stream->cursor),
+ "operationTime") &&
+ BSON_ITER_HOLDS_TIMESTAMP (&iter)) {
+ _mongoc_timestamp_set_from_bson (&stream->operation_time, &iter);
+ }
+
+cleanup:
+ bson_destroy (&command);
+ bson_destroy (&command_opts);
+ bson_destroy (&getmore_opts);
+ return stream->err.code == 0;
+}
+
+/*---------------------------------------------------------------------------
+ *
+ * _change_stream_init --
+ *
+ * Called after @stream has the collection name, database name, read
+ * preferences, and read concern set. Creates the change streams
+ * cursor.
+ *
+ *--------------------------------------------------------------------------
+ */
+void
+_change_stream_init (mongoc_change_stream_t *stream,
+ const bson_t *pipeline,
+ const bson_t *opts)
+{
+ BSON_ASSERT (pipeline);
+
+ stream->max_await_time_ms = -1;
+ stream->batch_size = -1;
+ bson_init (&stream->pipeline_to_append);
+ bson_init (&stream->resume_token);
+ bson_init (&stream->err_doc);
+
+ if (!_mongoc_change_stream_opts_parse (
+ stream->client, opts, &stream->opts, &stream->err)) {
+ return;
+ }
+
+ stream->full_document = BCON_NEW ("fullDocument", stream->opts.fullDocument);
+
+ _mongoc_timestamp_set (&stream->operation_time,
+ &stream->opts.startAtOperationTime);
+
+ stream->batch_size = stream->opts.batchSize;
+ stream->max_await_time_ms = stream->opts.maxAwaitTimeMS;
+
+ /* Accept two forms of user pipeline:
+ * 1. A document like: { "pipeline": [...] }
+ * 2. An array-like document: { "0": {}, "1": {}, ... }
+ * If the passed pipeline is invalid, we pass it along and let the server
+ * error instead.
+ */
+ if (!bson_empty (pipeline)) {
+ bson_iter_t iter;
+ if (bson_iter_init_find (&iter, pipeline, "pipeline") &&
+ BSON_ITER_HOLDS_ARRAY (&iter)) {
+ if (!BSON_APPEND_VALUE (&stream->pipeline_to_append,
+ "pipeline",
+ bson_iter_value (&iter))) {
+ CHANGE_STREAM_ERR ("pipeline");
+ }
+ } else {
+ if (!BSON_APPEND_ARRAY (
+ &stream->pipeline_to_append, "pipeline", pipeline)) {
+ CHANGE_STREAM_ERR ("pipeline");
+ }
+ }
+ }
+
+ if (stream->err.code == 0) {
+ (void) _make_cursor (stream);
+ }
+}
+
+mongoc_change_stream_t *
+_mongoc_change_stream_new_from_collection (const mongoc_collection_t *coll,
+ const bson_t *pipeline,
+ const bson_t *opts)
+{
+ mongoc_change_stream_t *stream;
+ BSON_ASSERT (coll);
+
+ stream =
+ (mongoc_change_stream_t *) bson_malloc0 (sizeof (mongoc_change_stream_t));
+ stream->db = bson_strdup (coll->db);
+ stream->coll = bson_strdup (coll->collection);
+ stream->read_prefs = mongoc_read_prefs_copy (coll->read_prefs);
+ stream->read_concern = mongoc_read_concern_copy (coll->read_concern);
+ stream->client = coll->client;
+ stream->change_stream_type = MONGOC_CHANGE_STREAM_COLLECTION;
+ _change_stream_init (stream, pipeline, opts);
+ return stream;
+}
+
+mongoc_change_stream_t *
+_mongoc_change_stream_new_from_database (const mongoc_database_t *db,
+ const bson_t *pipeline,
+ const bson_t *opts)
+{
+ mongoc_change_stream_t *stream;
+ BSON_ASSERT (db);
+
+ stream =
+ (mongoc_change_stream_t *) bson_malloc0 (sizeof (mongoc_change_stream_t));
+ stream->db = bson_strdup (db->name);
+ stream->coll = NULL;
+ stream->read_prefs = mongoc_read_prefs_copy (db->read_prefs);
+ stream->read_concern = mongoc_read_concern_copy (db->read_concern);
+ stream->client = db->client;
+ stream->change_stream_type = MONGOC_CHANGE_STREAM_DATABASE;
+ _change_stream_init (stream, pipeline, opts);
+ return stream;
+}
+
+mongoc_change_stream_t *
+_mongoc_change_stream_new_from_client (mongoc_client_t *client,
+ const bson_t *pipeline,
+ const bson_t *opts)
+{
+ mongoc_change_stream_t *stream;
+ BSON_ASSERT (client);
+
+ stream =
+ (mongoc_change_stream_t *) bson_malloc0 (sizeof (mongoc_change_stream_t));
+ stream->db = bson_strdup ("admin");
+ stream->coll = NULL;
+ stream->read_prefs = mongoc_read_prefs_copy (client->read_prefs);
+ stream->read_concern = mongoc_read_concern_copy (client->read_concern);
+ stream->client = client;
+ stream->change_stream_type = MONGOC_CHANGE_STREAM_CLIENT;
+ _change_stream_init (stream, pipeline, opts);
+ return stream;
+}
+
+
+const bson_t *
+mongoc_change_stream_get_resume_token (mongoc_change_stream_t *stream)
+{
+ if (!bson_empty (&stream->resume_token)) {
+ return &stream->resume_token;
+ }
+
+ return NULL;
+}
+
+
+bool
+mongoc_change_stream_next (mongoc_change_stream_t *stream, const bson_t **bson)
+{
+ bson_iter_t iter;
+ bson_t doc_resume_token;
+ uint32_t len;
+ const uint8_t *data;
+ bool ret = false;
+
+ BSON_ASSERT (stream);
+ BSON_ASSERT (bson);
+
+ if (stream->err.code != 0) {
+ goto end;
+ }
+
+ BSON_ASSERT (stream->cursor);
+ if (!mongoc_cursor_next (stream->cursor, bson)) {
+ const bson_t *err_doc;
+ bson_error_t err;
+ bool resumable = false;
+
+ if (!mongoc_cursor_error_document (stream->cursor, &err, &err_doc)) {
+ /* no error occurred, just no documents left. */
+ goto end;
+ }
+
+ resumable = _is_resumable_error (stream, err_doc);
+ while (resumable) {
+ /* recreate the cursor. */
+ mongoc_cursor_destroy (stream->cursor);
+ stream->cursor = NULL;
+ stream->resumed = true;
+ if (!_make_cursor (stream)) {
+ goto end;
+ }
+ if (mongoc_cursor_next (stream->cursor, bson)) {
+ break;
+ }
+ if (!mongoc_cursor_error_document (stream->cursor, &err, &err_doc)) {
+ goto end;
+ }
+ if (err_doc) {
+ resumable = _is_resumable_error (stream, err_doc);
+ } else {
+ resumable = false;
+ }
+ }
+
+ if (!resumable) {
+ stream->err = err;
+ bson_destroy (&stream->err_doc);
+ bson_copy_to (err_doc, &stream->err_doc);
+ goto end;
+ }
+ }
+
+ /* we have received documents, either from the first call to next or after a
+ * resume. */
+ stream->has_returned_results = true;
+
+ if (!bson_iter_init_find (&iter, *bson, "_id") ||
+ !BSON_ITER_HOLDS_DOCUMENT (&iter)) {
+ bson_set_error (&stream->err,
+ MONGOC_ERROR_CURSOR,
+ MONGOC_ERROR_CHANGE_STREAM_NO_RESUME_TOKEN,
+ "Cannot provide resume functionality when the resume "
+ "token is missing");
+ goto end;
+ }
+
+ /* copy the resume token. */
+ bson_iter_document (&iter, &len, &data);
+ BSON_ASSERT (bson_init_static (&doc_resume_token, data, len));
+ _set_resume_token (stream, &doc_resume_token);
+
+ /* clear out the operation time, since we no longer need it to resume. */
+ _mongoc_timestamp_clear (&stream->operation_time);
+ ret = true;
+
+end:
+ /* Change stream spec: Updating the Cached Resume Token */
+ if (stream->cursor && !mongoc_cursor_error (stream->cursor, NULL) &&
+ _mongoc_cursor_change_stream_end_of_batch (stream->cursor) &&
+ _mongoc_cursor_change_stream_has_post_batch_resume_token (
+ stream->cursor)) {
+ _set_resume_token (
+ stream,
+ _mongoc_cursor_change_stream_get_post_batch_resume_token (
+ stream->cursor));
+ }
+
+
+ /* Driver Sessions Spec: "When an implicit session is associated with a
+ * cursor for use with getMore operations, the session MUST be returned to
+ * the pool immediately following a getMore operation that indicates that the
+ * cursor has been exhausted." */
+ if (stream->implicit_session) {
+ /* if creating the change stream cursor errored, it may be null. */
+ if (!stream->cursor || stream->cursor->cursor_id == 0) {
+ mongoc_client_session_destroy (stream->implicit_session);
+ stream->implicit_session = NULL;
+ }
+ }
+ return ret;
+}
+
+bool
+mongoc_change_stream_error_document (const mongoc_change_stream_t *stream,
+ bson_error_t *err,
+ const bson_t **bson)
+{
+ BSON_ASSERT (stream);
+
+ if (stream->err.code != 0) {
+ if (err) {
+ *err = stream->err;
+ }
+ if (bson) {
+ *bson = &stream->err_doc;
+ }
+ return true;
+ }
+
+ if (bson) {
+ *bson = NULL;
+ }
+ return false;
+}
+
+void
+mongoc_change_stream_destroy (mongoc_change_stream_t *stream)
+{
+ if (!stream) {
+ return;
+ }
+
+ bson_destroy (&stream->pipeline_to_append);
+ bson_destroy (&stream->resume_token);
+ bson_destroy (stream->full_document);
+ bson_destroy (&stream->err_doc);
+ _mongoc_change_stream_opts_cleanup (&stream->opts);
+ mongoc_cursor_destroy (stream->cursor);
+ mongoc_client_session_destroy (stream->implicit_session);
+ mongoc_read_prefs_destroy (stream->read_prefs);
+ mongoc_read_concern_destroy (stream->read_concern);
+
+ bson_free (stream->db);
+ bson_free (stream->coll);
+ bson_free (stream);
+}
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-change-stream.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-change-stream.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-change-stream.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-change-stream.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-pool-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-pool-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-pool-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-pool-private.h
diff --git a/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-pool.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-pool.c
new file mode 100644
index 00000000..987938a6
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-pool.c
@@ -0,0 +1,574 @@
+/*
+ * Copyright 2013 MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include "mongoc.h"
+#include "mongoc-apm-private.h"
+#include "mongoc-counters-private.h"
+#include "mongoc-client-pool-private.h"
+#include "mongoc-client-pool.h"
+#include "mongoc-client-private.h"
+#include "mongoc-client-side-encryption-private.h"
+#include "mongoc-queue-private.h"
+#include "mongoc-thread-private.h"
+#include "mongoc-topology-private.h"
+#include "mongoc-topology-background-monitoring-private.h"
+#include "mongoc-trace-private.h"
+
+#ifdef MONGOC_ENABLE_SSL
+#include "mongoc-ssl-private.h"
+#endif
+
+struct _mongoc_client_pool_t {
+ bson_mutex_t mutex;
+ mongoc_cond_t cond;
+ mongoc_queue_t queue;
+ mongoc_topology_t *topology;
+ mongoc_uri_t *uri;
+ uint32_t min_pool_size;
+ uint32_t max_pool_size;
+ uint32_t size;
+#ifdef MONGOC_ENABLE_SSL
+ bool ssl_opts_set;
+ mongoc_ssl_opt_t ssl_opts;
+#endif
+ bool apm_callbacks_set;
+ mongoc_apm_callbacks_t apm_callbacks;
+ void *apm_context;
+ int32_t error_api_version;
+ bool error_api_set;
+ mongoc_server_api_t *api;
+ bool client_initialized;
+};
+
+
+#ifdef MONGOC_ENABLE_SSL
+void
+mongoc_client_pool_set_ssl_opts (mongoc_client_pool_t *pool,
+ const mongoc_ssl_opt_t *opts)
+{
+ bson_mutex_lock (&pool->mutex);
+
+ _mongoc_ssl_opts_cleanup (&pool->ssl_opts,
+ false /* don't free internal opts. */);
+
+ pool->ssl_opts_set = false;
+
+ if (opts) {
+ _mongoc_ssl_opts_copy_to (
+ opts, &pool->ssl_opts, false /* don't overwrite internal opts. */);
+ pool->ssl_opts_set = true;
+ }
+
+ mongoc_topology_scanner_set_ssl_opts (pool->topology->scanner,
+ &pool->ssl_opts);
+
+ bson_mutex_unlock (&pool->mutex);
+}
+
+void
+_mongoc_client_pool_set_internal_tls_opts (
+ mongoc_client_pool_t *pool, _mongoc_internal_tls_opts_t *internal)
+{
+ bson_mutex_lock (&pool->mutex);
+ if (!pool->ssl_opts_set) {
+ bson_mutex_unlock (&pool->mutex);
+ return;
+ }
+ pool->ssl_opts.internal = bson_malloc (sizeof (_mongoc_internal_tls_opts_t));
+ memcpy (
+ pool->ssl_opts.internal, internal, sizeof (_mongoc_internal_tls_opts_t));
+ bson_mutex_unlock (&pool->mutex);
+}
+#endif
+
+
+mongoc_client_pool_t *
+mongoc_client_pool_new (const mongoc_uri_t *uri)
+{
+ mongoc_client_pool_t *pool;
+ bson_error_t error = {0};
+
+ if (!(pool = mongoc_client_pool_new_with_error (uri, &error))) {
+ MONGOC_ERROR ("%s", error.message);
+ }
+
+ return pool;
+}
+
+
+mongoc_client_pool_t *
+mongoc_client_pool_new_with_error (const mongoc_uri_t *uri, bson_error_t *error)
+{
+ mongoc_topology_t *topology;
+ mongoc_client_pool_t *pool;
+ const bson_t *b;
+ bson_iter_t iter;
+ const char *appname;
+
+
+ ENTRY;
+
+ BSON_ASSERT (uri);
+
+#ifndef MONGOC_ENABLE_SSL
+ if (mongoc_uri_get_tls (uri)) {
+ bson_set_error (error,
+ MONGOC_ERROR_COMMAND,
+ MONGOC_ERROR_COMMAND_INVALID_ARG,
+ "Can't create SSL client pool, SSL not enabled in this "
+ "build.");
+ return NULL;
+ }
+#endif
+
+ topology = mongoc_topology_new (uri, false);
+
+ if (!topology->valid) {
+ if (error) {
+ memcpy (error, &topology->scanner->error, sizeof (bson_error_t));
+ }
+
+ mongoc_topology_destroy (topology);
+
+ RETURN (NULL);
+ }
+
+ pool = (mongoc_client_pool_t *) bson_malloc0 (sizeof *pool);
+ bson_mutex_init (&pool->mutex);
+ mongoc_cond_init (&pool->cond);
+ _mongoc_queue_init (&pool->queue);
+ pool->uri = mongoc_uri_copy (uri);
+ pool->min_pool_size = 0;
+ pool->max_pool_size = 100;
+ pool->size = 0;
+ pool->topology = topology;
+ pool->error_api_version = MONGOC_ERROR_API_VERSION_LEGACY;
+
+ b = mongoc_uri_get_options (pool->uri);
+
+ if (bson_iter_init_find_case (&iter, b, MONGOC_URI_MINPOOLSIZE)) {
+ MONGOC_WARNING (
+ MONGOC_URI_MINPOOLSIZE
+ " is deprecated; its behavior does not match its name, and its actual"
+ " behavior will likely hurt performance.");
+
+ if (BSON_ITER_HOLDS_INT32 (&iter)) {
+ pool->min_pool_size = BSON_MAX (0, bson_iter_int32 (&iter));
+ }
+ }
+
+ if (bson_iter_init_find_case (&iter, b, MONGOC_URI_MAXPOOLSIZE)) {
+ if (BSON_ITER_HOLDS_INT32 (&iter)) {
+ pool->max_pool_size = BSON_MAX (1, bson_iter_int32 (&iter));
+ }
+ }
+
+ appname =
+ mongoc_uri_get_option_as_utf8 (pool->uri, MONGOC_URI_APPNAME, NULL);
+ if (appname) {
+ /* the appname should have already been validated */
+ BSON_ASSERT (mongoc_client_pool_set_appname (pool, appname));
+ }
+
+#ifdef MONGOC_ENABLE_SSL
+ if (mongoc_uri_get_tls (pool->uri)) {
+ mongoc_ssl_opt_t ssl_opt = {0};
+ _mongoc_internal_tls_opts_t internal_tls_opts = {0};
+
+ _mongoc_ssl_opts_from_uri (&ssl_opt, &internal_tls_opts, pool->uri);
+ /* sets use_ssl = true */
+ mongoc_client_pool_set_ssl_opts (pool, &ssl_opt);
+ _mongoc_client_pool_set_internal_tls_opts (pool, &internal_tls_opts);
+ }
+#endif
+ mongoc_counter_client_pools_active_inc ();
+
+ RETURN (pool);
+}
+
+
+void
+mongoc_client_pool_destroy (mongoc_client_pool_t *pool)
+{
+ mongoc_client_t *client;
+
+ ENTRY;
+
+ if (!pool) {
+ EXIT;
+ }
+
+ if (!mongoc_server_session_pool_is_empty (pool->topology->session_pool)) {
+ client = mongoc_client_pool_pop (pool);
+ _mongoc_client_end_sessions (client);
+ mongoc_client_pool_push (pool, client);
+ }
+
+ while (
+ (client = (mongoc_client_t *) _mongoc_queue_pop_head (&pool->queue))) {
+ mongoc_client_destroy (client);
+ }
+
+ mongoc_topology_destroy (pool->topology);
+
+ mongoc_uri_destroy (pool->uri);
+ bson_mutex_destroy (&pool->mutex);
+ mongoc_cond_destroy (&pool->cond);
+
+ mongoc_server_api_destroy (pool->api);
+
+#ifdef MONGOC_ENABLE_SSL
+ _mongoc_ssl_opts_cleanup (&pool->ssl_opts, true);
+#endif
+
+ bson_free (pool);
+
+ mongoc_counter_client_pools_active_dec ();
+ mongoc_counter_client_pools_disposed_inc ();
+
+ EXIT;
+}
+
+
+/*
+ * Start the background topology scanner.
+ *
+ * This function assumes the pool's mutex is locked
+ */
+static void
+_start_scanner_if_needed (mongoc_client_pool_t *pool)
+{
+ if (!pool->topology->single_threaded) {
+ _mongoc_topology_background_monitoring_start (pool->topology);
+ }
+}
+
+static void
+_initialize_new_client (mongoc_client_pool_t *pool, mongoc_client_t *client)
+{
+ /* for tests */
+ mongoc_client_set_stream_initiator (
+ client,
+ pool->topology->scanner->initiator,
+ pool->topology->scanner->initiator_context);
+
+ pool->client_initialized = true;
+ client->is_pooled = true;
+ client->error_api_version = pool->error_api_version;
+ _mongoc_client_set_apm_callbacks_private (
+ client, &pool->apm_callbacks, pool->apm_context);
+
+ client->api = mongoc_server_api_copy (pool->api);
+
+#ifdef MONGOC_ENABLE_SSL
+ if (pool->ssl_opts_set) {
+ mongoc_client_set_ssl_opts (client, &pool->ssl_opts);
+ }
+#endif
+}
+
+mongoc_client_t *
+mongoc_client_pool_pop (mongoc_client_pool_t *pool)
+{
+ mongoc_client_t *client;
+ int32_t wait_queue_timeout_ms;
+ int64_t expire_at_ms = -1;
+ int64_t now_ms;
+ int r;
+
+ ENTRY;
+
+ BSON_ASSERT (pool);
+
+ wait_queue_timeout_ms = mongoc_uri_get_option_as_int32 (
+ pool->uri, MONGOC_URI_WAITQUEUETIMEOUTMS, -1);
+ if (wait_queue_timeout_ms > 0) {
+ expire_at_ms =
+ (bson_get_monotonic_time () / 1000) + wait_queue_timeout_ms;
+ }
+ bson_mutex_lock (&pool->mutex);
+
+again:
+ if (!(client = (mongoc_client_t *) _mongoc_queue_pop_head (&pool->queue))) {
+ if (pool->size < pool->max_pool_size) {
+ client = _mongoc_client_new_from_topology (pool->topology);
+ BSON_ASSERT (client);
+ _initialize_new_client (pool, client);
+ pool->size++;
+ } else {
+ if (wait_queue_timeout_ms > 0) {
+ now_ms = bson_get_monotonic_time () / 1000;
+ if (now_ms < expire_at_ms) {
+ r = mongoc_cond_timedwait (
+ &pool->cond, &pool->mutex, expire_at_ms - now_ms);
+ if (mongo_cond_ret_is_timedout (r)) {
+ GOTO (done);
+ }
+ } else {
+ GOTO (done);
+ }
+ } else {
+ mongoc_cond_wait (&pool->cond, &pool->mutex);
+ }
+ GOTO (again);
+ }
+ }
+
+ _start_scanner_if_needed (pool);
+done:
+ bson_mutex_unlock (&pool->mutex);
+
+ RETURN (client);
+}
+
+
+mongoc_client_t *
+mongoc_client_pool_try_pop (mongoc_client_pool_t *pool)
+{
+ mongoc_client_t *client;
+
+ ENTRY;
+
+ BSON_ASSERT (pool);
+
+ bson_mutex_lock (&pool->mutex);
+
+ if (!(client = (mongoc_client_t *) _mongoc_queue_pop_head (&pool->queue))) {
+ if (pool->size < pool->max_pool_size) {
+ client = _mongoc_client_new_from_topology (pool->topology);
+ BSON_ASSERT (client);
+ _initialize_new_client (pool, client);
+ pool->size++;
+ }
+ }
+
+ if (client) {
+ _start_scanner_if_needed (pool);
+ }
+ bson_mutex_unlock (&pool->mutex);
+
+ RETURN (client);
+}
+
+
+void
+mongoc_client_pool_push (mongoc_client_pool_t *pool, mongoc_client_t *client)
+{
+ ENTRY;
+
+ BSON_ASSERT (pool);
+ BSON_ASSERT (client);
+
+ bson_mutex_lock (&pool->mutex);
+ _mongoc_queue_push_head (&pool->queue, client);
+
+ if (pool->min_pool_size &&
+ _mongoc_queue_get_length (&pool->queue) > pool->min_pool_size) {
+ mongoc_client_t *old_client;
+ old_client = (mongoc_client_t *) _mongoc_queue_pop_tail (&pool->queue);
+ if (old_client) {
+ mongoc_client_destroy (old_client);
+ pool->size--;
+ }
+ }
+
+ mongoc_cond_signal (&pool->cond);
+ bson_mutex_unlock (&pool->mutex);
+
+ EXIT;
+}
+
+/* for tests */
+void
+_mongoc_client_pool_set_stream_initiator (mongoc_client_pool_t *pool,
+ mongoc_stream_initiator_t si,
+ void *context)
+{
+ mongoc_topology_scanner_set_stream_initiator (
+ pool->topology->scanner, si, context);
+}
+
+/* for tests */
+size_t
+mongoc_client_pool_get_size (mongoc_client_pool_t *pool)
+{
+ size_t size = 0;
+
+ ENTRY;
+
+ bson_mutex_lock (&pool->mutex);
+ size = pool->size;
+ bson_mutex_unlock (&pool->mutex);
+
+ RETURN (size);
+}
+
+
+size_t
+mongoc_client_pool_num_pushed (mongoc_client_pool_t *pool)
+{
+ size_t num_pushed = 0;
+
+ ENTRY;
+
+ bson_mutex_lock (&pool->mutex);
+ num_pushed = pool->queue.length;
+ bson_mutex_unlock (&pool->mutex);
+
+ RETURN (num_pushed);
+}
+
+
+mongoc_topology_t *
+_mongoc_client_pool_get_topology (mongoc_client_pool_t *pool)
+{
+ return pool->topology;
+}
+
+
+void
+mongoc_client_pool_max_size (mongoc_client_pool_t *pool, uint32_t max_pool_size)
+{
+ ENTRY;
+
+ bson_mutex_lock (&pool->mutex);
+ pool->max_pool_size = max_pool_size;
+ bson_mutex_unlock (&pool->mutex);
+
+ EXIT;
+}
+
+void
+mongoc_client_pool_min_size (mongoc_client_pool_t *pool, uint32_t min_pool_size)
+{
+ ENTRY;
+
+ MONGOC_WARNING (
+ "mongoc_client_pool_min_size is deprecated; its behavior does not match"
+ " its name, and its actual behavior will likely hurt performance.");
+
+ bson_mutex_lock (&pool->mutex);
+ pool->min_pool_size = min_pool_size;
+ bson_mutex_unlock (&pool->mutex);
+
+ EXIT;
+}
+
+bool
+mongoc_client_pool_set_apm_callbacks (mongoc_client_pool_t *pool,
+ mongoc_apm_callbacks_t *callbacks,
+ void *context)
+{
+ mongoc_topology_t *const topology = BSON_ASSERT_PTR_INLINE (pool)->topology;
+ mc_tpld_modification tdmod;
+
+ if (pool->apm_callbacks_set) {
+ MONGOC_ERROR ("Can only set callbacks once");
+ return false;
+ }
+
+ tdmod = mc_tpld_modify_begin (topology);
+
+ if (callbacks) {
+ memcpy (&tdmod.new_td->apm_callbacks,
+ callbacks,
+ sizeof (mongoc_apm_callbacks_t));
+ memcpy (&pool->apm_callbacks, callbacks, sizeof (mongoc_apm_callbacks_t));
+ }
+
+ mongoc_topology_set_apm_callbacks (
+ topology, tdmod.new_td, callbacks, context);
+ tdmod.new_td->apm_context = context;
+ pool->apm_context = context;
+ pool->apm_callbacks_set = true;
+
+ mc_tpld_modify_commit (tdmod);
+
+ return true;
+}
+
+bool
+mongoc_client_pool_set_error_api (mongoc_client_pool_t *pool, int32_t version)
+{
+ if (version != MONGOC_ERROR_API_VERSION_LEGACY &&
+ version != MONGOC_ERROR_API_VERSION_2) {
+ MONGOC_ERROR ("Unsupported Error API Version: %" PRId32, version);
+ return false;
+ }
+
+ if (pool->error_api_set) {
+ MONGOC_ERROR ("Can only set Error API Version once");
+ return false;
+ }
+
+ pool->error_api_version = version;
+ pool->error_api_set = true;
+
+ return true;
+}
+
+bool
+mongoc_client_pool_set_appname (mongoc_client_pool_t *pool, const char *appname)
+{
+ bool ret;
+
+ bson_mutex_lock (&pool->mutex);
+ ret = _mongoc_topology_set_appname (pool->topology, appname);
+ bson_mutex_unlock (&pool->mutex);
+
+ return ret;
+}
+
+bool
+mongoc_client_pool_enable_auto_encryption (mongoc_client_pool_t *pool,
+ mongoc_auto_encryption_opts_t *opts,
+ bson_error_t *error)
+{
+ return _mongoc_cse_client_pool_enable_auto_encryption (
+ pool->topology, opts, error);
+}
+
+bool
+mongoc_client_pool_set_server_api (mongoc_client_pool_t *pool,
+ const mongoc_server_api_t *api,
+ bson_error_t *error)
+{
+ BSON_ASSERT_PARAM (pool);
+ BSON_ASSERT_PARAM (api);
+
+ if (pool->api) {
+ bson_set_error (error,
+ MONGOC_ERROR_POOL,
+ MONGOC_ERROR_POOL_API_ALREADY_SET,
+ "Cannot set server api more than once per pool");
+ return false;
+ }
+
+ if (pool->client_initialized) {
+ bson_set_error (error,
+ MONGOC_ERROR_POOL,
+ MONGOC_ERROR_POOL_API_TOO_LATE,
+ "Cannot set server api after a client has been created");
+ return false;
+ }
+
+ pool->api = mongoc_server_api_copy (api);
+
+ _mongoc_topology_scanner_set_server_api (pool->topology->scanner, api);
+
+ return true;
+}
diff --git a/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-pool.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-pool.h
new file mode 100644
index 00000000..c4df560f
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-pool.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2013 MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mongoc-prelude.h"
+
+#ifndef MONGOC_CLIENT_POOL_H
+#define MONGOC_CLIENT_POOL_H
+
+#include <bson/bson.h>
+
+#include "mongoc-macros.h"
+#include "mongoc-apm.h"
+#include "mongoc-client.h"
+#include "mongoc-config.h"
+#ifdef MONGOC_ENABLE_SSL
+#include "mongoc-ssl.h"
+#endif
+#include "mongoc-uri.h"
+
+
+BSON_BEGIN_DECLS
+
+
+typedef struct _mongoc_client_pool_t mongoc_client_pool_t;
+
+
+MONGOC_EXPORT (mongoc_client_pool_t *)
+mongoc_client_pool_new (const mongoc_uri_t *uri) BSON_GNUC_WARN_UNUSED_RESULT;
+MONGOC_EXPORT (mongoc_client_pool_t *)
+mongoc_client_pool_new_with_error (const mongoc_uri_t *uri, bson_error_t *error)
+ BSON_GNUC_WARN_UNUSED_RESULT;
+MONGOC_EXPORT (void)
+mongoc_client_pool_destroy (mongoc_client_pool_t *pool);
+MONGOC_EXPORT (mongoc_client_t *)
+mongoc_client_pool_pop (mongoc_client_pool_t *pool)
+ BSON_GNUC_WARN_UNUSED_RESULT;
+MONGOC_EXPORT (void)
+mongoc_client_pool_push (mongoc_client_pool_t *pool, mongoc_client_t *client);
+MONGOC_EXPORT (mongoc_client_t *)
+mongoc_client_pool_try_pop (mongoc_client_pool_t *pool)
+ BSON_GNUC_WARN_UNUSED_RESULT;
+MONGOC_EXPORT (void)
+mongoc_client_pool_max_size (mongoc_client_pool_t *pool,
+ uint32_t max_pool_size);
+MONGOC_EXPORT (void)
+mongoc_client_pool_min_size (mongoc_client_pool_t *pool,
+ uint32_t min_pool_size) BSON_GNUC_DEPRECATED;
+#ifdef MONGOC_ENABLE_SSL
+MONGOC_EXPORT (void)
+mongoc_client_pool_set_ssl_opts (mongoc_client_pool_t *pool,
+ const mongoc_ssl_opt_t *opts);
+#endif
+MONGOC_EXPORT (bool)
+mongoc_client_pool_set_apm_callbacks (mongoc_client_pool_t *pool,
+ mongoc_apm_callbacks_t *callbacks,
+ void *context);
+MONGOC_EXPORT (bool)
+mongoc_client_pool_set_error_api (mongoc_client_pool_t *pool, int32_t version);
+MONGOC_EXPORT (bool)
+mongoc_client_pool_set_appname (mongoc_client_pool_t *pool,
+ const char *appname);
+MONGOC_EXPORT (bool)
+mongoc_client_pool_enable_auto_encryption (mongoc_client_pool_t *pool,
+ mongoc_auto_encryption_opts_t *opts,
+ bson_error_t *error);
+MONGOC_EXPORT (bool)
+mongoc_client_pool_set_server_api (mongoc_client_pool_t *pool,
+ const mongoc_server_api_t *api,
+ bson_error_t *error);
+
+BSON_END_DECLS
+
+
+#endif /* MONGOC_CLIENT_POOL_H */
diff --git a/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-private.h
new file mode 100644
index 00000000..379cb62d
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-private.h
@@ -0,0 +1,249 @@
+/*
+ * Copyright 2013 MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mongoc-prelude.h"
+
+#ifndef MONGOC_CLIENT_PRIVATE_H
+#define MONGOC_CLIENT_PRIVATE_H
+
+#include <bson/bson.h>
+
+#include "mongoc-apm-private.h"
+#include "mongoc-buffer-private.h"
+#include "mongoc-client.h"
+#include "mongoc-cluster-private.h"
+#include "mongoc-config.h"
+#include "mongoc-host-list.h"
+#include "mongoc-read-prefs.h"
+#include "mongoc-rpc-private.h"
+#include "mongoc-opcode.h"
+#ifdef MONGOC_ENABLE_SSL
+#include "mongoc-ssl.h"
+#endif
+
+#include "mongoc-stream.h"
+#include "mongoc-topology-private.h"
+#include "mongoc-write-concern.h"
+#include "mongoc-crypt-private.h"
+
+BSON_BEGIN_DECLS
+
+/* Range of wire protocol versions this driver supports. Bumping
+ * WIRE_VERSION_MAX must be accompanied by an update to
+ * `_mongoc_wire_version_to_server_version`. */
+#define WIRE_VERSION_MIN 6 /* a.k.a. minWireVersion */
+#define WIRE_VERSION_MAX 15 /* a.k.a. maxWireVersion */
+
+/* first version that supported "find" and "getMore" commands */
+#define WIRE_VERSION_FIND_CMD 4
+/* first version with "killCursors" command */
+#define WIRE_VERSION_KILLCURSORS_CMD 4
+/* first version when findAndModify accepts writeConcern */
+#define WIRE_VERSION_FAM_WRITE_CONCERN 4
+/* first version to support readConcern */
+#define WIRE_VERSION_READ_CONCERN 4
+/* first version to support maxStalenessSeconds */
+#define WIRE_VERSION_MAX_STALENESS 5
+/* first version to support writeConcern */
+#define WIRE_VERSION_CMD_WRITE_CONCERN 5
+/* first version to support collation */
+#define WIRE_VERSION_COLLATION 5
+/* first version to support server-side errors for unsupported hint options */
+#define WIRE_VERSION_HINT_SERVER_SIDE_ERROR 5
+/* first version to support OP_MSG */
+#define WIRE_VERSION_OP_MSG 6
+/* first version to support array filters for "update" command */
+#define WIRE_VERSION_ARRAY_FILTERS 6
+/* first version to support retryable reads */
+#define WIRE_VERSION_RETRY_READS 6
+/* first version to support retryable writes */
+#define WIRE_VERSION_RETRY_WRITES 6
+/* version corresponding to server 4.0 release */
+#define WIRE_VERSION_4_0 7
+/* first version to support hint for "update" command */
+#define WIRE_VERSION_UPDATE_HINT 8
+/* version corresponding to server 4.2 release */
+#define WIRE_VERSION_4_2 8
+/* version corresponding to client side field level encryption support. */
+#define WIRE_VERSION_CSE 8
+/* first version to throw server-side errors for unsupported hint in
+ * "findAndModify" command */
+#define WIRE_VERSION_FIND_AND_MODIFY_HINT_SERVER_SIDE_ERROR 8
+/* first version to support hint for "delete" command */
+#define WIRE_VERSION_DELETE_HINT 9
+/* first version to support hint for "findAndModify" command */
+#define WIRE_VERSION_FIND_AND_MODIFY_HINT 9
+/* version corresponding to server 4.4 release */
+#define WIRE_VERSION_4_4 9
+/* version corresponding to retryable writes error label */
+#define WIRE_VERSION_RETRYABLE_WRITE_ERROR_LABEL 9
+/* first version to support server hedged reads */
+#define WIRE_VERSION_HEDGED_READS 9
+/* first version to support estimatedDocumentCount with collStats */
+#define WIRE_VERSION_4_9 12
+/* version corresponding to server 5.0 release */
+#define WIRE_VERSION_5_0 13
+/* first version to support snapshot reads */
+#define WIRE_VERSION_SNAPSHOT_READS 13
+/* version corresponding to server 5.1 release */
+#define WIRE_VERSION_5_1 14
+
+struct _mongoc_collection_t;
+
+struct _mongoc_client_t {
+ mongoc_uri_t *uri;
+ mongoc_cluster_t cluster;
+ bool in_exhaust;
+ bool is_pooled;
+
+ mongoc_stream_initiator_t initiator;
+ void *initiator_data;
+
+#ifdef MONGOC_ENABLE_SSL
+ bool use_ssl;
+ mongoc_ssl_opt_t ssl_opts;
+#endif
+
+ mongoc_topology_t *topology;
+
+ mongoc_read_prefs_t *read_prefs;
+ mongoc_read_concern_t *read_concern;
+ mongoc_write_concern_t *write_concern;
+
+ mongoc_apm_callbacks_t apm_callbacks;
+ void *apm_context;
+
+ int32_t error_api_version;
+ bool error_api_set;
+
+ mongoc_server_api_t *api;
+
+ /* mongoc_client_session_t's in use, to look up lsids and clusterTimes */
+ mongoc_set_t *client_sessions;
+ unsigned int csid_rand_seed;
+
+ uint32_t generation;
+};
+
+/* Defines whether _mongoc_client_command_with_opts() is acting as a read
+ * command helper for a command like "distinct", or a write command helper for
+ * a command like "createRole", or both, like "aggregate" with "$out".
+ */
+typedef enum {
+ MONGOC_CMD_RAW = 0,
+ MONGOC_CMD_READ = 1,
+ MONGOC_CMD_WRITE = 2,
+ MONGOC_CMD_RW = 3,
+} mongoc_command_mode_t;
+
+BSON_STATIC_ASSERT2 (mongoc_cmd_rw,
+ MONGOC_CMD_RW == (MONGOC_CMD_READ | MONGOC_CMD_WRITE));
+
+
+/* TODO (CDRIVER-4052): Move MONGOC_RR_DEFAULT_BUFFER_SIZE and
+ * _mongoc_client_get_rr to mongoc-topology-private.h or in a separate file.
+ * There is no reason these should be in mongoc-client. */
+#define MONGOC_RR_DEFAULT_BUFFER_SIZE 1024
+bool
+_mongoc_client_get_rr (const char *hostname,
+ mongoc_rr_type_t rr_type,
+ mongoc_rr_data_t *rr_data,
+ size_t initial_buffer_size,
+ bson_error_t *error);
+
+mongoc_client_t *
+_mongoc_client_new_from_topology (mongoc_topology_t *topology);
+
+bool
+_mongoc_client_set_apm_callbacks_private (mongoc_client_t *client,
+ mongoc_apm_callbacks_t *callbacks,
+ void *context);
+
+mongoc_stream_t *
+mongoc_client_default_stream_initiator (const mongoc_uri_t *uri,
+ const mongoc_host_list_t *host,
+ void *user_data,
+ bson_error_t *error);
+
+mongoc_stream_t *
+_mongoc_client_create_stream (mongoc_client_t *client,
+ const mongoc_host_list_t *host,
+ bson_error_t *error);
+
+bool
+_mongoc_client_recv (mongoc_client_t *client,
+ mongoc_rpc_t *rpc,
+ mongoc_buffer_t *buffer,
+ mongoc_server_stream_t *server_stream,
+ bson_error_t *error);
+
+void
+_mongoc_client_kill_cursor (mongoc_client_t *client,
+ uint32_t server_id,
+ int64_t cursor_id,
+ int64_t operation_id,
+ const char *db,
+ const char *collection,
+ mongoc_client_session_t *cs);
+bool
+_mongoc_client_command_with_opts (mongoc_client_t *client,
+ const char *db_name,
+ const bson_t *command,
+ mongoc_command_mode_t mode,
+ const bson_t *opts,
+ mongoc_query_flags_t flags,
+ const mongoc_read_prefs_t *user_prefs,
+ const mongoc_read_prefs_t *default_prefs,
+ mongoc_read_concern_t *default_rc,
+ mongoc_write_concern_t *default_wc,
+ bson_t *reply,
+ bson_error_t *error);
+
+mongoc_server_session_t *
+_mongoc_client_pop_server_session (mongoc_client_t *client,
+ bson_error_t *error);
+
+bool
+_mongoc_client_lookup_session (const mongoc_client_t *client,
+ uint32_t client_session_id,
+ mongoc_client_session_t **cs,
+ bson_error_t *error);
+
+void
+_mongoc_client_unregister_session (mongoc_client_t *client,
+ mongoc_client_session_t *session);
+
+void
+_mongoc_client_push_server_session (mongoc_client_t *client,
+ mongoc_server_session_t *server_session);
+void
+_mongoc_client_end_sessions (mongoc_client_t *client);
+
+mongoc_stream_t *
+mongoc_client_connect_tcp (int32_t connecttimeoutms,
+ const mongoc_host_list_t *host,
+ bson_error_t *error);
+
+mongoc_stream_t *
+mongoc_client_connect (bool buffered,
+ bool use_ssl,
+ void *ssl_opts_void,
+ const mongoc_uri_t *uri,
+ const mongoc_host_list_t *host,
+ bson_error_t *error);
+BSON_END_DECLS
+
+#endif /* MONGOC_CLIENT_PRIVATE_H */
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-session-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-session-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-session-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-session-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-session.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-session.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-session.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-session.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-session.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-session.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-session.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-session.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-side-encryption-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-side-encryption-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-side-encryption-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-side-encryption-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-side-encryption.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-side-encryption.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-side-encryption.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-side-encryption.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-side-encryption.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-side-encryption.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-side-encryption.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-side-encryption.h
diff --git a/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client.c
new file mode 100644
index 00000000..46a3c504
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client.c
@@ -0,0 +1,3168 @@
+/*
+ * Copyright 2013 MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include <bson/bson.h>
+#include "mongoc-config.h"
+#ifdef MONGOC_HAVE_DNSAPI
+/* for DnsQuery_UTF8 */
+#include <Windows.h>
+#include <WinDNS.h>
+#include <ws2tcpip.h>
+#else
+#if defined(MONGOC_HAVE_RES_NSEARCH) || defined(MONGOC_HAVE_RES_SEARCH)
+#include <netdb.h>
+#include <netinet/tcp.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+#define BSON_INSIDE
+#include <bson/bson-string.h>
+#undef BSON_INSIDE
+
+#endif
+#endif
+
+#include "mongoc-client-private.h"
+#include "mongoc-client-side-encryption-private.h"
+#include "mongoc-collection-private.h"
+#include "mongoc-counters-private.h"
+#include "mongoc-database-private.h"
+#include "mongoc-gridfs-private.h"
+#include "mongoc-error.h"
+#include "mongoc-error-private.h"
+#include "mongoc-log.h"
+#include "mongoc-queue-private.h"
+#include "mongoc-socket.h"
+#include "mongoc-stream-buffered.h"
+#include "mongoc-stream-socket.h"
+#include "mongoc-thread-private.h"
+#include "mongoc-trace-private.h"
+#include "mongoc-uri-private.h"
+#include "mongoc-util-private.h"
+#include "mongoc-set-private.h"
+#include "mongoc-log.h"
+#include "mongoc-write-concern-private.h"
+#include "mongoc-read-concern-private.h"
+#include "mongoc-host-list-private.h"
+#include "mongoc-read-prefs-private.h"
+#include "mongoc-change-stream-private.h"
+#include "mongoc-client-session-private.h"
+#include "mongoc-cursor-private.h"
+
+#ifdef MONGOC_ENABLE_SSL
+#include "mongoc-stream-tls.h"
+#include "mongoc-ssl-private.h"
+#include "mongoc-cmd-private.h"
+#include "mongoc-opts-private.h"
+#endif
+
+
+#undef MONGOC_LOG_DOMAIN
+#define MONGOC_LOG_DOMAIN "client"
+
+
+static void
+_mongoc_client_op_killcursors (mongoc_cluster_t *cluster,
+ mongoc_server_stream_t *server_stream,
+ int64_t cursor_id,
+ int64_t operation_id,
+ const char *db,
+ const char *collection);
+
+static void
+_mongoc_client_killcursors_command (mongoc_cluster_t *cluster,
+ mongoc_server_stream_t *server_stream,
+ int64_t cursor_id,
+ const char *db,
+ const char *collection,
+ mongoc_client_session_t *cs);
+
+#define DNS_ERROR(_msg, ...) \
+ do { \
+ bson_set_error (error, \
+ MONGOC_ERROR_STREAM, \
+ MONGOC_ERROR_STREAM_NAME_RESOLUTION, \
+ _msg, \
+ __VA_ARGS__); \
+ GOTO (done); \
+ } while (0)
+
+
+#ifdef MONGOC_HAVE_DNSAPI
+
+typedef bool (*mongoc_rr_callback_t) (const char *hostname,
+ PDNS_RECORD pdns,
+ mongoc_rr_data_t *rr_data,
+ bson_error_t *error);
+
+static bool
+srv_callback (const char *hostname,
+ PDNS_RECORD pdns,
+ mongoc_rr_data_t *rr_data,
+ bson_error_t *error)
+{
+ mongoc_host_list_t new_host;
+
+ if (rr_data && rr_data->hosts) {
+ _mongoc_host_list_remove_host (
+ &(rr_data->hosts), pdns->Data.SRV.pNameTarget, pdns->Data.SRV.wPort);
+ }
+
+ if (!_mongoc_host_list_from_hostport_with_err (
+ &new_host, pdns->Data.SRV.pNameTarget, pdns->Data.SRV.wPort, error)) {
+ return false;
+ }
+ _mongoc_host_list_upsert (&rr_data->hosts, &new_host);
+
+ return true;
+}
+
+/* rr_data is unused, but here to match srv_callback signature */
+static bool
+txt_callback (const char *hostname,
+ PDNS_RECORD pdns,
+ mongoc_rr_data_t *rr_data,
+ bson_error_t *error)
+{
+ DWORD i;
+ bson_string_t *txt;
+
+ txt = bson_string_new (NULL);
+
+ for (i = 0; i < pdns->Data.TXT.dwStringCount; i++) {
+ bson_string_append (txt, pdns->Data.TXT.pStringArray[i]);
+ }
+
+ rr_data->txt_record_opts = bson_strdup (txt->str);
+ bson_string_free (txt, true);
+
+ return true;
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_get_rr_dnsapi --
+ *
+ * Fetch SRV or TXT resource records using the Windows DNS API and
+ * put results in @rr_data.
+ *
+ * Returns:
+ * Success or failure.
+ *
+ * For an SRV lookup, returns false if there is any error.
+ *
+ * For TXT lookup, ignores any error fetching the resource record and
+ * always returns true.
+ *
+ * Side effects:
+ * @error is set if there is a failure.
+ * @rr_data->hosts may be set if querying SRV. Caller must destroy.
+ * @rr_data->txt_record_opts may be set if querying TXT. Caller must
+ * free.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+static bool
+_mongoc_get_rr_dnsapi (const char *hostname,
+ mongoc_rr_type_t rr_type,
+ mongoc_rr_data_t *rr_data,
+ bson_error_t *error)
+{
+ const char *rr_type_name;
+ WORD nst;
+ mongoc_rr_callback_t callback;
+ PDNS_RECORD pdns = NULL;
+ DNS_STATUS res;
+ LPVOID lpMsgBuf = NULL;
+ bool dns_success;
+ bool callback_success = true;
+ int i;
+
+ ENTRY;
+
+ if (rr_type == MONGOC_RR_SRV) {
+ /* return true only if DNS succeeds */
+ dns_success = false;
+ rr_type_name = "SRV";
+ nst = DNS_TYPE_SRV;
+ callback = srv_callback;
+ } else {
+ /* return true whether or not DNS succeeds */
+ dns_success = true;
+ rr_type_name = "TXT";
+ nst = DNS_TYPE_TEXT;
+ callback = txt_callback;
+ }
+
+ res = DnsQuery_UTF8 (hostname,
+ nst,
+ DNS_QUERY_BYPASS_CACHE,
+ NULL /* IP Address */,
+ &pdns,
+ 0 /* reserved */);
+
+ if (res) {
+ DWORD flags = FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS;
+
+ if (FormatMessage (flags,
+ 0,
+ res,
+ MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPTSTR) &lpMsgBuf,
+ 0,
+ 0)) {
+ DNS_ERROR ("Failed to look up %s record \"%s\": %s",
+ rr_type_name,
+ hostname,
+ (char *) lpMsgBuf);
+ }
+
+ DNS_ERROR ("Failed to look up %s record \"%s\": Unknown error",
+ rr_type_name,
+ hostname);
+ }
+
+ if (!pdns) {
+ DNS_ERROR ("No %s records for \"%s\"", rr_type_name, hostname);
+ }
+
+ i = 0;
+
+ do {
+ /* DnsQuery can return additional records not of the requested type */
+ if ((rr_type == MONGOC_RR_TXT && pdns->wType == DNS_TYPE_TEXT) ||
+ (rr_type == MONGOC_RR_SRV && pdns->wType == DNS_TYPE_SRV)) {
+ if (i > 0 && rr_type == MONGOC_RR_TXT) {
+ /* Initial DNS Seedlist Discovery Spec: a client "MUST raise an
+ error when multiple TXT records are encountered". */
+ callback_success = false;
+ DNS_ERROR ("Multiple TXT records for \"%s\"", hostname);
+ }
+
+ if (rr_data) {
+ if ((i == 0) || (pdns->dwTtl < rr_data->min_ttl)) {
+ rr_data->min_ttl = pdns->dwTtl;
+ }
+ }
+
+ if (!callback (hostname, pdns, rr_data, error)) {
+ callback_success = false;
+ GOTO (done);
+ }
+
+ i++;
+ }
+
+ pdns = pdns->pNext;
+ } while (pdns);
+
+
+ rr_data->count = i;
+ if (i == 0) {
+ DNS_ERROR ("No matching %s records for \"%s\"", rr_type_name, hostname);
+ }
+ dns_success = true;
+
+done:
+ if (pdns) {
+ DnsRecordListFree (pdns, DnsFreeRecordList);
+ }
+
+ if (lpMsgBuf) {
+ LocalFree (lpMsgBuf);
+ }
+
+ RETURN (dns_success && callback_success);
+}
+
+#elif (defined(MONGOC_HAVE_RES_NSEARCH) || defined(MONGOC_HAVE_RES_SEARCH))
+
+typedef bool (*mongoc_rr_callback_t) (const char *hostname,
+ ns_msg *ns_answer,
+ ns_rr *rr,
+ mongoc_rr_data_t *rr_data,
+ bson_error_t *error);
+
+static const char *
+_mongoc_hstrerror (int code)
+{
+ switch (code) {
+ case HOST_NOT_FOUND:
+ return "The specified host is unknown.";
+ case NO_ADDRESS:
+ return "The requested name is valid but does not have an IP address.";
+ case NO_RECOVERY:
+ return "A nonrecoverable name server error occurred.";
+ case TRY_AGAIN:
+ return "A temporary error occurred on an authoritative name server. Try "
+ "again later.";
+ default:
+ return "An unknown error occurred.";
+ }
+}
+
+static bool
+srv_callback (const char *hostname,
+ ns_msg *ns_answer,
+ ns_rr *rr,
+ mongoc_rr_data_t *rr_data,
+ bson_error_t *error)
+{
+ const uint8_t *data;
+ char name[1024];
+ uint16_t port;
+ int size;
+ bool ret = false;
+ mongoc_host_list_t new_host;
+
+ data = ns_rr_rdata (*rr);
+ /* memcpy the network endian port before converting to host endian. we cannot
+ * cast (data + 4) directly as a uint16_t*, because it may not align on an
+ * 2-byte boundary. */
+ memcpy (&port, data + 4, sizeof (port));
+ port = ntohs (port);
+ size = dn_expand (ns_msg_base (*ns_answer),
+ ns_msg_end (*ns_answer),
+ data + 6,
+ name,
+ sizeof (name));
+
+ if (size < 1) {
+ DNS_ERROR ("Invalid record in SRV answer for \"%s\": \"%s\"",
+ hostname,
+ _mongoc_hstrerror (h_errno));
+ }
+
+ if (!_mongoc_host_list_from_hostport_with_err (
+ &new_host, name, port, error)) {
+ GOTO (done);
+ }
+ _mongoc_host_list_upsert (&rr_data->hosts, &new_host);
+ ret = true;
+done:
+ return ret;
+}
+
+static bool
+txt_callback (const char *hostname,
+ ns_msg *ns_answer,
+ ns_rr *rr,
+ mongoc_rr_data_t *rr_data,
+ bson_error_t *error)
+{
+ char s[256];
+ const uint8_t *data;
+ bson_string_t *txt;
+ uint16_t pos, total;
+ uint8_t len;
+ bool ret = false;
+
+ total = (uint16_t) ns_rr_rdlen (*rr);
+ if (total < 1 || total > 255) {
+ DNS_ERROR ("Invalid TXT record size %hu for \"%s\"", total, hostname);
+ }
+
+ /* a TXT record has one or more strings, each up to 255 chars, each is
+ * prefixed by its length as 1 byte. thus endianness doesn't matter. */
+ txt = bson_string_new (NULL);
+ pos = 0;
+ data = ns_rr_rdata (*rr);
+
+ while (pos < total) {
+ memcpy (&len, data + pos, sizeof (uint8_t));
+ pos++;
+ bson_strncpy (s, (const char *) (data + pos), (size_t) len + 1);
+ bson_string_append (txt, s);
+ pos += len;
+ }
+
+ rr_data->txt_record_opts = bson_strdup (txt->str);
+ bson_string_free (txt, true);
+ ret = true;
+
+done:
+ return ret;
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_get_rr_search --
+ *
+ * Fetch SRV or TXT resource records using libresolv and put results in
+ * @rr_data.
+ *
+ * Returns:
+ * Success or failure.
+ *
+ * For an SRV lookup, returns false if there is any error.
+ *
+ * For TXT lookup, ignores any error fetching the resource record and
+ * always returns true.
+ *
+ * Side effects:
+ * @error is set if there is a failure.
+ * @rr_data->hosts may be set if querying SRV. Caller must destroy.
+ * @rr_data->txt_record_opts may be set if querying TXT. Caller must
+ * free.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+static bool
+_mongoc_get_rr_search (const char *hostname,
+ mongoc_rr_type_t rr_type,
+ mongoc_rr_data_t *rr_data,
+ size_t initial_buffer_size,
+ bson_error_t *error)
+{
+#ifdef MONGOC_HAVE_RES_NSEARCH
+ struct __res_state state = {0};
+#endif
+ int size = 0;
+ unsigned char *search_buf = NULL;
+ size_t buffer_size = initial_buffer_size;
+ ns_msg ns_answer;
+ int n;
+ int i;
+ const char *rr_type_name;
+ ns_type nst;
+ mongoc_rr_callback_t callback;
+ ns_rr resource_record;
+ bool dns_success;
+ bool callback_success = true;
+ int num_matching_records;
+ uint32_t ttl;
+
+ ENTRY;
+
+ if (rr_type == MONGOC_RR_SRV) {
+ /* return true only if DNS succeeds */
+ dns_success = false;
+ rr_type_name = "SRV";
+ nst = ns_t_srv;
+ callback = srv_callback;
+ } else {
+ /* return true whether or not DNS succeeds */
+ dns_success = true;
+ rr_type_name = "TXT";
+ nst = ns_t_txt;
+ callback = txt_callback;
+ }
+
+ do {
+ if (search_buf) {
+ bson_free (search_buf);
+
+ /* increase buffer size by the previous response size. This ensures
+ * that even if a subsequent response is larger, we'll still be able
+ * to fit it in the response buffer */
+ buffer_size = buffer_size + size;
+ }
+
+ search_buf = (unsigned char *) bson_malloc (buffer_size);
+ BSON_ASSERT (search_buf);
+
+#ifdef MONGOC_HAVE_RES_NSEARCH
+ /* thread-safe */
+ res_ninit (&state);
+ size =
+ res_nsearch (&state, hostname, ns_c_in, nst, search_buf, buffer_size);
+#elif defined(MONGOC_HAVE_RES_SEARCH)
+ size = res_search (hostname, ns_c_in, nst, search_buf, buffer_size);
+#endif
+
+ if (size < 0) {
+ DNS_ERROR ("Failed to look up %s record \"%s\": %s",
+ rr_type_name,
+ hostname,
+ _mongoc_hstrerror (h_errno));
+ }
+ } while (size >= buffer_size);
+
+ if (ns_initparse (search_buf, size, &ns_answer)) {
+ DNS_ERROR ("Invalid %s answer for \"%s\"", rr_type_name, hostname);
+ }
+
+ n = ns_msg_count (ns_answer, ns_s_an);
+ if (!n) {
+ DNS_ERROR ("No %s records for \"%s\"", rr_type_name, hostname);
+ }
+
+ rr_data->count = n;
+ num_matching_records = 0;
+ for (i = 0; i < n; i++) {
+ if (ns_parserr (&ns_answer, ns_s_an, i, &resource_record)) {
+ DNS_ERROR ("Invalid record %d of %s answer for \"%s\": \"%s\"",
+ i,
+ rr_type_name,
+ hostname,
+ _mongoc_hstrerror (h_errno));
+ }
+
+ /* Skip records that don't match the ones we requested. CDRIVER-3628 shows
+ * that we can receive records that were not requested. */
+ if (rr_type == MONGOC_RR_TXT) {
+ if (ns_rr_type (resource_record) != ns_t_txt) {
+ continue;
+ }
+ } else if (rr_type == MONGOC_RR_SRV) {
+ if (ns_rr_type (resource_record) != ns_t_srv) {
+ continue;
+ }
+ }
+
+ if (num_matching_records > 0 && rr_type == MONGOC_RR_TXT) {
+ /* Initial DNS Seedlist Discovery Spec: a client "MUST raise an error
+ * when multiple TXT records are encountered". */
+ callback_success = false;
+ DNS_ERROR ("Multiple TXT records for \"%s\"", hostname);
+ }
+
+ num_matching_records++;
+
+ ttl = ns_rr_ttl (resource_record);
+ if ((i == 0) || (ttl < rr_data->min_ttl)) {
+ rr_data->min_ttl = ttl;
+ }
+
+ if (!callback (hostname, &ns_answer, &resource_record, rr_data, error)) {
+ callback_success = false;
+ GOTO (done);
+ }
+ }
+
+ if (num_matching_records == 0) {
+ DNS_ERROR ("No matching %s records for \"%s\"", rr_type_name, hostname);
+ }
+
+ dns_success = true;
+
+done:
+
+ bson_free (search_buf);
+
+#ifdef MONGOC_HAVE_RES_NDESTROY
+ /* defined on BSD/Darwin, and only if MONGOC_HAVE_RES_NSEARCH is defined */
+ res_ndestroy (&state);
+#elif defined(MONGOC_HAVE_RES_NCLOSE)
+ /* defined on Linux, and only if MONGOC_HAVE_RES_NSEARCH is defined */
+ res_nclose (&state);
+#endif
+ RETURN (dns_success && callback_success);
+}
+#endif
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_client_get_rr --
+ *
+ * Fetch an SRV or TXT resource record and update put results in
+ * @rr_data.
+ *
+ * See RFCs 1464 and 2782, MongoDB's "Initial DNS Seedlist Discovery"
+ * spec, and MongoDB's "Polling SRV Records for Mongos Discovery"
+ * spec.
+ *
+ * Returns:
+ * Success or failure.
+ *
+ * Side effects:
+ * @error is set if there is a failure. Errors fetching TXT are
+ * ignored.
+ * @rr_data->hosts may be set if querying SRV. Caller must destroy.
+ * @rr_data->txt_record_opts may be set if querying TXT. Caller must
+ * free.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+bool
+_mongoc_client_get_rr (const char *hostname,
+ mongoc_rr_type_t rr_type,
+ mongoc_rr_data_t *rr_data,
+ size_t initial_buffer_size,
+ bson_error_t *error)
+{
+ BSON_ASSERT (rr_data);
+
+#ifdef MONGOC_HAVE_DNSAPI
+ return _mongoc_get_rr_dnsapi (hostname, rr_type, rr_data, error);
+#elif (defined(MONGOC_HAVE_RES_NSEARCH) || defined(MONGOC_HAVE_RES_SEARCH))
+ return _mongoc_get_rr_search (
+ hostname, rr_type, rr_data, initial_buffer_size, error);
+#else
+ bson_set_error (error,
+ MONGOC_ERROR_STREAM,
+ MONGOC_ERROR_STREAM_NAME_RESOLUTION,
+ "libresolv unavailable, cannot use mongodb+srv URI");
+ return false;
+#endif
+}
+
+#undef DNS_ERROR
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_client_connect_tcp --
+ *
+ * Connect to a host using a TCP socket.
+ *
+ * This will be performed synchronously and return a mongoc_stream_t
+ * that can be used to connect with the remote host.
+ *
+ * Returns:
+ * A newly allocated mongoc_stream_t if successful; otherwise
+ * NULL and @error is set.
+ *
+ * Side effects:
+ * @error is set if return value is NULL.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+mongoc_stream_t *
+mongoc_client_connect_tcp (int32_t connecttimeoutms,
+ const mongoc_host_list_t *host,
+ bson_error_t *error)
+{
+ mongoc_socket_t *sock = NULL;
+ struct addrinfo hints;
+ struct addrinfo *result, *rp;
+ int64_t expire_at;
+ char portstr[8];
+ int s;
+
+ ENTRY;
+
+ BSON_ASSERT (connecttimeoutms);
+ BSON_ASSERT (host);
+
+ bson_snprintf (portstr, sizeof portstr, "%hu", host->port);
+
+ memset (&hints, 0, sizeof hints);
+ hints.ai_family = host->family;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = 0;
+ hints.ai_protocol = 0;
+
+ TRACE ("DNS lookup for %s", host->host);
+ s = getaddrinfo (host->host, portstr, &hints, &result);
+
+ if (s != 0) {
+ mongoc_counter_dns_failure_inc ();
+ TRACE ("Failed to resolve %s", host->host);
+ bson_set_error (error,
+ MONGOC_ERROR_STREAM,
+ MONGOC_ERROR_STREAM_NAME_RESOLUTION,
+ "Failed to resolve %s",
+ host->host);
+ RETURN (NULL);
+ }
+
+ mongoc_counter_dns_success_inc ();
+
+ for (rp = result; rp; rp = rp->ai_next) {
+ /*
+ * Create a new non-blocking socket.
+ */
+ if (!(sock = mongoc_socket_new (
+ rp->ai_family, rp->ai_socktype, rp->ai_protocol))) {
+ continue;
+ }
+
+ /*
+ * Try to connect to the peer.
+ */
+ expire_at = bson_get_monotonic_time () + (connecttimeoutms * 1000L);
+ if (0 !=
+ mongoc_socket_connect (
+ sock, rp->ai_addr, (mongoc_socklen_t) rp->ai_addrlen, expire_at)) {
+ mongoc_socket_destroy (sock);
+ sock = NULL;
+ continue;
+ }
+
+ break;
+ }
+
+ if (!sock) {
+ bson_set_error (error,
+ MONGOC_ERROR_STREAM,
+ MONGOC_ERROR_STREAM_CONNECT,
+ "Failed to connect to target host: %s",
+ host->host_and_port);
+ freeaddrinfo (result);
+ RETURN (NULL);
+ }
+
+ freeaddrinfo (result);
+
+ return mongoc_stream_socket_new (sock);
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_client_connect_unix --
+ *
+ * Connect to a MongoDB server using a UNIX domain socket.
+ *
+ * Returns:
+ * A newly allocated mongoc_stream_t if successful; otherwise
+ * NULL and @error is set.
+ *
+ * Side effects:
+ * @error is set if return value is NULL.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+static mongoc_stream_t *
+mongoc_client_connect_unix (const mongoc_host_list_t *host, bson_error_t *error)
+{
+#ifdef _WIN32
+ ENTRY;
+ bson_set_error (error,
+ MONGOC_ERROR_STREAM,
+ MONGOC_ERROR_STREAM_CONNECT,
+ "UNIX domain sockets not supported on win32.");
+ RETURN (NULL);
+#else
+ struct sockaddr_un saddr;
+ mongoc_socket_t *sock;
+ mongoc_stream_t *ret = NULL;
+
+ ENTRY;
+
+ BSON_ASSERT (host);
+
+ memset (&saddr, 0, sizeof saddr);
+ saddr.sun_family = AF_UNIX;
+ bson_snprintf (saddr.sun_path, sizeof saddr.sun_path - 1, "%s", host->host);
+
+ sock = mongoc_socket_new (AF_UNIX, SOCK_STREAM, 0);
+
+ if (sock == NULL) {
+ bson_set_error (error,
+ MONGOC_ERROR_STREAM,
+ MONGOC_ERROR_STREAM_SOCKET,
+ "Failed to create socket.");
+ RETURN (NULL);
+ }
+
+ if (-1 == mongoc_socket_connect (
+ sock, (struct sockaddr *) &saddr, sizeof saddr, -1)) {
+ mongoc_socket_destroy (sock);
+ bson_set_error (error,
+ MONGOC_ERROR_STREAM,
+ MONGOC_ERROR_STREAM_CONNECT,
+ "Failed to connect to UNIX domain socket.");
+ RETURN (NULL);
+ }
+
+ ret = mongoc_stream_socket_new (sock);
+
+ RETURN (ret);
+#endif
+}
+
+mongoc_stream_t *
+mongoc_client_connect (bool buffered,
+ bool use_ssl,
+ void *ssl_opts_void,
+ const mongoc_uri_t *uri,
+ const mongoc_host_list_t *host,
+ bson_error_t *error)
+{
+ mongoc_stream_t *base_stream = NULL;
+ int32_t connecttimeoutms;
+
+ BSON_ASSERT (uri);
+ BSON_ASSERT (host);
+
+#ifndef MONGOC_ENABLE_SSL
+ if (ssl_opts_void || mongoc_uri_get_tls (uri)) {
+ bson_set_error (error,
+ MONGOC_ERROR_CLIENT,
+ MONGOC_ERROR_CLIENT_NO_ACCEPTABLE_PEER,
+ "TLS is not enabled in this build of mongo-c-driver.");
+ return NULL;
+ }
+#endif
+
+ connecttimeoutms = mongoc_uri_get_option_as_int32 (
+ uri, MONGOC_URI_CONNECTTIMEOUTMS, MONGOC_DEFAULT_CONNECTTIMEOUTMS);
+
+ switch (host->family) {
+ case AF_UNSPEC:
+#if defined(AF_INET6)
+ case AF_INET6:
+#endif
+ case AF_INET:
+ base_stream = mongoc_client_connect_tcp (connecttimeoutms, host, error);
+ break;
+ case AF_UNIX:
+ base_stream = mongoc_client_connect_unix (host, error);
+ break;
+ default:
+ bson_set_error (error,
+ MONGOC_ERROR_STREAM,
+ MONGOC_ERROR_STREAM_INVALID_TYPE,
+ "Invalid address family: 0x%02x",
+ host->family);
+ break;
+ }
+
+#ifdef MONGOC_ENABLE_SSL
+ if (base_stream) {
+ mongoc_ssl_opt_t *ssl_opts;
+ const char *mechanism;
+
+ ssl_opts = (mongoc_ssl_opt_t *) ssl_opts_void;
+ mechanism = mongoc_uri_get_auth_mechanism (uri);
+
+ if (use_ssl || (mechanism && (0 == strcmp (mechanism, "MONGODB-X509")))) {
+ mongoc_stream_t *original = base_stream;
+
+ base_stream = mongoc_stream_tls_new_with_hostname (
+ base_stream, host->host, ssl_opts, true);
+
+ if (!base_stream) {
+ mongoc_stream_destroy (original);
+ bson_set_error (error,
+ MONGOC_ERROR_STREAM,
+ MONGOC_ERROR_STREAM_SOCKET,
+ "Failed initialize TLS state.");
+ return NULL;
+ }
+
+ if (!mongoc_stream_tls_handshake_block (
+ base_stream, host->host, connecttimeoutms, error)) {
+ mongoc_stream_destroy (base_stream);
+ return NULL;
+ }
+ }
+ }
+#endif
+
+ if (!base_stream) {
+ return NULL;
+ }
+ if (buffered) {
+ return mongoc_stream_buffered_new (base_stream, 1024);
+ }
+ return base_stream;
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_client_default_stream_initiator --
+ *
+ * A mongoc_stream_initiator_t that will handle the various type
+ * of supported sockets by MongoDB including TCP and UNIX.
+ *
+ * Language binding authors may want to implement an alternate
+ * version of this method to use their native stream format.
+ *
+ * Returns:
+ * A mongoc_stream_t if successful; otherwise NULL and @error is set.
+ *
+ * Side effects:
+ * @error is set if return value is NULL.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+mongoc_stream_t *
+mongoc_client_default_stream_initiator (const mongoc_uri_t *uri,
+ const mongoc_host_list_t *host,
+ void *user_data,
+ bson_error_t *error)
+{
+ void *ssl_opts_void = NULL;
+ bool use_ssl = false;
+#ifdef MONGOC_ENABLE_SSL
+ mongoc_client_t *client = (mongoc_client_t *) user_data;
+
+ use_ssl = client->use_ssl;
+ ssl_opts_void = (void *) &client->ssl_opts;
+
+#endif
+
+ return mongoc_client_connect (
+ true, use_ssl, ssl_opts_void, uri, host, error);
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_client_create_stream --
+ *
+ * INTERNAL API
+ *
+ * This function is used by the mongoc_cluster_t to initiate a
+ * new stream. This is done because cluster is private API and
+ * those using mongoc_client_t may need to override this process.
+ *
+ * This function calls the default initiator for new streams.
+ *
+ * Returns:
+ * A newly allocated mongoc_stream_t if successful; otherwise
+ * NULL and @error is set.
+ *
+ * Side effects:
+ * @error is set if return value is NULL.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+mongoc_stream_t *
+_mongoc_client_create_stream (mongoc_client_t *client,
+ const mongoc_host_list_t *host,
+ bson_error_t *error)
+{
+ BSON_ASSERT (client);
+ BSON_ASSERT (host);
+
+ return client->initiator (client->uri, host, client->initiator_data, error);
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_client_recv --
+ *
+ * Receives a RPC from a remote MongoDB cluster node.
+ *
+ * Returns:
+ * true if successful; otherwise false and @error is set.
+ *
+ * Side effects:
+ * @error is set if return value is false.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+bool
+_mongoc_client_recv (mongoc_client_t *client,
+ mongoc_rpc_t *rpc,
+ mongoc_buffer_t *buffer,
+ mongoc_server_stream_t *server_stream,
+ bson_error_t *error)
+{
+ BSON_ASSERT (client);
+ BSON_ASSERT (rpc);
+ BSON_ASSERT (buffer);
+ BSON_ASSERT (server_stream);
+
+ return mongoc_cluster_try_recv (
+ &client->cluster, rpc, buffer, server_stream, error);
+}
+
+
+mongoc_client_t *
+mongoc_client_new (const char *uri_string)
+{
+ mongoc_client_t *client;
+ mongoc_uri_t *uri;
+ bson_error_t error = {0};
+
+ if (!uri_string) {
+ uri_string = "mongodb://127.0.0.1/";
+ }
+
+ if (!(uri = mongoc_uri_new_with_error (uri_string, &error))) {
+ /* Log URI errors as a warning for consistency with mongoc_uri_new */
+ MONGOC_WARNING ("Error parsing URI: '%s'", error.message);
+ return NULL;
+ }
+
+ if (!(client = mongoc_client_new_from_uri_with_error (uri, &error))) {
+ MONGOC_ERROR ("%s", error.message);
+ }
+
+ mongoc_uri_destroy (uri);
+
+ return client;
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_client_set_ssl_opts
+ *
+ * set ssl opts for a client
+ *
+ * Returns:
+ * Nothing
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+#ifdef MONGOC_ENABLE_SSL
+/* Only called internally. Caller must ensure opts->internal is valid. */
+void
+_mongoc_client_set_internal_tls_opts (mongoc_client_t *client,
+ _mongoc_internal_tls_opts_t *internal)
+{
+ if (!client->use_ssl) {
+ return;
+ }
+ client->ssl_opts.internal =
+ bson_malloc (sizeof (_mongoc_internal_tls_opts_t));
+ memcpy (client->ssl_opts.internal,
+ internal,
+ sizeof (_mongoc_internal_tls_opts_t));
+}
+
+void
+mongoc_client_set_ssl_opts (mongoc_client_t *client,
+ const mongoc_ssl_opt_t *opts)
+{
+ BSON_ASSERT (client);
+ BSON_ASSERT (opts);
+
+ _mongoc_ssl_opts_cleanup (&client->ssl_opts,
+ false /* don't free internal opts */);
+
+ client->use_ssl = true;
+ _mongoc_ssl_opts_copy_to (
+ opts, &client->ssl_opts, false /* don't overwrite internal opts */);
+
+ if (client->topology->single_threaded) {
+ mongoc_topology_scanner_set_ssl_opts (client->topology->scanner,
+ &client->ssl_opts);
+ }
+}
+#endif
+
+
+mongoc_client_t *
+mongoc_client_new_from_uri (const mongoc_uri_t *uri)
+{
+ mongoc_client_t *client;
+ bson_error_t error = {0};
+
+ if (!(client = mongoc_client_new_from_uri_with_error (uri, &error))) {
+ MONGOC_ERROR ("%s", error.message);
+ }
+
+ return client;
+}
+
+
+mongoc_client_t *
+mongoc_client_new_from_uri_with_error (const mongoc_uri_t *uri,
+ bson_error_t *error)
+{
+ mongoc_client_t *client;
+ mongoc_topology_t *topology;
+
+
+ ENTRY;
+
+ BSON_ASSERT (uri);
+
+#ifndef MONGOC_ENABLE_SSL
+ if (mongoc_uri_get_tls (uri)) {
+ bson_set_error (
+ error,
+ MONGOC_ERROR_COMMAND,
+ MONGOC_ERROR_COMMAND_INVALID_ARG,
+ "Can't create SSL client, SSL not enabled in this build.");
+ RETURN (NULL);
+ }
+#endif
+
+ topology = mongoc_topology_new (uri, true);
+
+ if (!topology->valid) {
+ if (error) {
+ memcpy (error, &topology->scanner->error, sizeof (bson_error_t));
+ }
+
+ mongoc_topology_destroy (topology);
+
+ RETURN (NULL);
+ }
+
+ client = _mongoc_client_new_from_topology (topology);
+ BSON_ASSERT (client);
+
+ RETURN (client);
+}
+
+
+/* precondition: topology is valid */
+mongoc_client_t *
+_mongoc_client_new_from_topology (mongoc_topology_t *topology)
+{
+ mongoc_client_t *client;
+ const mongoc_read_prefs_t *read_prefs;
+ const mongoc_read_concern_t *read_concern;
+ const mongoc_write_concern_t *write_concern;
+ const char *appname;
+
+ BSON_ASSERT (topology);
+ BSON_ASSERT (topology->valid);
+
+ client = (mongoc_client_t *) bson_malloc0 (sizeof *client);
+ client->uri = mongoc_uri_copy (topology->uri);
+ client->initiator = mongoc_client_default_stream_initiator;
+ client->initiator_data = client;
+ client->topology = topology;
+ client->error_api_version = MONGOC_ERROR_API_VERSION_LEGACY;
+ client->error_api_set = false;
+ client->client_sessions = mongoc_set_new (8, NULL, NULL);
+ client->csid_rand_seed = (unsigned int) bson_get_monotonic_time ();
+
+ write_concern = mongoc_uri_get_write_concern (client->uri);
+ client->write_concern = mongoc_write_concern_copy (write_concern);
+
+ read_concern = mongoc_uri_get_read_concern (client->uri);
+ client->read_concern = mongoc_read_concern_copy (read_concern);
+
+ read_prefs = mongoc_uri_get_read_prefs_t (client->uri);
+ client->read_prefs = mongoc_read_prefs_copy (read_prefs);
+
+ appname =
+ mongoc_uri_get_option_as_utf8 (client->uri, MONGOC_URI_APPNAME, NULL);
+ if (appname && client->topology->single_threaded) {
+ /* the appname should have already been validated */
+ BSON_ASSERT (mongoc_client_set_appname (client, appname));
+ }
+
+ mongoc_cluster_init (&client->cluster, client->uri, client);
+
+#ifdef MONGOC_ENABLE_SSL
+ client->use_ssl = false;
+ if (mongoc_uri_get_tls (client->uri)) {
+ mongoc_ssl_opt_t ssl_opt = {0};
+ _mongoc_internal_tls_opts_t internal_tls_opts = {0};
+
+ _mongoc_ssl_opts_from_uri (&ssl_opt, &internal_tls_opts, client->uri);
+ /* sets use_ssl = true */
+ mongoc_client_set_ssl_opts (client, &ssl_opt);
+ _mongoc_client_set_internal_tls_opts (client, &internal_tls_opts);
+ }
+#endif
+
+ mongoc_counter_clients_active_inc ();
+
+ return client;
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_client_destroy --
+ *
+ * Destroys a mongoc_client_t and cleans up all resources associated
+ * with the client instance.
+ *
+ * Returns:
+ * None.
+ *
+ * Side effects:
+ * @client is destroyed.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+void
+mongoc_client_destroy (mongoc_client_t *client)
+{
+ if (client) {
+ if (client->topology->single_threaded) {
+ _mongoc_client_end_sessions (client);
+ mongoc_topology_destroy (client->topology);
+ }
+
+ mongoc_write_concern_destroy (client->write_concern);
+ mongoc_read_concern_destroy (client->read_concern);
+ mongoc_read_prefs_destroy (client->read_prefs);
+ mongoc_cluster_destroy (&client->cluster);
+ mongoc_uri_destroy (client->uri);
+ mongoc_set_destroy (client->client_sessions);
+ mongoc_server_api_destroy (client->api);
+
+#ifdef MONGOC_ENABLE_SSL
+ _mongoc_ssl_opts_cleanup (&client->ssl_opts, true);
+#endif
+
+ bson_free (client);
+
+ mongoc_counter_clients_active_dec ();
+ mongoc_counter_clients_disposed_inc ();
+ }
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_client_get_uri --
+ *
+ * Fetch the URI used for @client.
+ *
+ * Returns:
+ * A mongoc_uri_t that should not be modified or freed.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+const mongoc_uri_t *
+mongoc_client_get_uri (const mongoc_client_t *client)
+{
+ BSON_ASSERT (client);
+
+ return client->uri;
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_client_start_session --
+ *
+ * Creates a structure to communicate in a session over @client.
+ *
+ * This structure should be freed when the caller is done with it
+ * using mongoc_client_session_destroy().
+ *
+ * Returns:
+ * A newly allocated mongoc_client_session_t.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+mongoc_client_session_t *
+mongoc_client_start_session (mongoc_client_t *client,
+ const mongoc_session_opt_t *opts,
+ bson_error_t *error)
+{
+ mongoc_server_session_t *ss;
+ mongoc_client_session_t *cs;
+ uint32_t csid;
+
+ ENTRY;
+
+ ss = _mongoc_client_pop_server_session (client, error);
+ if (!ss) {
+ RETURN (NULL);
+ }
+
+ /* get a random internal id for the session, retrying on collision */
+ do {
+ csid = (uint32_t) _mongoc_rand_simple (&client->csid_rand_seed);
+ } while (mongoc_set_get (client->client_sessions, csid));
+
+ /* causal consistency and snapshot cannot both be set. */
+ if (opts && mongoc_session_opts_get_causal_consistency (opts) &&
+ mongoc_session_opts_get_snapshot (opts)) {
+ bson_set_error (
+ error,
+ MONGOC_ERROR_CLIENT,
+ MONGOC_ERROR_CLIENT_SESSION_FAILURE,
+ "Only one of causal consistency and snapshot can be enabled.");
+ _mongoc_client_push_server_session (client, ss);
+ RETURN (NULL);
+ }
+ cs = _mongoc_client_session_new (client, ss, opts, csid);
+
+ /* remember session so if we see its client_session_id in a command, we can
+ * find its lsid and clusterTime */
+ mongoc_set_add (client->client_sessions, csid, cs);
+
+ RETURN (cs);
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_client_get_database --
+ *
+ * Fetches a newly allocated database structure to communicate with
+ * a database over @client.
+ *
+ * @database should be a db name such as "test".
+ *
+ * This structure should be freed when the caller is done with it
+ * using mongoc_database_destroy().
+ *
+ * Returns:
+ * A newly allocated mongoc_database_t.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+mongoc_database_t *
+mongoc_client_get_database (mongoc_client_t *client, const char *name)
+{
+ BSON_ASSERT (client);
+ BSON_ASSERT (name);
+
+ return _mongoc_database_new (client,
+ name,
+ client->read_prefs,
+ client->read_concern,
+ client->write_concern);
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_client_get_default_database --
+ *
+ * Get the database named in the MongoDB connection URI, or NULL
+ * if none was specified in the URI.
+ *
+ * This structure should be freed when the caller is done with it
+ * using mongoc_database_destroy().
+ *
+ * Returns:
+ * A newly allocated mongoc_database_t or NULL.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+mongoc_database_t *
+mongoc_client_get_default_database (mongoc_client_t *client)
+{
+ const char *db;
+
+ BSON_ASSERT (client);
+ db = mongoc_uri_get_database (client->uri);
+
+ if (db) {
+ return mongoc_client_get_database (client, db);
+ }
+
+ return NULL;
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_client_get_collection --
+ *
+ * This function returns a newly allocated collection structure.
+ *
+ * @db should be the name of the database, such as "test".
+ * @collection should be the name of the collection such as "test".
+ *
+ * The above would result in the namespace "test.test".
+ *
+ * You should free this structure when you are done with it using
+ * mongoc_collection_destroy().
+ *
+ * Returns:
+ * A newly allocated mongoc_collection_t that should be freed with
+ * mongoc_collection_destroy().
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+mongoc_collection_t *
+mongoc_client_get_collection (mongoc_client_t *client,
+ const char *db,
+ const char *collection)
+{
+ BSON_ASSERT (client);
+ BSON_ASSERT (db);
+ BSON_ASSERT (collection);
+
+ return _mongoc_collection_new (client,
+ db,
+ collection,
+ client->read_prefs,
+ client->read_concern,
+ client->write_concern);
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_client_get_gridfs --
+ *
+ * This function returns a newly allocated collection structure.
+ *
+ * @db should be the name of the database, such as "test".
+ *
+ * @prefix optional prefix for GridFS collection names, or NULL. Default
+ * is "fs", thus the default collection names for GridFS are "fs.files"
+ * and "fs.chunks".
+ *
+ * Returns:
+ * A newly allocated mongoc_gridfs_t that should be freed with
+ * mongoc_gridfs_destroy().
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+mongoc_gridfs_t *
+mongoc_client_get_gridfs (mongoc_client_t *client,
+ const char *db,
+ const char *prefix,
+ bson_error_t *error)
+{
+ BSON_ASSERT (client);
+ BSON_ASSERT (db);
+
+ if (!prefix) {
+ prefix = "fs";
+ }
+
+ return _mongoc_gridfs_new (client, db, prefix, error);
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_client_get_write_concern --
+ *
+ * Fetches the default write concern for @client.
+ *
+ * Returns:
+ * A mongoc_write_concern_t that should not be modified or freed.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+const mongoc_write_concern_t *
+mongoc_client_get_write_concern (const mongoc_client_t *client)
+{
+ BSON_ASSERT (client);
+
+ return client->write_concern;
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_client_set_write_concern --
+ *
+ * Sets the default write concern for @client.
+ *
+ * Returns:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+void
+mongoc_client_set_write_concern (mongoc_client_t *client,
+ const mongoc_write_concern_t *write_concern)
+{
+ BSON_ASSERT (client);
+
+ if (write_concern != client->write_concern) {
+ if (client->write_concern) {
+ mongoc_write_concern_destroy (client->write_concern);
+ }
+ client->write_concern = write_concern
+ ? mongoc_write_concern_copy (write_concern)
+ : mongoc_write_concern_new ();
+ }
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_client_get_read_concern --
+ *
+ * Fetches the default read concern for @client.
+ *
+ * Returns:
+ * A mongoc_read_concern_t that should not be modified or freed.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+const mongoc_read_concern_t *
+mongoc_client_get_read_concern (const mongoc_client_t *client)
+{
+ BSON_ASSERT (client);
+
+ return client->read_concern;
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_client_set_read_concern --
+ *
+ * Sets the default read concern for @client.
+ *
+ * Returns:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+void
+mongoc_client_set_read_concern (mongoc_client_t *client,
+ const mongoc_read_concern_t *read_concern)
+{
+ BSON_ASSERT (client);
+
+ if (read_concern != client->read_concern) {
+ if (client->read_concern) {
+ mongoc_read_concern_destroy (client->read_concern);
+ }
+ client->read_concern = read_concern
+ ? mongoc_read_concern_copy (read_concern)
+ : mongoc_read_concern_new ();
+ }
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_client_get_read_prefs --
+ *
+ * Fetch the default read preferences for @client.
+ *
+ * Returns:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+const mongoc_read_prefs_t *
+mongoc_client_get_read_prefs (const mongoc_client_t *client)
+{
+ BSON_ASSERT (client);
+
+ return client->read_prefs;
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_client_set_read_prefs --
+ *
+ * Set the default read preferences for @client.
+ *
+ * Returns:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+void
+mongoc_client_set_read_prefs (mongoc_client_t *client,
+ const mongoc_read_prefs_t *read_prefs)
+{
+ BSON_ASSERT (client);
+
+ if (read_prefs != client->read_prefs) {
+ if (client->read_prefs) {
+ mongoc_read_prefs_destroy (client->read_prefs);
+ }
+ client->read_prefs = read_prefs
+ ? mongoc_read_prefs_copy (read_prefs)
+ : mongoc_read_prefs_new (MONGOC_READ_PRIMARY);
+ }
+}
+
+mongoc_cursor_t *
+mongoc_client_command (mongoc_client_t *client,
+ const char *db_name,
+ mongoc_query_flags_t flags,
+ uint32_t skip,
+ uint32_t limit,
+ uint32_t batch_size,
+ const bson_t *query,
+ const bson_t *fields,
+ const mongoc_read_prefs_t *read_prefs)
+{
+ char *ns = NULL;
+ mongoc_cursor_t *cursor;
+
+ BSON_ASSERT (client);
+ BSON_ASSERT (db_name);
+ BSON_ASSERT (query);
+
+ /*
+ * Allow a caller to provide a fully qualified namespace
+ */
+ if (NULL == strstr (db_name, "$cmd")) {
+ ns = bson_strdup_printf ("%s.$cmd", db_name);
+ db_name = ns;
+ }
+
+ cursor =
+ _mongoc_cursor_cmd_deprecated_new (client, db_name, query, read_prefs);
+
+ bson_free (ns);
+ return cursor;
+}
+
+
+static bool
+_mongoc_client_retryable_write_command_with_stream (
+ mongoc_client_t *client,
+ mongoc_cmd_parts_t *parts,
+ mongoc_server_stream_t *server_stream,
+ bson_t *reply,
+ bson_error_t *error)
+{
+ mongoc_server_stream_t *retry_server_stream = NULL;
+ bson_iter_t txn_number_iter;
+ bool is_retryable = true;
+ bool ret;
+
+ ENTRY;
+
+ BSON_ASSERT (parts->is_retryable_write);
+
+ /* increment the transaction number for the first attempt of each retryable
+ * write command */
+ BSON_ASSERT (bson_iter_init_find (
+ &txn_number_iter, parts->assembled.command, "txnNumber"));
+ bson_iter_overwrite_int64 (
+ &txn_number_iter, ++parts->assembled.session->server_session->txn_number);
+
+retry:
+ ret = mongoc_cluster_run_command_monitored (
+ &client->cluster, &parts->assembled, reply, error);
+
+ _mongoc_write_error_handle_labels (
+ ret, error, reply, server_stream->sd->max_wire_version);
+
+ if (is_retryable) {
+ _mongoc_write_error_update_if_unsupported_storage_engine (
+ ret, error, reply);
+ }
+
+ /* If a retryable error is encountered and the write is retryable, select
+ * a new writable stream and retry. If server selection fails or the selected
+ * server does not support retryable writes, fall through and allow the
+ * original error to be reported. */
+ if (is_retryable &&
+ _mongoc_write_error_get_type (reply) == MONGOC_WRITE_ERR_RETRY) {
+ bson_error_t ignored_error;
+
+ /* each write command may be retried at most once */
+ is_retryable = false;
+
+ if (retry_server_stream) {
+ mongoc_server_stream_cleanup (retry_server_stream);
+ }
+
+ retry_server_stream = mongoc_cluster_stream_for_writes (
+ &client->cluster, parts->assembled.session, NULL, &ignored_error);
+
+ if (retry_server_stream && retry_server_stream->sd->max_wire_version >=
+ WIRE_VERSION_RETRY_WRITES) {
+ parts->assembled.server_stream = retry_server_stream;
+ bson_destroy (reply);
+ GOTO (retry);
+ }
+ }
+
+ if (retry_server_stream) {
+ mongoc_server_stream_cleanup (retry_server_stream);
+ }
+
+ if (ret && error) {
+ /* if a retry succeeded, clear the initial error */
+ memset (error, 0, sizeof (bson_error_t));
+ }
+
+ RETURN (ret);
+}
+
+
+static bool
+_mongoc_client_retryable_read_command_with_stream (
+ mongoc_client_t *client,
+ mongoc_cmd_parts_t *parts,
+ mongoc_server_stream_t *server_stream,
+ bson_t *reply,
+ bson_error_t *error)
+{
+ mongoc_server_stream_t *retry_server_stream = NULL;
+ bool is_retryable = true;
+ bool ret;
+ bson_t reply_local;
+
+ if (reply == NULL) {
+ reply = &reply_local;
+ }
+
+ ENTRY;
+
+ BSON_ASSERT (parts->is_retryable_read);
+
+retry:
+ ret = mongoc_cluster_run_command_monitored (
+ &client->cluster, &parts->assembled, reply, error);
+
+ /* If a retryable error is encountered and the read is retryable, select
+ * a new readable stream and retry. If server selection fails or the selected
+ * server does not support retryable reads, fall through and allow the
+ * original error to be reported. */
+ if (is_retryable && _mongoc_read_error_get_type (ret, error, reply) ==
+ MONGOC_READ_ERR_RETRY) {
+ bson_error_t ignored_error;
+
+ /* each read command may be retried at most once */
+ is_retryable = false;
+
+ if (retry_server_stream) {
+ mongoc_server_stream_cleanup (retry_server_stream);
+ }
+
+ retry_server_stream =
+ mongoc_cluster_stream_for_reads (&client->cluster,
+ parts->read_prefs,
+ parts->assembled.session,
+ NULL,
+ /* Not aggregate-with-write */ false,
+ &ignored_error);
+
+ if (retry_server_stream && retry_server_stream->sd->max_wire_version >=
+ WIRE_VERSION_RETRY_READS) {
+ parts->assembled.server_stream = retry_server_stream;
+ bson_destroy (reply);
+ GOTO (retry);
+ }
+ }
+
+ if (retry_server_stream) {
+ mongoc_server_stream_cleanup (retry_server_stream);
+ }
+
+ if (ret && error) {
+ /* if a retry succeeded, clear the initial error */
+ memset (error, 0, sizeof (bson_error_t));
+ }
+
+ RETURN (ret);
+}
+
+
+static bool
+_mongoc_client_command_with_stream (mongoc_client_t *client,
+ mongoc_cmd_parts_t *parts,
+ const mongoc_read_prefs_t *read_prefs,
+ mongoc_server_stream_t *server_stream,
+ bson_t *reply,
+ bson_error_t *error)
+{
+ ENTRY;
+
+ parts->assembled.operation_id = ++client->cluster.operation_id;
+ if (!mongoc_cmd_parts_assemble (parts, server_stream, error)) {
+ _mongoc_bson_init_if_set (reply);
+ return false;
+ };
+
+ if (parts->is_retryable_write) {
+ RETURN (_mongoc_client_retryable_write_command_with_stream (
+ client, parts, server_stream, reply, error));
+ }
+
+ if (parts->is_retryable_read) {
+ RETURN (_mongoc_client_retryable_read_command_with_stream (
+ client, parts, server_stream, reply, error));
+ }
+
+ RETURN (mongoc_cluster_run_command_monitored (
+ &client->cluster, &parts->assembled, reply, error));
+}
+
+
+bool
+mongoc_client_command_simple (mongoc_client_t *client,
+ const char *db_name,
+ const bson_t *command,
+ const mongoc_read_prefs_t *read_prefs,
+ bson_t *reply,
+ bson_error_t *error)
+{
+ mongoc_cluster_t *cluster;
+ mongoc_server_stream_t *server_stream = NULL;
+ mongoc_cmd_parts_t parts;
+ bool ret;
+
+ ENTRY;
+
+ BSON_ASSERT (client);
+ BSON_ASSERT (db_name);
+ BSON_ASSERT (command);
+
+ if (!_mongoc_read_prefs_validate (read_prefs, error)) {
+ RETURN (false);
+ }
+
+ cluster = &client->cluster;
+ mongoc_cmd_parts_init (&parts, client, db_name, MONGOC_QUERY_NONE, command);
+ parts.read_prefs = read_prefs;
+
+ /* Server Selection Spec: "The generic command method has a default read
+ * preference of mode 'primary'. The generic command method MUST ignore any
+ * default read preference from client, database or collection
+ * configuration. The generic command method SHOULD allow an optional read
+ * preference argument."
+ */
+ server_stream =
+ mongoc_cluster_stream_for_reads (cluster,
+ read_prefs,
+ NULL,
+ reply,
+ /* Not aggregate-with-write */ false,
+ error);
+
+ if (server_stream) {
+ ret = _mongoc_client_command_with_stream (
+ client, &parts, read_prefs, server_stream, reply, error);
+ } else {
+ /* reply initialized by mongoc_cluster_stream_for_reads */
+ ret = false;
+ }
+
+ mongoc_cmd_parts_cleanup (&parts);
+ mongoc_server_stream_cleanup (server_stream);
+
+ RETURN (ret);
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_client_command_with_opts --
+ *
+ * Execute a command on the server. If mode is MONGOC_CMD_READ or
+ * MONGOC_CMD_RW, then read concern is applied from @opts, or else from
+ * @default_rc, and read preferences are applied from @user_prefs, or else
+ * from @default_prefs. If mode is MONGOC_CMD_WRITE or MONGOC_CMD_RW, then
+ * write concern is applied from @opts if present, or else @default_wc.
+ *
+ * If mode is MONGOC_CMD_RAW, then read concern and write concern are
+ * applied from @opts only. Read preferences are applied from
+ * @user_prefs.
+ *
+ * The mongoc_client_t's read preference, read concern, and write concern
+ * are *NOT* applied.
+ *
+ * Returns:
+ * Success or failure.
+ * A write concern timeout or write concern error is considered a failure.
+ *
+ * Side effects:
+ * @reply is always initialized.
+ * @error is filled out if the command fails.
+ *
+ *--------------------------------------------------------------------------
+ */
+bool
+_mongoc_client_command_with_opts (mongoc_client_t *client,
+ const char *db_name,
+ const bson_t *command,
+ mongoc_command_mode_t mode,
+ const bson_t *opts,
+ mongoc_query_flags_t flags,
+ const mongoc_read_prefs_t *user_prefs,
+ const mongoc_read_prefs_t *default_prefs,
+ mongoc_read_concern_t *default_rc,
+ mongoc_write_concern_t *default_wc,
+ bson_t *reply,
+ bson_error_t *error)
+{
+ mongoc_read_write_opts_t read_write_opts;
+ mongoc_cmd_parts_t parts;
+ const char *command_name;
+ const mongoc_read_prefs_t *prefs = COALESCE (user_prefs, default_prefs);
+ mongoc_server_stream_t *server_stream = NULL;
+ mongoc_cluster_t *cluster;
+ mongoc_client_session_t *cs;
+ bson_t reply_local;
+ bson_t *reply_ptr;
+ int32_t wire_version;
+ int32_t wc_wire_version;
+ bool reply_initialized = false;
+ bool ret = false;
+
+ ENTRY;
+
+ BSON_ASSERT (client);
+ BSON_ASSERT (db_name);
+ BSON_ASSERT (command);
+
+ command_name = _mongoc_get_command_name (command);
+ cluster = &client->cluster;
+ reply_ptr = reply ? reply : &reply_local;
+
+ mongoc_cmd_parts_init (&parts, client, db_name, flags, command);
+ parts.is_read_command = (mode & MONGOC_CMD_READ);
+ parts.is_write_command = (mode & MONGOC_CMD_WRITE);
+
+ if (!_mongoc_read_write_opts_parse (client, opts, &read_write_opts, error)) {
+ GOTO (done);
+ }
+
+ cs = read_write_opts.client_session;
+
+ if (!command_name) {
+ bson_set_error (error,
+ MONGOC_ERROR_COMMAND,
+ MONGOC_ERROR_COMMAND_INVALID_ARG,
+ "Empty command document");
+ GOTO (done);
+ }
+
+ if (_mongoc_client_session_in_txn (read_write_opts.client_session)) {
+ if ((mode == MONGOC_CMD_READ || mode == MONGOC_CMD_RAW) &&
+ !IS_PREF_PRIMARY (user_prefs)) {
+ bson_set_error (error,
+ MONGOC_ERROR_COMMAND,
+ MONGOC_ERROR_COMMAND_INVALID_ARG,
+ "Read preference in a transaction must be primary");
+ GOTO (done);
+ }
+
+ if (!bson_empty (&read_write_opts.readConcern)) {
+ bson_set_error (error,
+ MONGOC_ERROR_COMMAND,
+ MONGOC_ERROR_COMMAND_INVALID_ARG,
+ "Cannot set read concern after starting transaction");
+ GOTO (done);
+ }
+
+ if (read_write_opts.writeConcern &&
+ strcmp (command_name, "commitTransaction") != 0 &&
+ strcmp (command_name, "abortTransaction") != 0) {
+ bson_set_error (error,
+ MONGOC_ERROR_COMMAND,
+ MONGOC_ERROR_COMMAND_INVALID_ARG,
+ "Cannot set write concern after starting transaction");
+ GOTO (done);
+ }
+ }
+
+ if (mode == MONGOC_CMD_READ || mode == MONGOC_CMD_RAW) {
+ /* NULL read pref is ok */
+ if (!_mongoc_read_prefs_validate (prefs, error)) {
+ GOTO (done);
+ }
+
+ parts.read_prefs = prefs;
+ } else {
+ /* this is a command that writes */
+ prefs = NULL;
+ }
+
+ if (read_write_opts.serverId) {
+ /* "serverId" passed in opts */
+ server_stream =
+ mongoc_cluster_stream_for_server (cluster,
+ read_write_opts.serverId,
+ true /* reconnect ok */,
+ cs,
+ reply_ptr,
+ error);
+
+ if (server_stream && server_stream->sd->type != MONGOC_SERVER_MONGOS) {
+ parts.user_query_flags |= MONGOC_QUERY_SECONDARY_OK;
+ }
+ } else if (parts.is_write_command) {
+ server_stream =
+ mongoc_cluster_stream_for_writes (cluster, cs, reply_ptr, error);
+ } else {
+ server_stream =
+ mongoc_cluster_stream_for_reads (cluster,
+ prefs,
+ cs,
+ reply_ptr,
+ /* Not aggregate-with-write */ false,
+ error);
+ }
+
+ if (!server_stream) {
+ /* stream_for_reads/writes/server has initialized reply */
+ reply_initialized = true;
+ GOTO (done);
+ }
+
+ wire_version = server_stream->sd->max_wire_version;
+ if (!mongoc_cmd_parts_append_read_write (
+ &parts, &read_write_opts, wire_version, error)) {
+ GOTO (done);
+ }
+
+ if (mode & MONGOC_CMD_WRITE) {
+ wc_wire_version = !strcasecmp (command_name, "findandmodify")
+ ? WIRE_VERSION_FAM_WRITE_CONCERN
+ : WIRE_VERSION_CMD_WRITE_CONCERN;
+
+ if (read_write_opts.write_concern_owned &&
+ wire_version < wc_wire_version) {
+ bson_set_error (error,
+ MONGOC_ERROR_COMMAND,
+ MONGOC_ERROR_PROTOCOL_BAD_WIRE_VERSION,
+ "\"%s\" command does not support writeConcern with "
+ "wire version %d, wire version %d is required",
+ command_name,
+ wire_version,
+ wc_wire_version);
+ GOTO (done);
+ }
+
+ /* use default write concern unless it's in opts */
+ if (!mongoc_write_concern_is_default (default_wc) &&
+ !read_write_opts.write_concern_owned &&
+ wire_version >= wc_wire_version) {
+ if (!mongoc_cmd_parts_set_write_concern (
+ &parts, default_wc, wire_version, error)) {
+ GOTO (done);
+ }
+ }
+ }
+
+ /* use default read concern for read command, unless it's in opts */
+ if ((mode & MONGOC_CMD_READ) && bson_empty (&read_write_opts.readConcern)) {
+ if (!mongoc_cmd_parts_set_read_concern (
+ &parts, default_rc, wire_version, error)) {
+ GOTO (done);
+ }
+ }
+
+ ret = _mongoc_client_command_with_stream (
+ client, &parts, user_prefs, server_stream, reply_ptr, error);
+
+ reply_initialized = true;
+
+ if (ret && (mode & MONGOC_CMD_WRITE)) {
+ ret = !_mongoc_parse_wc_err (reply_ptr, error);
+ }
+
+done:
+ if (reply_ptr == &reply_local) {
+ if (reply_initialized) {
+ bson_destroy (reply_ptr);
+ }
+ } else if (!reply_initialized) {
+ _mongoc_bson_init_if_set (reply);
+ }
+
+ if (server_stream) {
+ mongoc_server_stream_cleanup (server_stream);
+ }
+
+ mongoc_cmd_parts_cleanup (&parts);
+ _mongoc_read_write_opts_cleanup (&read_write_opts);
+
+ RETURN (ret);
+}
+
+
+bool
+mongoc_client_read_command_with_opts (mongoc_client_t *client,
+ const char *db_name,
+ const bson_t *command,
+ const mongoc_read_prefs_t *read_prefs,
+ const bson_t *opts,
+ bson_t *reply,
+ bson_error_t *error)
+{
+ return _mongoc_client_command_with_opts (client,
+ db_name,
+ command,
+ MONGOC_CMD_READ,
+ opts,
+ MONGOC_QUERY_NONE,
+ read_prefs,
+ client->read_prefs,
+ client->read_concern,
+ client->write_concern,
+ reply,
+ error);
+}
+
+
+bool
+mongoc_client_write_command_with_opts (mongoc_client_t *client,
+ const char *db_name,
+ const bson_t *command,
+ const bson_t *opts,
+ bson_t *reply,
+ bson_error_t *error)
+{
+ return _mongoc_client_command_with_opts (client,
+ db_name,
+ command,
+ MONGOC_CMD_WRITE,
+ opts,
+ MONGOC_QUERY_NONE,
+ NULL,
+ client->read_prefs,
+ client->read_concern,
+ client->write_concern,
+ reply,
+ error);
+}
+
+
+bool
+mongoc_client_read_write_command_with_opts (
+ mongoc_client_t *client,
+ const char *db_name,
+ const bson_t *command,
+ const mongoc_read_prefs_t *read_prefs /* IGNORED */,
+ const bson_t *opts,
+ bson_t *reply,
+ bson_error_t *error)
+{
+ return _mongoc_client_command_with_opts (client,
+ db_name,
+ command,
+ MONGOC_CMD_RW,
+ opts,
+ MONGOC_QUERY_NONE,
+ read_prefs,
+ client->read_prefs,
+ client->read_concern,
+ client->write_concern,
+ reply,
+ error);
+}
+
+
+bool
+mongoc_client_command_with_opts (mongoc_client_t *client,
+ const char *db_name,
+ const bson_t *command,
+ const mongoc_read_prefs_t *read_prefs,
+ const bson_t *opts,
+ bson_t *reply,
+ bson_error_t *error)
+{
+ return _mongoc_client_command_with_opts (client,
+ db_name,
+ command,
+ MONGOC_CMD_RAW,
+ opts,
+ MONGOC_QUERY_NONE,
+ read_prefs,
+ NULL,
+ client->read_concern,
+ client->write_concern,
+ reply,
+ error);
+}
+
+
+bool
+mongoc_client_command_simple_with_server_id (
+ mongoc_client_t *client,
+ const char *db_name,
+ const bson_t *command,
+ const mongoc_read_prefs_t *read_prefs,
+ uint32_t server_id,
+ bson_t *reply,
+ bson_error_t *error)
+{
+ mongoc_server_stream_t *server_stream;
+ mongoc_cmd_parts_t parts;
+ bool ret;
+
+ ENTRY;
+
+ BSON_ASSERT (client);
+ BSON_ASSERT (db_name);
+ BSON_ASSERT (command);
+
+ if (!_mongoc_read_prefs_validate (read_prefs, error)) {
+ RETURN (false);
+ }
+
+ server_stream = mongoc_cluster_stream_for_server (
+ &client->cluster, server_id, true /* reconnect ok */, NULL, reply, error);
+
+ if (server_stream) {
+ mongoc_cmd_parts_init (
+ &parts, client, db_name, MONGOC_QUERY_NONE, command);
+ parts.read_prefs = read_prefs;
+
+ ret = _mongoc_client_command_with_stream (
+ client, &parts, read_prefs, server_stream, reply, error);
+
+ mongoc_cmd_parts_cleanup (&parts);
+ mongoc_server_stream_cleanup (server_stream);
+ RETURN (ret);
+ } else {
+ /* stream_for_server initialized reply */
+ RETURN (false);
+ }
+}
+
+
+static void
+_mongoc_client_prepare_killcursors_command (int64_t cursor_id,
+ const char *collection,
+ bson_t *command)
+{
+ bson_t child;
+
+ bson_append_utf8 (command, "killCursors", 11, collection, -1);
+ bson_append_array_begin (command, "cursors", 7, &child);
+ bson_append_int64 (&child, "0", 1, cursor_id);
+ bson_append_array_end (command, &child);
+}
+
+
+void
+_mongoc_client_kill_cursor (mongoc_client_t *client,
+ uint32_t server_id,
+ int64_t cursor_id,
+ int64_t operation_id,
+ const char *db,
+ const char *collection,
+ mongoc_client_session_t *cs)
+{
+ mongoc_server_stream_t *server_stream;
+
+ ENTRY;
+
+ BSON_ASSERT (client);
+ BSON_ASSERT (cursor_id);
+
+ /* don't attempt reconnect if server unavailable, and ignore errors */
+ server_stream = mongoc_cluster_stream_for_server (
+ &client->cluster, server_id, false /* reconnect_ok */, NULL, NULL, NULL);
+
+ if (!server_stream) {
+ return;
+ }
+
+ if (db && collection &&
+ server_stream->sd->max_wire_version >= WIRE_VERSION_KILLCURSORS_CMD) {
+ _mongoc_client_killcursors_command (
+ &client->cluster, server_stream, cursor_id, db, collection, cs);
+ } else {
+ _mongoc_client_op_killcursors (&client->cluster,
+ server_stream,
+ cursor_id,
+ operation_id,
+ db,
+ collection);
+ }
+
+ mongoc_server_stream_cleanup (server_stream);
+
+ EXIT;
+}
+
+
+static void
+_mongoc_client_monitor_op_killcursors (mongoc_cluster_t *cluster,
+ mongoc_server_stream_t *server_stream,
+ int64_t cursor_id,
+ int64_t operation_id,
+ const char *db,
+ const char *collection)
+{
+ bson_t doc;
+ mongoc_client_t *client;
+ mongoc_apm_command_started_t event;
+
+ ENTRY;
+
+ client = cluster->client;
+
+ if (!client->apm_callbacks.started) {
+ return;
+ }
+
+ bson_init (&doc);
+ _mongoc_client_prepare_killcursors_command (cursor_id, collection, &doc);
+ mongoc_apm_command_started_init (&event,
+ &doc,
+ db,
+ "killCursors",
+ cluster->request_id,
+ operation_id,
+ &server_stream->sd->host,
+ server_stream->sd->id,
+ &server_stream->sd->service_id,
+ NULL,
+ client->apm_context);
+
+ client->apm_callbacks.started (&event);
+ mongoc_apm_command_started_cleanup (&event);
+ bson_destroy (&doc);
+
+ EXIT;
+}
+
+
+static void
+_mongoc_client_monitor_op_killcursors_succeeded (
+ mongoc_cluster_t *cluster,
+ int64_t duration,
+ mongoc_server_stream_t *server_stream,
+ int64_t cursor_id,
+ int64_t operation_id)
+{
+ mongoc_client_t *client;
+ bson_t doc;
+ bson_t cursors_unknown;
+ mongoc_apm_command_succeeded_t event;
+
+ ENTRY;
+
+ client = cluster->client;
+
+ if (!client->apm_callbacks.succeeded) {
+ EXIT;
+ }
+
+ /* fake server reply to killCursors command: {ok: 1, cursorsUnknown: [42]} */
+ bson_init (&doc);
+ bson_append_int32 (&doc, "ok", 2, 1);
+ bson_append_array_begin (&doc, "cursorsUnknown", 14, &cursors_unknown);
+ bson_append_int64 (&cursors_unknown, "0", 1, cursor_id);
+ bson_append_array_end (&doc, &cursors_unknown);
+
+ mongoc_apm_command_succeeded_init (&event,
+ duration,
+ &doc,
+ "killCursors",
+ cluster->request_id,
+ operation_id,
+ &server_stream->sd->host,
+ server_stream->sd->id,
+ &server_stream->sd->service_id,
+ false,
+ client->apm_context);
+
+ client->apm_callbacks.succeeded (&event);
+
+ mongoc_apm_command_succeeded_cleanup (&event);
+ bson_destroy (&doc);
+}
+
+
+static void
+_mongoc_client_monitor_op_killcursors_failed (
+ mongoc_cluster_t *cluster,
+ int64_t duration,
+ mongoc_server_stream_t *server_stream,
+ const bson_error_t *error,
+ int64_t operation_id)
+{
+ mongoc_client_t *client;
+ bson_t doc;
+ mongoc_apm_command_failed_t event;
+
+ ENTRY;
+
+ client = cluster->client;
+
+ if (!client->apm_callbacks.failed) {
+ EXIT;
+ }
+
+ /* fake server reply to killCursors command: {ok: 0} */
+ bson_init (&doc);
+ bson_append_int32 (&doc, "ok", 2, 0);
+
+ mongoc_apm_command_failed_init (&event,
+ duration,
+ "killCursors",
+ error,
+ &doc,
+ cluster->request_id,
+ operation_id,
+ &server_stream->sd->host,
+ server_stream->sd->id,
+ &server_stream->sd->service_id,
+ false,
+ client->apm_context);
+
+ client->apm_callbacks.failed (&event);
+
+ mongoc_apm_command_failed_cleanup (&event);
+ bson_destroy (&doc);
+}
+
+
+static void
+_mongoc_client_op_killcursors (mongoc_cluster_t *cluster,
+ mongoc_server_stream_t *server_stream,
+ int64_t cursor_id,
+ int64_t operation_id,
+ const char *db,
+ const char *collection)
+{
+ int64_t started;
+ mongoc_rpc_t rpc = {{0}};
+ bson_error_t error;
+ bool has_ns;
+ bool r;
+
+ /* called by old mongoc_client_kill_cursor without db/collection? */
+ has_ns = (db && collection);
+ started = bson_get_monotonic_time ();
+
+ ++cluster->request_id;
+
+ rpc.header.msg_len = 0;
+ rpc.header.request_id = cluster->request_id;
+ rpc.header.response_to = 0;
+ rpc.header.opcode = MONGOC_OPCODE_KILL_CURSORS;
+ rpc.kill_cursors.zero = 0;
+ rpc.kill_cursors.cursors = &cursor_id;
+ rpc.kill_cursors.n_cursors = 1;
+
+ if (has_ns) {
+ _mongoc_client_monitor_op_killcursors (
+ cluster, server_stream, cursor_id, operation_id, db, collection);
+ }
+
+ r = mongoc_cluster_legacy_rpc_sendv_to_server (
+ cluster, &rpc, server_stream, &error);
+
+ if (has_ns) {
+ if (r) {
+ _mongoc_client_monitor_op_killcursors_succeeded (
+ cluster,
+ bson_get_monotonic_time () - started,
+ server_stream,
+ cursor_id,
+ operation_id);
+ } else {
+ _mongoc_client_monitor_op_killcursors_failed (
+ cluster,
+ bson_get_monotonic_time () - started,
+ server_stream,
+ &error,
+ operation_id);
+ }
+ }
+}
+
+
+static void
+_mongoc_client_killcursors_command (mongoc_cluster_t *cluster,
+ mongoc_server_stream_t *server_stream,
+ int64_t cursor_id,
+ const char *db,
+ const char *collection,
+ mongoc_client_session_t *cs)
+{
+ bson_t command = BSON_INITIALIZER;
+ mongoc_cmd_parts_t parts;
+
+ ENTRY;
+
+ _mongoc_client_prepare_killcursors_command (cursor_id, collection, &command);
+ mongoc_cmd_parts_init (
+ &parts, cluster->client, db, MONGOC_QUERY_SECONDARY_OK, &command);
+ parts.assembled.operation_id = ++cluster->operation_id;
+ mongoc_cmd_parts_set_session (&parts, cs);
+
+ if (mongoc_cmd_parts_assemble (&parts, server_stream, NULL)) {
+ /* Find, getMore And killCursors Commands Spec: "The result from the
+ * killCursors command MAY be safely ignored."
+ */
+ (void) mongoc_cluster_run_command_monitored (
+ cluster, &parts.assembled, NULL, NULL);
+ }
+
+ mongoc_cmd_parts_cleanup (&parts);
+ bson_destroy (&command);
+
+ EXIT;
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_client_kill_cursor --
+ *
+ * Destroy a cursor on the server.
+ *
+ * NOTE: this is only reliable when connected to a single mongod or
+ * mongos. If connected to a replica set, the driver attempts to
+ * kill the cursor on the primary. If connected to multiple mongoses
+ * the kill-cursors message is sent to a *random* mongos.
+ *
+ * If no primary, mongos, or standalone server is known, return
+ * without attempting to reconnect.
+ *
+ * Returns:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+void
+mongoc_client_kill_cursor (mongoc_client_t *client, int64_t cursor_id)
+{
+ mongoc_topology_t *const topology =
+ BSON_ASSERT_PTR_INLINE (client)->topology;
+ mongoc_server_description_t const *selected_server;
+ mongoc_read_prefs_t *read_prefs;
+ bson_error_t error;
+ uint32_t server_id = 0;
+ mc_shared_tpld td = mc_tpld_take_ref (topology);
+
+ read_prefs = mongoc_read_prefs_new (MONGOC_READ_PRIMARY);
+
+ if (!mongoc_topology_compatible (td.ptr, NULL, &error)) {
+ MONGOC_ERROR ("Could not kill cursor: %s", error.message);
+ mc_tpld_drop_ref (&td);
+ mongoc_read_prefs_destroy (read_prefs);
+ return;
+ }
+
+ /* see if there's a known writable server - do no I/O or retries */
+ selected_server =
+ mongoc_topology_description_select (td.ptr,
+ MONGOC_SS_WRITE,
+ read_prefs,
+ NULL /* chosen read mode */,
+ topology->local_threshold_msec);
+
+ if (selected_server) {
+ server_id = selected_server->id;
+ }
+
+ if (server_id) {
+ _mongoc_client_kill_cursor (client,
+ server_id,
+ cursor_id,
+ 0 /* operation_id */,
+ NULL /* db */,
+ NULL /* collection */,
+ NULL /* session */);
+ } else {
+ MONGOC_INFO ("No server available for mongoc_client_kill_cursor");
+ }
+
+ mongoc_read_prefs_destroy (read_prefs);
+ mc_tpld_drop_ref (&td);
+}
+
+
+char **
+mongoc_client_get_database_names (mongoc_client_t *client, bson_error_t *error)
+{
+ return mongoc_client_get_database_names_with_opts (client, NULL, error);
+}
+
+
+char **
+mongoc_client_get_database_names_with_opts (mongoc_client_t *client,
+ const bson_t *opts,
+ bson_error_t *error)
+{
+ bson_iter_t iter;
+ const char *name;
+ char **ret = NULL;
+ int i = 0;
+ mongoc_cursor_t *cursor;
+ const bson_t *doc;
+ bson_t cmd = BSON_INITIALIZER;
+
+ BSON_ASSERT (client);
+ BSON_APPEND_INT32 (&cmd, "listDatabases", 1);
+ BSON_APPEND_BOOL (&cmd, "nameOnly", true);
+
+ /* ignore client read prefs */
+ cursor = _mongoc_cursor_array_new (client, "admin", &cmd, opts, "databases");
+ bson_destroy (&cmd);
+
+ while (mongoc_cursor_next (cursor, &doc)) {
+ if (bson_iter_init (&iter, doc) && bson_iter_find (&iter, "name") &&
+ BSON_ITER_HOLDS_UTF8 (&iter) &&
+ (name = bson_iter_utf8 (&iter, NULL))) {
+ ret = (char **) bson_realloc (ret, sizeof (char *) * (i + 2));
+ ret[i] = bson_strdup (name);
+ ret[++i] = NULL;
+ }
+ }
+
+ if (!ret && !mongoc_cursor_error (cursor, error)) {
+ ret = (char **) bson_malloc0 (sizeof (void *));
+ }
+
+ mongoc_cursor_destroy (cursor);
+
+ return ret;
+}
+
+
+mongoc_cursor_t *
+mongoc_client_find_databases (mongoc_client_t *client, bson_error_t *error)
+{
+ /* existing bug in this deprecated API: error pointer is unused */
+ return mongoc_client_find_databases_with_opts (client, NULL);
+}
+
+
+mongoc_cursor_t *
+mongoc_client_find_databases_with_opts (mongoc_client_t *client,
+ const bson_t *opts)
+{
+ bson_t cmd = BSON_INITIALIZER;
+ mongoc_cursor_t *cursor;
+
+ BSON_ASSERT (client);
+ BSON_APPEND_INT32 (&cmd, "listDatabases", 1);
+ cursor = _mongoc_cursor_array_new (client, "admin", &cmd, opts, "databases");
+ bson_destroy (&cmd);
+ return cursor;
+}
+
+
+int32_t
+mongoc_client_get_max_message_size (mongoc_client_t *client) /* IN */
+{
+ BSON_ASSERT (client);
+
+ return mongoc_cluster_get_max_msg_size (&client->cluster);
+}
+
+
+int32_t
+mongoc_client_get_max_bson_size (mongoc_client_t *client) /* IN */
+{
+ BSON_ASSERT (client);
+
+ return mongoc_cluster_get_max_bson_obj_size (&client->cluster);
+}
+
+
+bool
+mongoc_client_get_server_status (mongoc_client_t *client, /* IN */
+ mongoc_read_prefs_t *read_prefs, /* IN */
+ bson_t *reply, /* OUT */
+ bson_error_t *error) /* OUT */
+{
+ bson_t cmd = BSON_INITIALIZER;
+ bool ret = false;
+
+ BSON_ASSERT (client);
+
+ BSON_APPEND_INT32 (&cmd, "serverStatus", 1);
+ ret = mongoc_client_command_simple (
+ client, "admin", &cmd, read_prefs, reply, error);
+ bson_destroy (&cmd);
+
+ return ret;
+}
+
+
+void
+mongoc_client_set_stream_initiator (mongoc_client_t *client,
+ mongoc_stream_initiator_t initiator,
+ void *user_data)
+{
+ BSON_ASSERT (client);
+
+ if (!initiator) {
+ initiator = mongoc_client_default_stream_initiator;
+ user_data = client;
+ } else {
+ MONGOC_DEBUG ("Using custom stream initiator.");
+ }
+
+ client->initiator = initiator;
+ client->initiator_data = user_data;
+
+ if (client->topology->single_threaded) {
+ mongoc_topology_scanner_set_stream_initiator (
+ client->topology->scanner, initiator, user_data);
+ }
+}
+
+
+bool
+_mongoc_client_set_apm_callbacks_private (mongoc_client_t *client,
+ mongoc_apm_callbacks_t *callbacks,
+ void *context)
+{
+ if (callbacks) {
+ memcpy (
+ &client->apm_callbacks, callbacks, sizeof (mongoc_apm_callbacks_t));
+ } else {
+ memset (&client->apm_callbacks, 0, sizeof (mongoc_apm_callbacks_t));
+ }
+
+ client->apm_context = context;
+
+ /* A client pool sets APM callbacks for the entire pool. */
+ if (client->topology->single_threaded) {
+ mongoc_topology_set_apm_callbacks (
+ client->topology,
+ /* We are safe to modify the shared_descr directly, since we are
+ * single-threaded */
+ mc_tpld_unsafe_get_mutable (client->topology),
+ callbacks,
+ context);
+ }
+
+ return true;
+}
+
+
+bool
+mongoc_client_set_apm_callbacks (mongoc_client_t *client,
+ mongoc_apm_callbacks_t *callbacks,
+ void *context)
+{
+ if (!client->topology->single_threaded) {
+ MONGOC_ERROR ("Cannot set callbacks on a pooled client, use "
+ "mongoc_client_pool_set_apm_callbacks");
+ return false;
+ }
+
+ return _mongoc_client_set_apm_callbacks_private (client, callbacks, context);
+}
+
+mongoc_server_description_t *
+mongoc_client_get_server_description (mongoc_client_t *client,
+ uint32_t server_id)
+{
+ mongoc_server_description_t *ret;
+ mc_shared_tpld td = mc_tpld_take_ref (client->topology);
+ mongoc_server_description_t const *sd =
+ mongoc_topology_description_server_by_id_const (
+ td.ptr, server_id, NULL /* <- the error info isn't useful */);
+ ret = mongoc_server_description_new_copy (sd);
+ mc_tpld_drop_ref (&td);
+ return ret;
+}
+
+
+mongoc_server_description_t **
+mongoc_client_get_server_descriptions (const mongoc_client_t *client,
+ size_t *n /* OUT */)
+{
+ mc_shared_tpld td =
+ mc_tpld_take_ref (BSON_ASSERT_PTR_INLINE (client)->topology);
+ mongoc_server_description_t **const sds =
+ mongoc_topology_description_get_servers (td.ptr,
+ BSON_ASSERT_PTR_INLINE (n));
+ mc_tpld_drop_ref (&td);
+ return sds;
+}
+
+
+void
+mongoc_server_descriptions_destroy_all (mongoc_server_description_t **sds,
+ size_t n)
+{
+ size_t i;
+
+ for (i = 0; i < n; ++i) {
+ mongoc_server_description_destroy (sds[i]);
+ }
+
+ bson_free (sds);
+}
+
+
+mongoc_server_description_t *
+mongoc_client_select_server (mongoc_client_t *client,
+ bool for_writes,
+ const mongoc_read_prefs_t *prefs,
+ bson_error_t *error)
+{
+ mongoc_ss_optype_t optype = for_writes ? MONGOC_SS_WRITE : MONGOC_SS_READ;
+ mongoc_server_description_t *sd;
+
+ if (for_writes && prefs) {
+ bson_set_error (error,
+ MONGOC_ERROR_SERVER_SELECTION,
+ MONGOC_ERROR_SERVER_SELECTION_FAILURE,
+ "Cannot use read preferences with for_writes = true");
+ return NULL;
+ }
+
+ if (!_mongoc_read_prefs_validate (prefs, error)) {
+ return NULL;
+ }
+
+ sd = mongoc_topology_select (
+ client->topology, optype, prefs, NULL /* chosen read mode */, error);
+ if (!sd) {
+ return NULL;
+ }
+
+ if (mongoc_cluster_check_interval (&client->cluster, sd->id)) {
+ /* check not required, or it succeeded */
+ return sd;
+ }
+
+ /* check failed, retry once */
+ mongoc_server_description_destroy (sd);
+ sd = mongoc_topology_select (
+ client->topology, optype, prefs, NULL /* chosen read mode */, error);
+ if (sd) {
+ return sd;
+ }
+
+ return NULL;
+}
+
+bool
+mongoc_client_set_error_api (mongoc_client_t *client, int32_t version)
+{
+ if (!client->topology->single_threaded) {
+ MONGOC_ERROR ("Cannot set Error API Version on a pooled client, use "
+ "mongoc_client_pool_set_error_api");
+ return false;
+ }
+
+ if (version != MONGOC_ERROR_API_VERSION_LEGACY &&
+ version != MONGOC_ERROR_API_VERSION_2) {
+ MONGOC_ERROR ("Unsupported Error API Version: %" PRId32, version);
+ return false;
+ }
+
+ if (client->error_api_set) {
+ MONGOC_ERROR ("Can only set Error API Version once");
+ return false;
+ }
+
+ client->error_api_version = version;
+ client->error_api_set = true;
+
+ return true;
+}
+
+bool
+mongoc_client_set_appname (mongoc_client_t *client, const char *appname)
+{
+ if (!client->topology->single_threaded) {
+ MONGOC_ERROR ("Cannot call set_appname on a client from a pool");
+ return false;
+ }
+
+ return _mongoc_topology_set_appname (client->topology, appname);
+}
+
+mongoc_server_session_t *
+_mongoc_client_pop_server_session (mongoc_client_t *client, bson_error_t *error)
+{
+ return _mongoc_topology_pop_server_session (client->topology, error);
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_client_lookup_session --
+ *
+ * Retrieve a mongoc_client_session_t associated with @client_session_id.
+ * Use this to find the "lsid" and "$clusterTime" to send in the server
+ * command.
+ *
+ * Returns:
+ * True on success, false on error and @error is set. Will return false
+ * if the session is from an outdated client generation, a holdover
+ * from before a call to mongoc_client_reset.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+bool
+_mongoc_client_lookup_session (const mongoc_client_t *client,
+ uint32_t client_session_id,
+ mongoc_client_session_t **cs /* OUT */,
+ bson_error_t *error /* OUT */)
+{
+ ENTRY;
+
+ *cs = mongoc_set_get (client->client_sessions, client_session_id);
+
+ if (*cs) {
+ RETURN (true);
+ }
+
+ bson_set_error (error,
+ MONGOC_ERROR_COMMAND,
+ MONGOC_ERROR_COMMAND_INVALID_ARG,
+ "Invalid sessionId");
+
+ RETURN (false);
+}
+
+void
+_mongoc_client_unregister_session (mongoc_client_t *client,
+ mongoc_client_session_t *session)
+{
+ mongoc_set_rm (client->client_sessions, session->client_session_id);
+}
+
+void
+_mongoc_client_push_server_session (mongoc_client_t *client,
+ mongoc_server_session_t *server_session)
+{
+ _mongoc_topology_push_server_session (client->topology, server_session);
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_client_end_sessions --
+ *
+ * End all server sessions in the topology's server session pool.
+ * Don't block long: if server selection or connecting fails, quit.
+ *
+ * The server session pool becomes invalid, but may not be empty.
+ * Destroy the topology after this without using any sessions.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+void
+_mongoc_client_end_sessions (mongoc_client_t *client)
+{
+ mongoc_topology_t *t = client->topology;
+ mongoc_read_prefs_t *prefs;
+ bson_error_t error;
+ uint32_t server_id;
+ bson_t cmd;
+ mongoc_server_stream_t *stream;
+ mongoc_cmd_parts_t parts;
+ mongoc_cluster_t *cluster = &client->cluster;
+ bool r;
+
+ while (!mongoc_server_session_pool_is_empty (t->session_pool)) {
+ prefs = mongoc_read_prefs_new (MONGOC_READ_PRIMARY_PREFERRED);
+ server_id = mongoc_topology_select_server_id (
+ t, MONGOC_SS_READ, prefs, NULL /* chosen read mode */, &error);
+
+ mongoc_read_prefs_destroy (prefs);
+ if (!server_id) {
+ MONGOC_WARNING ("Couldn't send \"endSessions\": %s", error.message);
+ return;
+ }
+
+ stream = mongoc_cluster_stream_for_server (
+ cluster, server_id, false /* reconnect_ok */, NULL, NULL, &error);
+
+ if (!stream) {
+ MONGOC_WARNING ("Couldn't send \"endSessions\": %s", error.message);
+ return;
+ }
+
+ /* end sessions in chunks */
+ while (_mongoc_topology_end_sessions_cmd (t, &cmd)) {
+ mongoc_cmd_parts_init (
+ &parts, client, "admin", MONGOC_QUERY_SECONDARY_OK, &cmd);
+ parts.assembled.operation_id = ++cluster->operation_id;
+ parts.prohibit_lsid = true;
+
+ r = mongoc_cmd_parts_assemble (&parts, stream, &error);
+ if (!r) {
+ MONGOC_WARNING ("Couldn't construct \"endSessions\" command: %s",
+ error.message);
+ } else {
+ r = mongoc_cluster_run_command_monitored (
+ cluster, &parts.assembled, NULL, &error);
+
+ if (!r) {
+ MONGOC_WARNING ("Couldn't send \"endSessions\": %s",
+ error.message);
+ }
+ }
+
+ mongoc_cmd_parts_cleanup (&parts);
+
+ if (!mongoc_cluster_stream_valid (cluster, stream)) {
+ /* The stream was invalidated as a result of a network error, so we
+ * stop sending commands. */
+ break;
+ }
+
+ bson_destroy (&cmd);
+ }
+
+ bson_destroy (&cmd);
+ mongoc_server_stream_cleanup (stream);
+ }
+}
+
+void
+mongoc_client_reset (mongoc_client_t *client)
+{
+ BSON_ASSERT (client);
+
+ client->generation++;
+
+ /* Client sessions are owned and destroyed by the user, but we keep
+ local pointers to them for reference. On reset, clear our local
+ set without destroying the sessions or calling endSessions.
+ client_sessions has no dtor, so it won't destroy its items.
+
+ Destroying the local cache of client sessions here ensures they
+ cannot be used by future operations--lookup for them will fail. */
+ mongoc_set_destroy (client->client_sessions);
+ client->client_sessions = mongoc_set_new (8, NULL, NULL);
+
+ /* Server sessions are owned by us, so we clear the pool on reset. */
+ mongoc_server_session_pool_clear (client->topology->session_pool);
+}
+
+mongoc_change_stream_t *
+mongoc_client_watch (mongoc_client_t *client,
+ const bson_t *pipeline,
+ const bson_t *opts)
+{
+ return _mongoc_change_stream_new_from_client (client, pipeline, opts);
+}
+
+bool
+mongoc_client_enable_auto_encryption (mongoc_client_t *client,
+ mongoc_auto_encryption_opts_t *opts,
+ bson_error_t *error)
+{
+ if (!client->topology->single_threaded) {
+ bson_set_error (error,
+ MONGOC_ERROR_CLIENT,
+ MONGOC_ERROR_CLIENT_INVALID_ENCRYPTION_ARG,
+ "Cannot enable auto encryption on a pooled client, use "
+ "mongoc_client_pool_enable_auto_encryption");
+ return false;
+ }
+ return _mongoc_cse_client_enable_auto_encryption (client, opts, error);
+}
+
+bool
+mongoc_client_set_server_api (mongoc_client_t *client,
+ const mongoc_server_api_t *api,
+ bson_error_t *error)
+{
+ BSON_ASSERT_PARAM (client);
+ BSON_ASSERT_PARAM (api);
+
+ if (client->is_pooled) {
+ bson_set_error (
+ error,
+ MONGOC_ERROR_CLIENT,
+ MONGOC_ERROR_CLIENT_API_FROM_POOL,
+ "Cannot set server api on a client checked out from a pool");
+ return false;
+ }
+
+ if (client->api) {
+ bson_set_error (error,
+ MONGOC_ERROR_CLIENT,
+ MONGOC_ERROR_CLIENT_API_ALREADY_SET,
+ "Cannot set server api more than once per client");
+ return false;
+ }
+
+ client->api = mongoc_server_api_copy (api);
+ _mongoc_topology_scanner_set_server_api (client->topology->scanner, api);
+ return true;
+}
+
+mongoc_server_description_t *
+mongoc_client_get_handshake_description (mongoc_client_t *client,
+ uint32_t server_id,
+ bson_t *opts,
+ bson_error_t *error)
+{
+ mongoc_server_stream_t *server_stream;
+ mongoc_server_description_t *sd;
+
+ server_stream = mongoc_cluster_stream_for_server (&client->cluster,
+ server_id,
+ true /* reconnect */,
+ NULL /* client session */,
+ NULL /* reply */,
+ error);
+ if (!server_stream) {
+ return NULL;
+ }
+
+ sd = mongoc_server_description_new_copy (server_stream->sd);
+ mongoc_server_stream_cleanup (server_stream);
+ return sd;
+}
diff --git a/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client.h
new file mode 100644
index 00000000..e72eb084
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-client.h
@@ -0,0 +1,298 @@
+/*
+ * Copyright 2013 MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mongoc-prelude.h"
+
+#ifndef MONGOC_CLIENT_H
+#define MONGOC_CLIENT_H
+
+#include <bson/bson.h>
+
+#include "mongoc-apm.h"
+#include "mongoc-client-side-encryption.h"
+#include "mongoc-collection.h"
+#include "mongoc-config.h"
+#include "mongoc-cursor.h"
+#include "mongoc-database.h"
+#include "mongoc-gridfs.h"
+#include "mongoc-index.h"
+#include "mongoc-macros.h"
+#include "mongoc-read-prefs.h"
+#include "mongoc-server-api.h"
+#ifdef MONGOC_ENABLE_SSL
+#include "mongoc-ssl.h"
+#endif
+#include "mongoc-stream.h"
+#include "mongoc-uri.h"
+#include "mongoc-write-concern.h"
+#include "mongoc-read-concern.h"
+#include "mongoc-server-description.h"
+
+BSON_BEGIN_DECLS
+
+/* This define is part of our public API. But per MongoDB 4.4, there is no
+ * longer a size limit on collection names. */
+#define MONGOC_NAMESPACE_MAX 128
+
+
+#ifndef MONGOC_DEFAULT_CONNECTTIMEOUTMS
+#define MONGOC_DEFAULT_CONNECTTIMEOUTMS (10 * 1000L)
+#endif
+
+
+#ifndef MONGOC_DEFAULT_SOCKETTIMEOUTMS
+/*
+ * NOTE: The default socket timeout for connections is 5 minutes. This
+ * means that if your MongoDB server dies or becomes unavailable
+ * it will take 5 minutes to detect this.
+ *
+ * You can change this by providing sockettimeoutms= in your
+ * connection URI.
+ */
+#define MONGOC_DEFAULT_SOCKETTIMEOUTMS (1000L * 60L * 5L)
+#endif
+
+
+/**
+ * mongoc_client_t:
+ *
+ * The mongoc_client_t structure maintains information about a connection to
+ * a MongoDB server.
+ */
+typedef struct _mongoc_client_t mongoc_client_t;
+
+
+typedef struct _mongoc_client_session_t mongoc_client_session_t;
+typedef struct _mongoc_session_opt_t mongoc_session_opt_t;
+typedef struct _mongoc_transaction_opt_t mongoc_transaction_opt_t;
+
+/**
+ * mongoc_stream_initiator_t:
+ * @uri: The uri and options for the stream.
+ * @host: The host and port (or UNIX domain socket path) to connect to.
+ * @user_data: The pointer passed to mongoc_client_set_stream_initiator.
+ * @error: A location for an error.
+ *
+ * Creates a new mongoc_stream_t for the host and port. Begin a
+ * non-blocking connect and return immediately.
+ *
+ * This can be used by language bindings to create network transports other
+ * than those built into libmongoc. An example of such would be the streams
+ * API provided by PHP.
+ *
+ * Returns: A newly allocated mongoc_stream_t or NULL on failure.
+ */
+typedef mongoc_stream_t *(*mongoc_stream_initiator_t) (
+ const mongoc_uri_t *uri,
+ const mongoc_host_list_t *host,
+ void *user_data,
+ bson_error_t *error);
+
+
+MONGOC_EXPORT (mongoc_client_t *)
+mongoc_client_new (const char *uri_string) BSON_GNUC_WARN_UNUSED_RESULT;
+MONGOC_EXPORT (mongoc_client_t *)
+mongoc_client_new_from_uri (const mongoc_uri_t *uri)
+ BSON_GNUC_WARN_UNUSED_RESULT;
+MONGOC_EXPORT (mongoc_client_t *)
+mongoc_client_new_from_uri_with_error (
+ const mongoc_uri_t *uri, bson_error_t *error) BSON_GNUC_WARN_UNUSED_RESULT;
+MONGOC_EXPORT (const mongoc_uri_t *)
+mongoc_client_get_uri (const mongoc_client_t *client);
+MONGOC_EXPORT (void)
+mongoc_client_set_stream_initiator (mongoc_client_t *client,
+ mongoc_stream_initiator_t initiator,
+ void *user_data);
+MONGOC_EXPORT (mongoc_cursor_t *)
+mongoc_client_command (mongoc_client_t *client,
+ const char *db_name,
+ mongoc_query_flags_t flags,
+ uint32_t skip,
+ uint32_t limit,
+ uint32_t batch_size,
+ const bson_t *query,
+ const bson_t *fields,
+ const mongoc_read_prefs_t *read_prefs)
+ BSON_GNUC_WARN_UNUSED_RESULT;
+MONGOC_EXPORT (void)
+mongoc_client_kill_cursor (mongoc_client_t *client,
+ int64_t cursor_id) BSON_GNUC_DEPRECATED;
+MONGOC_EXPORT (bool)
+mongoc_client_command_simple (mongoc_client_t *client,
+ const char *db_name,
+ const bson_t *command,
+ const mongoc_read_prefs_t *read_prefs,
+ bson_t *reply,
+ bson_error_t *error);
+MONGOC_EXPORT (bool)
+mongoc_client_read_command_with_opts (mongoc_client_t *client,
+ const char *db_name,
+ const bson_t *command,
+ const mongoc_read_prefs_t *read_prefs,
+ const bson_t *opts,
+ bson_t *reply,
+ bson_error_t *error);
+MONGOC_EXPORT (bool)
+mongoc_client_write_command_with_opts (mongoc_client_t *client,
+ const char *db_name,
+ const bson_t *command,
+ const bson_t *opts,
+ bson_t *reply,
+ bson_error_t *error);
+MONGOC_EXPORT (bool)
+mongoc_client_read_write_command_with_opts (
+ mongoc_client_t *client,
+ const char *db_name,
+ const bson_t *command,
+ const mongoc_read_prefs_t *read_prefs /* IGNORED */,
+ const bson_t *opts,
+ bson_t *reply,
+ bson_error_t *error);
+MONGOC_EXPORT (bool)
+mongoc_client_command_with_opts (mongoc_client_t *client,
+ const char *db_name,
+ const bson_t *command,
+ const mongoc_read_prefs_t *read_prefs,
+ const bson_t *opts,
+ bson_t *reply,
+ bson_error_t *error);
+MONGOC_EXPORT (bool)
+mongoc_client_command_simple_with_server_id (
+ mongoc_client_t *client,
+ const char *db_name,
+ const bson_t *command,
+ const mongoc_read_prefs_t *read_prefs,
+ uint32_t server_id,
+ bson_t *reply,
+ bson_error_t *error);
+MONGOC_EXPORT (void)
+mongoc_client_destroy (mongoc_client_t *client);
+MONGOC_EXPORT (mongoc_client_session_t *)
+mongoc_client_start_session (mongoc_client_t *client,
+ const mongoc_session_opt_t *opts,
+ bson_error_t *error) BSON_GNUC_WARN_UNUSED_RESULT;
+MONGOC_EXPORT (mongoc_database_t *)
+mongoc_client_get_database (mongoc_client_t *client,
+ const char *name) BSON_GNUC_WARN_UNUSED_RESULT;
+MONGOC_EXPORT (mongoc_database_t *)
+mongoc_client_get_default_database (mongoc_client_t *client)
+ BSON_GNUC_WARN_UNUSED_RESULT;
+MONGOC_EXPORT (mongoc_gridfs_t *)
+mongoc_client_get_gridfs (mongoc_client_t *client,
+ const char *db,
+ const char *prefix,
+ bson_error_t *error) BSON_GNUC_WARN_UNUSED_RESULT;
+MONGOC_EXPORT (mongoc_collection_t *)
+mongoc_client_get_collection (mongoc_client_t *client,
+ const char *db,
+ const char *collection)
+ BSON_GNUC_WARN_UNUSED_RESULT;
+MONGOC_EXPORT (char **)
+mongoc_client_get_database_names (mongoc_client_t *client, bson_error_t *error)
+ BSON_GNUC_WARN_UNUSED_RESULT
+ BSON_GNUC_DEPRECATED_FOR (mongoc_client_get_database_names_with_opts);
+MONGOC_EXPORT (char **)
+mongoc_client_get_database_names_with_opts (mongoc_client_t *client,
+ const bson_t *opts,
+ bson_error_t *error)
+ BSON_GNUC_WARN_UNUSED_RESULT;
+MONGOC_EXPORT (mongoc_cursor_t *)
+mongoc_client_find_databases (mongoc_client_t *client,
+ bson_error_t *error) BSON_GNUC_WARN_UNUSED_RESULT
+ BSON_GNUC_DEPRECATED_FOR (mongoc_client_find_databases_with_opts);
+MONGOC_EXPORT (mongoc_cursor_t *)
+mongoc_client_find_databases_with_opts (
+ mongoc_client_t *client, const bson_t *opts) BSON_GNUC_WARN_UNUSED_RESULT;
+MONGOC_EXPORT (bool)
+mongoc_client_get_server_status (mongoc_client_t *client,
+ mongoc_read_prefs_t *read_prefs,
+ bson_t *reply,
+ bson_error_t *error) BSON_GNUC_DEPRECATED;
+MONGOC_EXPORT (int32_t)
+mongoc_client_get_max_message_size (mongoc_client_t *client)
+ BSON_GNUC_DEPRECATED;
+MONGOC_EXPORT (int32_t)
+mongoc_client_get_max_bson_size (mongoc_client_t *client) BSON_GNUC_DEPRECATED;
+MONGOC_EXPORT (const mongoc_write_concern_t *)
+mongoc_client_get_write_concern (const mongoc_client_t *client);
+MONGOC_EXPORT (void)
+mongoc_client_set_write_concern (mongoc_client_t *client,
+ const mongoc_write_concern_t *write_concern);
+MONGOC_EXPORT (const mongoc_read_concern_t *)
+mongoc_client_get_read_concern (const mongoc_client_t *client);
+MONGOC_EXPORT (void)
+mongoc_client_set_read_concern (mongoc_client_t *client,
+ const mongoc_read_concern_t *read_concern);
+MONGOC_EXPORT (const mongoc_read_prefs_t *)
+mongoc_client_get_read_prefs (const mongoc_client_t *client);
+MONGOC_EXPORT (void)
+mongoc_client_set_read_prefs (mongoc_client_t *client,
+ const mongoc_read_prefs_t *read_prefs);
+#ifdef MONGOC_ENABLE_SSL
+MONGOC_EXPORT (void)
+mongoc_client_set_ssl_opts (mongoc_client_t *client,
+ const mongoc_ssl_opt_t *opts);
+#endif
+MONGOC_EXPORT (bool)
+mongoc_client_set_apm_callbacks (mongoc_client_t *client,
+ mongoc_apm_callbacks_t *callbacks,
+ void *context);
+MONGOC_EXPORT (mongoc_server_description_t *)
+mongoc_client_get_server_description (
+ mongoc_client_t *client, uint32_t server_id) BSON_GNUC_WARN_UNUSED_RESULT;
+MONGOC_EXPORT (mongoc_server_description_t **)
+mongoc_client_get_server_descriptions (const mongoc_client_t *client,
+ size_t *n) BSON_GNUC_WARN_UNUSED_RESULT;
+MONGOC_EXPORT (void)
+mongoc_server_descriptions_destroy_all (mongoc_server_description_t **sds,
+ size_t n);
+MONGOC_EXPORT (mongoc_server_description_t *)
+mongoc_client_select_server (mongoc_client_t *client,
+ bool for_writes,
+ const mongoc_read_prefs_t *prefs,
+ bson_error_t *error) BSON_GNUC_WARN_UNUSED_RESULT;
+MONGOC_EXPORT (bool)
+mongoc_client_set_error_api (mongoc_client_t *client, int32_t version);
+MONGOC_EXPORT (bool)
+mongoc_client_set_appname (mongoc_client_t *client, const char *appname);
+MONGOC_EXPORT (mongoc_change_stream_t *)
+mongoc_client_watch (mongoc_client_t *client,
+ const bson_t *pipeline,
+ const bson_t *opts) BSON_GNUC_WARN_UNUSED_RESULT;
+MONGOC_EXPORT (void)
+mongoc_client_reset (mongoc_client_t *client);
+
+MONGOC_EXPORT (bool)
+mongoc_client_enable_auto_encryption (mongoc_client_t *client,
+ mongoc_auto_encryption_opts_t *opts,
+ bson_error_t *error);
+
+MONGOC_EXPORT (bool)
+mongoc_client_set_server_api (mongoc_client_t *client,
+ const mongoc_server_api_t *api,
+ bson_error_t *error);
+
+MONGOC_EXPORT (mongoc_server_description_t *)
+mongoc_client_get_handshake_description (mongoc_client_t *client,
+ uint32_t server_id,
+ bson_t *opts,
+ bson_error_t *error)
+ BSON_GNUC_WARN_UNUSED_RESULT;
+
+BSON_END_DECLS
+
+
+#endif /* MONGOC_CLIENT_H */
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cluster-aws-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cluster-aws-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cluster-aws-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cluster-aws-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cluster-aws.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cluster-aws.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cluster-aws.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cluster-aws.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cluster-cyrus-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cluster-cyrus-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cluster-cyrus-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cluster-cyrus-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cluster-cyrus.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cluster-cyrus.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cluster-cyrus.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cluster-cyrus.c
diff --git a/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cluster-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cluster-private.h
new file mode 100644
index 00000000..675102f9
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cluster-private.h
@@ -0,0 +1,234 @@
+/*
+ * Copyright 2013 MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mongoc-prelude.h"
+
+#ifndef MONGOC_CLUSTER_PRIVATE_H
+#define MONGOC_CLUSTER_PRIVATE_H
+
+#include <bson/bson.h>
+
+#include "mongoc-array-private.h"
+#include "mongoc-buffer-private.h"
+#include "mongoc-config.h"
+#include "mongoc-client.h"
+#include "mongoc-list-private.h"
+#include "mongoc-opcode.h"
+#include "mongoc-rpc-private.h"
+#include "mongoc-server-stream-private.h"
+#include "mongoc-set-private.h"
+#include "mongoc-stream.h"
+#include "mongoc-topology-private.h"
+#include "mongoc-topology-description-private.h"
+#include "mongoc-write-concern.h"
+#include "mongoc-scram-private.h"
+#include "mongoc-cmd-private.h"
+#include "mongoc-crypto-private.h"
+
+BSON_BEGIN_DECLS
+
+
+typedef struct _mongoc_cluster_node_t {
+ mongoc_stream_t *stream;
+ char *connection_address;
+ /* handshake_sd is a server description created from the handshake on the
+ * stream. */
+ mongoc_server_description_t *handshake_sd;
+} mongoc_cluster_node_t;
+
+typedef struct _mongoc_cluster_t {
+ int64_t operation_id;
+ uint32_t request_id;
+ uint32_t sockettimeoutms;
+ uint32_t socketcheckintervalms;
+ mongoc_uri_t *uri;
+ unsigned requires_auth : 1;
+
+ mongoc_client_t *client;
+
+ mongoc_set_t *nodes;
+ mongoc_array_t iov;
+
+ mongoc_scram_cache_t *scram_cache;
+} mongoc_cluster_t;
+
+
+void
+mongoc_cluster_init (mongoc_cluster_t *cluster,
+ const mongoc_uri_t *uri,
+ void *client);
+
+void
+mongoc_cluster_destroy (mongoc_cluster_t *cluster);
+
+void
+mongoc_cluster_disconnect_node (mongoc_cluster_t *cluster, uint32_t id);
+
+int32_t
+mongoc_cluster_get_max_bson_obj_size (mongoc_cluster_t *cluster);
+
+int32_t
+mongoc_cluster_get_max_msg_size (mongoc_cluster_t *cluster);
+
+size_t
+_mongoc_cluster_buffer_iovec (mongoc_iovec_t *iov,
+ size_t iovcnt,
+ int skip,
+ char *buffer);
+
+bool
+mongoc_cluster_check_interval (mongoc_cluster_t *cluster, uint32_t server_id);
+
+bool
+mongoc_cluster_legacy_rpc_sendv_to_server (
+ mongoc_cluster_t *cluster,
+ mongoc_rpc_t *rpcs,
+ mongoc_server_stream_t *server_stream,
+ bson_error_t *error);
+
+bool
+mongoc_cluster_try_recv (mongoc_cluster_t *cluster,
+ mongoc_rpc_t *rpc,
+ mongoc_buffer_t *buffer,
+ mongoc_server_stream_t *server_stream,
+ bson_error_t *error);
+
+/**
+ * @brief Obtain a server stream appropriate for read operations on the
+ * cluster.
+ *
+ * Returns a new stream (that must be freed) or NULL and sets an error via
+ * `error`.
+ *
+ * @note The returned stream must be released via
+ * `mongoc_server_stream_cleanup`.
+ *
+ * @note May add nodes and/or update the cluster's topology.
+ */
+mongoc_server_stream_t *
+mongoc_cluster_stream_for_reads (mongoc_cluster_t *cluster,
+ const mongoc_read_prefs_t *read_prefs,
+ mongoc_client_session_t *cs,
+ bson_t *reply,
+ bool is_aggr_with_write,
+ bson_error_t *error);
+
+/**
+ * @brief Obtain a server stream appropriate for write operations on the
+ * cluster.
+ *
+ * Returns a new stream (that must be freed) or NULL and sets an error via
+ * `error`.
+ *
+ * @note The returned stream must be released via `mongoc_server_stream_cleanup`
+ *
+ * @note May add nodes and/or update the cluster's topology.
+ */
+mongoc_server_stream_t *
+mongoc_cluster_stream_for_writes (mongoc_cluster_t *cluster,
+ mongoc_client_session_t *cs,
+ bson_t *reply,
+ bson_error_t *error);
+
+/**
+ * @brief Obtain a server stream associated with the cluster node associated
+ * with the given server ID.
+ *
+ * Returns a new server stream (that must be freed) or NULL and sets `error`.
+ *
+ * @param server_id The ID of a server in the cluster topology.
+ * @param reconnect_ok If `true`, the server exists in the topology but is not
+ * connected, then attempt to reconnect with the server. If `false`, then only
+ * create a stream if the server is connected and ready.
+ *
+ * @note The returned stream must be released via `mongoc_server_stream_cleanup`
+ *
+ * @note May update the cluster's topology.
+ */
+mongoc_server_stream_t *
+mongoc_cluster_stream_for_server (mongoc_cluster_t *cluster,
+ uint32_t server_id,
+ bool reconnect_ok,
+ mongoc_client_session_t *cs,
+ bson_t *reply,
+ bson_error_t *error);
+
+bool
+mongoc_cluster_stream_valid (mongoc_cluster_t *cluster,
+ mongoc_server_stream_t *server_stream);
+
+bool
+mongoc_cluster_run_command_monitored (mongoc_cluster_t *cluster,
+ mongoc_cmd_t *cmd,
+ bson_t *reply,
+ bson_error_t *error);
+
+bool
+mongoc_cluster_run_command_parts (mongoc_cluster_t *cluster,
+ mongoc_server_stream_t *server_stream,
+ mongoc_cmd_parts_t *parts,
+ bson_t *reply,
+ bson_error_t *error);
+
+bool
+mongoc_cluster_run_command_private (mongoc_cluster_t *cluster,
+ mongoc_cmd_t *cmd,
+ bson_t *reply,
+ bson_error_t *error);
+
+void
+_mongoc_cluster_build_sasl_start (bson_t *cmd,
+ const char *mechanism,
+ const char *buf,
+ uint32_t buflen);
+
+void
+_mongoc_cluster_build_sasl_continue (bson_t *cmd,
+ int conv_id,
+ const char *buf,
+ uint32_t buflen);
+
+int
+_mongoc_cluster_get_conversation_id (const bson_t *reply);
+
+mongoc_server_stream_t *
+_mongoc_cluster_create_server_stream (const mongoc_topology_description_t *td,
+ const mongoc_server_description_t *sd,
+ mongoc_stream_t *stream);
+
+bool
+_mongoc_cluster_get_auth_cmd_x509 (const mongoc_uri_t *uri,
+ const mongoc_ssl_opt_t *ssl_opts,
+ bson_t *cmd /* OUT */,
+ bson_error_t *error /* OUT */);
+
+#ifdef MONGOC_ENABLE_CRYPTO
+void
+_mongoc_cluster_init_scram (const mongoc_cluster_t *cluster,
+ mongoc_scram_t *scram,
+ mongoc_crypto_hash_algorithm_t algo);
+
+bool
+_mongoc_cluster_get_auth_cmd_scram (mongoc_crypto_hash_algorithm_t algo,
+ mongoc_scram_t *scram,
+ bson_t *cmd /* OUT */,
+ bson_error_t *error /* OUT */);
+#endif /* MONGOC_ENABLE_CRYPTO */
+
+BSON_END_DECLS
+
+
+#endif /* MONGOC_CLUSTER_PRIVATE_H */
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cluster-sasl-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cluster-sasl-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cluster-sasl-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cluster-sasl-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cluster-sasl.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cluster-sasl.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cluster-sasl.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cluster-sasl.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cluster-sspi-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cluster-sspi-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cluster-sspi-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cluster-sspi-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cluster-sspi.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cluster-sspi.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cluster-sspi.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cluster-sspi.c
diff --git a/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cluster.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cluster.c
new file mode 100644
index 00000000..82cfe44d
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cluster.c
@@ -0,0 +1,3560 @@
+/*
+ * Copyright 2013 MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include "mongoc-config.h"
+
+#include <string.h>
+
+#include "mongoc-cluster-private.h"
+#include "mongoc-client-private.h"
+#include "mongoc-client-side-encryption-private.h"
+#include "mongoc-counters-private.h"
+#include "mongoc-config.h"
+#include "mongoc-error.h"
+#include "mongoc-flags-private.h"
+#include "mongoc-host-list-private.h"
+#include "mongoc-log.h"
+#include "mongoc-cluster-sasl-private.h"
+#ifdef MONGOC_ENABLE_SSL
+#include "mongoc-ssl.h"
+#include "mongoc-ssl-private.h"
+#include "mongoc-stream-tls.h"
+#endif
+#include "common-b64-private.h"
+#include "mongoc-scram-private.h"
+#include "mongoc-set-private.h"
+#include "mongoc-socket.h"
+#include "mongoc-stream-private.h"
+#include "mongoc-stream-socket.h"
+#include "mongoc-stream-tls.h"
+#include "mongoc-thread-private.h"
+#include "mongoc-topology-private.h"
+#include "mongoc-topology-background-monitoring-private.h"
+#include "mongoc-trace-private.h"
+#include "mongoc-util-private.h"
+#include "mongoc-write-concern-private.h"
+#include "mongoc-uri-private.h"
+#include "mongoc-rpc-private.h"
+#include "mongoc-compression-private.h"
+#include "mongoc-cmd-private.h"
+#include "utlist.h"
+#include "mongoc-handshake-private.h"
+#include "mongoc-cluster-aws-private.h"
+#include "mongoc-error-private.h"
+
+#undef MONGOC_LOG_DOMAIN
+#define MONGOC_LOG_DOMAIN "cluster"
+
+
+#define CHECK_CLOSED_DURATION_MSEC 1000
+
+#define IS_NOT_COMMAND(_name) (!!strcasecmp (cmd->command_name, _name))
+
+static mongoc_server_stream_t *
+_cluster_fetch_stream_single (mongoc_cluster_t *cluster,
+ const mongoc_topology_description_t *td,
+ uint32_t server_id,
+ bool reconnect_ok,
+ bson_error_t *error);
+
+static mongoc_server_stream_t *
+_cluster_fetch_stream_pooled (mongoc_cluster_t *cluster,
+ const mongoc_topology_description_t *td,
+ uint32_t server_id,
+ bool reconnect_ok,
+ bson_error_t *error);
+
+static bool
+mongoc_cluster_run_opmsg (mongoc_cluster_t *cluster,
+ mongoc_cmd_t *cmd,
+ bson_t *reply,
+ bson_error_t *error);
+
+static void
+_bson_error_message_printf (bson_error_t *error, const char *format, ...)
+ BSON_GNUC_PRINTF (2, 3);
+
+static void
+_handle_not_primary_error (mongoc_cluster_t *cluster,
+ const mongoc_server_stream_t *server_stream,
+ const bson_t *reply)
+{
+ uint32_t server_id;
+
+ server_id = server_stream->sd->id;
+ if (_mongoc_topology_handle_app_error (cluster->client->topology,
+ server_id,
+ true /* handshake complete */,
+ MONGOC_SDAM_APP_ERROR_COMMAND,
+ reply,
+ NULL,
+ server_stream->sd->max_wire_version,
+ server_stream->sd->generation,
+ &server_stream->sd->service_id)) {
+ mongoc_cluster_disconnect_node (cluster, server_id);
+ }
+}
+
+/* Called when a network error occurs on an application socket.
+ */
+static void
+_handle_network_error (mongoc_cluster_t *cluster,
+ mongoc_server_stream_t *server_stream,
+ bool handshake_complete,
+ const bson_error_t *why)
+{
+ mongoc_topology_t *topology;
+ uint32_t server_id;
+ _mongoc_sdam_app_error_type_t type;
+
+ BSON_ASSERT (server_stream);
+
+ ENTRY;
+ topology = cluster->client->topology;
+ server_id = server_stream->sd->id;
+ type = MONGOC_SDAM_APP_ERROR_NETWORK;
+ if (mongoc_stream_timed_out (server_stream->stream)) {
+ type = MONGOC_SDAM_APP_ERROR_TIMEOUT;
+ }
+
+ _mongoc_topology_handle_app_error (topology,
+ server_id,
+ handshake_complete,
+ type,
+ NULL,
+ why,
+ server_stream->sd->max_wire_version,
+ server_stream->sd->generation,
+ &server_stream->sd->service_id);
+ /* Always disconnect the current connection on network error. */
+ mongoc_cluster_disconnect_node (cluster, server_id);
+
+ EXIT;
+}
+
+
+size_t
+_mongoc_cluster_buffer_iovec (mongoc_iovec_t *iov,
+ size_t iovcnt,
+ int skip,
+ char *buffer)
+{
+ int n;
+ size_t buffer_offset = 0;
+ int total_iov_len = 0;
+ int difference = 0;
+
+ for (n = 0; n < iovcnt; n++) {
+ total_iov_len += iov[n].iov_len;
+
+ if (total_iov_len <= skip) {
+ continue;
+ }
+
+ /* If this iovec starts before the skip, and takes the total count
+ * beyond the skip, we need to figure out the portion of the iovec
+ * we should skip passed */
+ if (total_iov_len - iov[n].iov_len < skip) {
+ difference = skip - (total_iov_len - iov[n].iov_len);
+ } else {
+ difference = 0;
+ }
+
+ memcpy (buffer + buffer_offset,
+ ((char *) iov[n].iov_base) + difference,
+ iov[n].iov_len - difference);
+ buffer_offset += iov[n].iov_len - difference;
+ }
+
+ return buffer_offset;
+}
+
+/* Allows caller to safely overwrite error->message with a formatted string,
+ * even if the formatted string includes original error->message. */
+static void
+_bson_error_message_printf (bson_error_t *error, const char *format, ...)
+{
+ va_list args;
+ char error_message[sizeof error->message];
+
+ if (error) {
+ va_start (args, format);
+ bson_vsnprintf (error_message, sizeof error->message, format, args);
+ va_end (args);
+
+ bson_strncpy (error->message, error_message, sizeof error->message);
+ }
+}
+
+#define RUN_CMD_ERR_DECORATE \
+ do { \
+ _bson_error_message_printf ( \
+ error, \
+ "Failed to send \"%s\" command with database \"%s\": %s", \
+ cmd->command_name, \
+ cmd->db_name, \
+ error->message); \
+ } while (0)
+
+#define RUN_CMD_ERR(_domain, _code, ...) \
+ do { \
+ bson_set_error (error, _domain, _code, __VA_ARGS__); \
+ RUN_CMD_ERR_DECORATE; \
+ } while (0)
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_cluster_run_command_opquery --
+ *
+ * Internal function to run a command on a given stream. @error and
+ * @reply are optional out-pointers.
+ *
+ * Returns:
+ * true if successful; otherwise false and @error is set.
+ *
+ * Side effects:
+ * @reply is set and should ALWAYS be released with bson_destroy().
+ * On failure, @error is filled out. If this was a network error
+ * and server_id is nonzero, the cluster disconnects from the server.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+static bool
+mongoc_cluster_run_command_opquery (mongoc_cluster_t *cluster,
+ mongoc_cmd_t *cmd,
+ int32_t compressor_id,
+ bson_t *reply,
+ bson_error_t *error)
+{
+ const size_t reply_header_size = sizeof (mongoc_rpc_reply_header_t);
+ uint8_t reply_header_buf[sizeof (mongoc_rpc_reply_header_t)];
+ uint8_t *reply_buf; /* reply body */
+ mongoc_rpc_t rpc; /* sent to server */
+ bson_t reply_local;
+ bson_t *reply_ptr;
+ char *cmd_ns;
+ uint32_t request_id;
+ int32_t msg_len;
+ size_t doc_len;
+ bool ret = false;
+ char *output = NULL;
+ mongoc_stream_t *stream;
+
+ ENTRY;
+
+ BSON_ASSERT (cluster);
+ BSON_ASSERT (cmd);
+ BSON_ASSERT (cmd->server_stream);
+
+ stream = cmd->server_stream->stream;
+ /*
+ * setup
+ */
+ reply_ptr = reply ? reply : &reply_local;
+ bson_init (reply_ptr);
+
+ error->code = 0;
+
+ /*
+ * prepare the request
+ */
+
+ _mongoc_array_clear (&cluster->iov);
+
+ cmd_ns = bson_strdup_printf ("%s.$cmd", cmd->db_name);
+ request_id = ++cluster->request_id;
+ _mongoc_rpc_prep_command (&rpc, cmd_ns, cmd);
+ rpc.header.request_id = request_id;
+
+ _mongoc_rpc_gather (&rpc, &cluster->iov);
+ _mongoc_rpc_swab_to_le (&rpc);
+
+ if (compressor_id != -1 && IS_NOT_COMMAND (HANDSHAKE_CMD_LEGACY_HELLO) &&
+ IS_NOT_COMMAND ("hello") && IS_NOT_COMMAND ("saslstart") &&
+ IS_NOT_COMMAND ("saslcontinue") && IS_NOT_COMMAND ("getnonce") &&
+ IS_NOT_COMMAND ("authenticate") && IS_NOT_COMMAND ("createuser") &&
+ IS_NOT_COMMAND ("updateuser")) {
+ output = _mongoc_rpc_compress (cluster, compressor_id, &rpc, error);
+ if (output == NULL) {
+ GOTO (done);
+ }
+ }
+
+ if (cluster->client->in_exhaust) {
+ bson_set_error (error,
+ MONGOC_ERROR_CLIENT,
+ MONGOC_ERROR_CLIENT_IN_EXHAUST,
+ "A cursor derived from this client is in exhaust.");
+ GOTO (done);
+ }
+
+ /*
+ * send and receive
+ */
+ if (!_mongoc_stream_writev_full (stream,
+ cluster->iov.data,
+ cluster->iov.len,
+ cluster->sockettimeoutms,
+ error)) {
+ _handle_network_error (
+ cluster, cmd->server_stream, true /* handshake complete */, error);
+
+ /* add info about the command to writev_full's error message */
+ RUN_CMD_ERR_DECORATE;
+ GOTO (done);
+ }
+
+ if (reply_header_size != mongoc_stream_read (stream,
+ &reply_header_buf,
+ reply_header_size,
+ reply_header_size,
+ cluster->sockettimeoutms)) {
+ RUN_CMD_ERR (MONGOC_ERROR_STREAM,
+ MONGOC_ERROR_STREAM_SOCKET,
+ "socket error or timeout");
+
+ _handle_network_error (
+ cluster, cmd->server_stream, true /* handshake complete */, error);
+ GOTO (done);
+ }
+
+ memcpy (&msg_len, reply_header_buf, 4);
+ msg_len = BSON_UINT32_FROM_LE (msg_len);
+ if ((msg_len < reply_header_size) ||
+ (msg_len > MONGOC_DEFAULT_MAX_MSG_SIZE)) {
+ _handle_network_error (
+ cluster, cmd->server_stream, true /* handshake complete */, error);
+ GOTO (done);
+ }
+
+ if (!_mongoc_rpc_scatter_reply_header_only (
+ &rpc, reply_header_buf, reply_header_size)) {
+ _handle_network_error (
+ cluster, cmd->server_stream, true /* handshake complete */, error);
+ GOTO (done);
+ }
+ doc_len = (size_t) msg_len - reply_header_size;
+
+ if (BSON_UINT32_FROM_LE (rpc.header.opcode) == MONGOC_OPCODE_COMPRESSED) {
+ bson_t tmp = BSON_INITIALIZER;
+ uint8_t *buf = NULL;
+ size_t len = BSON_UINT32_FROM_LE (rpc.compressed.uncompressed_size) +
+ sizeof (mongoc_rpc_header_t);
+
+ reply_buf = bson_malloc0 (msg_len);
+ memcpy (reply_buf, reply_header_buf, reply_header_size);
+
+ if (doc_len != mongoc_stream_read (stream,
+ reply_buf + reply_header_size,
+ doc_len,
+ doc_len,
+ cluster->sockettimeoutms)) {
+ RUN_CMD_ERR (MONGOC_ERROR_STREAM,
+ MONGOC_ERROR_STREAM_SOCKET,
+ "socket error or timeout");
+ _handle_network_error (
+ cluster, cmd->server_stream, true /* handshake complete */, error);
+ GOTO (done);
+ }
+ if (!_mongoc_rpc_scatter (&rpc, reply_buf, msg_len)) {
+ GOTO (done);
+ }
+
+ buf = bson_malloc0 (len);
+ if (!_mongoc_rpc_decompress (&rpc, buf, len)) {
+ RUN_CMD_ERR (MONGOC_ERROR_PROTOCOL,
+ MONGOC_ERROR_PROTOCOL_INVALID_REPLY,
+ "Could not decompress server reply");
+ bson_free (reply_buf);
+ bson_free (buf);
+ GOTO (done);
+ }
+
+ _mongoc_rpc_swab_from_le (&rpc);
+
+ if (!_mongoc_rpc_get_first_document (&rpc, &tmp)) {
+ RUN_CMD_ERR (MONGOC_ERROR_PROTOCOL,
+ MONGOC_ERROR_PROTOCOL_INVALID_REPLY,
+ "Corrupt compressed OP_QUERY reply from server");
+ bson_free (reply_buf);
+ bson_free (buf);
+ GOTO (done);
+ }
+ bson_copy_to (&tmp, reply_ptr);
+ bson_free (reply_buf);
+ bson_free (buf);
+ } else if (BSON_UINT32_FROM_LE (rpc.header.opcode) == MONGOC_OPCODE_REPLY &&
+ BSON_UINT32_FROM_LE (rpc.reply_header.n_returned) == 1) {
+ reply_buf = bson_reserve_buffer (reply_ptr, (uint32_t) doc_len);
+ BSON_ASSERT (reply_buf);
+
+ if (doc_len != mongoc_stream_read (stream,
+ (void *) reply_buf,
+ doc_len,
+ doc_len,
+ cluster->sockettimeoutms)) {
+ RUN_CMD_ERR (MONGOC_ERROR_STREAM,
+ MONGOC_ERROR_STREAM_SOCKET,
+ "socket error or timeout");
+ _handle_network_error (
+ cluster, cmd->server_stream, true /* handshake complete */, error);
+ GOTO (done);
+ }
+ _mongoc_rpc_swab_from_le (&rpc);
+ } else {
+ GOTO (done);
+ }
+
+ if (!_mongoc_cmd_check_ok (
+ reply_ptr, cluster->client->error_api_version, error)) {
+ GOTO (done);
+ }
+
+ ret = true;
+
+done:
+
+ if (!ret && error->code == 0) {
+ /* generic error */
+ RUN_CMD_ERR (MONGOC_ERROR_PROTOCOL,
+ MONGOC_ERROR_PROTOCOL_INVALID_REPLY,
+ "Invalid reply from server.");
+ }
+
+ if (reply_ptr == &reply_local) {
+ bson_destroy (reply_ptr);
+ }
+ bson_free (output);
+ bson_free (cmd_ns);
+
+ RETURN (ret);
+}
+
+bool
+_in_sharded_txn (const mongoc_client_session_t *session)
+{
+ return session && _mongoc_client_session_in_txn_or_ending (session) &&
+ _mongoc_topology_get_type (session->client->topology) ==
+ MONGOC_TOPOLOGY_SHARDED;
+}
+
+static void
+_handle_txn_error_labels (bool cmd_ret,
+ const bson_error_t *cmd_err,
+ const mongoc_cmd_t *cmd,
+ bson_t *reply)
+{
+ if (!cmd->is_txn_finish) {
+ return;
+ }
+
+ _mongoc_write_error_handle_labels (
+ cmd_ret, cmd_err, reply, cmd->server_stream->sd->max_wire_version);
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_cluster_run_command_monitored --
+ *
+ * Internal function to run a command on a given stream.
+ * @error and @reply are optional out-pointers.
+ *
+ * Returns:
+ * true if successful; otherwise false and @error is set.
+ *
+ * Side effects:
+ * If the client's APM callbacks are set, they are executed.
+ * @reply is set and should ALWAYS be released with bson_destroy().
+ *
+ *--------------------------------------------------------------------------
+ */
+
+bool
+mongoc_cluster_run_command_monitored (mongoc_cluster_t *cluster,
+ mongoc_cmd_t *cmd,
+ bson_t *reply,
+ bson_error_t *error)
+{
+ bool retval;
+ uint32_t request_id = ++cluster->request_id;
+ uint32_t server_id;
+ mongoc_apm_callbacks_t *callbacks;
+ mongoc_apm_command_started_t started_event;
+ mongoc_apm_command_succeeded_t succeeded_event;
+ mongoc_apm_command_failed_t failed_event;
+ int64_t started = bson_get_monotonic_time ();
+ const mongoc_server_stream_t *server_stream;
+ bson_t reply_local;
+ bson_error_t error_local;
+ int32_t compressor_id;
+ bson_iter_t iter;
+ bson_t encrypted = BSON_INITIALIZER;
+ bson_t decrypted = BSON_INITIALIZER;
+ mongoc_cmd_t encrypted_cmd;
+ bool is_redacted = false;
+
+ server_stream = cmd->server_stream;
+ server_id = server_stream->sd->id;
+ compressor_id = mongoc_server_description_compressor_id (server_stream->sd);
+
+ callbacks = &cluster->client->apm_callbacks;
+ if (!reply) {
+ reply = &reply_local;
+ }
+ if (!error) {
+ error = &error_local;
+ }
+
+ if (_mongoc_cse_is_enabled (cluster->client)) {
+ bson_destroy (&encrypted);
+
+ retval = _mongoc_cse_auto_encrypt (
+ cluster->client, cmd, &encrypted_cmd, &encrypted, error);
+ cmd = &encrypted_cmd;
+ if (!retval) {
+ bson_init (reply);
+ goto fail_no_events;
+ }
+ }
+
+ if (callbacks->started) {
+ mongoc_apm_command_started_init_with_cmd (&started_event,
+ cmd,
+ request_id,
+ &is_redacted,
+ cluster->client->apm_context);
+
+ callbacks->started (&started_event);
+ mongoc_apm_command_started_cleanup (&started_event);
+ }
+
+ if (server_stream->sd->max_wire_version >= WIRE_VERSION_OP_MSG) {
+ retval = mongoc_cluster_run_opmsg (cluster, cmd, reply, error);
+ } else {
+ retval = mongoc_cluster_run_command_opquery (
+ cluster, cmd, compressor_id, reply, error);
+ }
+
+ if (_mongoc_cse_is_enabled (cluster->client)) {
+ bson_destroy (&decrypted);
+ retval = _mongoc_cse_auto_decrypt (
+ cluster->client, cmd->db_name, reply, &decrypted, error);
+ bson_destroy (reply);
+ bson_steal (reply, &decrypted);
+ bson_init (&decrypted);
+ if (!retval) {
+ goto fail_no_events;
+ }
+ }
+
+ if (retval && callbacks->succeeded) {
+ bson_t fake_reply = BSON_INITIALIZER;
+ /*
+ * Unacknowledged writes must provide a CommandSucceededEvent with an
+ * {ok: 1} reply.
+ * https://github.com/mongodb/specifications/blob/master/source/command-monitoring/command-monitoring.rst#unacknowledged-acknowledged-writes
+ */
+ if (!cmd->is_acknowledged) {
+ bson_append_int32 (&fake_reply, "ok", 2, 1);
+ }
+ mongoc_apm_command_succeeded_init (&succeeded_event,
+ bson_get_monotonic_time () - started,
+ cmd->is_acknowledged ? reply
+ : &fake_reply,
+ cmd->command_name,
+ request_id,
+ cmd->operation_id,
+ &server_stream->sd->host,
+ server_id,
+ &server_stream->sd->service_id,
+ is_redacted,
+ cluster->client->apm_context);
+
+ callbacks->succeeded (&succeeded_event);
+ mongoc_apm_command_succeeded_cleanup (&succeeded_event);
+ bson_destroy (&fake_reply);
+ }
+ if (!retval && callbacks->failed) {
+ mongoc_apm_command_failed_init (&failed_event,
+ bson_get_monotonic_time () - started,
+ cmd->command_name,
+ error,
+ reply,
+ request_id,
+ cmd->operation_id,
+ &server_stream->sd->host,
+ server_id,
+ &server_stream->sd->service_id,
+ is_redacted,
+ cluster->client->apm_context);
+
+ callbacks->failed (&failed_event);
+ mongoc_apm_command_failed_cleanup (&failed_event);
+ }
+
+ _handle_not_primary_error (cluster, server_stream, reply);
+
+ _handle_txn_error_labels (retval, error, cmd, reply);
+
+ if (retval && _in_sharded_txn (cmd->session) &&
+ bson_iter_init_find (&iter, reply, "recoveryToken")) {
+ bson_destroy (cmd->session->recovery_token);
+ if (BSON_ITER_HOLDS_DOCUMENT (&iter)) {
+ cmd->session->recovery_token =
+ bson_new_from_data (bson_iter_value (&iter)->value.v_doc.data,
+ bson_iter_value (&iter)->value.v_doc.data_len);
+ } else {
+ MONGOC_ERROR ("Malformed recovery token from server");
+ cmd->session->recovery_token = NULL;
+ }
+ }
+
+fail_no_events:
+ if (reply == &reply_local) {
+ bson_destroy (&reply_local);
+ }
+
+ bson_destroy (&encrypted);
+ bson_destroy (&decrypted);
+
+ _mongoc_topology_update_last_used (cluster->client->topology, server_id);
+
+ return retval;
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_cluster_run_command_private --
+ *
+ * Internal function to run a command on a given stream.
+ * @error and @reply are optional out-pointers.
+ * The client's APM callbacks are not executed.
+ * Automatic encryption/decryption is not performed.
+ *
+ * Returns:
+ * true if successful; otherwise false and @error is set.
+ *
+ * Side effects:
+ * @reply is set and should ALWAYS be released with bson_destroy().
+ *
+ *--------------------------------------------------------------------------
+ */
+
+bool
+mongoc_cluster_run_command_private (mongoc_cluster_t *cluster,
+ mongoc_cmd_t *cmd,
+ bson_t *reply,
+ bson_error_t *error)
+{
+ bool retval;
+ const mongoc_server_stream_t *server_stream;
+ bson_t reply_local;
+ bson_error_t error_local;
+
+ if (!error) {
+ error = &error_local;
+ }
+
+ if (!reply) {
+ reply = &reply_local;
+ }
+ server_stream = cmd->server_stream;
+ if (server_stream->sd->max_wire_version >= WIRE_VERSION_OP_MSG) {
+ retval = mongoc_cluster_run_opmsg (cluster, cmd, reply, error);
+ } else {
+ retval =
+ mongoc_cluster_run_command_opquery (cluster, cmd, -1, reply, error);
+ }
+ _handle_not_primary_error (cluster, server_stream, reply);
+ if (reply == &reply_local) {
+ bson_destroy (&reply_local);
+ }
+
+ _mongoc_topology_update_last_used (cluster->client->topology,
+ server_stream->sd->id);
+
+ return retval;
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_cluster_run_command_parts --
+ *
+ * Internal function to assemble command parts and run a command
+ * on a given stream. @error and @reply are optional out-pointers.
+ * The client's APM callbacks are not executed.
+ *
+ * Returns:
+ * true if successful; otherwise false and @error is set.
+ *
+ * Side effects:
+ * @reply is set and should ALWAYS be released with bson_destroy().
+ * mongoc_cmd_parts_cleanup will be always be called on parts. The
+ * caller should *not* call cleanup on the parts.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+bool
+mongoc_cluster_run_command_parts (mongoc_cluster_t *cluster,
+ mongoc_server_stream_t *server_stream,
+ mongoc_cmd_parts_t *parts,
+ bson_t *reply,
+ bson_error_t *error)
+{
+ bool ret;
+
+ if (!mongoc_cmd_parts_assemble (parts, server_stream, error)) {
+ _mongoc_bson_init_if_set (reply);
+ mongoc_cmd_parts_cleanup (parts);
+ return false;
+ }
+
+ ret = mongoc_cluster_run_command_private (
+ cluster, &parts->assembled, reply, error);
+ mongoc_cmd_parts_cleanup (parts);
+ return ret;
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _stream_run_hello --
+ *
+ * Run a hello command on the given stream. If
+ * @negotiate_sasl_supported_mechs is true, then saslSupportedMechs is
+ * added to the hello command.
+ *
+ * Returns:
+ * A mongoc_server_description_t you must destroy or NULL. If the call
+ * failed its error is set and its type is MONGOC_SERVER_UNKNOWN.
+ *
+ *--------------------------------------------------------------------------
+ */
+static mongoc_server_description_t *
+_stream_run_hello (mongoc_cluster_t *cluster,
+ mongoc_stream_t *stream,
+ const char *address,
+ uint32_t server_id,
+ bool negotiate_sasl_supported_mechs,
+ mongoc_scram_cache_t *scram_cache,
+ mongoc_scram_t *scram,
+ bson_t *speculative_auth_response /* OUT */,
+ bson_error_t *error)
+{
+ bson_t command; /* Initialized by dup_handshake below */
+ mongoc_cmd_t hello_cmd;
+ bson_t reply;
+ int64_t start;
+ int64_t rtt_msec;
+ mongoc_server_description_t empty_sd;
+ mongoc_server_description_t *ret_handshake_sd;
+ mongoc_server_stream_t *server_stream;
+ bool r;
+ bson_iter_t iter;
+ mongoc_ssl_opt_t *ssl_opts = NULL;
+ mc_shared_tpld td =
+ mc_tpld_take_ref (BSON_ASSERT_PTR_INLINE (cluster)->client->topology);
+
+ ENTRY;
+
+ BSON_ASSERT (stream);
+
+ _mongoc_topology_dup_handshake_cmd (cluster->client->topology, &command);
+
+ if (cluster->requires_auth && speculative_auth_response) {
+#ifdef MONGOC_ENABLE_SSL
+ ssl_opts = &cluster->client->ssl_opts;
+#endif
+
+ _mongoc_topology_scanner_add_speculative_authentication (
+ &command, cluster->uri, ssl_opts, scram_cache, scram);
+ }
+
+ if (negotiate_sasl_supported_mechs) {
+ _mongoc_handshake_append_sasl_supported_mechs (cluster->uri, &command);
+ }
+
+ start = bson_get_monotonic_time ();
+ /* TODO CDRIVER-3654: do not use a mongoc_server_stream here.
+ * Instead, use a plain stream. If a network error occurs, check the cluster
+ * node's generation (which is the generation of the created connection) to
+ * determine if the error should be handled.
+ * The current behavior may double invalidate.
+ * If a network error occurs in mongoc_cluster_run_command_private below,
+ * that invalidates (thinking the error is a post-handshake network error).
+ * Then _mongoc_cluster_stream_for_server also handles the error, and
+ * invalidates again.
+ */
+ mongoc_server_description_init (&empty_sd, address, server_id);
+ server_stream =
+ _mongoc_cluster_create_server_stream (td.ptr, &empty_sd, stream);
+ mongoc_server_description_cleanup (&empty_sd);
+
+ /* Always use OP_QUERY for the handshake, regardless of whether the last
+ * known hello indicates the server supports a newer wire protocol.
+ */
+ memset (&hello_cmd, 0, sizeof (hello_cmd));
+ hello_cmd.db_name = "admin";
+ hello_cmd.command = &command;
+ hello_cmd.command_name = _mongoc_get_command_name (&command);
+ hello_cmd.query_flags = MONGOC_QUERY_SECONDARY_OK;
+ hello_cmd.server_stream = server_stream;
+
+ if (!mongoc_cluster_run_command_private (
+ cluster, &hello_cmd, &reply, error)) {
+ if (negotiate_sasl_supported_mechs) {
+ if (bson_iter_init_find (&iter, &reply, "ok") &&
+ !bson_iter_as_bool (&iter)) {
+ /* hello response returned ok: 0. According to auth spec: "If the
+ * hello of the MongoDB Handshake fails with an error, drivers
+ * MUST treat this an authentication error." */
+ error->domain = MONGOC_ERROR_CLIENT;
+ error->code = MONGOC_ERROR_CLIENT_AUTHENTICATE;
+ }
+ }
+
+ mongoc_server_stream_cleanup (server_stream);
+ ret_handshake_sd = NULL;
+ goto done;
+ }
+
+ rtt_msec = (bson_get_monotonic_time () - start) / 1000;
+
+ ret_handshake_sd = (mongoc_server_description_t *) bson_malloc0 (
+ sizeof (mongoc_server_description_t));
+
+ mongoc_server_description_init (ret_handshake_sd, address, server_id);
+ /* send the error from run_command IN to handle_hello */
+ mongoc_server_description_handle_hello (
+ ret_handshake_sd, &reply, rtt_msec, error);
+
+ if (cluster->requires_auth && speculative_auth_response) {
+ _mongoc_topology_scanner_parse_speculative_authentication (
+ &reply, speculative_auth_response);
+ }
+
+ /* Note: This call will render our copy of the topology description to be
+ * stale */
+ r = _mongoc_topology_update_from_handshake (cluster->client->topology,
+ ret_handshake_sd);
+ if (!r) {
+ mongoc_server_description_reset (ret_handshake_sd);
+ bson_set_error (&ret_handshake_sd->error,
+ MONGOC_ERROR_STREAM,
+ MONGOC_ERROR_STREAM_NOT_ESTABLISHED,
+ "\"%s\" removed from topology",
+ address);
+ }
+
+ mongoc_server_stream_cleanup (server_stream);
+
+done:
+ bson_destroy (&command);
+ bson_destroy (&reply);
+ mc_tpld_drop_ref (&td);
+
+ RETURN (ret_handshake_sd);
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_cluster_run_hello --
+ *
+ * Run an initial hello command for the given node and handle result.
+ *
+ * Returns:
+ * mongoc_server_description_t on success, NULL otherwise.
+ * the mongoc_server_description_t MUST BE DESTROYED BY THE CALLER.
+ *
+ * Side effects:
+ * Makes a blocking I/O call, updates cluster->topology->description
+ * with hello result.
+ *
+ *--------------------------------------------------------------------------
+ */
+static mongoc_server_description_t *
+_cluster_run_hello (mongoc_cluster_t *cluster,
+ mongoc_cluster_node_t *node,
+ uint32_t server_id,
+ mongoc_scram_cache_t *scram_cache,
+ mongoc_scram_t *scram /* OUT */,
+ bson_t *speculative_auth_response /* OUT */,
+ bson_error_t *error /* OUT */)
+{
+ mongoc_server_description_t *sd;
+
+ ENTRY;
+
+ BSON_ASSERT (cluster);
+ BSON_ASSERT (node);
+ BSON_ASSERT (node->stream);
+
+ sd = _stream_run_hello (cluster,
+ node->stream,
+ node->connection_address,
+ server_id,
+ _mongoc_uri_requires_auth_negotiation (cluster->uri),
+ scram_cache,
+ scram,
+ speculative_auth_response,
+ error);
+
+ if (!sd) {
+ return NULL;
+ }
+
+ if (sd->type == MONGOC_SERVER_UNKNOWN) {
+ memcpy (error, &sd->error, sizeof (bson_error_t));
+ mongoc_server_description_destroy (sd);
+ return NULL;
+ }
+
+ return sd;
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_cluster_build_basic_auth_digest --
+ *
+ * Computes the Basic Authentication digest using the credentials
+ * configured for @cluster and the @nonce provided.
+ *
+ * The result should be freed by the caller using bson_free() when
+ * they are finished with it.
+ *
+ * Returns:
+ * A newly allocated string containing the digest.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+static char *
+_mongoc_cluster_build_basic_auth_digest (mongoc_cluster_t *cluster,
+ const char *nonce)
+{
+ const char *username;
+ const char *password;
+ char *password_digest;
+ char *password_md5;
+ char *digest_in;
+ char *ret;
+
+ ENTRY;
+
+ /*
+ * The following generates the digest to be used for basic authentication
+ * with a MongoDB server. More information on the format can be found
+ * at the following location:
+ *
+ * http://docs.mongodb.org/meta-driver/latest/legacy/
+ * implement-authentication-in-driver/
+ */
+
+ BSON_ASSERT (cluster);
+ BSON_ASSERT (cluster->uri);
+
+ username = mongoc_uri_get_username (cluster->uri);
+ password = mongoc_uri_get_password (cluster->uri);
+ password_digest = bson_strdup_printf ("%s:mongo:%s", username, password);
+ password_md5 = _mongoc_hex_md5 (password_digest);
+ digest_in = bson_strdup_printf ("%s%s%s", nonce, username, password_md5);
+ ret = _mongoc_hex_md5 (digest_in);
+ bson_free (digest_in);
+ bson_free (password_md5);
+ bson_free (password_digest);
+
+ RETURN (ret);
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_cluster_auth_node_cr --
+ *
+ * Performs authentication of @node using the credentials provided
+ * when configuring the @cluster instance.
+ *
+ * This is the Challenge-Response mode of authentication.
+ *
+ * Returns:
+ * true if authentication was successful; otherwise false and
+ * @error is set.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+static bool
+_mongoc_cluster_auth_node_cr (mongoc_cluster_t *cluster,
+ mongoc_stream_t *stream,
+ mongoc_server_description_t *sd,
+ bson_error_t *error)
+{
+ mongoc_cmd_parts_t parts;
+ bson_iter_t iter;
+ const char *auth_source;
+ bson_t command;
+ bson_t reply;
+ char *digest;
+ char *nonce;
+ bool ret;
+ mongoc_server_stream_t *server_stream;
+ mc_shared_tpld td;
+
+ ENTRY;
+
+ BSON_ASSERT (cluster);
+ BSON_ASSERT (stream);
+
+ if (!(auth_source = mongoc_uri_get_auth_source (cluster->uri)) ||
+ (*auth_source == '\0')) {
+ auth_source = "admin";
+ }
+
+ /*
+ * To authenticate a node using basic authentication, we need to first
+ * get the nonce from the server. We use that to hash our password which
+ * is sent as a reply to the server. If everything went good we get a
+ * success notification back from the server.
+ */
+
+ /*
+ * Execute the getnonce command to fetch the nonce used for generating
+ * md5 digest of our password information.
+ */
+ bson_init (&command);
+ bson_append_int32 (&command, "getnonce", 8, 1);
+ mongoc_cmd_parts_init (&parts,
+ cluster->client,
+ auth_source,
+ MONGOC_QUERY_SECONDARY_OK,
+ &command);
+ parts.prohibit_lsid = true;
+
+ td = mc_tpld_take_ref (cluster->client->topology);
+ server_stream = _mongoc_cluster_create_server_stream (td.ptr, sd, stream);
+ mc_tpld_drop_ref (&td);
+
+ if (!mongoc_cluster_run_command_parts (
+ cluster, server_stream, &parts, &reply, error)) {
+ mongoc_server_stream_cleanup (server_stream);
+ bson_destroy (&command);
+ bson_destroy (&reply);
+ RETURN (false);
+ }
+ bson_destroy (&command);
+ if (!bson_iter_init_find_case (&iter, &reply, "nonce")) {
+ bson_set_error (error,
+ MONGOC_ERROR_CLIENT,
+ MONGOC_ERROR_CLIENT_GETNONCE,
+ "Invalid reply from getnonce");
+ bson_destroy (&reply);
+ RETURN (false);
+ }
+
+ /*
+ * Build our command to perform the authentication.
+ */
+ nonce = bson_iter_dup_utf8 (&iter, NULL);
+ digest = _mongoc_cluster_build_basic_auth_digest (cluster, nonce);
+ bson_init (&command);
+ bson_append_int32 (&command, "authenticate", 12, 1);
+ bson_append_utf8 (
+ &command, "user", 4, mongoc_uri_get_username (cluster->uri), -1);
+ bson_append_utf8 (&command, "nonce", 5, nonce, -1);
+ bson_append_utf8 (&command, "key", 3, digest, -1);
+ bson_destroy (&reply);
+ bson_free (nonce);
+ bson_free (digest);
+
+ /*
+ * Execute the authenticate command. mongoc_cluster_run_command_private
+ * checks for {ok: 1} in the response.
+ */
+ mongoc_cmd_parts_init (&parts,
+ cluster->client,
+ auth_source,
+ MONGOC_QUERY_SECONDARY_OK,
+ &command);
+ parts.prohibit_lsid = true;
+ ret = mongoc_cluster_run_command_parts (
+ cluster, server_stream, &parts, &reply, error);
+
+ if (!ret) {
+ /* error->message is already set */
+ error->domain = MONGOC_ERROR_CLIENT;
+ error->code = MONGOC_ERROR_CLIENT_AUTHENTICATE;
+ }
+
+ mongoc_server_stream_cleanup (server_stream);
+ bson_destroy (&command);
+ bson_destroy (&reply);
+
+ RETURN (ret);
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_cluster_auth_node_plain --
+ *
+ * Perform SASL PLAIN authentication for @node. We do this manually
+ * instead of using the SASL module because it is rather simplistic.
+ *
+ * Returns:
+ * true if successful; otherwise false and error is set.
+ *
+ * Side effects:
+ * error may be set.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+static bool
+_mongoc_cluster_auth_node_plain (mongoc_cluster_t *cluster,
+ mongoc_stream_t *stream,
+ mongoc_server_description_t *sd,
+ bson_error_t *error)
+{
+ mongoc_cmd_parts_t parts;
+ char buf[4096];
+ int buflen = 0;
+ const char *username;
+ const char *password;
+ bson_t b = BSON_INITIALIZER;
+ bson_t reply;
+ size_t len;
+ char *str;
+ bool ret;
+ mongoc_server_stream_t *server_stream;
+ mc_shared_tpld td;
+
+ BSON_ASSERT (cluster);
+ BSON_ASSERT (stream);
+
+ username = mongoc_uri_get_username (cluster->uri);
+ if (!username) {
+ username = "";
+ }
+
+ password = mongoc_uri_get_password (cluster->uri);
+ if (!password) {
+ password = "";
+ }
+
+ str = bson_strdup_printf ("%c%s%c%s", '\0', username, '\0', password);
+ len = strlen (username) + strlen (password) + 2;
+ buflen = COMMON_PREFIX (
+ bson_b64_ntop ((const uint8_t *) str, len, buf, sizeof buf));
+ bson_free (str);
+
+ if (buflen == -1) {
+ bson_set_error (error,
+ MONGOC_ERROR_CLIENT,
+ MONGOC_ERROR_CLIENT_AUTHENTICATE,
+ "failed base64 encoding message");
+ return false;
+ }
+
+ BSON_APPEND_INT32 (&b, "saslStart", 1);
+ BSON_APPEND_UTF8 (&b, "mechanism", "PLAIN");
+ bson_append_utf8 (&b, "payload", 7, (const char *) buf, buflen);
+ BSON_APPEND_INT32 (&b, "autoAuthorize", 1);
+
+ mongoc_cmd_parts_init (
+ &parts, cluster->client, "$external", MONGOC_QUERY_SECONDARY_OK, &b);
+ parts.prohibit_lsid = true;
+
+ td = mc_tpld_take_ref (cluster->client->topology);
+ server_stream = _mongoc_cluster_create_server_stream (td.ptr, sd, stream);
+ mc_tpld_drop_ref (&td);
+
+ ret = mongoc_cluster_run_command_parts (
+ cluster, server_stream, &parts, &reply, error);
+ mongoc_server_stream_cleanup (server_stream);
+ if (!ret) {
+ /* error->message is already set */
+ error->domain = MONGOC_ERROR_CLIENT;
+ error->code = MONGOC_ERROR_CLIENT_AUTHENTICATE;
+ }
+
+ bson_destroy (&b);
+ bson_destroy (&reply);
+
+ return ret;
+}
+
+bool
+_mongoc_cluster_get_auth_cmd_x509 (const mongoc_uri_t *uri,
+ const mongoc_ssl_opt_t *ssl_opts,
+ bson_t *cmd /* OUT */,
+ bson_error_t *error /* OUT */)
+{
+#ifndef MONGOC_ENABLE_SSL
+ bson_set_error (error,
+ MONGOC_ERROR_CLIENT,
+ MONGOC_ERROR_CLIENT_AUTHENTICATE,
+ "The MONGODB-X509 authentication mechanism requires "
+ "libmongoc built with ENABLE_SSL");
+ return false;
+#else
+ const char *username_from_uri = NULL;
+ char *username_from_subject = NULL;
+
+ BSON_ASSERT (uri);
+
+ username_from_uri = mongoc_uri_get_username (uri);
+ if (username_from_uri) {
+ TRACE ("%s", "X509: got username from URI");
+ } else {
+ if (!ssl_opts || !ssl_opts->pem_file) {
+ bson_set_error (error,
+ MONGOC_ERROR_CLIENT,
+ MONGOC_ERROR_CLIENT_AUTHENTICATE,
+ "cannot determine username for "
+ "X-509 authentication.");
+ return false;
+ }
+
+ username_from_subject =
+ mongoc_ssl_extract_subject (ssl_opts->pem_file, ssl_opts->pem_pwd);
+ if (!username_from_subject) {
+ bson_set_error (error,
+ MONGOC_ERROR_CLIENT,
+ MONGOC_ERROR_CLIENT_AUTHENTICATE,
+ "No username provided for X509 authentication.");
+ return false;
+ }
+
+ TRACE ("%s", "X509: got username from certificate");
+ }
+
+ bson_init (cmd);
+ BSON_APPEND_INT32 (cmd, "authenticate", 1);
+ BSON_APPEND_UTF8 (cmd, "mechanism", "MONGODB-X509");
+ BSON_APPEND_UTF8 (cmd,
+ "user",
+ username_from_uri ? username_from_uri
+ : username_from_subject);
+
+ bson_free (username_from_subject);
+
+ return true;
+#endif
+}
+
+
+static bool
+_mongoc_cluster_auth_node_x509 (mongoc_cluster_t *cluster,
+ mongoc_stream_t *stream,
+ mongoc_server_description_t *sd,
+ bson_error_t *error)
+{
+#ifndef MONGOC_ENABLE_SSL
+ bson_set_error (error,
+ MONGOC_ERROR_CLIENT,
+ MONGOC_ERROR_CLIENT_AUTHENTICATE,
+ "The MONGODB-X509 authentication mechanism requires "
+ "libmongoc built with ENABLE_SSL");
+ return false;
+#else
+ mongoc_cmd_parts_t parts;
+ bson_t cmd;
+ bson_t reply;
+ bool ret;
+ mongoc_server_stream_t *server_stream;
+ mc_shared_tpld td;
+
+ BSON_ASSERT (cluster);
+ BSON_ASSERT (stream);
+
+ if (!_mongoc_cluster_get_auth_cmd_x509 (
+ cluster->uri, &cluster->client->ssl_opts, &cmd, error)) {
+ return false;
+ }
+
+ mongoc_cmd_parts_init (
+ &parts, cluster->client, "$external", MONGOC_QUERY_SECONDARY_OK, &cmd);
+ parts.prohibit_lsid = true;
+ td = mc_tpld_take_ref (cluster->client->topology);
+ server_stream = _mongoc_cluster_create_server_stream (td.ptr, sd, stream);
+ mc_tpld_drop_ref (&td);
+
+ ret = mongoc_cluster_run_command_parts (
+ cluster, server_stream, &parts, &reply, error);
+ mongoc_server_stream_cleanup (server_stream);
+ if (!ret) {
+ /* error->message is already set */
+ error->domain = MONGOC_ERROR_CLIENT;
+ error->code = MONGOC_ERROR_CLIENT_AUTHENTICATE;
+ }
+
+ bson_destroy (&cmd);
+ bson_destroy (&reply);
+
+ return ret;
+#endif
+}
+
+#ifdef MONGOC_ENABLE_CRYPTO
+void
+_mongoc_cluster_init_scram (const mongoc_cluster_t *cluster,
+ mongoc_scram_t *scram,
+ mongoc_crypto_hash_algorithm_t algo)
+{
+ _mongoc_uri_init_scram (cluster->uri, scram, algo);
+
+ /* Apply previously cached SCRAM secrets if available */
+ if (cluster->scram_cache) {
+ _mongoc_scram_set_cache (scram, cluster->scram_cache);
+ }
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_cluster_get_auth_cmd_scram --
+ *
+ * Generates the saslStart command for scram authentication. Used
+ * during explicit authentication as well as speculative
+ * authentication during hello.
+ *
+ *
+ * Returns:
+ * true if the command could be generated, false otherwise
+ *
+ * Side effects:
+ * @error is set on failure.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+bool
+_mongoc_cluster_get_auth_cmd_scram (mongoc_crypto_hash_algorithm_t algo,
+ mongoc_scram_t *scram,
+ bson_t *cmd /* OUT */,
+ bson_error_t *error /* OUT */)
+{
+ uint8_t buf[4096] = {0};
+ uint32_t buflen = 0;
+ bson_t options;
+
+ if (!_mongoc_scram_step (
+ scram, buf, buflen, buf, sizeof buf, &buflen, error)) {
+ return false;
+ }
+
+ BSON_ASSERT (scram->step == 1);
+
+ bson_init (cmd);
+
+ BSON_APPEND_INT32 (cmd, "saslStart", 1);
+ if (algo == MONGOC_CRYPTO_ALGORITHM_SHA_1) {
+ BSON_APPEND_UTF8 (cmd, "mechanism", "SCRAM-SHA-1");
+ } else if (algo == MONGOC_CRYPTO_ALGORITHM_SHA_256) {
+ BSON_APPEND_UTF8 (cmd, "mechanism", "SCRAM-SHA-256");
+ } else {
+ BSON_ASSERT (false);
+ }
+ bson_append_binary (cmd, "payload", 7, BSON_SUBTYPE_BINARY, buf, buflen);
+ BSON_APPEND_INT32 (cmd, "autoAuthorize", 1);
+
+ BSON_APPEND_DOCUMENT_BEGIN (cmd, "options", &options);
+ BSON_APPEND_BOOL (&options, "skipEmptyExchange", true);
+ bson_append_document_end (cmd, &options);
+
+ bson_destroy (&options);
+
+ return true;
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_cluster_run_scram_command --
+ *
+ * Runs a scram authentication command, handling auth_source and
+ * errors during the command.
+ *
+ *
+ * Returns:
+ * true if the command was successful, false otherwise
+ *
+ * Side effects:
+ * @error is set on failure.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+static bool
+_mongoc_cluster_run_scram_command (
+ mongoc_cluster_t *cluster,
+ mongoc_stream_t *stream,
+ const mongoc_server_description_t *handshake_sd,
+ const bson_t *cmd,
+ bson_t *reply,
+ bson_error_t *error)
+{
+ mongoc_cmd_parts_t parts;
+ mongoc_server_stream_t *server_stream;
+ const char *auth_source;
+ mc_shared_tpld td =
+ mc_tpld_take_ref (BSON_ASSERT_PTR_INLINE (cluster)->client->topology);
+
+ if (!(auth_source = mongoc_uri_get_auth_source (cluster->uri)) ||
+ (*auth_source == '\0')) {
+ auth_source = "admin";
+ }
+
+ mongoc_cmd_parts_init (
+ &parts, cluster->client, auth_source, MONGOC_QUERY_SECONDARY_OK, cmd);
+ parts.prohibit_lsid = true;
+ server_stream =
+ _mongoc_cluster_create_server_stream (td.ptr, handshake_sd, stream);
+ mc_tpld_drop_ref (&td);
+
+ if (!mongoc_cluster_run_command_parts (
+ cluster, server_stream, &parts, reply, error)) {
+ mongoc_server_stream_cleanup (server_stream);
+ bson_destroy (reply);
+
+ /* error->message is already set */
+ error->domain = MONGOC_ERROR_CLIENT;
+ error->code = MONGOC_ERROR_CLIENT_AUTHENTICATE;
+
+ return false;
+ }
+
+ mongoc_server_stream_cleanup (server_stream);
+
+ return true;
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_cluster_auth_scram_start --
+ *
+ * Starts scram authentication by generating and sending the saslStart
+ * command. The conversation can then be resumed using
+ * _mongoc_cluster_auth_scram_continue.
+ *
+ *
+ * Returns:
+ * true if the saslStart command was successful, false otherwise
+ *
+ * Side effects:
+ * @error is set on failure.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+static bool
+_mongoc_cluster_auth_scram_start (
+ mongoc_cluster_t *cluster,
+ mongoc_stream_t *stream,
+ const mongoc_server_description_t *handshake_sd,
+ mongoc_crypto_hash_algorithm_t algo,
+ mongoc_scram_t *scram,
+ bson_t *reply,
+ bson_error_t *error)
+{
+ bson_t cmd;
+
+ BSON_ASSERT (scram->step == 0);
+
+ if (!_mongoc_cluster_get_auth_cmd_scram (algo, scram, &cmd, error)) {
+ /* error->message is already set */
+ error->domain = MONGOC_ERROR_CLIENT;
+ error->code = MONGOC_ERROR_CLIENT_AUTHENTICATE;
+
+ return false;
+ }
+
+ if (!_mongoc_cluster_run_scram_command (
+ cluster, stream, handshake_sd, &cmd, reply, error)) {
+ bson_destroy (&cmd);
+
+ return false;
+ }
+
+ bson_destroy (&cmd);
+
+ return true;
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_cluster_scram_handle_reply --
+ *
+ * Handles replies from _mongoc_cluster_run_scram_command. The @done
+ * argument will be set to true if the scram conversation was
+ * completed successfully.
+ *
+ *
+ * Returns:
+ * true if the reply was handled successfully, false if there was an
+ * error. Note that the return value itself does not indicate whether
+ * authentication was completed successfully.
+ *
+ * Side effects:
+ * @error is set on failure. @done, @conv_id, @buf, and @buflen are
+ * set for use in the next scram step.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+static bool
+_mongoc_cluster_scram_handle_reply (mongoc_scram_t *scram,
+ const bson_t *reply,
+ bool *done /* OUT */,
+ int *conv_id /* OUT */,
+ uint8_t *buf /* OUT */,
+ uint32_t bufmax,
+ uint32_t *buflen /* OUT */,
+ bson_error_t *error)
+{
+ bson_iter_t iter;
+ bson_subtype_t btype;
+ const char *tmpstr;
+
+ BSON_ASSERT (scram);
+
+ if (bson_iter_init_find (&iter, reply, "done") &&
+ bson_iter_as_bool (&iter)) {
+ if (scram->step < 2) {
+ /* Prior to step 2, we haven't even received server proof. */
+ bson_set_error (error,
+ MONGOC_ERROR_CLIENT,
+ MONGOC_ERROR_CLIENT_AUTHENTICATE,
+ "Incorrect step for 'done'");
+ return false;
+ }
+ *done = true;
+ if (scram->step >= 3) {
+ return true;
+ }
+ }
+
+ if (!bson_iter_init_find (&iter, reply, "conversationId") ||
+ !BSON_ITER_HOLDS_INT32 (&iter) ||
+ !(*conv_id = bson_iter_int32 (&iter)) ||
+ !bson_iter_init_find (&iter, reply, "payload") ||
+ !BSON_ITER_HOLDS_BINARY (&iter)) {
+ const char *errmsg = "Received invalid SCRAM reply from MongoDB server.";
+
+ MONGOC_DEBUG ("SCRAM: authentication failed");
+
+ if (bson_iter_init_find (&iter, reply, "errmsg") &&
+ BSON_ITER_HOLDS_UTF8 (&iter)) {
+ errmsg = bson_iter_utf8 (&iter, NULL);
+ }
+
+ bson_set_error (error,
+ MONGOC_ERROR_CLIENT,
+ MONGOC_ERROR_CLIENT_AUTHENTICATE,
+ "%s",
+ errmsg);
+ return false;
+ }
+
+ bson_iter_binary (&iter, &btype, buflen, (const uint8_t **) &tmpstr);
+
+ if (*buflen > bufmax) {
+ bson_set_error (error,
+ MONGOC_ERROR_CLIENT,
+ MONGOC_ERROR_CLIENT_AUTHENTICATE,
+ "SCRAM reply from MongoDB is too large.");
+ return false;
+ }
+
+ memcpy (buf, tmpstr, *buflen);
+
+ return true;
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_cluster_auth_scram_continue --
+ *
+ * Continues the scram conversation from the reply to a saslStart
+ * command, either sent explicitly or received through speculative
+ * authentication during hello.
+ *
+ *
+ * Returns:
+ * true if authenticated. false on failure and @error is set.
+ *
+ * Side effects:
+ * @error is set on failure.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+static bool
+_mongoc_cluster_auth_scram_continue (
+ mongoc_cluster_t *cluster,
+ mongoc_stream_t *stream,
+ const mongoc_server_description_t *handshake_sd,
+ mongoc_scram_t *scram,
+ const bson_t *sasl_start_reply,
+ bson_error_t *error)
+{
+ bson_t cmd;
+ uint8_t buf[4096] = {0};
+ uint32_t buflen = 0;
+ int conv_id = 0;
+ bool done = false;
+ bson_t reply_local;
+
+ if (!_mongoc_cluster_scram_handle_reply (scram,
+ sasl_start_reply,
+ &done,
+ &conv_id,
+ buf,
+ sizeof buf,
+ &buflen,
+ error)) {
+ return false;
+ }
+
+ for (;;) {
+ if (!_mongoc_scram_step (
+ scram, buf, buflen, buf, sizeof buf, &buflen, error)) {
+ return false;
+ }
+
+ if (done && (scram->step >= 3)) {
+ break;
+ }
+
+ bson_init (&cmd);
+
+ BSON_APPEND_INT32 (&cmd, "saslContinue", 1);
+ BSON_APPEND_INT32 (&cmd, "conversationId", conv_id);
+ bson_append_binary (&cmd, "payload", 7, BSON_SUBTYPE_BINARY, buf, buflen);
+
+ TRACE ("SCRAM: authenticating (step %d)", scram->step);
+
+ if (!_mongoc_cluster_run_scram_command (
+ cluster, stream, handshake_sd, &cmd, &reply_local, error)) {
+ bson_destroy (&cmd);
+ return false;
+ }
+
+ bson_destroy (&cmd);
+
+ if (!_mongoc_cluster_scram_handle_reply (scram,
+ &reply_local,
+ &done,
+ &conv_id,
+ buf,
+ sizeof buf,
+ &buflen,
+ error)) {
+ bson_destroy (&reply_local);
+ return false;
+ }
+
+ bson_destroy (&reply_local);
+
+ if (done && (scram->step >= 3)) {
+ break;
+ }
+ }
+
+ TRACE ("%s", "SCRAM: authenticated");
+
+ /* Save cached SCRAM secrets for future use */
+ if (cluster->scram_cache) {
+ _mongoc_scram_cache_destroy (cluster->scram_cache);
+ }
+
+ cluster->scram_cache = _mongoc_scram_get_cache (scram);
+
+ return true;
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_cluster_auth_node_scram --
+ *
+ * Invokes scram authentication by sending a saslStart command and
+ * handling all replies.
+ *
+ *
+ * Returns:
+ * true if authenticated. false on failure and @error is set.
+ *
+ * Side effects:
+ * @error is set on failure.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+static bool
+_mongoc_cluster_auth_node_scram (mongoc_cluster_t *cluster,
+ mongoc_stream_t *stream,
+ mongoc_server_description_t *handshake_sd,
+ mongoc_crypto_hash_algorithm_t algo,
+ bson_error_t *error)
+{
+ mongoc_scram_t scram;
+ bool ret = false;
+ bson_t reply;
+
+ BSON_ASSERT (cluster);
+
+ _mongoc_cluster_init_scram (cluster, &scram, algo);
+
+ if (!_mongoc_cluster_auth_scram_start (
+ cluster, stream, handshake_sd, algo, &scram, &reply, error)) {
+ goto failure;
+ }
+
+ if (!_mongoc_cluster_auth_scram_continue (
+ cluster, stream, handshake_sd, &scram, &reply, error)) {
+ bson_destroy (&reply);
+
+ goto failure;
+ }
+
+ TRACE ("%s", "SCRAM: authenticated");
+
+ ret = true;
+
+ bson_destroy (&reply);
+
+failure:
+ _mongoc_scram_destroy (&scram);
+
+ return ret;
+}
+#endif
+
+static bool
+_mongoc_cluster_auth_node_scram_sha_1 (mongoc_cluster_t *cluster,
+ mongoc_stream_t *stream,
+ mongoc_server_description_t *sd,
+ bson_error_t *error)
+{
+#ifndef MONGOC_ENABLE_CRYPTO
+ bson_set_error (error,
+ MONGOC_ERROR_CLIENT,
+ MONGOC_ERROR_CLIENT_AUTHENTICATE,
+ "The SCRAM_SHA_1 authentication mechanism requires "
+ "libmongoc built with ENABLE_SSL");
+ return false;
+#else
+ return _mongoc_cluster_auth_node_scram (
+ cluster, stream, sd, MONGOC_CRYPTO_ALGORITHM_SHA_1, error);
+#endif
+}
+
+static bool
+_mongoc_cluster_auth_node_scram_sha_256 (mongoc_cluster_t *cluster,
+ mongoc_stream_t *stream,
+ mongoc_server_description_t *sd,
+ bson_error_t *error)
+{
+#ifndef MONGOC_ENABLE_CRYPTO
+ bson_set_error (error,
+ MONGOC_ERROR_CLIENT,
+ MONGOC_ERROR_CLIENT_AUTHENTICATE,
+ "The SCRAM_SHA_256 authentication mechanism requires "
+ "libmongoc built with ENABLE_SSL");
+ return false;
+#else
+ return _mongoc_cluster_auth_node_scram (
+ cluster, stream, sd, MONGOC_CRYPTO_ALGORITHM_SHA_256, error);
+#endif
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_cluster_auth_node --
+ *
+ * Authenticate a cluster node depending on the required mechanism.
+ *
+ * Returns:
+ * true if authenticated. false on failure and @error is set.
+ *
+ * Side effects:
+ * @error is set on failure.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+static bool
+_mongoc_cluster_auth_node (
+ mongoc_cluster_t *cluster,
+ mongoc_stream_t *stream,
+ mongoc_server_description_t *sd,
+ const mongoc_handshake_sasl_supported_mechs_t *sasl_supported_mechs,
+ bson_error_t *error)
+{
+ bool ret = false;
+ const char *mechanism;
+ ENTRY;
+
+ BSON_ASSERT (cluster);
+ BSON_ASSERT (stream);
+
+ mechanism = mongoc_uri_get_auth_mechanism (cluster->uri);
+
+ if (!mechanism) {
+ if (sasl_supported_mechs->scram_sha_256) {
+ /* Auth spec: "If SCRAM-SHA-256 is present in the list of mechanisms,
+ * then it MUST be used as the default; otherwise, SCRAM-SHA-1 MUST be
+ * used as the default, regardless of whether SCRAM-SHA-1 is in the
+ * list. Drivers MUST NOT attempt to use any other mechanism (e.g.
+ * PLAIN) as the default." [...] "If saslSupportedMechs is not present
+ * in the hello results for mechanism negotiation, then SCRAM-SHA-1
+ * MUST be used when talking to servers >= 3.0." */
+ mechanism = "SCRAM-SHA-256";
+ } else {
+ mechanism = "SCRAM-SHA-1";
+ }
+ }
+
+ if (0 == strcasecmp (mechanism, "MONGODB-CR")) {
+ ret = _mongoc_cluster_auth_node_cr (cluster, stream, sd, error);
+ } else if (0 == strcasecmp (mechanism, "MONGODB-X509")) {
+ ret = _mongoc_cluster_auth_node_x509 (cluster, stream, sd, error);
+ } else if (0 == strcasecmp (mechanism, "SCRAM-SHA-1")) {
+ ret = _mongoc_cluster_auth_node_scram_sha_1 (cluster, stream, sd, error);
+ } else if (0 == strcasecmp (mechanism, "SCRAM-SHA-256")) {
+ ret =
+ _mongoc_cluster_auth_node_scram_sha_256 (cluster, stream, sd, error);
+ } else if (0 == strcasecmp (mechanism, "GSSAPI")) {
+ ret = _mongoc_cluster_auth_node_sasl (cluster, stream, sd, error);
+ } else if (0 == strcasecmp (mechanism, "PLAIN")) {
+ ret = _mongoc_cluster_auth_node_plain (cluster, stream, sd, error);
+ } else if (0 == strcasecmp (mechanism, "MONGODB-AWS")) {
+ ret = _mongoc_cluster_auth_node_aws (cluster, stream, sd, error);
+ } else {
+ bson_set_error (error,
+ MONGOC_ERROR_CLIENT,
+ MONGOC_ERROR_CLIENT_AUTHENTICATE,
+ "Unknown authentication mechanism \"%s\".",
+ mechanism);
+ }
+
+ if (!ret) {
+ mongoc_counter_auth_failure_inc ();
+ MONGOC_DEBUG ("Authentication failed: %s", error->message);
+ } else {
+ mongoc_counter_auth_success_inc ();
+ TRACE ("%s", "Authentication succeeded");
+ }
+
+ RETURN (ret);
+}
+
+
+/*
+ * Close the connection associated with this server.
+ *
+ * Called when a network error occurs, or to close connection tied to an exhaust
+ * cursor.
+ * If the cluster is pooled, removes the node from cluster's set of nodes.
+ * WARNING: pointers to a disconnected mongoc_cluster_node_t or its stream are
+ * now invalid, be careful of dangling pointers.
+ */
+
+void
+mongoc_cluster_disconnect_node (mongoc_cluster_t *cluster, uint32_t server_id)
+{
+ mongoc_topology_t *topology = cluster->client->topology;
+
+ ENTRY;
+
+ if (topology->single_threaded) {
+ mongoc_topology_scanner_node_t *scanner_node;
+
+ scanner_node =
+ mongoc_topology_scanner_get_node (topology->scanner, server_id);
+
+ /* might never actually have connected */
+ if (scanner_node && scanner_node->stream) {
+ mongoc_topology_scanner_node_disconnect (scanner_node, true);
+ }
+ } else {
+ mongoc_set_rm (cluster->nodes, server_id);
+ }
+
+ EXIT;
+}
+
+static void
+_mongoc_cluster_node_destroy (mongoc_cluster_node_t *node)
+{
+ /* Failure, or Replica Set reconfigure without this node */
+ mongoc_stream_failed (node->stream);
+ bson_free (node->connection_address);
+ mongoc_server_description_destroy (node->handshake_sd);
+
+ bson_free (node);
+}
+
+static void
+_mongoc_cluster_node_dtor (void *data_, void *ctx_)
+{
+ mongoc_cluster_node_t *node = (mongoc_cluster_node_t *) data_;
+
+ _mongoc_cluster_node_destroy (node);
+}
+
+static mongoc_cluster_node_t *
+_mongoc_cluster_node_new (mongoc_stream_t *stream,
+ const char *connection_address)
+{
+ mongoc_cluster_node_t *node;
+
+ if (!stream) {
+ return NULL;
+ }
+
+ node = (mongoc_cluster_node_t *) bson_malloc0 (sizeof *node);
+
+ node->stream = stream;
+ node->connection_address = bson_strdup (connection_address);
+
+ return node;
+}
+
+static bool
+_mongoc_cluster_finish_speculative_auth (
+ mongoc_cluster_t *cluster,
+ mongoc_stream_t *stream,
+ mongoc_server_description_t *handshake_sd,
+ bson_t *speculative_auth_response,
+ mongoc_scram_t *scram,
+ bson_error_t *error)
+{
+ const char *mechanism =
+ _mongoc_topology_scanner_get_speculative_auth_mechanism (cluster->uri);
+ bool ret = false;
+ bool auth_handled = false;
+
+ BSON_ASSERT (handshake_sd);
+ BSON_ASSERT (speculative_auth_response);
+
+ if (!mechanism) {
+ return false;
+ }
+
+ if (bson_empty (speculative_auth_response)) {
+ return false;
+ }
+
+#ifdef MONGOC_ENABLE_SSL
+ if (strcasecmp (mechanism, "MONGODB-X509") == 0) {
+ /* For X509, a successful hello with speculativeAuthenticate field
+ * indicates successful auth */
+ ret = true;
+ auth_handled = true;
+ }
+#endif
+
+#ifdef MONGOC_ENABLE_CRYPTO
+ if (strcasecmp (mechanism, "SCRAM-SHA-1") == 0 ||
+ strcasecmp (mechanism, "SCRAM-SHA-256") == 0) {
+ /* Don't attempt authentication if scram objects have advanced past
+ * saslStart */
+ if (scram->step != 1) {
+ return false;
+ }
+
+ auth_handled = true;
+
+ ret = _mongoc_cluster_auth_scram_continue (cluster,
+ stream,
+ handshake_sd,
+ scram,
+ speculative_auth_response,
+ error);
+ }
+#endif
+
+ if (auth_handled) {
+ if (!ret) {
+ mongoc_counter_auth_failure_inc ();
+ MONGOC_DEBUG ("Speculative authentication failed: %s", error->message);
+ } else {
+ mongoc_counter_auth_success_inc ();
+ TRACE ("%s", "Speculative authentication succeeded");
+ }
+ }
+
+ bson_reinit (speculative_auth_response);
+
+ return ret;
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_cluster_add_node --
+ *
+ * Add a new node to this cluster for the given server description.
+ *
+ * NOTE: does NOT check if this server is already in the cluster.
+ *
+ * Returns:
+ * A stream connected to the server, or NULL on failure.
+ *
+ * Side effects:
+ * Adds a cluster node, or sets error on failure.
+ *
+ *--------------------------------------------------------------------------
+ */
+static mongoc_cluster_node_t *
+_cluster_add_node (mongoc_cluster_t *cluster,
+ const mongoc_topology_description_t *td,
+ uint32_t server_id,
+ bson_error_t *error /* OUT */)
+{
+ mongoc_host_list_t *host = NULL;
+ mongoc_cluster_node_t *cluster_node = NULL;
+ mongoc_stream_t *stream;
+ mongoc_server_description_t *handshake_sd;
+ mongoc_handshake_sasl_supported_mechs_t sasl_supported_mechs;
+ mongoc_scram_t scram = {0};
+ bson_t speculative_auth_response = BSON_INITIALIZER;
+
+ ENTRY;
+
+ BSON_ASSERT (!cluster->client->topology->single_threaded);
+
+ host = _mongoc_topology_host_by_id (td, server_id, error);
+
+ if (!host) {
+ GOTO (error);
+ }
+
+ TRACE ("Adding new server to cluster: %s", host->host_and_port);
+
+ stream = _mongoc_client_create_stream (cluster->client, host, error);
+
+ if (!stream) {
+ MONGOC_WARNING (
+ "Failed connection to %s (%s)", host->host_and_port, error->message);
+ GOTO (error);
+ /* TODO CDRIVER-3654: if this is a non-timeout network error and the
+ * generation is not stale, mark the server unknown and increment the
+ * generation. */
+ }
+
+ /* take critical fields from a fresh hello */
+ cluster_node = _mongoc_cluster_node_new (stream, host->host_and_port);
+
+ handshake_sd = _cluster_run_hello (cluster,
+ cluster_node,
+ server_id,
+ cluster->scram_cache,
+ &scram,
+ &speculative_auth_response,
+ error);
+ if (!handshake_sd) {
+ GOTO (error);
+ }
+
+ _mongoc_handshake_parse_sasl_supported_mechs (
+ &handshake_sd->last_hello_response, &sasl_supported_mechs);
+
+ if (cluster->requires_auth) {
+ /* Complete speculative authentication */
+ bool is_auth =
+ _mongoc_cluster_finish_speculative_auth (cluster,
+ stream,
+ handshake_sd,
+ &speculative_auth_response,
+ &scram,
+ error);
+
+ if (!is_auth && !_mongoc_cluster_auth_node (cluster,
+ cluster_node->stream,
+ handshake_sd,
+ &sasl_supported_mechs,
+ error)) {
+ MONGOC_WARNING ("Failed authentication to %s (%s)",
+ host->host_and_port,
+ error->message);
+ mongoc_server_description_destroy (handshake_sd);
+ GOTO (error);
+ }
+ }
+
+ /* Transfer ownership of the server description into the cluster node. */
+ cluster_node->handshake_sd = handshake_sd;
+ /* Copy the latest connection pool generation.
+ * TODO (CDRIVER-4078) do not store the generation counter on the server
+ * description */
+ handshake_sd->generation = _mongoc_topology_get_connection_pool_generation (
+ td, server_id, &handshake_sd->service_id);
+
+ bson_destroy (&speculative_auth_response);
+ mongoc_set_add (cluster->nodes, server_id, cluster_node);
+ _mongoc_host_list_destroy_all (host);
+
+#ifdef MONGOC_ENABLE_CRYPTO
+ _mongoc_scram_destroy (&scram);
+#endif
+
+ RETURN (cluster_node);
+
+error:
+ bson_destroy (&speculative_auth_response);
+ _mongoc_host_list_destroy_all (host); /* null ok */
+
+#ifdef MONGOC_ENABLE_CRYPTO
+ _mongoc_scram_destroy (&scram);
+#endif
+
+ if (cluster_node) {
+ _mongoc_cluster_node_destroy (cluster_node); /* also destroys stream */
+ }
+
+ RETURN (NULL);
+}
+
+static void
+node_not_found (const mongoc_topology_description_t *td,
+ uint32_t server_id,
+ bson_error_t *error /* OUT */)
+{
+ mongoc_server_description_t const *sd;
+
+ if (!error) {
+ return;
+ }
+
+ sd = mongoc_topology_description_server_by_id_const (td, server_id, error);
+
+ if (!sd) {
+ return;
+ }
+
+ if (sd->error.code) {
+ memcpy (error, &sd->error, sizeof *error);
+ } else {
+ bson_set_error (error,
+ MONGOC_ERROR_STREAM,
+ MONGOC_ERROR_STREAM_NOT_ESTABLISHED,
+ "Could not find node %s",
+ sd->host.host_and_port);
+ }
+}
+
+
+static void
+stream_not_found (const mongoc_topology_description_t *td,
+ uint32_t server_id,
+ const char *connection_address,
+ bson_error_t *error /* OUT */)
+{
+ mongoc_server_description_t const *sd;
+
+ sd = mongoc_topology_description_server_by_id_const (td, server_id, error);
+
+ if (error) {
+ if (sd && sd->error.code) {
+ memcpy (error, &sd->error, sizeof *error);
+ } else {
+ bson_set_error (error,
+ MONGOC_ERROR_STREAM,
+ MONGOC_ERROR_STREAM_NOT_ESTABLISHED,
+ "Could not find stream for node %s",
+ connection_address);
+ }
+ }
+}
+
+static mongoc_server_stream_t *
+_try_get_server_stream (mongoc_cluster_t *cluster,
+ const mongoc_topology_description_t *td,
+ uint32_t server_id,
+ bool reconnect_ok,
+ bson_error_t *error)
+{
+ if (cluster->client->topology->single_threaded) {
+ /* in the single-threaded use case we share topology's streams */
+ return _cluster_fetch_stream_single (
+ cluster, td, server_id, reconnect_ok, error);
+ } else {
+ return _cluster_fetch_stream_pooled (
+ cluster, td, server_id, reconnect_ok, error);
+ }
+}
+
+mongoc_server_stream_t *
+_mongoc_cluster_stream_for_server (mongoc_cluster_t *cluster,
+ uint32_t server_id,
+ bool reconnect_ok,
+ const mongoc_client_session_t *cs,
+ bson_t *reply,
+ bson_error_t *error /* OUT */)
+{
+ mongoc_topology_t *const topology =
+ BSON_ASSERT_PTR_INLINE (cluster)->client->topology;
+ mongoc_server_stream_t *ret_server_stream;
+ bson_error_t err_local;
+ /* if fetch_stream fails we need a place to receive error details and pass
+ * them to mongoc_topology_description_invalidate_server. */
+ bson_error_t *err_ptr = error ? error : &err_local;
+ mc_tpld_modification tdmod;
+ mc_shared_tpld td;
+
+ ENTRY;
+
+ td = mc_tpld_take_ref (topology);
+
+ ret_server_stream = _try_get_server_stream (
+ cluster, td.ptr, server_id, reconnect_ok, err_ptr);
+
+ if (!ret_server_stream) {
+ /* TODO CDRIVER-3654. A null server stream could be due to:
+ * 1. Network error during handshake.
+ * 2. Failure to retrieve server description (if it was removed from
+ * topology).
+ * 3. Auth error during handshake.
+ * Only (1) should mark the server unknown and clear the pool.
+ * Network errors should be checked at a lower layer than this, when an
+ * operation on a stream fails, and should take the connection generation
+ * into account.
+ */
+
+ /* Update the topology */
+ tdmod = mc_tpld_modify_begin (topology);
+
+ /* Add a transient transaction label if applicable. */
+ _mongoc_bson_init_with_transient_txn_error (cs, reply);
+
+ /* When establishing a new connection in load balanced mode, drivers MUST
+ * NOT perform SDAM error handling for any errors that occur before the
+ * MongoDB Handshake. */
+ if (tdmod.new_td->type == MONGOC_TOPOLOGY_LOAD_BALANCED) {
+ mc_tpld_modify_drop (tdmod);
+ ret_server_stream = NULL;
+ goto done;
+ }
+
+ mongoc_topology_description_invalidate_server (
+ tdmod.new_td, server_id, err_ptr);
+ mongoc_cluster_disconnect_node (cluster, server_id);
+ /* This is not load balanced mode, so there are no service IDs associated
+ * with connections. Pass kZeroServiceId to clear the entire connection
+ * pool to this server. */
+ _mongoc_topology_description_clear_connection_pool (
+ tdmod.new_td, server_id, &kZeroServiceId);
+
+ if (!topology->single_threaded) {
+ _mongoc_topology_background_monitoring_cancel_check (topology,
+ server_id);
+ }
+ mc_tpld_modify_commit (tdmod);
+ ret_server_stream = NULL;
+ goto done;
+ }
+
+ /* If this is a load balanced topology and the server stream does not have a
+ * service id, disconnect and return an error. */
+ if (td.ptr->type == MONGOC_TOPOLOGY_LOAD_BALANCED) {
+ if (!mongoc_server_description_has_service_id (ret_server_stream->sd)) {
+ bson_set_error (error,
+ MONGOC_ERROR_CLIENT,
+ MONGOC_ERROR_CLIENT_INVALID_LOAD_BALANCER,
+ "Driver attempted to initialize in load balancing "
+ "mode, but the server does not support this mode.");
+ mongoc_server_stream_cleanup (ret_server_stream);
+ mongoc_cluster_disconnect_node (cluster, server_id);
+ _mongoc_bson_init_if_set (reply);
+ ret_server_stream = NULL;
+ goto done;
+ }
+ }
+
+done:
+ mc_tpld_drop_ref (&td);
+ RETURN (ret_server_stream);
+}
+
+
+mongoc_server_stream_t *
+mongoc_cluster_stream_for_server (mongoc_cluster_t *cluster,
+ uint32_t server_id,
+ bool reconnect_ok,
+ mongoc_client_session_t *cs,
+ bson_t *reply,
+ bson_error_t *error)
+{
+ mongoc_server_stream_t *server_stream = NULL;
+ bson_error_t err_local = {0};
+
+ ENTRY;
+
+ BSON_ASSERT (cluster);
+
+ if (cs && cs->server_id && cs->server_id != server_id) {
+ _mongoc_bson_init_if_set (reply);
+ bson_set_error (error,
+ MONGOC_ERROR_COMMAND,
+ MONGOC_ERROR_SERVER_SELECTION_INVALID_ID,
+ "Requested server id does not matched pinned server id");
+ RETURN (NULL);
+ }
+
+ if (!error) {
+ error = &err_local;
+ }
+
+ server_stream = _mongoc_cluster_stream_for_server (
+ cluster, server_id, reconnect_ok, cs, reply, error);
+
+
+ if (_in_sharded_txn (cs)) {
+ _mongoc_client_session_pin (cs, server_id);
+ } else {
+ /* Transactions Spec: Additionally, any non-transaction operation using
+ * a pinned ClientSession MUST unpin the session and the operation MUST
+ * perform normal server selection. */
+ if (cs && !_mongoc_client_session_in_txn_or_ending (cs)) {
+ _mongoc_client_session_unpin (cs);
+ }
+ }
+
+ RETURN (server_stream);
+}
+
+
+static mongoc_server_stream_t *
+_cluster_fetch_stream_single (mongoc_cluster_t *cluster,
+ const mongoc_topology_description_t *td,
+ uint32_t server_id,
+ bool reconnect_ok,
+ bson_error_t *error /* OUT */)
+{
+ mongoc_server_description_t *handshake_sd;
+ mongoc_topology_scanner_node_t *scanner_node;
+ char *address;
+
+ scanner_node = mongoc_topology_scanner_get_node (
+ cluster->client->topology->scanner, server_id);
+ /* This could happen if a user explicitly passes a bad server id. */
+ if (!scanner_node) {
+ bson_set_error (error,
+ MONGOC_ERROR_COMMAND,
+ MONGOC_ERROR_COMMAND_INVALID_ARG,
+ "Could not find server with id: %d",
+ server_id);
+ return NULL;
+ }
+
+ /* Retired scanner nodes are removed at the end of a scan. If the node was
+ * retired, that would indicate a bug. */
+ if (scanner_node->retired) {
+ bson_set_error (error,
+ MONGOC_ERROR_COMMAND,
+ MONGOC_ERROR_COMMAND_INVALID_ARG,
+ "Unexpected, selecting server marked for removal: %s",
+ scanner_node->host.host_and_port);
+ return NULL;
+ }
+
+ if (scanner_node->stream) {
+ handshake_sd =
+ mongoc_server_description_new_copy (scanner_node->handshake_sd);
+ } else {
+ if (!reconnect_ok) {
+ stream_not_found (
+ td, server_id, scanner_node->host.host_and_port, error);
+ return NULL;
+ }
+
+ /* save the scanner node address in case it is removed during the scan. */
+ address = bson_strdup (scanner_node->host.host_and_port);
+ _mongoc_topology_do_blocking_scan (cluster->client->topology, error);
+ if (error->code) {
+ bson_free (address);
+ return NULL;
+ }
+
+ scanner_node = mongoc_topology_scanner_get_node (
+ cluster->client->topology->scanner, server_id);
+
+ if (!scanner_node || !scanner_node->stream) {
+ stream_not_found (td, server_id, address, error);
+ bson_free (address);
+ return NULL;
+ }
+ bson_free (address);
+
+ handshake_sd =
+ mongoc_server_description_new_copy (scanner_node->handshake_sd);
+ }
+
+ if (handshake_sd->type == MONGOC_SERVER_UNKNOWN) {
+ *error = handshake_sd->error;
+ mongoc_server_description_destroy (handshake_sd);
+ return NULL;
+ }
+
+ /* stream open but not auth'ed: first use since connect or reconnect */
+ if (cluster->requires_auth && !scanner_node->has_auth) {
+ /* Complete speculative authentication */
+ bool has_speculative_auth = _mongoc_cluster_finish_speculative_auth (
+ cluster,
+ scanner_node->stream,
+ handshake_sd,
+ &scanner_node->speculative_auth_response,
+ &scanner_node->scram,
+ &handshake_sd->error);
+
+#ifdef MONGOC_ENABLE_CRYPTO
+ _mongoc_scram_destroy (&scanner_node->scram);
+#endif
+
+ if (!scanner_node->stream) {
+ *error = handshake_sd->error;
+ mongoc_server_description_destroy (handshake_sd);
+ return NULL;
+ }
+
+ if (!has_speculative_auth &&
+ !_mongoc_cluster_auth_node (cluster,
+ scanner_node->stream,
+ handshake_sd,
+ &scanner_node->sasl_supported_mechs,
+ &handshake_sd->error)) {
+ *error = handshake_sd->error;
+ mongoc_server_description_destroy (handshake_sd);
+ return NULL;
+ }
+
+ scanner_node->has_auth = true;
+ }
+
+ /* Copy the latest connection pool generation.
+ * TODO (CDRIVER-4078) do not store the generation counter on the server
+ * description */
+ handshake_sd->generation = _mongoc_topology_get_connection_pool_generation (
+ td, server_id, &handshake_sd->service_id);
+ return mongoc_server_stream_new (td, handshake_sd, scanner_node->stream);
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_cluster_stream_valid --
+ *
+ * Internal function to determine if @server_stream is valid and
+ * associated with the given cluster.
+ *
+ * Returns:
+ * true if @server_stream is not NULL, hasn't been freed or changed;
+ * otherwise false.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+bool
+mongoc_cluster_stream_valid (mongoc_cluster_t *cluster,
+ mongoc_server_stream_t *server_stream)
+{
+ mongoc_server_stream_t *tmp_stream = NULL;
+ mongoc_topology_t *topology =
+ BSON_ASSERT_PTR_INLINE (cluster)->client->topology;
+ const mongoc_server_description_t *sd;
+ bool ret = false;
+ bson_error_t error;
+ mc_shared_tpld td = mc_tpld_take_ref (topology);
+
+ if (!server_stream) {
+ goto done;
+ }
+
+ tmp_stream = mongoc_cluster_stream_for_server (
+ cluster, server_stream->sd->id, false, NULL, NULL, NULL);
+ if (!tmp_stream || tmp_stream->stream != server_stream->stream) {
+ /* stream was freed, or has changed. */
+ goto done;
+ }
+
+ /* Check that the server stream is still valid for the given server, and that
+ * the server is still registered. */
+ sd = mongoc_topology_description_server_by_id_const (
+ td.ptr, server_stream->sd->id, &error);
+ if (!sd ||
+ server_stream->sd->generation <
+ _mongoc_topology_get_connection_pool_generation (
+ td.ptr, server_stream->sd->id, &server_stream->sd->service_id)) {
+ /* No server description, or the pool has been cleared. */
+ goto done;
+ }
+
+ ret = true;
+done:
+ mc_tpld_drop_ref (&td);
+ mongoc_server_stream_cleanup (tmp_stream);
+ return ret;
+}
+
+mongoc_server_stream_t *
+_mongoc_cluster_create_server_stream (
+ mongoc_topology_description_t const *td,
+ const mongoc_server_description_t *handshake_sd,
+ mongoc_stream_t *stream)
+{
+ mongoc_server_description_t *const sd =
+ mongoc_server_description_new_copy (handshake_sd);
+ /* can't just use mongoc_topology_server_by_id(), since we must hold the
+ * lock while copying topology->shared_descr.ptr->logical_time below */
+ return mongoc_server_stream_new (td, sd, stream);
+}
+
+
+static mongoc_server_stream_t *
+_cluster_fetch_stream_pooled (mongoc_cluster_t *cluster,
+ const mongoc_topology_description_t *td,
+ uint32_t server_id,
+ bool reconnect_ok,
+ bson_error_t *error /* OUT */)
+{
+ mongoc_cluster_node_t *cluster_node;
+ mongoc_server_description_t const *sd;
+ bool has_server_description = false;
+
+ cluster_node =
+ (mongoc_cluster_node_t *) mongoc_set_get (cluster->nodes, server_id);
+
+ sd = mongoc_topology_description_server_by_id_const (td, server_id, error);
+ if (sd) {
+ has_server_description = true;
+ }
+
+ if (cluster_node) {
+ uint32_t connection_pool_generation = 0;
+ BSON_ASSERT (cluster_node->stream);
+
+ connection_pool_generation =
+ _mongoc_topology_get_connection_pool_generation (
+ td, server_id, &cluster_node->handshake_sd->service_id);
+
+ if (!has_server_description ||
+ cluster_node->handshake_sd->generation < connection_pool_generation) {
+ /* Since the stream was created, connections to this server were
+ * invalidated.
+ * This may have happened if:
+ * - A background scan removed the server description.
+ * - A network error or a "not primary"/"node is recovering" error
+ * occurred on an app connection.
+ * - A network error occurred on the monitor connection.
+ */
+ mongoc_cluster_disconnect_node (cluster, server_id);
+ } else {
+ return _mongoc_cluster_create_server_stream (
+ td, cluster_node->handshake_sd, cluster_node->stream);
+ }
+ }
+
+ /* no node, or out of date */
+ if (!reconnect_ok) {
+ node_not_found (td, server_id, error);
+ return NULL;
+ }
+
+ cluster_node = _cluster_add_node (cluster, td, server_id, error);
+ if (cluster_node) {
+ return _mongoc_cluster_create_server_stream (
+ td, cluster_node->handshake_sd, cluster_node->stream);
+ } else {
+ return NULL;
+ }
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_cluster_init --
+ *
+ * Initializes @cluster using the @uri and @client provided. The
+ * @uri is used to determine the "mode" of the cluster. Based on the
+ * uri we can determine if we are connected to a single host, a
+ * replicaSet, or a shardedCluster.
+ *
+ * Returns:
+ * None.
+ *
+ * Side effects:
+ * @cluster is initialized.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+void
+mongoc_cluster_init (mongoc_cluster_t *cluster,
+ const mongoc_uri_t *uri,
+ void *client)
+{
+ ENTRY;
+
+ BSON_ASSERT (cluster);
+ BSON_ASSERT (uri);
+
+ memset (cluster, 0, sizeof *cluster);
+
+ cluster->uri = mongoc_uri_copy (uri);
+ cluster->client = (mongoc_client_t *) client;
+ cluster->requires_auth =
+ (mongoc_uri_get_username (uri) || mongoc_uri_get_auth_mechanism (uri));
+
+ cluster->sockettimeoutms = mongoc_uri_get_option_as_int32 (
+ uri, MONGOC_URI_SOCKETTIMEOUTMS, MONGOC_DEFAULT_SOCKETTIMEOUTMS);
+
+ cluster->socketcheckintervalms =
+ mongoc_uri_get_option_as_int32 (uri,
+ MONGOC_URI_SOCKETCHECKINTERVALMS,
+ MONGOC_TOPOLOGY_SOCKET_CHECK_INTERVAL_MS);
+
+ /* TODO for single-threaded case we don't need this */
+ cluster->nodes = mongoc_set_new (8, _mongoc_cluster_node_dtor, NULL);
+
+ _mongoc_array_init (&cluster->iov, sizeof (mongoc_iovec_t));
+
+ cluster->operation_id = rand ();
+
+ EXIT;
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_cluster_destroy --
+ *
+ * Clean up after @cluster and destroy all active connections.
+ * All resources for @cluster are released.
+ *
+ * Returns:
+ * None.
+ *
+ * Side effects:
+ * Everything.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+void
+mongoc_cluster_destroy (mongoc_cluster_t *cluster) /* INOUT */
+{
+ ENTRY;
+
+ BSON_ASSERT (cluster);
+
+ mongoc_uri_destroy (cluster->uri);
+
+ mongoc_set_destroy (cluster->nodes);
+
+ _mongoc_array_destroy (&cluster->iov);
+
+#ifdef MONGOC_ENABLE_CRYPTO
+ if (cluster->scram_cache) {
+ _mongoc_scram_cache_destroy (cluster->scram_cache);
+ }
+#endif
+
+ EXIT;
+}
+
+static uint32_t
+_mongoc_cluster_select_server_id (mongoc_client_session_t *cs,
+ mongoc_topology_t *topology,
+ mongoc_ss_optype_t optype,
+ const mongoc_read_prefs_t *read_prefs,
+ bool *must_use_primary,
+ bson_error_t *error)
+{
+ uint32_t server_id;
+
+ if (_in_sharded_txn (cs)) {
+ server_id = cs->server_id;
+ if (!server_id) {
+ server_id = mongoc_topology_select_server_id (
+ topology, optype, read_prefs, must_use_primary, error);
+ if (server_id) {
+ _mongoc_client_session_pin (cs, server_id);
+ }
+ }
+ } else {
+ server_id = mongoc_topology_select_server_id (
+ topology, optype, read_prefs, must_use_primary, error);
+ /* Transactions Spec: Additionally, any non-transaction operation using a
+ * pinned ClientSession MUST unpin the session and the operation MUST
+ * perform normal server selection. */
+ if (cs && !_mongoc_client_session_in_txn_or_ending (cs)) {
+ _mongoc_client_session_unpin (cs);
+ }
+ }
+
+ return server_id;
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_cluster_stream_for_optype --
+ *
+ * Internal server selection.
+ *
+ * Returns:
+ * A mongoc_server_stream_t on which you must call
+ * mongoc_server_stream_cleanup, or NULL on failure (sets @error)
+ *
+ * Side effects:
+ * May add or disconnect nodes in @cluster->nodes.
+ * Sets @error and initializes @reply on error.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+static mongoc_server_stream_t *
+_mongoc_cluster_stream_for_optype (mongoc_cluster_t *cluster,
+ mongoc_ss_optype_t optype,
+ const mongoc_read_prefs_t *read_prefs,
+ mongoc_client_session_t *cs,
+ bson_t *reply,
+ bson_error_t *error)
+{
+ mongoc_server_stream_t *server_stream;
+ uint32_t server_id;
+ mongoc_topology_t *topology = cluster->client->topology;
+ bool must_use_primary = false;
+
+ ENTRY;
+
+ BSON_ASSERT (cluster);
+
+ server_id = _mongoc_cluster_select_server_id (
+ cs, topology, optype, read_prefs, &must_use_primary, error);
+
+ if (!server_id) {
+ _mongoc_bson_init_with_transient_txn_error (cs, reply);
+ RETURN (NULL);
+ }
+
+ if (!mongoc_cluster_check_interval (cluster, server_id)) {
+ /* Server Selection Spec: try once more */
+ server_id = _mongoc_cluster_select_server_id (
+ cs, topology, optype, read_prefs, &must_use_primary, error);
+
+ if (!server_id) {
+ _mongoc_bson_init_with_transient_txn_error (cs, reply);
+ RETURN (NULL);
+ }
+ }
+
+ /* connect or reconnect to server if necessary */
+ server_stream = _mongoc_cluster_stream_for_server (
+ cluster, server_id, true /* reconnect_ok */, cs, reply, error);
+ if (server_stream) {
+ server_stream->must_use_primary = must_use_primary;
+ }
+
+ RETURN (server_stream);
+}
+
+mongoc_server_stream_t *
+mongoc_cluster_stream_for_reads (mongoc_cluster_t *cluster,
+ const mongoc_read_prefs_t *read_prefs,
+ mongoc_client_session_t *cs,
+ bson_t *reply,
+ bool has_write_stage,
+ bson_error_t *error)
+{
+ const mongoc_read_prefs_t *prefs_override = read_prefs;
+
+ if (_mongoc_client_session_in_txn (cs)) {
+ prefs_override = cs->txn.opts.read_prefs;
+ }
+
+ return _mongoc_cluster_stream_for_optype (
+ cluster,
+ /* Narrow down the optype if this is an aggregate op with a write stage */
+ has_write_stage ? MONGOC_SS_AGGREGATE_WITH_WRITE : MONGOC_SS_READ,
+ prefs_override,
+ cs,
+ reply,
+ error);
+}
+
+mongoc_server_stream_t *
+mongoc_cluster_stream_for_writes (mongoc_cluster_t *cluster,
+ mongoc_client_session_t *cs,
+ bson_t *reply,
+ bson_error_t *error)
+{
+ return _mongoc_cluster_stream_for_optype (
+ cluster, MONGOC_SS_WRITE, NULL, cs, reply, error);
+}
+
+static bool
+_mongoc_cluster_min_of_max_obj_size_sds (const void *item, void *ctx)
+{
+ const mongoc_server_description_t *sd = item;
+ int32_t *current_min = (int32_t *) ctx;
+
+ if (sd->max_bson_obj_size < *current_min) {
+ *current_min = sd->max_bson_obj_size;
+ }
+ return true;
+}
+
+static bool
+_mongoc_cluster_min_of_max_obj_size_nodes (void *item, void *ctx)
+{
+ mongoc_cluster_node_t *node = (mongoc_cluster_node_t *) item;
+ int32_t *current_min = (int32_t *) ctx;
+
+ if (node->handshake_sd->max_bson_obj_size < *current_min) {
+ *current_min = node->handshake_sd->max_bson_obj_size;
+ }
+ return true;
+}
+
+static bool
+_mongoc_cluster_min_of_max_msg_size_sds (const void *item, void *ctx)
+{
+ const mongoc_server_description_t *sd = item;
+ int32_t *current_min = (int32_t *) ctx;
+
+ if (sd->max_msg_size < *current_min) {
+ *current_min = sd->max_msg_size;
+ }
+ return true;
+}
+
+static bool
+_mongoc_cluster_min_of_max_msg_size_nodes (void *item, void *ctx)
+{
+ mongoc_cluster_node_t *node = (mongoc_cluster_node_t *) item;
+ int32_t *current_min = (int32_t *) ctx;
+
+ if (node->handshake_sd->max_msg_size < *current_min) {
+ *current_min = node->handshake_sd->max_msg_size;
+ }
+ return true;
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_cluster_get_max_bson_obj_size --
+ *
+ * Return the minimum max_bson_obj_size across all servers in cluster.
+ *
+ * Returns:
+ * The minimum max_bson_obj_size.
+ *
+ * Side effects:
+ * None
+ *
+ *--------------------------------------------------------------------------
+ */
+int32_t
+mongoc_cluster_get_max_bson_obj_size (mongoc_cluster_t *cluster)
+{
+ int32_t max_bson_obj_size = -1;
+
+ max_bson_obj_size = MONGOC_DEFAULT_BSON_OBJ_SIZE;
+
+ if (!cluster->client->topology->single_threaded) {
+ mongoc_set_for_each (cluster->nodes,
+ _mongoc_cluster_min_of_max_obj_size_nodes,
+ &max_bson_obj_size);
+ } else {
+ mc_shared_tpld td =
+ mc_tpld_take_ref (BSON_ASSERT_PTR_INLINE (cluster)->client->topology);
+ mongoc_set_for_each_const (mc_tpld_servers_const (td.ptr),
+ _mongoc_cluster_min_of_max_obj_size_sds,
+ &max_bson_obj_size);
+ mc_tpld_drop_ref (&td);
+ }
+
+ return max_bson_obj_size;
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_cluster_get_max_msg_size --
+ *
+ * Return the minimum max msg size across all servers in cluster.
+ *
+ * Returns:
+ * The minimum max_msg_size
+ *
+ * Side effects:
+ * None
+ *
+ *--------------------------------------------------------------------------
+ */
+int32_t
+mongoc_cluster_get_max_msg_size (mongoc_cluster_t *cluster)
+{
+ int32_t max_msg_size = MONGOC_DEFAULT_MAX_MSG_SIZE;
+
+ if (!cluster->client->topology->single_threaded) {
+ mongoc_set_for_each (cluster->nodes,
+ _mongoc_cluster_min_of_max_msg_size_nodes,
+ &max_msg_size);
+ } else {
+ mc_shared_tpld td =
+ mc_tpld_take_ref (BSON_ASSERT_PTR_INLINE (cluster)->client->topology);
+ mongoc_set_for_each_const (mc_tpld_servers_const (td.ptr),
+ _mongoc_cluster_min_of_max_msg_size_sds,
+ &max_msg_size);
+ mc_tpld_drop_ref (&td);
+ }
+
+ return max_msg_size;
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_cluster_check_interval --
+ *
+ * Server Selection Spec:
+ *
+ * Only for single-threaded drivers.
+ *
+ * If a server is selected that has an existing connection that has been
+ * idle for socketCheckIntervalMS, the driver MUST check the connection
+ * with the "ping" command. If the ping succeeds, use the selected
+ * connection. If not, set the server's type to Unknown and update the
+ * Topology Description according to the Server Discovery and Monitoring
+ * Spec, and attempt once more to select a server.
+ *
+ * Returns:
+ * True if the check succeeded or no check was required, false if the
+ * check failed.
+ *
+ * Side effects:
+ * If a check fails, closes stream and may set server type Unknown.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+bool
+mongoc_cluster_check_interval (mongoc_cluster_t *cluster, uint32_t server_id)
+{
+ mongoc_cmd_parts_t parts;
+ mongoc_topology_t *topology;
+ mongoc_topology_scanner_node_t *scanner_node;
+ mongoc_stream_t *stream;
+ int64_t now;
+ bson_t command;
+ bson_error_t error;
+ bool r = true;
+ mongoc_server_stream_t *server_stream;
+ mongoc_server_description_t *handshake_sd;
+
+ topology = cluster->client->topology;
+
+ if (!topology->single_threaded) {
+ return true;
+ }
+
+ scanner_node =
+ mongoc_topology_scanner_get_node (topology->scanner, server_id);
+
+ if (!scanner_node) {
+ return false;
+ }
+
+ BSON_ASSERT (!scanner_node->retired);
+
+ stream = scanner_node->stream;
+
+ if (!stream) {
+ return false;
+ }
+
+ handshake_sd = scanner_node->handshake_sd;
+ BSON_ASSERT (handshake_sd);
+
+ now = bson_get_monotonic_time ();
+
+ if (scanner_node->last_used + (1000 * CHECK_CLOSED_DURATION_MSEC) < now) {
+ if (mongoc_stream_check_closed (stream)) {
+ mc_tpld_modification tdmod;
+ bson_set_error (&error,
+ MONGOC_ERROR_STREAM,
+ MONGOC_ERROR_STREAM_SOCKET,
+ "connection closed");
+ mongoc_cluster_disconnect_node (cluster, server_id);
+ tdmod = mc_tpld_modify_begin (topology);
+ /* invalidate_server() is okay if 'server_id' was already removed. */
+ mongoc_topology_description_invalidate_server (
+ tdmod.new_td, server_id, &error);
+ mc_tpld_modify_commit (tdmod);
+ return false;
+ }
+ }
+
+ if (scanner_node->last_used + (1000 * cluster->socketcheckintervalms) <
+ now) {
+ mc_shared_tpld td;
+
+ bson_init (&command);
+ BSON_APPEND_INT32 (&command, "ping", 1);
+ mongoc_cmd_parts_init (
+ &parts, cluster->client, "admin", MONGOC_QUERY_SECONDARY_OK, &command);
+ parts.prohibit_lsid = true;
+
+ td = mc_tpld_take_ref (cluster->client->topology);
+ server_stream =
+ _mongoc_cluster_create_server_stream (td.ptr, handshake_sd, stream);
+ mc_tpld_drop_ref (&td);
+
+ if (!server_stream) {
+ bson_destroy (&command);
+ return false;
+ }
+ r = mongoc_cluster_run_command_parts (
+ cluster, server_stream, &parts, NULL, &error);
+
+ mongoc_server_stream_cleanup (server_stream);
+ bson_destroy (&command);
+
+ if (!r) {
+ mc_tpld_modification tdmod;
+ mongoc_cluster_disconnect_node (cluster, server_id);
+ tdmod = mc_tpld_modify_begin (cluster->client->topology);
+ /* invalidate_server() is okay if 'server_id' was already removed. */
+ mongoc_topology_description_invalidate_server (
+ tdmod.new_td, server_id, &error);
+ mc_tpld_modify_commit (tdmod);
+ }
+ }
+
+ return r;
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_cluster_legacy_rpc_sendv_to_server --
+ *
+ * Sends the given RPCs to the given server. Used for OP_QUERY cursors,
+ * OP_KILLCURSORS, and legacy writes with OP_INSERT, OP_UPDATE, and
+ * OP_DELETE. This function is *not* in the OP_QUERY command path.
+ *
+ * Returns:
+ * True if successful.
+ *
+ * Side effects:
+ * @rpc may be mutated and should be considered invalid after calling
+ * this method.
+ *
+ * @error may be set.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+bool
+mongoc_cluster_legacy_rpc_sendv_to_server (
+ mongoc_cluster_t *cluster,
+ mongoc_rpc_t *rpc,
+ mongoc_server_stream_t *server_stream,
+ bson_error_t *error)
+{
+ uint32_t server_id;
+ int32_t max_msg_size;
+ bool ret = false;
+ int32_t compressor_id = 0;
+ char *output = NULL;
+
+ ENTRY;
+
+ BSON_ASSERT (cluster);
+ BSON_ASSERT (rpc);
+ BSON_ASSERT (server_stream);
+
+ server_id = server_stream->sd->id;
+
+ if (cluster->client->in_exhaust) {
+ bson_set_error (error,
+ MONGOC_ERROR_CLIENT,
+ MONGOC_ERROR_CLIENT_IN_EXHAUST,
+ "A cursor derived from this client is in exhaust.");
+ GOTO (done);
+ }
+
+ _mongoc_array_clear (&cluster->iov);
+ compressor_id = mongoc_server_description_compressor_id (server_stream->sd);
+
+ _mongoc_rpc_gather (rpc, &cluster->iov);
+ _mongoc_rpc_swab_to_le (rpc);
+
+ if (compressor_id != -1) {
+ output = _mongoc_rpc_compress (cluster, compressor_id, rpc, error);
+ if (output == NULL) {
+ GOTO (done);
+ }
+ }
+
+ max_msg_size = mongoc_server_stream_max_msg_size (server_stream);
+
+ if (BSON_UINT32_FROM_LE (rpc->header.msg_len) > max_msg_size) {
+ bson_set_error (error,
+ MONGOC_ERROR_CLIENT,
+ MONGOC_ERROR_CLIENT_TOO_BIG,
+ "Attempted to send an RPC larger than the "
+ "max allowed message size. Was %u, allowed %u.",
+ BSON_UINT32_FROM_LE (rpc->header.msg_len),
+ max_msg_size);
+ GOTO (done);
+ }
+
+ if (!_mongoc_stream_writev_full (server_stream->stream,
+ cluster->iov.data,
+ cluster->iov.len,
+ cluster->sockettimeoutms,
+ error)) {
+ GOTO (done);
+ }
+
+ _mongoc_topology_update_last_used (cluster->client->topology, server_id);
+
+ ret = true;
+
+done:
+
+ if (compressor_id) {
+ bson_free (output);
+ }
+
+ RETURN (ret);
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_cluster_try_recv --
+ *
+ * Tries to receive the next event from the MongoDB server.
+ * The contents are loaded into @buffer and then
+ * scattered into the @rpc structure. @rpc is valid as long as
+ * @buffer contains the contents read into it.
+ *
+ * Callers that can optimize a reuse of @buffer should do so. It
+ * can save many memory allocations.
+ *
+ * Returns:
+ * True if successful.
+ *
+ * Side effects:
+ * @rpc is set on success, @error on failure.
+ * @buffer will be filled with the input data.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+bool
+mongoc_cluster_try_recv (mongoc_cluster_t *cluster,
+ mongoc_rpc_t *rpc,
+ mongoc_buffer_t *buffer,
+ mongoc_server_stream_t *server_stream,
+ bson_error_t *error)
+{
+ bson_error_t err_local;
+ int32_t msg_len;
+ int32_t max_msg_size;
+ off_t pos;
+
+ ENTRY;
+
+ BSON_ASSERT (cluster);
+ BSON_ASSERT (rpc);
+ BSON_ASSERT (buffer);
+ BSON_ASSERT (server_stream);
+
+
+ TRACE ("Waiting for reply from server_id \"%u\"", server_stream->sd->id);
+
+ if (!error) {
+ error = &err_local;
+ }
+
+ /*
+ * Buffer the message length to determine how much more to read.
+ */
+ pos = buffer->len;
+ if (!_mongoc_buffer_append_from_stream (
+ buffer, server_stream->stream, 4, cluster->sockettimeoutms, error)) {
+ MONGOC_DEBUG (
+ "Could not read 4 bytes, stream probably closed or timed out");
+ mongoc_counter_protocol_ingress_error_inc ();
+ _handle_network_error (
+ cluster, server_stream, true /* handshake complete */, error);
+ RETURN (false);
+ }
+
+ /*
+ * Read the msg length from the buffer.
+ */
+ memcpy (&msg_len, &buffer->data[pos], 4);
+ msg_len = BSON_UINT32_FROM_LE (msg_len);
+ max_msg_size = mongoc_server_stream_max_msg_size (server_stream);
+ if ((msg_len < 16) || (msg_len > max_msg_size)) {
+ bson_set_error (error,
+ MONGOC_ERROR_PROTOCOL,
+ MONGOC_ERROR_PROTOCOL_INVALID_REPLY,
+ "Corrupt or malicious reply received.");
+ _handle_network_error (
+ cluster, server_stream, true /* handshake complete */, error);
+ mongoc_counter_protocol_ingress_error_inc ();
+ RETURN (false);
+ }
+
+ /*
+ * Read the rest of the message from the stream.
+ */
+ if (!_mongoc_buffer_append_from_stream (buffer,
+ server_stream->stream,
+ msg_len - 4,
+ cluster->sockettimeoutms,
+ error)) {
+ _handle_network_error (
+ cluster, server_stream, true /* handshake complete */, error);
+ mongoc_counter_protocol_ingress_error_inc ();
+ RETURN (false);
+ }
+
+ /*
+ * Scatter the buffer into the rpc structure.
+ */
+ if (!_mongoc_rpc_scatter (rpc, &buffer->data[pos], msg_len)) {
+ bson_set_error (error,
+ MONGOC_ERROR_PROTOCOL,
+ MONGOC_ERROR_PROTOCOL_INVALID_REPLY,
+ "Failed to decode reply from server.");
+ _handle_network_error (
+ cluster, server_stream, true /* handshake complete */, error);
+ mongoc_counter_protocol_ingress_error_inc ();
+ RETURN (false);
+ }
+
+ if (BSON_UINT32_FROM_LE (rpc->header.opcode) == MONGOC_OPCODE_COMPRESSED) {
+ uint8_t *buf = NULL;
+ size_t len = BSON_UINT32_FROM_LE (rpc->compressed.uncompressed_size) +
+ sizeof (mongoc_rpc_header_t);
+
+ buf = bson_malloc0 (len);
+ if (!_mongoc_rpc_decompress (rpc, buf, len)) {
+ bson_free (buf);
+ bson_set_error (error,
+ MONGOC_ERROR_PROTOCOL,
+ MONGOC_ERROR_PROTOCOL_INVALID_REPLY,
+ "Could not decompress server reply");
+ RETURN (false);
+ }
+
+ _mongoc_buffer_destroy (buffer);
+ _mongoc_buffer_init (buffer, buf, len, NULL, NULL);
+ }
+ _mongoc_rpc_swab_from_le (rpc);
+
+ RETURN (true);
+}
+
+
+static void
+network_error_reply (bson_t *reply, mongoc_cmd_t *cmd)
+{
+ bson_t labels;
+
+ if (reply) {
+ bson_init (reply);
+ }
+
+ if (cmd->session) {
+ if (cmd->session->server_session) {
+ cmd->session->server_session->dirty = true;
+ }
+ /* Transactions Spec defines TransientTransactionError: "Any
+ * network error or server selection error encountered running any
+ * command besides commitTransaction in a transaction. In the case
+ * of command errors, the server adds the label; in the case of
+ * network errors or server selection errors where the client
+ * receives no server reply, the client adds the label." */
+ if (_mongoc_client_session_in_txn (cmd->session) && !cmd->is_txn_finish) {
+ /* Transaction Spec: "Drivers MUST unpin a ClientSession when a command
+ * within a transaction, including commitTransaction and
+ * abortTransaction,
+ * fails with a TransientTransactionError". If we're about to add
+ * a TransientTransactionError label due to a client side error then we
+ * unpin. If commitTransaction/abortTransation includes a label in the
+ * server reply, we unpin in _mongoc_client_session_handle_reply. */
+ cmd->session->server_id = 0;
+ if (!reply) {
+ return;
+ }
+
+ BSON_APPEND_ARRAY_BEGIN (reply, "errorLabels", &labels);
+ BSON_APPEND_UTF8 (&labels, "0", TRANSIENT_TXN_ERR);
+ bson_append_array_end (reply, &labels);
+ }
+ }
+}
+
+
+static bool
+mongoc_cluster_run_opmsg (mongoc_cluster_t *cluster,
+ mongoc_cmd_t *cmd,
+ bson_t *reply,
+ bson_error_t *error)
+{
+ mongoc_rpc_section_t section[2];
+ mongoc_buffer_t buffer;
+ bson_t reply_local; /* only statically initialized */
+ char *output = NULL;
+ mongoc_rpc_t rpc;
+ int32_t msg_len;
+ bool ok;
+ mongoc_server_stream_t *server_stream;
+
+ server_stream = cmd->server_stream;
+ if (!cmd->command_name) {
+ bson_set_error (error,
+ MONGOC_ERROR_COMMAND,
+ MONGOC_ERROR_COMMAND_INVALID_ARG,
+ "Empty command document");
+ _mongoc_bson_init_if_set (reply);
+ return false;
+ }
+ if (cluster->client->in_exhaust) {
+ bson_set_error (error,
+ MONGOC_ERROR_CLIENT,
+ MONGOC_ERROR_CLIENT_IN_EXHAUST,
+ "A cursor derived from this client is in exhaust.");
+ _mongoc_bson_init_if_set (reply);
+ return false;
+ }
+
+ _mongoc_array_clear (&cluster->iov);
+ _mongoc_buffer_init (&buffer, NULL, 0, NULL, NULL);
+
+ rpc.header.msg_len = 0;
+ rpc.header.request_id = ++cluster->request_id;
+ rpc.header.response_to = 0;
+ rpc.header.opcode = MONGOC_OPCODE_MSG;
+
+ if (cmd->is_acknowledged) {
+ rpc.msg.flags = 0;
+ } else {
+ rpc.msg.flags = MONGOC_MSG_MORE_TO_COME;
+ }
+
+ rpc.msg.n_sections = 1;
+
+ section[0].payload_type = 0;
+ section[0].payload.bson_document = bson_get_data (cmd->command);
+ rpc.msg.sections[0] = section[0];
+
+ if (cmd->payload) {
+ section[1].payload_type = 1;
+ section[1].payload.sequence.size = cmd->payload_size +
+ strlen (cmd->payload_identifier) + 1 +
+ sizeof (int32_t);
+ section[1].payload.sequence.identifier = cmd->payload_identifier;
+ section[1].payload.sequence.bson_documents = cmd->payload;
+ rpc.msg.sections[1] = section[1];
+ rpc.msg.n_sections++;
+ }
+
+ _mongoc_rpc_gather (&rpc, &cluster->iov);
+ _mongoc_rpc_swab_to_le (&rpc);
+
+ if (mongoc_cmd_is_compressible (cmd)) {
+ int32_t compressor_id =
+ mongoc_server_description_compressor_id (server_stream->sd);
+
+ TRACE (
+ "Function '%s' is compressible: %d", cmd->command_name, compressor_id);
+ if (compressor_id != -1) {
+ output = _mongoc_rpc_compress (cluster, compressor_id, &rpc, error);
+ if (output == NULL) {
+ _mongoc_bson_init_if_set (reply);
+ _mongoc_buffer_destroy (&buffer);
+ return false;
+ }
+ }
+ }
+ ok = _mongoc_stream_writev_full (server_stream->stream,
+ (mongoc_iovec_t *) cluster->iov.data,
+ cluster->iov.len,
+ cluster->sockettimeoutms,
+ error);
+ if (!ok) {
+ /* add info about the command to writev_full's error message */
+ RUN_CMD_ERR_DECORATE;
+ _handle_network_error (
+ cluster, server_stream, true /* handshake complete */, error);
+ server_stream->stream = NULL;
+ bson_free (output);
+ network_error_reply (reply, cmd);
+ _mongoc_buffer_destroy (&buffer);
+ return false;
+ }
+
+ /* If acknowledged, wait for a server response. Otherwise, exit early */
+ if (cmd->is_acknowledged) {
+ ok = _mongoc_buffer_append_from_stream (
+ &buffer, server_stream->stream, 4, cluster->sockettimeoutms, error);
+ if (!ok) {
+ RUN_CMD_ERR_DECORATE;
+ _handle_network_error (
+ cluster, server_stream, true /* handshake complete */, error);
+ server_stream->stream = NULL;
+ bson_free (output);
+ network_error_reply (reply, cmd);
+ _mongoc_buffer_destroy (&buffer);
+ return false;
+ }
+
+ BSON_ASSERT (buffer.len == 4);
+ memcpy (&msg_len, buffer.data, 4);
+ msg_len = BSON_UINT32_FROM_LE (msg_len);
+ if ((msg_len < 16) || (msg_len > server_stream->sd->max_msg_size)) {
+ RUN_CMD_ERR (
+ MONGOC_ERROR_PROTOCOL,
+ MONGOC_ERROR_PROTOCOL_INVALID_REPLY,
+ "Message size %d is not within expected range 16-%d bytes",
+ msg_len,
+ server_stream->sd->max_msg_size);
+ _handle_network_error (
+ cluster, server_stream, true /* handshake complete */, error);
+ server_stream->stream = NULL;
+ bson_free (output);
+ network_error_reply (reply, cmd);
+ _mongoc_buffer_destroy (&buffer);
+ return false;
+ }
+
+ ok = _mongoc_buffer_append_from_stream (&buffer,
+ server_stream->stream,
+ (size_t) msg_len - 4,
+ cluster->sockettimeoutms,
+ error);
+ if (!ok) {
+ RUN_CMD_ERR_DECORATE;
+ _handle_network_error (
+ cluster, server_stream, true /* handshake complete */, error);
+ server_stream->stream = NULL;
+ bson_free (output);
+ network_error_reply (reply, cmd);
+ _mongoc_buffer_destroy (&buffer);
+ return false;
+ }
+
+ ok = _mongoc_rpc_scatter (&rpc, buffer.data, buffer.len);
+ if (!ok) {
+ RUN_CMD_ERR (MONGOC_ERROR_PROTOCOL,
+ MONGOC_ERROR_PROTOCOL_INVALID_REPLY,
+ "Malformed message from server");
+ bson_free (output);
+ network_error_reply (reply, cmd);
+ _mongoc_buffer_destroy (&buffer);
+ return false;
+ }
+ if (BSON_UINT32_FROM_LE (rpc.header.opcode) == MONGOC_OPCODE_COMPRESSED) {
+ size_t len = BSON_UINT32_FROM_LE (rpc.compressed.uncompressed_size) +
+ sizeof (mongoc_rpc_header_t);
+
+ output = bson_realloc (output, len);
+ if (!_mongoc_rpc_decompress (&rpc, (uint8_t *) output, len)) {
+ RUN_CMD_ERR (MONGOC_ERROR_PROTOCOL,
+ MONGOC_ERROR_PROTOCOL_INVALID_REPLY,
+ "Could not decompress message from server");
+ _handle_network_error (
+ cluster, server_stream, true /* handshake complete */, error);
+ server_stream->stream = NULL;
+ bson_free (output);
+ network_error_reply (reply, cmd);
+ _mongoc_buffer_destroy (&buffer);
+ return false;
+ }
+ }
+ _mongoc_rpc_swab_from_le (&rpc);
+
+ memcpy (&msg_len, rpc.msg.sections[0].payload.bson_document, 4);
+ msg_len = BSON_UINT32_FROM_LE (msg_len);
+ bson_init_static (
+ &reply_local, rpc.msg.sections[0].payload.bson_document, msg_len);
+
+ _mongoc_topology_update_cluster_time (cluster->client->topology,
+ &reply_local);
+ ok = _mongoc_cmd_check_ok (
+ &reply_local, cluster->client->error_api_version, error);
+
+ if (cmd->session) {
+ _mongoc_client_session_handle_reply (cmd->session,
+ cmd->is_acknowledged,
+ cmd->command_name,
+ &reply_local);
+ }
+
+ if (reply) {
+ bson_copy_to (&reply_local, reply);
+ }
+ } else {
+ _mongoc_bson_init_if_set (reply);
+ }
+
+ _mongoc_buffer_destroy (&buffer);
+ bson_free (output);
+
+ return ok;
+}
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cmd-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cmd-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cmd-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cmd-private.h
diff --git a/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cmd.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cmd.c
new file mode 100644
index 00000000..3a71e8e1
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cmd.c
@@ -0,0 +1,1197 @@
+/*
+ * Copyright 2017 MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include "mongoc-cmd-private.h"
+#include "mongoc-read-prefs-private.h"
+#include "mongoc-trace-private.h"
+#include "mongoc-client-private.h"
+#include "mongoc-read-concern-private.h"
+#include "mongoc-server-api-private.h"
+#include "mongoc-write-concern-private.h"
+/* For strcasecmp on Windows */
+#include "mongoc-util-private.h"
+
+
+void
+mongoc_cmd_parts_init (mongoc_cmd_parts_t *parts,
+ mongoc_client_t *client,
+ const char *db_name,
+ mongoc_query_flags_t user_query_flags,
+ const bson_t *command_body)
+{
+ parts->body = command_body;
+ parts->user_query_flags = user_query_flags;
+ parts->read_prefs = NULL;
+ parts->is_read_command = false;
+ parts->is_write_command = false;
+ parts->prohibit_lsid = false;
+ parts->allow_txn_number = MONGOC_CMD_PARTS_ALLOW_TXN_NUMBER_UNKNOWN;
+ parts->is_retryable_read = false;
+ parts->is_retryable_write = false;
+ parts->has_temp_session = false;
+ parts->client = client;
+ bson_init (&parts->read_concern_document);
+ bson_init (&parts->write_concern_document);
+ bson_init (&parts->extra);
+ bson_init (&parts->assembled_body);
+
+ parts->assembled.db_name = db_name;
+ parts->assembled.command = NULL;
+ parts->assembled.query_flags = MONGOC_QUERY_NONE;
+ parts->assembled.payload_identifier = NULL;
+ parts->assembled.payload = NULL;
+ parts->assembled.session = NULL;
+ parts->assembled.is_acknowledged = true;
+ parts->assembled.is_txn_finish = false;
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_cmd_parts_set_session --
+ *
+ * Set the client session field.
+ *
+ * Side effects:
+ * Aborts if the command is assembled or if mongoc_cmd_parts_append_opts
+ * was called before.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+void
+mongoc_cmd_parts_set_session (mongoc_cmd_parts_t *parts,
+ mongoc_client_session_t *cs)
+{
+ BSON_ASSERT (parts);
+ BSON_ASSERT (!parts->assembled.command);
+ BSON_ASSERT (!parts->assembled.session);
+
+ parts->assembled.session = cs;
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_cmd_parts_append_opts --
+ *
+ * Take an iterator over user-supplied options document and append the
+ * options to @parts->command_extra, taking the selected server's max
+ * wire version into account.
+ *
+ * Return:
+ * True if the options were successfully applied. If any options are
+ * invalid, returns false and fills out @error. In that case @parts is
+ * invalid and must not be used.
+ *
+ * Side effects:
+ * May partly apply options before returning an error.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+bool
+mongoc_cmd_parts_append_opts (mongoc_cmd_parts_t *parts,
+ bson_iter_t *iter,
+ int max_wire_version,
+ bson_error_t *error)
+{
+ mongoc_client_session_t *cs = NULL;
+ mongoc_write_concern_t *wc;
+ uint32_t len;
+ const uint8_t *data;
+ bson_t read_concern;
+ const char *to_append;
+
+ ENTRY;
+
+ /* not yet assembled */
+ BSON_ASSERT (!parts->assembled.command);
+
+ while (bson_iter_next (iter)) {
+ if (BSON_ITER_IS_KEY (iter, "collation")) {
+ if (max_wire_version < WIRE_VERSION_COLLATION) {
+ bson_set_error (error,
+ MONGOC_ERROR_COMMAND,
+ MONGOC_ERROR_PROTOCOL_BAD_WIRE_VERSION,
+ "The selected server does not support collation");
+ RETURN (false);
+ }
+
+ } else if (BSON_ITER_IS_KEY (iter, "writeConcern")) {
+ wc = _mongoc_write_concern_new_from_iter (iter, error);
+ if (!wc) {
+ RETURN (false);
+ }
+
+ if (!mongoc_cmd_parts_set_write_concern (
+ parts, wc, max_wire_version, error)) {
+ mongoc_write_concern_destroy (wc);
+ RETURN (false);
+ }
+
+ mongoc_write_concern_destroy (wc);
+ continue;
+ } else if (BSON_ITER_IS_KEY (iter, "readConcern")) {
+ if (max_wire_version < WIRE_VERSION_READ_CONCERN) {
+ bson_set_error (error,
+ MONGOC_ERROR_COMMAND,
+ MONGOC_ERROR_PROTOCOL_BAD_WIRE_VERSION,
+ "The selected server does not support readConcern");
+ RETURN (false);
+ }
+
+ if (!BSON_ITER_HOLDS_DOCUMENT (iter)) {
+ bson_set_error (error,
+ MONGOC_ERROR_COMMAND,
+ MONGOC_ERROR_PROTOCOL_BAD_WIRE_VERSION,
+ "Invalid readConcern");
+ RETURN (false);
+ }
+
+ /* add readConcern later, once we know about causal consistency */
+ bson_iter_document (iter, &len, &data);
+ BSON_ASSERT (bson_init_static (&read_concern, data, (size_t) len));
+ bson_destroy (&parts->read_concern_document);
+ bson_copy_to (&read_concern, &parts->read_concern_document);
+ continue;
+ } else if (BSON_ITER_IS_KEY (iter, "sessionId")) {
+ BSON_ASSERT (!parts->assembled.session);
+
+ if (!_mongoc_client_session_from_iter (
+ parts->client, iter, &cs, error)) {
+ RETURN (false);
+ }
+
+ parts->assembled.session = cs;
+ continue;
+ } else if (BSON_ITER_IS_KEY (iter, "serverId") ||
+ BSON_ITER_IS_KEY (iter, "maxAwaitTimeMS") ||
+ BSON_ITER_IS_KEY (iter, "exhaust")) {
+ continue;
+ }
+
+ to_append = bson_iter_key (iter);
+ if (!bson_append_iter (&parts->extra, to_append, -1, iter)) {
+ bson_set_error (error,
+ MONGOC_ERROR_COMMAND,
+ MONGOC_ERROR_COMMAND_INVALID_ARG,
+ "Failed to append \"%s\" to create command.",
+ to_append);
+ RETURN (false);
+ }
+ }
+
+ RETURN (true);
+}
+
+
+#define OPTS_ERR(_code, ...) \
+ do { \
+ bson_set_error ( \
+ error, MONGOC_ERROR_COMMAND, MONGOC_ERROR_##_code, __VA_ARGS__); \
+ RETURN (false); \
+ } while (0)
+
+
+/* set readConcern if allowed, otherwise error */
+bool
+mongoc_cmd_parts_set_read_concern (mongoc_cmd_parts_t *parts,
+ const mongoc_read_concern_t *rc,
+ int max_wire_version,
+ bson_error_t *error)
+{
+ const char *command_name;
+
+ ENTRY;
+
+ /* In a txn, set read concern in mongoc_cmd_parts_assemble, not here. *
+ * Transactions Spec: "The readConcern MUST NOT be inherited from the
+ * collection, database, or client associated with the driver method that
+ * invokes the first command." */
+ if (_mongoc_client_session_in_txn (parts->assembled.session)) {
+ RETURN (true);
+ }
+
+ command_name = _mongoc_get_command_name (parts->body);
+
+ if (!command_name) {
+ OPTS_ERR (COMMAND_INVALID_ARG, "Empty command document");
+ }
+
+ if (mongoc_read_concern_is_default (rc)) {
+ RETURN (true);
+ }
+
+ if (max_wire_version < WIRE_VERSION_READ_CONCERN) {
+ bson_set_error (error,
+ MONGOC_ERROR_COMMAND,
+ MONGOC_ERROR_PROTOCOL_BAD_WIRE_VERSION,
+ "\"%s\" command does not support readConcern with "
+ "wire version %d, wire version %d is required",
+ command_name,
+ max_wire_version,
+ WIRE_VERSION_READ_CONCERN);
+ RETURN (false);
+ }
+
+ bson_destroy (&parts->read_concern_document);
+ bson_copy_to (_mongoc_read_concern_get_bson ((mongoc_read_concern_t *) rc),
+ &parts->read_concern_document);
+
+ RETURN (true);
+}
+
+
+/* set writeConcern if allowed, otherwise ignore - unlike set_read_concern, it's
+ * the caller's responsibility to check if writeConcern is supported */
+bool
+mongoc_cmd_parts_set_write_concern (mongoc_cmd_parts_t *parts,
+ const mongoc_write_concern_t *wc,
+ int max_wire_version,
+ bson_error_t *error)
+{
+ const char *command_name;
+ bool is_fam;
+ bool wc_allowed;
+
+ ENTRY;
+
+ if (!wc) {
+ RETURN (true);
+ }
+
+ command_name = _mongoc_get_command_name (parts->body);
+
+ if (!command_name) {
+ OPTS_ERR (COMMAND_INVALID_ARG, "Empty command document");
+ }
+
+ is_fam = !strcasecmp (command_name, "findandmodify");
+
+ wc_allowed =
+ parts->is_write_command ||
+ (is_fam && max_wire_version >= WIRE_VERSION_FAM_WRITE_CONCERN) ||
+ (!is_fam && max_wire_version >= WIRE_VERSION_CMD_WRITE_CONCERN);
+
+ if (wc_allowed) {
+ parts->assembled.is_acknowledged =
+ mongoc_write_concern_is_acknowledged (wc);
+ bson_destroy (&parts->write_concern_document);
+ bson_copy_to (
+ _mongoc_write_concern_get_bson ((mongoc_write_concern_t *) wc),
+ &parts->write_concern_document);
+ }
+
+ RETURN (true);
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_cmd_parts_append_read_write --
+ *
+ * Append user-supplied options to @parts->command_extra, taking the
+ * selected server's max wire version into account.
+ *
+ * Return:
+ * True if the options were successfully applied. If any options are
+ * invalid, returns false and fills out @error. In that case @parts is
+ * invalid and must not be used.
+ *
+ * Side effects:
+ * May partly apply options before returning an error.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+bool
+mongoc_cmd_parts_append_read_write (mongoc_cmd_parts_t *parts,
+ mongoc_read_write_opts_t *rw_opts,
+ int max_wire_version,
+ bson_error_t *error)
+{
+ ENTRY;
+
+ /* not yet assembled */
+ BSON_ASSERT (!parts->assembled.command);
+
+ if (!bson_empty (&rw_opts->collation)) {
+ if (max_wire_version < WIRE_VERSION_COLLATION) {
+ OPTS_ERR (PROTOCOL_BAD_WIRE_VERSION,
+ "The selected server does not support collation");
+ }
+
+ if (!bson_append_document (
+ &parts->extra, "collation", 9, &rw_opts->collation)) {
+ OPTS_ERR (COMMAND_INVALID_ARG, "'opts' with 'collation' is too large");
+ }
+ }
+
+ if (!mongoc_cmd_parts_set_write_concern (
+ parts, rw_opts->writeConcern, max_wire_version, error)) {
+ RETURN (false);
+ }
+
+ /* process explicit read concern */
+ if (!bson_empty (&rw_opts->readConcern)) {
+ if (max_wire_version < WIRE_VERSION_READ_CONCERN) {
+ OPTS_ERR (PROTOCOL_BAD_WIRE_VERSION,
+ "The selected server does not support readConcern");
+ }
+
+ /* save readConcern for later, once we know about causal consistency */
+ bson_destroy (&parts->read_concern_document);
+ bson_copy_to (&rw_opts->readConcern, &parts->read_concern_document);
+ }
+
+ if (rw_opts->client_session) {
+ BSON_ASSERT (!parts->assembled.session);
+ parts->assembled.session = rw_opts->client_session;
+ }
+
+ if (!bson_concat (&parts->extra, &rw_opts->extra)) {
+ OPTS_ERR (COMMAND_INVALID_ARG, "'opts' with extra fields is too large");
+ }
+
+ RETURN (true);
+}
+
+#undef OPTS_ERR
+
+static void
+_mongoc_cmd_parts_ensure_copied (mongoc_cmd_parts_t *parts)
+{
+ if (parts->assembled.command == parts->body) {
+ bson_concat (&parts->assembled_body, parts->body);
+ bson_concat (&parts->assembled_body, &parts->extra);
+ parts->assembled.command = &parts->assembled_body;
+ }
+}
+
+
+static void
+_mongoc_cmd_parts_add_write_concern (mongoc_cmd_parts_t *parts)
+{
+ if (!bson_empty (&parts->write_concern_document)) {
+ _mongoc_cmd_parts_ensure_copied (parts);
+ bson_append_document (&parts->assembled_body,
+ "writeConcern",
+ 12,
+ &parts->write_concern_document);
+ }
+}
+
+
+/* The server type must be mongos, or message must be OP_MSG. */
+static void
+_mongoc_cmd_parts_add_read_prefs (bson_t *query,
+ const mongoc_read_prefs_t *prefs)
+{
+ bson_t child;
+ const char *mode_str;
+ const bson_t *tags;
+ int64_t stale;
+ const bson_t *hedge;
+
+ mode_str = _mongoc_read_mode_as_str (mongoc_read_prefs_get_mode (prefs));
+ tags = mongoc_read_prefs_get_tags (prefs);
+ stale = mongoc_read_prefs_get_max_staleness_seconds (prefs);
+ hedge = mongoc_read_prefs_get_hedge (prefs);
+
+ bson_append_document_begin (query, "$readPreference", 15, &child);
+ bson_append_utf8 (&child, "mode", 4, mode_str, -1);
+ if (!bson_empty0 (tags)) {
+ bson_append_array (&child, "tags", 4, tags);
+ }
+
+ if (stale != MONGOC_NO_MAX_STALENESS) {
+ bson_append_int64 (&child, "maxStalenessSeconds", 19, stale);
+ }
+
+ if (!bson_empty0 (hedge)) {
+ bson_append_document (&child, "hedge", 5, hedge);
+ }
+
+ bson_append_document_end (query, &child);
+}
+
+
+static void
+_iter_concat (bson_t *dst, bson_iter_t *iter)
+{
+ uint32_t len;
+ const uint8_t *data;
+ bson_t src;
+
+ bson_iter_document (iter, &len, &data);
+ BSON_ASSERT (bson_init_static (&src, data, len));
+ BSON_ASSERT (bson_concat (dst, &src));
+}
+
+
+/* Update result with the read prefs. Server must be mongos.
+ */
+static void
+_mongoc_cmd_parts_assemble_mongos (mongoc_cmd_parts_t *parts,
+ const mongoc_server_stream_t *server_stream)
+{
+ mongoc_read_mode_t mode;
+ const bson_t *tags = NULL;
+ int64_t max_staleness_seconds = MONGOC_NO_MAX_STALENESS;
+ const bson_t *hedge = NULL;
+ bool add_read_prefs = false;
+ bson_t query;
+ bson_iter_t dollar_query;
+ bool has_dollar_query = false;
+ bool requires_read_concern;
+ bool requires_write_concern;
+
+ ENTRY;
+
+ mode = mongoc_read_prefs_get_mode (parts->read_prefs);
+ if (parts->read_prefs) {
+ max_staleness_seconds =
+ mongoc_read_prefs_get_max_staleness_seconds (parts->read_prefs);
+
+ tags = mongoc_read_prefs_get_tags (parts->read_prefs);
+ hedge = mongoc_read_prefs_get_hedge (parts->read_prefs);
+ }
+
+ if (server_stream->must_use_primary) {
+ /* Server selection has overriden the read mode used to generate this
+ * server stream. This has effects on the body of the message that we send
+ * to the server */
+ mode = MONGOC_READ_PRIMARY;
+ }
+
+ /* Server Selection Spec says:
+ *
+ * For mode 'primary', drivers MUST NOT set the secondaryOk wire protocol
+ * flag and MUST NOT use $readPreference
+ *
+ * For mode 'secondary', drivers MUST set the secondaryOk wire protocol flag
+ * and MUST also use $readPreference
+ *
+ * For mode 'primaryPreferred', drivers MUST set the secondaryOk wire
+ * protocol flag and MUST also use $readPreference
+ *
+ * For mode 'secondaryPreferred', drivers MUST set the secondaryOk wire
+ * protocol flag. If the read preference contains a non-empty tag_sets
+ * parameter, maxStalenessSeconds is a positive integer, or the hedge
+ * parameter is non-empty, drivers MUST use $readPreference; otherwise,
+ * drivers MUST NOT use $readPreference
+ *
+ * For mode 'nearest', drivers MUST set the secondaryOk wire protocol flag
+ * and MUST also use $readPreference
+ */
+ switch (mode) {
+ case MONGOC_READ_PRIMARY:
+ break;
+ case MONGOC_READ_SECONDARY_PREFERRED:
+ if (!bson_empty0 (tags) || max_staleness_seconds > 0 ||
+ !bson_empty0 (hedge)) {
+ add_read_prefs = true;
+ }
+ parts->assembled.query_flags |= MONGOC_QUERY_SECONDARY_OK;
+ break;
+ case MONGOC_READ_PRIMARY_PREFERRED:
+ case MONGOC_READ_SECONDARY:
+ case MONGOC_READ_NEAREST:
+ default:
+ parts->assembled.query_flags |= MONGOC_QUERY_SECONDARY_OK;
+ add_read_prefs = true;
+ }
+
+ requires_read_concern =
+ !bson_empty (&parts->read_concern_document) &&
+ strcmp (parts->assembled.command_name, "getMore") != 0;
+
+ requires_write_concern = !bson_empty (&parts->write_concern_document);
+
+ if (add_read_prefs) {
+ /* produce {$query: {user query, readConcern}, $readPreference: ... } */
+ bson_append_document_begin (&parts->assembled_body, "$query", 6, &query);
+
+ if (bson_iter_init_find (&dollar_query, parts->body, "$query")) {
+ /* user provided something like {$query: {key: "x"}} */
+ has_dollar_query = true;
+ _iter_concat (&query, &dollar_query);
+ } else {
+ bson_concat (&query, parts->body);
+ }
+
+ bson_concat (&query, &parts->extra);
+ if (requires_read_concern) {
+ bson_append_document (
+ &query, "readConcern", 11, &parts->read_concern_document);
+ }
+
+ if (requires_write_concern) {
+ bson_append_document (
+ &query, "writeConcern", 12, &parts->write_concern_document);
+ }
+
+ bson_append_document_end (&parts->assembled_body, &query);
+ _mongoc_cmd_parts_add_read_prefs (&parts->assembled_body,
+ parts->read_prefs);
+
+ if (has_dollar_query) {
+ /* copy anything that isn't in user's $query */
+ bson_copy_to_excluding_noinit (
+ parts->body, &parts->assembled_body, "$query", NULL);
+ }
+
+ parts->assembled.command = &parts->assembled_body;
+ } else if (bson_iter_init_find (&dollar_query, parts->body, "$query")) {
+ /* user provided $query, we have no read prefs */
+ bson_append_document_begin (&parts->assembled_body, "$query", 6, &query);
+ _iter_concat (&query, &dollar_query);
+ bson_concat (&query, &parts->extra);
+ if (requires_read_concern) {
+ bson_append_document (
+ &query, "readConcern", 11, &parts->read_concern_document);
+ }
+
+ if (requires_write_concern) {
+ bson_append_document (
+ &query, "writeConcern", 12, &parts->write_concern_document);
+ }
+
+ bson_append_document_end (&parts->assembled_body, &query);
+ /* copy anything that isn't in user's $query */
+ bson_copy_to_excluding_noinit (
+ parts->body, &parts->assembled_body, "$query", NULL);
+
+ parts->assembled.command = &parts->assembled_body;
+ } else {
+ if (requires_read_concern) {
+ _mongoc_cmd_parts_ensure_copied (parts);
+ bson_append_document (&parts->assembled_body,
+ "readConcern",
+ 11,
+ &parts->read_concern_document);
+ }
+
+ _mongoc_cmd_parts_add_write_concern (parts);
+ }
+
+ if (!bson_empty (&parts->extra)) {
+ /* if none of the above logic has merged "extra", do it now */
+ _mongoc_cmd_parts_ensure_copied (parts);
+ }
+
+ EXIT;
+}
+
+
+static void
+_mongoc_cmd_parts_assemble_mongod (mongoc_cmd_parts_t *parts,
+ const mongoc_server_stream_t *server_stream)
+{
+ ENTRY;
+
+ if (!parts->is_write_command) {
+ switch (server_stream->topology_type) {
+ case MONGOC_TOPOLOGY_SINGLE:
+ /* Server Selection Spec: for topology type single and server types
+ * besides mongos, "clients MUST always set the secondaryOk wire
+ * protocol flag on reads to ensure that any server type can handle
+ * the request."
+ */
+ parts->assembled.query_flags |= MONGOC_QUERY_SECONDARY_OK;
+ break;
+
+ case MONGOC_TOPOLOGY_RS_NO_PRIMARY:
+ case MONGOC_TOPOLOGY_RS_WITH_PRIMARY:
+ /* Server Selection Spec: for RS topology types, "For all read
+ * preferences modes except primary, clients MUST set the secondaryOk
+ * wire protocol flag to ensure that any suitable server can handle the
+ * request. Clients MUST NOT set the secondaryOk wire protocol flag if
+ * the read preference mode is primary.
+ */
+ if (parts->read_prefs &&
+ parts->read_prefs->mode != MONGOC_READ_PRIMARY) {
+ parts->assembled.query_flags |= MONGOC_QUERY_SECONDARY_OK;
+ }
+
+ break;
+ case MONGOC_TOPOLOGY_SHARDED:
+ case MONGOC_TOPOLOGY_UNKNOWN:
+ case MONGOC_TOPOLOGY_LOAD_BALANCED:
+ case MONGOC_TOPOLOGY_DESCRIPTION_TYPES:
+ default:
+ /* must not call this function w/ sharded, load balanced, or unknown
+ * topology type */
+ BSON_ASSERT (false);
+ }
+ } /* if (!parts->is_write_command) */
+
+ if (!bson_empty (&parts->extra)) {
+ _mongoc_cmd_parts_ensure_copied (parts);
+ }
+
+ if (!bson_empty (&parts->read_concern_document) &&
+ strcmp (parts->assembled.command_name, "getMore") != 0) {
+ _mongoc_cmd_parts_ensure_copied (parts);
+ bson_append_document (&parts->assembled_body,
+ "readConcern",
+ 11,
+ &parts->read_concern_document);
+ }
+
+ _mongoc_cmd_parts_add_write_concern (parts);
+
+ EXIT;
+}
+
+
+static const bson_t *
+_largest_cluster_time (const bson_t *a, const bson_t *b)
+{
+ if (!a) {
+ return b;
+ }
+
+ if (!b) {
+ return a;
+ }
+
+ if (_mongoc_cluster_time_greater (a, b)) {
+ return a;
+ }
+
+ return b;
+}
+
+
+/* Check if the command should allow a transaction number if that has not
+ * already been determined.
+ *
+ * This should only return true for write commands that are always retryable for
+ * the server stream's wire version.
+ *
+ * The basic write commands (i.e. insert, update, delete) are intentionally
+ * excluded here. While insert is always retryable, update and delete are only
+ * retryable if they include no multi-document writes. Since it would be costly
+ * to inspect the command document here, the bulk operation API explicitly sets
+ * allow_txn_number for us. This means that insert, update, and delete are not
+ * retryable if executed via mongoc_client_write_command_with_opts(); however,
+ * documentation already instructs users not to use that for basic writes.
+ */
+static bool
+_allow_txn_number (const mongoc_cmd_parts_t *parts,
+ const mongoc_server_stream_t *server_stream)
+{
+ /* There is no reason to call this function if allow_txn_number is set */
+ BSON_ASSERT (parts->allow_txn_number ==
+ MONGOC_CMD_PARTS_ALLOW_TXN_NUMBER_UNKNOWN);
+
+ if (!parts->is_write_command) {
+ return false;
+ }
+
+ if (server_stream->sd->max_wire_version < WIRE_VERSION_RETRY_WRITES) {
+ return false;
+ }
+
+ if (!parts->assembled.is_acknowledged) {
+ return false;
+ }
+
+ if (!strcasecmp (parts->assembled.command_name, "findandmodify")) {
+ return true;
+ }
+
+ return false;
+}
+
+
+/* Check if the write command should support retryable behavior. */
+static bool
+_is_retryable_write (const mongoc_cmd_parts_t *parts,
+ const mongoc_server_stream_t *server_stream)
+{
+ if (!parts->assembled.session) {
+ return false;
+ }
+
+ if (!parts->is_write_command) {
+ return false;
+ }
+
+ if (parts->allow_txn_number != MONGOC_CMD_PARTS_ALLOW_TXN_NUMBER_YES) {
+ return false;
+ }
+
+ if (server_stream->sd->max_wire_version < WIRE_VERSION_RETRY_WRITES) {
+ return false;
+ }
+
+ if (server_stream->sd->type == MONGOC_SERVER_STANDALONE) {
+ return false;
+ }
+
+ if (_mongoc_client_session_in_txn (parts->assembled.session)) {
+ return false;
+ }
+
+ if (!mongoc_uri_get_option_as_bool (parts->client->uri,
+ MONGOC_URI_RETRYWRITES,
+ MONGOC_DEFAULT_RETRYWRITES)) {
+ return false;
+ }
+
+ return true;
+}
+
+
+/* Check if the read command should support retryable behavior. */
+bool
+_is_retryable_read (const mongoc_cmd_parts_t *parts,
+ const mongoc_server_stream_t *server_stream)
+{
+ if (!parts->is_read_command) {
+ return false;
+ }
+
+ /* Commands that go through read_write_command helpers are also write
+ * commands. Prohibit from read retry. */
+ if (parts->is_write_command) {
+ return false;
+ }
+
+ if (server_stream->sd->max_wire_version < WIRE_VERSION_RETRY_READS) {
+ return false;
+ }
+
+ if (_mongoc_client_session_in_txn (parts->assembled.session)) {
+ return false;
+ }
+
+ if (!mongoc_uri_get_option_as_bool (parts->client->uri,
+ MONGOC_URI_RETRYREADS,
+ MONGOC_DEFAULT_RETRYREADS)) {
+ return false;
+ }
+
+ return true;
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_cmd_parts_assemble --
+ *
+ * Assemble the command body, options, and read preference into one
+ * command.
+ *
+ * Return:
+ * True if the options were successfully applied. If any options are
+ * invalid, returns false and fills out @error. In that case @parts is
+ * invalid and must not be used.
+ *
+ * Side effects:
+ * May partly assemble before returning an error.
+ * mongoc_cmd_parts_cleanup should be called in all cases.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+bool
+mongoc_cmd_parts_assemble (mongoc_cmd_parts_t *parts,
+ mongoc_server_stream_t *server_stream,
+ bson_error_t *error)
+{
+ mongoc_server_description_type_t server_type;
+ mongoc_client_session_t *cs;
+ const bson_t *cluster_time = NULL;
+ mongoc_read_prefs_t *prefs = NULL;
+ const char *cmd_name;
+ bool is_get_more;
+ const mongoc_read_prefs_t *prefs_ptr;
+ mongoc_read_mode_t mode = mongoc_read_prefs_get_mode (parts->read_prefs);
+ bool ret = false;
+
+ ENTRY;
+
+ BSON_ASSERT (parts);
+ BSON_ASSERT (server_stream);
+
+ server_type = server_stream->sd->type;
+ cs = parts->prohibit_lsid ? NULL : parts->assembled.session;
+
+ /* Assembling the command depends on the type of server. If the server has
+ * been invalidated, error. */
+ if (server_type == MONGOC_SERVER_UNKNOWN) {
+ if (error) {
+ bson_set_error (error,
+ MONGOC_ERROR_COMMAND,
+ MONGOC_ERROR_COMMAND_INVALID_ARG,
+ "Cannot assemble command for invalidated server: %s",
+ server_stream->sd->error.message);
+ }
+ RETURN (false);
+ }
+
+ /* must not be assembled already */
+ BSON_ASSERT (!parts->assembled.command);
+ BSON_ASSERT (bson_empty (&parts->assembled_body));
+
+ /* begin with raw flags/cmd as assembled flags/cmd, might change below */
+ parts->assembled.command = parts->body;
+ /* unused in OP_MSG: */
+ parts->assembled.query_flags = parts->user_query_flags;
+ parts->assembled.server_stream = server_stream;
+ cmd_name = parts->assembled.command_name =
+ _mongoc_get_command_name (parts->assembled.command);
+
+ if (!parts->assembled.command_name) {
+ bson_set_error (error,
+ MONGOC_ERROR_COMMAND,
+ MONGOC_ERROR_COMMAND_INVALID_ARG,
+ "Empty command document");
+ GOTO (done);
+ }
+
+ TRACE ("Preparing '%s'", cmd_name);
+
+ is_get_more = !strcmp (cmd_name, "getMore");
+ parts->assembled.is_txn_finish = !strcmp (cmd_name, "commitTransaction") ||
+ !strcmp (cmd_name, "abortTransaction");
+
+ if (!parts->is_write_command && IS_PREF_PRIMARY (parts->read_prefs) &&
+ server_stream->topology_type == MONGOC_TOPOLOGY_SINGLE &&
+ server_type != MONGOC_SERVER_MONGOS) {
+ prefs = mongoc_read_prefs_new (MONGOC_READ_PRIMARY_PREFERRED);
+ prefs_ptr = prefs;
+ } else {
+ prefs_ptr = parts->read_prefs;
+ }
+
+ mode = mongoc_read_prefs_get_mode (prefs_ptr);
+ if (server_stream->must_use_primary) {
+ /* Server selection may have overriden the read mode used to generate this
+ * server stream. This has effects on the body of the message that we send
+ * to the server */
+ mode = MONGOC_READ_PRIMARY;
+ }
+
+ if (server_stream->sd->max_wire_version >= WIRE_VERSION_OP_MSG) {
+ if (!bson_has_field (parts->body, "$db")) {
+ BSON_APPEND_UTF8 (&parts->extra, "$db", parts->assembled.db_name);
+ }
+
+ if (cs && _mongoc_client_session_in_txn (cs)) {
+ if (!IS_PREF_PRIMARY (cs->txn.opts.read_prefs) &&
+ !parts->is_write_command) {
+ bson_set_error (error,
+ MONGOC_ERROR_TRANSACTION,
+ MONGOC_ERROR_TRANSACTION_INVALID_STATE,
+ "Read preference in a transaction must be primary");
+ GOTO (done);
+ }
+ } else if (mode != MONGOC_READ_PRIMARY &&
+ server_type != MONGOC_SERVER_STANDALONE) {
+ /* "Type Standalone: clients MUST NOT send the read preference to the
+ * server" */
+ _mongoc_cmd_parts_add_read_prefs (&parts->extra, prefs_ptr);
+ }
+
+ if (!bson_empty (&parts->extra)) {
+ _mongoc_cmd_parts_ensure_copied (parts);
+ }
+
+ /* If an explicit session was not provided and lsid is not prohibited,
+ * attempt to create an implicit session (ignoring any errors). */
+ if (!cs && !parts->prohibit_lsid && parts->assembled.is_acknowledged) {
+ cs = mongoc_client_start_session (parts->client, NULL, NULL);
+
+ if (cs) {
+ parts->assembled.session = cs;
+ parts->has_temp_session = true;
+ }
+ }
+
+ /* Driver Sessions Spec: "For unacknowledged writes with an explicit
+ * session, drivers SHOULD raise an error.... Without an explicit
+ * session, drivers SHOULD NOT use an implicit session." We intentionally
+ * do not restrict this logic to parts->is_write_command, since
+ * mongoc_client_command_with_opts() does not identify as a write
+ * command but may still include a write concern.
+ */
+ if (cs) {
+ if (!parts->assembled.is_acknowledged) {
+ bson_set_error (
+ error,
+ MONGOC_ERROR_COMMAND,
+ MONGOC_ERROR_COMMAND_INVALID_ARG,
+ "Cannot use client session with unacknowledged command");
+ GOTO (done);
+ }
+
+ _mongoc_cmd_parts_ensure_copied (parts);
+ bson_append_document (&parts->assembled_body,
+ "lsid",
+ 4,
+ mongoc_client_session_get_lsid (cs));
+
+ cs->server_session->last_used_usec = bson_get_monotonic_time ();
+ cluster_time = mongoc_client_session_get_cluster_time (cs);
+ }
+
+ /* Ensure we know if the write command allows a transaction number */
+ if (!_mongoc_client_session_txn_in_progress (cs) &&
+ parts->is_write_command &&
+ parts->allow_txn_number ==
+ MONGOC_CMD_PARTS_ALLOW_TXN_NUMBER_UNKNOWN) {
+ parts->allow_txn_number = _allow_txn_number (parts, server_stream)
+ ? MONGOC_CMD_PARTS_ALLOW_TXN_NUMBER_YES
+ : MONGOC_CMD_PARTS_ALLOW_TXN_NUMBER_NO;
+ }
+
+ /* Determine if the command is retryable. If so, append txnNumber now
+ * for future use and mark the command as such. */
+ if (_is_retryable_write (parts, server_stream)) {
+ _mongoc_cmd_parts_ensure_copied (parts);
+ bson_append_int64 (&parts->assembled_body, "txnNumber", 9, 0);
+ parts->is_retryable_write = true;
+ }
+
+ /* Conversely, check if the command is retryable if it is a read. */
+ if (_is_retryable_read (parts, server_stream) && !is_get_more) {
+ parts->is_retryable_read = true;
+ }
+
+ if (!bson_empty (&server_stream->cluster_time)) {
+ cluster_time =
+ _largest_cluster_time (&server_stream->cluster_time, cluster_time);
+ }
+
+ if (cluster_time && server_type != MONGOC_SERVER_STANDALONE) {
+ _mongoc_cmd_parts_ensure_copied (parts);
+ bson_append_document (
+ &parts->assembled_body, "$clusterTime", 12, cluster_time);
+ }
+
+ /* Add versioned server api, if it is set. */
+ if (parts->client->api) {
+ _mongoc_cmd_append_server_api (&parts->assembled_body,
+ parts->client->api);
+ }
+
+ if (!is_get_more) {
+ if (cs) {
+ /* Snapshot Sessions Spec: "Snapshot reads require MongoDB 5.0+."
+ * Throw an error if snapshot is enabled and wire version is less
+ * than 13 before potentially appending "snapshot" read concern. */
+ if (mongoc_session_opts_get_snapshot (&cs->opts) &&
+ server_stream->sd->max_wire_version <
+ WIRE_VERSION_SNAPSHOT_READS) {
+ bson_set_error (error,
+ MONGOC_ERROR_CLIENT,
+ MONGOC_ERROR_CLIENT_SESSION_FAILURE,
+ "Snapshot reads require MongoDB 5.0 or later");
+ GOTO (done);
+ }
+
+ _mongoc_cmd_parts_ensure_copied (parts);
+ _mongoc_client_session_append_read_concern (
+ cs,
+ &parts->read_concern_document,
+ parts->is_read_command,
+ &parts->assembled_body);
+ } else if (!bson_empty (&parts->read_concern_document)) {
+ _mongoc_cmd_parts_ensure_copied (parts);
+ bson_append_document (&parts->assembled_body,
+ "readConcern",
+ 11,
+ &parts->read_concern_document);
+ }
+ }
+
+ /* if transaction is in progress do not inherit write concern */
+ if (parts->assembled.is_txn_finish ||
+ !_mongoc_client_session_in_txn (cs)) {
+ _mongoc_cmd_parts_add_write_concern (parts);
+ }
+
+ _mongoc_cmd_parts_ensure_copied (parts);
+ if (!_mongoc_client_session_append_txn (
+ cs, &parts->assembled_body, error)) {
+ GOTO (done);
+ }
+
+ ret = true;
+ } else if (server_type == MONGOC_SERVER_MONGOS ||
+ server_stream->topology_type == MONGOC_TOPOLOGY_LOAD_BALANCED) {
+ /* TODO (CDRIVER-4117) remove the check of the topology description type.
+ */
+ _mongoc_cmd_parts_assemble_mongos (parts, server_stream);
+ ret = true;
+ } else {
+ _mongoc_cmd_parts_assemble_mongod (parts, server_stream);
+ ret = true;
+ }
+
+done:
+ mongoc_read_prefs_destroy (prefs);
+ RETURN (ret);
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_cmd_parts_cleanup --
+ *
+ * Free memory associated with a stack-allocated mongoc_cmd_parts_t.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+void
+mongoc_cmd_parts_cleanup (mongoc_cmd_parts_t *parts)
+{
+ bson_destroy (&parts->read_concern_document);
+ bson_destroy (&parts->write_concern_document);
+ bson_destroy (&parts->extra);
+ bson_destroy (&parts->assembled_body);
+
+ if (parts->has_temp_session) {
+ /* client session returns its server session to server session pool */
+ mongoc_client_session_destroy (parts->assembled.session);
+ }
+}
+
+bool
+mongoc_cmd_is_compressible (mongoc_cmd_t *cmd)
+{
+ BSON_ASSERT (cmd);
+ BSON_ASSERT (cmd->command_name);
+
+ return !!strcasecmp (cmd->command_name, "hello") &&
+ !!strcasecmp (cmd->command_name, HANDSHAKE_CMD_LEGACY_HELLO) &&
+ !!strcasecmp (cmd->command_name, "authenticate") &&
+ !!strcasecmp (cmd->command_name, "getnonce") &&
+ !!strcasecmp (cmd->command_name, "saslstart") &&
+ !!strcasecmp (cmd->command_name, "saslcontinue") &&
+ !!strcasecmp (cmd->command_name, "createuser") &&
+ !!strcasecmp (cmd->command_name, "updateuser");
+}
+
+/*--------------------------------------------------------------------------
+ *
+ * _mongoc_cmd_append_payload_as_array --
+ * Append a write command payload as an array in a BSON document.
+ * Used by APM and Client-Side Encryption
+ *
+ * Arguments:
+ * cmd The mongoc_cmd_t, which may contain a payload to be appended.
+ * out A bson_t, which will be appended to if @cmd->payload is set.
+ *
+ * Pre-conditions:
+ * - @out is initialized.
+ * - cmd has a payload (i.e. is a write command).
+ *
+ * Post-conditions:
+ * - If @cmd->payload is set, then @out is appended to with the payload
+ * field's name ("documents" if insert, "updates" if update,
+ * "deletes" if delete) an the payload as a BSON array.
+ *
+ *--------------------------------------------------------------------------
+ */
+void
+_mongoc_cmd_append_payload_as_array (const mongoc_cmd_t *cmd, bson_t *out)
+{
+ int32_t doc_len;
+ bson_t doc;
+ const uint8_t *pos;
+ const char *field_name;
+ bson_t bson;
+ char str[16];
+ const char *key;
+ uint32_t i;
+
+ BSON_ASSERT (cmd->payload && cmd->payload_size);
+
+ /* make array from outgoing OP_MSG payload type 1 on an "insert",
+ * "update", or "delete" command. */
+ field_name = _mongoc_get_documents_field_name (cmd->command_name);
+ BSON_ASSERT (field_name);
+ BSON_ASSERT (BSON_APPEND_ARRAY_BEGIN (out, field_name, &bson));
+
+ pos = cmd->payload;
+ i = 0;
+ while (pos < cmd->payload + cmd->payload_size) {
+ memcpy (&doc_len, pos, sizeof (doc_len));
+ doc_len = BSON_UINT32_FROM_LE (doc_len);
+ BSON_ASSERT (bson_init_static (&doc, pos, (size_t) doc_len));
+ bson_uint32_to_string (i, &key, str, sizeof (str));
+ BSON_APPEND_DOCUMENT (&bson, key, &doc);
+
+ pos += doc_len;
+ i++;
+ }
+
+ bson_append_array_end (out, &bson);
+}
+
+/*--------------------------------------------------------------------------
+ *
+ * _mongoc_cmd_append_server_api --
+ * Append versioned API fields to a mongoc_cmd_t
+ *
+ * Arguments:
+ * cmd The mongoc_cmd_t, which will have versioned API fields added
+ * api A mongoc_server_api_t holding server API information
+ *
+ * Pre-conditions:
+ * - @api is initialized.
+ * - @command_body is initialised
+ *
+ *--------------------------------------------------------------------------
+ */
+void
+_mongoc_cmd_append_server_api (bson_t *command_body,
+ const mongoc_server_api_t *api)
+{
+ const char *string_version;
+
+ BSON_ASSERT (command_body);
+ BSON_ASSERT (api);
+
+ string_version = mongoc_server_api_version_to_string (api->version);
+
+ bson_append_utf8 (command_body, "apiVersion", -1, string_version, -1);
+
+ if (api->strict.is_set) {
+ bson_append_bool (command_body, "apiStrict", -1, api->strict.value);
+ }
+
+ if (api->deprecation_errors.is_set) {
+ bson_append_bool (command_body,
+ "apiDeprecationErrors",
+ -1,
+ api->deprecation_errors.value);
+ }
+}
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-collection-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-collection-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-collection-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-collection-private.h
diff --git a/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-collection.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-collection.c
new file mode 100644
index 00000000..38a2377a
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-collection.c
@@ -0,0 +1,3592 @@
+/*
+ * Copyright 2013 MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include <stdio.h>
+
+#include "mongoc-aggregate-private.h"
+#include "mongoc-bulk-operation.h"
+#include "mongoc-bulk-operation-private.h"
+#include "mongoc-change-stream-private.h"
+#include "mongoc-client-private.h"
+#include "mongoc-find-and-modify-private.h"
+#include "mongoc-find-and-modify.h"
+#include "mongoc-collection.h"
+#include "mongoc-collection-private.h"
+#include "mongoc-cursor-private.h"
+#include "mongoc-error.h"
+#include "mongoc-index.h"
+#include "mongoc-log.h"
+#include "mongoc-trace-private.h"
+#include "mongoc-read-concern-private.h"
+#include "mongoc-write-concern-private.h"
+#include "mongoc-read-prefs-private.h"
+#include "mongoc-util-private.h"
+#include "mongoc-write-command-private.h"
+#include "mongoc-opts-private.h"
+#include "mongoc-write-command-private.h"
+#include "mongoc-error-private.h"
+
+#undef MONGOC_LOG_DOMAIN
+#define MONGOC_LOG_DOMAIN "collection"
+
+static void
+_mongoc_collection_write_command_execute (
+ mongoc_write_command_t *command,
+ const mongoc_collection_t *collection,
+ const mongoc_write_concern_t *write_concern,
+ mongoc_client_session_t *cs,
+ mongoc_write_result_t *result)
+{
+ mongoc_server_stream_t *server_stream;
+
+ ENTRY;
+
+ server_stream = mongoc_cluster_stream_for_writes (
+ &collection->client->cluster, cs, NULL, &result->error);
+
+ if (!server_stream) {
+ /* result->error has been filled out */
+ EXIT;
+ }
+
+ _mongoc_write_command_execute (command,
+ collection->client,
+ server_stream,
+ collection->db,
+ collection->collection,
+ write_concern,
+ 0 /* offset */,
+ cs,
+ result);
+
+ mongoc_server_stream_cleanup (server_stream);
+
+ EXIT;
+}
+
+
+static void
+_mongoc_collection_write_command_execute_idl (
+ mongoc_write_command_t *command,
+ const mongoc_collection_t *collection,
+ mongoc_crud_opts_t *crud,
+ mongoc_write_result_t *result)
+{
+ mongoc_server_stream_t *server_stream;
+ bson_t reply;
+
+ ENTRY;
+
+ server_stream =
+ mongoc_cluster_stream_for_writes (&collection->client->cluster,
+ crud->client_session,
+ &reply,
+ &result->error);
+
+ if (!server_stream) {
+ /* result->error and reply have been filled out */
+ _mongoc_bson_array_copy_labels_to (&reply, &result->errorLabels);
+ bson_destroy (&reply);
+ EXIT;
+ }
+
+ if (_mongoc_client_session_in_txn (crud->client_session) &&
+ crud->writeConcern) {
+ bson_set_error (&result->error,
+ MONGOC_ERROR_COMMAND,
+ MONGOC_ERROR_COMMAND_INVALID_ARG,
+ "Cannot set write concern after starting transaction");
+ mongoc_server_stream_cleanup (server_stream);
+ EXIT;
+ }
+
+ if (!crud->writeConcern &&
+ !_mongoc_client_session_in_txn (crud->client_session)) {
+ crud->writeConcern = collection->write_concern;
+ crud->write_concern_owned = false;
+ }
+
+ _mongoc_write_command_execute_idl (command,
+ collection->client,
+ server_stream,
+ collection->db,
+ collection->collection,
+ 0 /* offset */,
+ crud,
+ result);
+
+ mongoc_server_stream_cleanup (server_stream);
+
+ EXIT;
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_collection_new --
+ *
+ * INTERNAL API
+ *
+ * Create a new mongoc_collection_t structure for the given client.
+ *
+ * @client must remain valid during the lifetime of this structure.
+ * @db is the db name of the collection.
+ * @collection is the name of the collection.
+ * @read_prefs is the default read preferences to apply or NULL.
+ * @read_concern is the default read concern to apply or NULL.
+ * @write_concern is the default write concern to apply or NULL.
+ *
+ * Returns:
+ * A newly allocated mongoc_collection_t that should be freed with
+ * mongoc_collection_destroy().
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+mongoc_collection_t *
+_mongoc_collection_new (mongoc_client_t *client,
+ const char *db,
+ const char *collection,
+ const mongoc_read_prefs_t *read_prefs,
+ const mongoc_read_concern_t *read_concern,
+ const mongoc_write_concern_t *write_concern)
+{
+ mongoc_collection_t *col;
+
+ ENTRY;
+
+ BSON_ASSERT_PARAM (client);
+ BSON_ASSERT_PARAM (db);
+ BSON_ASSERT_PARAM (collection);
+
+ col = (mongoc_collection_t *) bson_malloc0 (sizeof *col);
+ col->client = client;
+ col->write_concern = write_concern
+ ? mongoc_write_concern_copy (write_concern)
+ : mongoc_write_concern_new ();
+ col->read_concern = read_concern ? mongoc_read_concern_copy (read_concern)
+ : mongoc_read_concern_new ();
+ col->read_prefs = read_prefs ? mongoc_read_prefs_copy (read_prefs)
+ : mongoc_read_prefs_new (MONGOC_READ_PRIMARY);
+
+ col->ns = bson_strdup_printf ("%s.%s", db, collection);
+ col->db = bson_strdup (db);
+ col->collection = bson_strdup (collection);
+
+ col->collectionlen = (uint32_t) strlen (col->collection);
+ col->nslen = (uint32_t) strlen (col->ns);
+
+ col->gle = NULL;
+
+ RETURN (col);
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_collection_destroy --
+ *
+ * Release resources associated with @collection and frees the
+ * structure.
+ *
+ * Returns:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+void
+mongoc_collection_destroy (mongoc_collection_t *collection) /* IN */
+{
+ ENTRY;
+
+ if (!collection) {
+ EXIT;
+ }
+
+ bson_clear (&collection->gle);
+
+ if (collection->read_prefs) {
+ mongoc_read_prefs_destroy (collection->read_prefs);
+ collection->read_prefs = NULL;
+ }
+
+ if (collection->read_concern) {
+ mongoc_read_concern_destroy (collection->read_concern);
+ collection->read_concern = NULL;
+ }
+
+ if (collection->write_concern) {
+ mongoc_write_concern_destroy (collection->write_concern);
+ collection->write_concern = NULL;
+ }
+
+ bson_free (collection->collection);
+ bson_free (collection->db);
+ bson_free (collection->ns);
+ bson_free (collection);
+
+ EXIT;
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_collection_copy --
+ *
+ * Returns a copy of @collection that needs to be freed by calling
+ * mongoc_collection_destroy.
+ *
+ * Returns:
+ * A copy of this collection.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+mongoc_collection_t *
+mongoc_collection_copy (mongoc_collection_t *collection) /* IN */
+{
+ ENTRY;
+
+ BSON_ASSERT_PARAM (collection);
+
+ RETURN (_mongoc_collection_new (collection->client,
+ collection->db,
+ collection->collection,
+ collection->read_prefs,
+ collection->read_concern,
+ collection->write_concern));
+}
+
+
+mongoc_cursor_t *
+mongoc_collection_aggregate (mongoc_collection_t *collection, /* IN */
+ mongoc_query_flags_t flags, /* IN */
+ const bson_t *pipeline, /* IN */
+ const bson_t *opts, /* IN */
+ const mongoc_read_prefs_t *read_prefs) /* IN */
+{
+ return _mongoc_aggregate (collection->client,
+ collection->ns,
+ flags,
+ pipeline,
+ opts,
+ read_prefs,
+ collection->read_prefs,
+ collection->read_concern,
+ collection->write_concern);
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_collection_find --
+ *
+ * DEPRECATED: use mongoc_collection_find_with_opts.
+ *
+ * Performs a query against the configured MongoDB server. If @read_prefs
+ * is provided, it will be used to locate a MongoDB node in the cluster
+ * to deliver the query to.
+ *
+ * @flags may be bitwise-or'd flags or MONGOC_QUERY_NONE.
+ *
+ * @skip may contain the number of documents to skip before returning the
+ * matching document.
+ *
+ * @limit may contain the maximum number of documents that may be
+ * returned.
+ *
+ * This function will always return a cursor, with the exception of
+ * invalid API use.
+ *
+ * Parameters:
+ * @collection: A mongoc_collection_t.
+ * @flags: A bitwise or of mongoc_query_flags_t.
+ * @skip: The number of documents to skip.
+ * @limit: The maximum number of items.
+ * @batch_size: The batch size
+ * @query: The query to locate matching documents.
+ * @fields: The fields to return, or NULL for all fields.
+ * @read_prefs: Read preferences to choose cluster node.
+ *
+ * Returns:
+ * A newly allocated mongoc_cursor_t that should be freed with
+ * mongoc_cursor_destroy().
+ *
+ * The client used by mongoc_collection_t must be valid for the
+ * lifetime of the resulting mongoc_cursor_t.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+mongoc_cursor_t *
+mongoc_collection_find (mongoc_collection_t *collection, /* IN */
+ mongoc_query_flags_t flags, /* IN */
+ uint32_t skip, /* IN */
+ uint32_t limit, /* IN */
+ uint32_t batch_size, /* IN */
+ const bson_t *query, /* IN */
+ const bson_t *fields, /* IN */
+ const mongoc_read_prefs_t *read_prefs) /* IN */
+{
+ bool has_unwrapped;
+ bson_t unwrapped;
+ bson_error_t error = {0};
+ bson_t opts;
+ bool secondary_ok;
+ mongoc_cursor_t *cursor;
+ BSON_ASSERT_PARAM (collection);
+ BSON_ASSERT_PARAM (query);
+
+ bson_clear (&collection->gle);
+
+ bson_init (&opts);
+ _mongoc_cursor_flags_to_opts (flags, &opts, &secondary_ok);
+ /* check if the query is wrapped in $query */
+ has_unwrapped = _mongoc_cursor_translate_dollar_query_opts (
+ query, &opts, &unwrapped, &error);
+ if (!bson_empty0 (fields)) {
+ bson_append_document (
+ &opts, MONGOC_CURSOR_PROJECTION, MONGOC_CURSOR_PROJECTION_LEN, fields);
+ }
+ cursor = _mongoc_cursor_find_new (collection->client,
+ collection->ns,
+ has_unwrapped ? &unwrapped : query,
+ &opts,
+ read_prefs,
+ collection->read_prefs,
+ collection->read_concern);
+ if (skip) {
+ _mongoc_cursor_set_opt_int64 (cursor, MONGOC_CURSOR_SKIP, skip);
+ }
+ if (limit) {
+ /* limit must be cast to int32_t. Although the argument is a uint32_t,
+ * callers can specify a negative limit by casting to a signed int32_t
+ * value to uint32_t. E.g. to set a limit of -4, the caller passes
+ * UINT32_MAX - 3 */
+ (void) mongoc_cursor_set_limit (cursor, (int32_t) limit);
+ }
+ if (batch_size) {
+ mongoc_cursor_set_batch_size (cursor, batch_size);
+ }
+ bson_destroy (&unwrapped);
+ bson_destroy (&opts);
+
+ if (error.domain) {
+ memcpy (&cursor->error, &error, sizeof (error));
+ }
+
+ return cursor;
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_collection_find_with_opts --
+ *
+ * Create a cursor with a query filter. All other options are
+ * specified in a free-form BSON document.
+ *
+ * Parameters:
+ * @collection: A mongoc_collection_t.
+ * @filter: The query to locate matching documents.
+ * @opts: Other options.
+ * @read_prefs: Optional read preferences to choose cluster node.
+ *
+ * Returns:
+ * A newly allocated mongoc_cursor_t that should be freed with
+ * mongoc_cursor_destroy().
+ *
+ * The client used by mongoc_collection_t must be valid for the
+ * lifetime of the resulting mongoc_cursor_t.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+mongoc_cursor_t *
+mongoc_collection_find_with_opts (mongoc_collection_t *collection,
+ const bson_t *filter,
+ const bson_t *opts,
+ const mongoc_read_prefs_t *read_prefs)
+{
+ BSON_ASSERT_PARAM (collection);
+ BSON_ASSERT_PARAM (filter);
+
+ bson_clear (&collection->gle);
+
+ return _mongoc_cursor_find_new (collection->client,
+ collection->ns,
+ filter,
+ opts,
+ read_prefs,
+ collection->read_prefs,
+ collection->read_concern);
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_collection_command --
+ *
+ * Executes a command on a cluster node matching @read_prefs. If
+ * @read_prefs is not provided, it will be run on the primary node.
+ *
+ * This function will always return a mongoc_cursor_t.
+ *
+ * Parameters:
+ * @collection: A mongoc_collection_t.
+ * @flags: Bitwise-or'd flags for command.
+ * @skip: Number of documents to skip, typically 0.
+ * @limit : Number of documents to return
+ * @batch_size : Batch size
+ * @query: The command to execute.
+ * @fields: The fields to return, or NULL.
+ * @read_prefs: Command read preferences or NULL.
+ *
+ * Returns:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+mongoc_cursor_t *
+mongoc_collection_command (mongoc_collection_t *collection,
+ mongoc_query_flags_t flags,
+ uint32_t skip,
+ uint32_t limit,
+ uint32_t batch_size,
+ const bson_t *query,
+ const bson_t *fields,
+ const mongoc_read_prefs_t *read_prefs)
+{
+ char *ns;
+ mongoc_cursor_t *cursor;
+
+ BSON_ASSERT_PARAM (collection);
+ BSON_ASSERT_PARAM (query);
+
+ if (!read_prefs) {
+ read_prefs = collection->read_prefs;
+ }
+
+ bson_clear (&collection->gle);
+
+ if (NULL == strstr (collection->collection, "$cmd")) {
+ ns = bson_strdup_printf ("%s.$cmd", collection->db);
+ } else {
+ ns = bson_strdup (collection->db);
+ }
+
+ /* Server Selection Spec: "The generic command method has a default read
+ * preference of mode 'primary'. The generic command method MUST ignore any
+ * default read preference from client, database or collection
+ * configuration. The generic command method SHOULD allow an optional read
+ * preference argument."
+ */
+
+ /* flags, skip, limit, batch_size, fields are unused */
+ cursor = _mongoc_cursor_cmd_deprecated_new (
+ collection->client, ns, query, read_prefs);
+ bson_free (ns);
+ return cursor;
+}
+
+
+bool
+mongoc_collection_read_command_with_opts (mongoc_collection_t *collection,
+ const bson_t *command,
+ const mongoc_read_prefs_t *read_prefs,
+ const bson_t *opts,
+ bson_t *reply,
+ bson_error_t *error)
+{
+ BSON_ASSERT_PARAM (collection);
+
+ return _mongoc_client_command_with_opts (collection->client,
+ collection->db,
+ command,
+ MONGOC_CMD_READ,
+ opts,
+ MONGOC_QUERY_NONE,
+ read_prefs,
+ collection->read_prefs,
+ collection->read_concern,
+ collection->write_concern,
+ reply,
+ error);
+}
+
+
+bool
+mongoc_collection_write_command_with_opts (mongoc_collection_t *collection,
+ const bson_t *command,
+ const bson_t *opts,
+ bson_t *reply,
+ bson_error_t *error)
+{
+ BSON_ASSERT_PARAM (collection);
+
+ return _mongoc_client_command_with_opts (collection->client,
+ collection->db,
+ command,
+ MONGOC_CMD_WRITE,
+ opts,
+ MONGOC_QUERY_NONE,
+ NULL,
+ collection->read_prefs,
+ collection->read_concern,
+ collection->write_concern,
+ reply,
+ error);
+}
+
+
+bool
+mongoc_collection_read_write_command_with_opts (
+ mongoc_collection_t *collection,
+ const bson_t *command,
+ const mongoc_read_prefs_t *read_prefs /* IGNORED */,
+ const bson_t *opts,
+ bson_t *reply,
+ bson_error_t *error)
+{
+ BSON_ASSERT_PARAM (collection);
+
+ return _mongoc_client_command_with_opts (collection->client,
+ collection->db,
+ command,
+ MONGOC_CMD_RW,
+ opts,
+ MONGOC_QUERY_NONE,
+ read_prefs,
+ collection->read_prefs,
+ collection->read_concern,
+ collection->write_concern,
+ reply,
+ error);
+}
+
+
+bool
+mongoc_collection_command_with_opts (mongoc_collection_t *collection,
+ const bson_t *command,
+ const mongoc_read_prefs_t *read_prefs,
+ const bson_t *opts,
+ bson_t *reply,
+ bson_error_t *error)
+{
+ BSON_ASSERT_PARAM (collection);
+
+ /* Server Selection Spec: "The generic command method has a default read
+ * preference of mode 'primary'. The generic command method MUST ignore any
+ * default read preference from client, database or collection
+ * configuration. The generic command method SHOULD allow an optional read
+ * preference argument." */
+
+ return _mongoc_client_command_with_opts (collection->client,
+ collection->db,
+ command,
+ MONGOC_CMD_RAW,
+ opts,
+ MONGOC_QUERY_NONE,
+ read_prefs,
+ NULL /* default prefs */,
+ collection->read_concern,
+ collection->write_concern,
+ reply,
+ error);
+}
+
+
+bool
+mongoc_collection_command_simple (mongoc_collection_t *collection,
+ const bson_t *command,
+ const mongoc_read_prefs_t *read_prefs,
+ bson_t *reply,
+ bson_error_t *error)
+{
+ BSON_ASSERT_PARAM (collection);
+ BSON_ASSERT_PARAM (command);
+
+ bson_clear (&collection->gle);
+
+ /* Server Selection Spec: "The generic command method has a default read
+ * preference of mode 'primary'. The generic command method MUST ignore any
+ * default read preference from client, database or collection
+ * configuration. The generic command method SHOULD allow an optional read
+ * preference argument."
+ */
+
+ return _mongoc_client_command_with_opts (collection->client,
+ collection->db,
+ command,
+ MONGOC_CMD_RAW,
+ NULL /* opts */,
+ MONGOC_QUERY_NONE,
+ read_prefs,
+ NULL /* default prefs */,
+ NULL /* read concern */,
+ NULL /* write concern */,
+ reply,
+ error);
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_collection_count --
+ *
+ * Count the number of documents matching @query.
+ *
+ * Parameters:
+ * @flags: A mongoc_query_flags_t describing the query flags or 0.
+ * @query: The query to perform or NULL for {}.
+ * @skip: The $skip to perform within the query or 0.
+ * @limit: The $limit to perform within the query or 0.
+ * @read_prefs: desired read preferences or NULL.
+ * @error: A location for an error or NULL.
+ *
+ * Returns:
+ * -1 on failure; otherwise the number of matching documents.
+ *
+ * Side effects:
+ * @error is set upon failure if non-NULL.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+int64_t
+mongoc_collection_count (mongoc_collection_t *collection, /* IN */
+ mongoc_query_flags_t flags, /* IN */
+ const bson_t *query, /* IN */
+ int64_t skip, /* IN */
+ int64_t limit, /* IN */
+ const mongoc_read_prefs_t *read_prefs, /* IN */
+ bson_error_t *error) /* OUT */
+{
+ int64_t ret;
+ bson_t opts = BSON_INITIALIZER;
+
+ /* Complex types must be parts of `opts`, otherwise we can't
+ * follow various specs that require validation etc */
+ if (collection->read_concern->level != NULL) {
+ const bson_t *read_concern_bson;
+
+ read_concern_bson =
+ _mongoc_read_concern_get_bson (collection->read_concern);
+ BSON_APPEND_DOCUMENT (&opts, "readConcern", read_concern_bson);
+ }
+
+ /* Server Selection Spec: "may-use-secondary" commands SHOULD take a read
+ * preference argument and otherwise MUST use the default read preference
+ * from client, database or collection configuration. */
+ BEGIN_IGNORE_DEPRECATIONS
+ ret = mongoc_collection_count_with_opts (
+ collection, flags, query, skip, limit, &opts, read_prefs, error);
+ END_IGNORE_DEPRECATIONS
+
+ bson_destroy (&opts);
+ return ret;
+}
+
+
+int64_t
+mongoc_collection_count_with_opts (
+ mongoc_collection_t *collection, /* IN */
+ mongoc_query_flags_t flags, /* IN */
+ const bson_t *query, /* IN */
+ int64_t skip, /* IN */
+ int64_t limit, /* IN */
+ const bson_t *opts, /* IN */
+ const mongoc_read_prefs_t *read_prefs, /* IN */
+ bson_error_t *error) /* OUT */
+{
+ bson_iter_t iter;
+ int64_t ret = -1;
+ bool success;
+ bson_t reply;
+ bson_t cmd = BSON_INITIALIZER;
+ bson_t q;
+
+ ENTRY;
+
+ BSON_ASSERT_PARAM (collection);
+
+ bson_append_utf8 (
+ &cmd, "count", 5, collection->collection, collection->collectionlen);
+ if (query) {
+ bson_append_document (&cmd, "query", 5, query);
+ } else {
+ bson_init (&q);
+ bson_append_document (&cmd, "query", 5, &q);
+ bson_destroy (&q);
+ }
+ if (limit) {
+ bson_append_int64 (&cmd, "limit", 5, limit);
+ }
+ if (skip) {
+ bson_append_int64 (&cmd, "skip", 4, skip);
+ }
+
+ success = _mongoc_client_command_with_opts (collection->client,
+ collection->db,
+ &cmd,
+ MONGOC_CMD_READ,
+ opts,
+ flags,
+ read_prefs,
+ collection->read_prefs,
+ collection->read_concern,
+ collection->write_concern,
+ &reply,
+ error);
+
+ if (success) {
+ if (bson_iter_init_find (&iter, &reply, "n")) {
+ ret = bson_iter_as_int64 (&iter);
+ }
+ }
+
+ bson_destroy (&reply);
+ bson_destroy (&cmd);
+
+ RETURN (ret);
+}
+
+/* --------------------------------------------------------------------------
+ *
+ * _make_aggregate_for_edc --
+ *
+ * Construct an aggregate pipeline with the following form:
+ *
+ *
+ * { pipeline: [
+ * { $collStats: { count: {} } },
+ * { $group: { _id: 1, n: { $sum: $count } } },
+ * ]
+ * }
+ *
+ *--------------------------------------------------------------------------
+ */
+static void
+_make_aggregate_for_edc (const mongoc_collection_t *coll, bson_t *out)
+{
+ bson_t pipeline;
+ bson_t coll_stats_stage;
+ bson_t coll_stats_stage_doc;
+ bson_t group_stage;
+ bson_t group_stage_doc;
+ bson_t sum;
+ bson_t cursor_empty;
+ bson_t empty;
+
+ BSON_APPEND_UTF8 (out, "aggregate", coll->collection);
+ BSON_APPEND_DOCUMENT_BEGIN (out, "cursor", &cursor_empty);
+ bson_append_document_end (out, &cursor_empty);
+ BSON_APPEND_ARRAY_BEGIN (out, "pipeline", &pipeline);
+
+ BSON_APPEND_DOCUMENT_BEGIN (&pipeline, "0", &coll_stats_stage);
+ BSON_APPEND_DOCUMENT_BEGIN (
+ &coll_stats_stage, "$collStats", &coll_stats_stage_doc);
+ BSON_APPEND_DOCUMENT_BEGIN (&coll_stats_stage_doc, "count", &empty);
+ bson_append_document_end (&coll_stats_stage_doc, &empty);
+ bson_append_document_end (&coll_stats_stage, &coll_stats_stage_doc);
+ bson_append_document_end (&pipeline, &coll_stats_stage);
+
+ BSON_APPEND_DOCUMENT_BEGIN (&pipeline, "1", &group_stage);
+ BSON_APPEND_DOCUMENT_BEGIN (&group_stage, "$group", &group_stage_doc);
+ BSON_APPEND_INT32 (&group_stage_doc, "_id", 1);
+ BSON_APPEND_DOCUMENT_BEGIN (&group_stage_doc, "n", &sum);
+ BSON_APPEND_UTF8 (&sum, "$sum", "$count");
+ bson_append_document_end (&group_stage_doc, &sum);
+ bson_append_document_end (&group_stage, &group_stage_doc);
+ bson_append_document_end (&pipeline, &group_stage);
+ bson_append_array_end (out, &pipeline);
+}
+
+int64_t
+mongoc_collection_estimated_document_count (
+ mongoc_collection_t *coll,
+ const bson_t *opts,
+ const mongoc_read_prefs_t *read_prefs,
+ bson_t *reply,
+ bson_error_t *error)
+{
+ bson_iter_t iter;
+ int64_t count = -1;
+ bool ret;
+ bson_t reply_local;
+ bson_t *reply_ptr;
+ bson_t cmd = BSON_INITIALIZER;
+ mongoc_server_stream_t *server_stream = NULL;
+
+ ENTRY;
+
+ BSON_ASSERT_PARAM (coll);
+
+ server_stream =
+ mongoc_cluster_stream_for_reads (&coll->client->cluster,
+ read_prefs,
+ NULL,
+ reply,
+ /* Not aggregate-with-write */ false,
+ error);
+
+ if (opts && bson_has_field (opts, "sessionId")) {
+ bson_set_error (error,
+ MONGOC_ERROR_COMMAND,
+ MONGOC_ERROR_COMMAND_INVALID_ARG,
+ "Collection count must not specify explicit session");
+ GOTO (done);
+ }
+
+ reply_ptr = reply ? reply : &reply_local;
+ if (server_stream->sd->max_wire_version < WIRE_VERSION_4_9) {
+ /* On < 4.9, use actual count command for estimatedDocumentCount */
+ BSON_APPEND_UTF8 (&cmd, "count", coll->collection);
+ ret = _mongoc_client_command_with_opts (coll->client,
+ coll->db,
+ &cmd,
+ MONGOC_CMD_READ,
+ opts,
+ MONGOC_QUERY_NONE,
+ read_prefs,
+ coll->read_prefs,
+ coll->read_concern,
+ coll->write_concern,
+ reply_ptr,
+ error);
+ if (ret) {
+ if (bson_iter_init_find (&iter, reply_ptr, "n")) {
+ count = bson_iter_as_int64 (&iter);
+ }
+ }
+ } else {
+ /* On >= 4.9, use aggregate with collStats for estimatedDocumentCount */
+ _make_aggregate_for_edc (coll, &cmd);
+ ret = mongoc_collection_read_command_with_opts (
+ coll, &cmd, read_prefs, opts, reply_ptr, error);
+
+ if (!ret && error->code == MONGOC_ERROR_COLLECTION_DOES_NOT_EXIST) {
+ /* Collection does not exist. From spec: return 0 but no err:
+ * https://github.com/mongodb/specifications/blob/master/source/crud/crud.rst#estimateddocumentcount
+ */
+ if (reply) {
+ bson_reinit (reply);
+ }
+ memset (error, 0, sizeof *error);
+ count = 0;
+ GOTO (done);
+ }
+ if (ret && bson_iter_init (&iter, reply_ptr)) {
+ if (bson_iter_find_descendant (
+ &iter, "cursor.firstBatch.0.n", &iter)) {
+ count = bson_iter_as_int64 (&iter);
+ }
+ }
+ }
+
+done:
+ if (!reply) {
+ bson_destroy (&reply_local);
+ }
+ bson_destroy (&cmd);
+ mongoc_server_stream_cleanup (server_stream);
+
+ RETURN (count);
+}
+
+
+/* --------------------------------------------------------------------------
+ *
+ * _make_aggregate_for_count --
+ *
+ * Construct an aggregate pipeline with the following form:
+ * { pipeline: [
+ * { $match: {...} },
+ * { $group: { _id: 1, n: { sum: 1 } } },
+ * { $skip: ... },
+ * { $limit: ... }
+ * ]
+ * }
+ *
+ *--------------------------------------------------------------------------
+ */
+static void
+_make_aggregate_for_count (const mongoc_collection_t *coll,
+ const bson_t *filter,
+ const bson_t *opts,
+ bson_t *out)
+{
+ bson_iter_t iter;
+ bson_t pipeline;
+ bson_t match_stage;
+ bson_t group_stage;
+ bson_t group_stage_doc;
+ bson_t sum;
+ bson_t empty;
+ const char *keys[] = {"0", "1", "2", "3"};
+ int key = 0;
+
+ bson_init (out);
+ bson_append_utf8 (
+ out, "aggregate", 9, coll->collection, coll->collectionlen);
+ bson_append_document_begin (out, "cursor", 6, &empty);
+ bson_append_document_end (out, &empty);
+ bson_append_array_begin (out, "pipeline", 8, &pipeline);
+
+ bson_append_document_begin (&pipeline, keys[key++], 1, &match_stage);
+ bson_append_document (&match_stage, "$match", 6, filter);
+ bson_append_document_end (&pipeline, &match_stage);
+ /* if @opts includes "skip", or "count", append $skip and $count stages to
+ * the aggregate pipeline. */
+ if (opts && bson_iter_init_find (&iter, opts, "skip")) {
+ bson_t skip_stage;
+ bson_append_document_begin (&pipeline, keys[key++], 1, &skip_stage);
+ bson_append_value (&skip_stage, "$skip", 5, bson_iter_value (&iter));
+ bson_append_document_end (&pipeline, &skip_stage);
+ }
+ if (opts && bson_iter_init_find (&iter, opts, "limit")) {
+ bson_t limit_stage;
+ bson_append_document_begin (&pipeline, keys[key++], 1, &limit_stage);
+ bson_append_value (&limit_stage, "$limit", 6, bson_iter_value (&iter));
+ bson_append_document_end (&pipeline, &limit_stage);
+ }
+ bson_append_document_begin (&pipeline, keys[key], 1, &group_stage);
+ bson_append_document_begin (&group_stage, "$group", 6, &group_stage_doc);
+ bson_append_int32 (&group_stage_doc, "_id", 3, 1);
+ bson_append_document_begin (&group_stage_doc, "n", 1, &sum);
+ bson_append_int32 (&sum, "$sum", 4, 1);
+ bson_append_document_end (&group_stage_doc, &sum);
+ bson_append_document_end (&group_stage, &group_stage_doc);
+ bson_append_document_end (&pipeline, &group_stage);
+ bson_append_array_end (out, &pipeline);
+}
+
+
+int64_t
+mongoc_collection_count_documents (mongoc_collection_t *coll,
+ const bson_t *filter,
+ const bson_t *opts,
+ const mongoc_read_prefs_t *read_prefs,
+ bson_t *reply,
+ bson_error_t *error)
+{
+ bson_t aggregate_cmd;
+ bson_t aggregate_opts;
+ bool ret;
+ const bson_t *result;
+ mongoc_cursor_t *cursor = NULL;
+ int64_t count = -1;
+ bson_t cmd_reply;
+ bson_iter_t iter;
+
+ ENTRY;
+
+ BSON_ASSERT_PARAM (coll);
+ BSON_ASSERT_PARAM (filter);
+
+ _make_aggregate_for_count (coll, filter, opts, &aggregate_cmd);
+ bson_init (&aggregate_opts);
+ if (opts) {
+ bson_copy_to_excluding_noinit (
+ opts, &aggregate_opts, "skip", "limit", NULL);
+ }
+
+ ret = mongoc_collection_read_command_with_opts (
+ coll, &aggregate_cmd, read_prefs, &aggregate_opts, &cmd_reply, error);
+ bson_destroy (&aggregate_cmd);
+ bson_destroy (&aggregate_opts);
+ if (reply) {
+ bson_copy_to (&cmd_reply, reply);
+ }
+
+ if (!ret) {
+ bson_destroy (&cmd_reply);
+ GOTO (done);
+ }
+
+ /* steals reply */
+ cursor = mongoc_cursor_new_from_command_reply_with_opts (
+ coll->client, &cmd_reply, NULL);
+ BSON_ASSERT (mongoc_cursor_get_id (cursor) == 0);
+ ret = mongoc_cursor_next (cursor, &result);
+ if (!ret) {
+ if (mongoc_cursor_error (cursor, error)) {
+ GOTO (done);
+ } else {
+ count = 0;
+ GOTO (done);
+ }
+ }
+
+ if (bson_iter_init_find (&iter, result, "n") &&
+ BSON_ITER_HOLDS_INT (&iter)) {
+ count = bson_iter_as_int64 (&iter);
+ }
+
+done:
+ if (cursor) {
+ mongoc_cursor_destroy (cursor);
+ }
+ RETURN (count);
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_collection_drop --
+ *
+ * Request the MongoDB server drop the collection.
+ *
+ * Returns:
+ * true if successful; otherwise false and @error is set.
+ *
+ * Side effects:
+ * @error is set upon failure.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+bool
+mongoc_collection_drop (mongoc_collection_t *collection, /* IN */
+ bson_error_t *error) /* OUT */
+{
+ return mongoc_collection_drop_with_opts (collection, NULL, error);
+}
+
+
+bool
+mongoc_collection_drop_with_opts (mongoc_collection_t *collection,
+ const bson_t *opts,
+ bson_error_t *error)
+{
+ bool ret;
+ bson_t cmd;
+
+ BSON_ASSERT_PARAM (collection);
+
+ bson_init (&cmd);
+ bson_append_utf8 (
+ &cmd, "drop", 4, collection->collection, collection->collectionlen);
+
+ ret = _mongoc_client_command_with_opts (collection->client,
+ collection->db,
+ &cmd,
+ MONGOC_CMD_WRITE,
+ opts,
+ MONGOC_QUERY_NONE,
+ NULL, /* user prefs */
+ collection->read_prefs,
+ collection->read_concern,
+ collection->write_concern,
+ NULL, /* reply */
+ error);
+ bson_destroy (&cmd);
+
+ return ret;
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_collection_drop_index --
+ *
+ * Request the MongoDB server drop the named index.
+ *
+ * Returns:
+ * true if successful; otherwise false and @error is set.
+ *
+ * Side effects:
+ * @error is setup upon failure if non-NULL.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+bool
+mongoc_collection_drop_index (mongoc_collection_t *collection, /* IN */
+ const char *index_name, /* IN */
+ bson_error_t *error) /* OUT */
+{
+ return mongoc_collection_drop_index_with_opts (
+ collection, index_name, NULL, error);
+}
+
+
+bool
+mongoc_collection_drop_index_with_opts (mongoc_collection_t *collection,
+ const char *index_name,
+ const bson_t *opts,
+ bson_error_t *error)
+{
+ bool ret;
+ bson_t cmd;
+
+ BSON_ASSERT_PARAM (collection);
+ BSON_ASSERT_PARAM (index_name);
+
+ bson_init (&cmd);
+ bson_append_utf8 (&cmd,
+ "dropIndexes",
+ -1,
+ collection->collection,
+ collection->collectionlen);
+ bson_append_utf8 (&cmd, "index", -1, index_name, -1);
+
+ ret = _mongoc_client_command_with_opts (collection->client,
+ collection->db,
+ &cmd,
+ MONGOC_CMD_WRITE,
+ opts,
+ MONGOC_QUERY_NONE,
+ NULL, /* user prefs */
+ collection->read_prefs,
+ collection->read_concern,
+ collection->write_concern,
+ NULL, /* reply */
+ error);
+ bson_destroy (&cmd);
+
+ return ret;
+}
+
+
+char *
+mongoc_collection_keys_to_index_string (const bson_t *keys)
+{
+ bson_string_t *s;
+ bson_iter_t iter;
+ bson_type_t type;
+ int i = 0;
+
+ BSON_ASSERT_PARAM (keys);
+
+ if (!bson_iter_init (&iter, keys)) {
+ return NULL;
+ }
+
+ s = bson_string_new (NULL);
+
+ while (bson_iter_next (&iter)) {
+ /* Index type can be specified as a string ("2d") or as an integer
+ * representing direction */
+ type = bson_iter_type (&iter);
+ if (type == BSON_TYPE_UTF8) {
+ bson_string_append_printf (s,
+ (i++ ? "_%s_%s" : "%s_%s"),
+ bson_iter_key (&iter),
+ bson_iter_utf8 (&iter, NULL));
+ } else if (type == BSON_TYPE_INT32) {
+ bson_string_append_printf (s,
+ (i++ ? "_%s_%d" : "%s_%d"),
+ bson_iter_key (&iter),
+ bson_iter_int32 (&iter));
+ } else if (type == BSON_TYPE_INT64) {
+ bson_string_append_printf (s,
+ (i++ ? "_%s_%" PRId64 : "%s_%" PRId64),
+ bson_iter_key (&iter),
+ bson_iter_int64 (&iter));
+ } else {
+ bson_string_free (s, true);
+ return NULL;
+ }
+ }
+ return bson_string_free (s, false);
+}
+
+
+bool
+mongoc_collection_create_index (mongoc_collection_t *collection,
+ const bson_t *keys,
+ const mongoc_index_opt_t *opt,
+ bson_error_t *error)
+{
+ bson_t reply;
+ bool ret;
+
+ BEGIN_IGNORE_DEPRECATIONS
+
+ ret = mongoc_collection_create_index_with_opts (
+ collection, keys, opt, NULL, &reply, error);
+
+ END_IGNORE_DEPRECATIONS
+
+ bson_destroy (&reply);
+ return ret;
+}
+
+static bool
+_mongoc_collection_index_keys_equal (const bson_t *expected,
+ const bson_t *actual)
+{
+ bson_iter_t iter_expected;
+ bson_iter_t iter_actual;
+
+ bson_iter_init (&iter_expected, expected);
+ bson_iter_init (&iter_actual, actual);
+
+ while (bson_iter_next (&iter_expected)) {
+ /* If the key document has fewer items than expected, indexes are unequal
+ */
+ if (!bson_iter_next (&iter_actual)) {
+ return false;
+ }
+
+ /* If key order does not match, indexes are unequal */
+ if (strcmp (bson_iter_key (&iter_expected),
+ bson_iter_key (&iter_actual)) != 0) {
+ return false;
+ }
+
+ if (BSON_ITER_HOLDS_NUMBER (&iter_expected) &&
+ BSON_ITER_HOLDS_NUMBER (&iter_actual)) {
+ if (bson_iter_as_int64 (&iter_expected) !=
+ bson_iter_as_int64 (&iter_actual)) {
+ return false;
+ }
+ } else if (BSON_ITER_HOLDS_UTF8 (&iter_expected) &&
+ BSON_ITER_HOLDS_UTF8 (&iter_actual)) {
+ if (strcmp (bson_iter_utf8 (&iter_expected, NULL),
+ bson_iter_utf8 (&iter_actual, NULL)) != 0) {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+
+ /* If our expected document is exhausted, make sure there are no extra keys
+ * in the actual key document */
+ if (bson_iter_next (&iter_actual)) {
+ return false;
+ }
+
+ return true;
+}
+
+bool
+_mongoc_collection_create_index_if_not_exists (mongoc_collection_t *collection,
+ const bson_t *keys,
+ const bson_t *opts,
+ bson_error_t *error)
+{
+ mongoc_cursor_t *cursor;
+ bool index_exists;
+ bool r = false;
+ const bson_t *doc;
+ bson_iter_t iter;
+ bson_t inner_doc;
+ uint32_t data_len;
+ const uint8_t *data;
+ bson_t index;
+ bson_t command;
+
+ BSON_ASSERT (collection);
+ BSON_ASSERT (keys);
+
+ cursor = mongoc_collection_find_indexes_with_opts (collection, NULL);
+
+ index_exists = false;
+
+ while (mongoc_cursor_next (cursor, &doc) && !index_exists) {
+ r = bson_iter_init_find (&iter, doc, "key");
+ if (!r) {
+ continue;
+ }
+
+ bson_iter_document (&iter, &data_len, &data);
+ bson_init_static (&inner_doc, data, data_len);
+
+ if (_mongoc_collection_index_keys_equal (keys, &inner_doc)) {
+ index_exists = true;
+ }
+
+ bson_destroy (&inner_doc);
+ }
+
+ if (mongoc_cursor_error (cursor, error)) {
+ mongoc_cursor_destroy (cursor);
+ return false;
+ }
+
+ mongoc_cursor_destroy (cursor);
+
+ if (index_exists) {
+ return true;
+ }
+
+ if (opts) {
+ bson_copy_to (opts, &index);
+ } else {
+ bson_init (&index);
+ }
+
+ BSON_APPEND_DOCUMENT (&index, "key", keys);
+
+ if (!bson_has_field (&index, "name")) {
+ char *alloc_name = mongoc_collection_keys_to_index_string (keys);
+
+ if (!alloc_name) {
+ bson_set_error (
+ error,
+ MONGOC_ERROR_BSON,
+ MONGOC_ERROR_BSON_INVALID,
+ "Cannot generate index name from invalid `keys` argument");
+ GOTO (done);
+ }
+
+ BSON_APPEND_UTF8 (&index, "name", alloc_name);
+
+ bson_free (alloc_name);
+ }
+
+ bson_init (&command);
+ BCON_APPEND (&command,
+ "createIndexes",
+ BCON_UTF8 (mongoc_collection_get_name (collection)),
+ "indexes",
+ "[",
+ BCON_DOCUMENT (&index),
+ "]");
+
+ r = mongoc_collection_write_command_with_opts (
+ collection, &command, NULL, NULL, error);
+
+done:
+ bson_destroy (&index);
+ bson_destroy (&command);
+
+ return r;
+}
+
+bool
+mongoc_collection_create_index_with_opts (mongoc_collection_t *collection,
+ const bson_t *keys,
+ const mongoc_index_opt_t *opt,
+ const bson_t *opts,
+ bson_t *reply,
+ bson_error_t *error)
+{
+ mongoc_create_index_opts_t parsed;
+ mongoc_cmd_parts_t parts;
+ const mongoc_index_opt_t *def_opt;
+ const mongoc_index_opt_geo_t *def_geo;
+ const char *name;
+ bson_t cmd = BSON_INITIALIZER;
+ bson_t ar;
+ bson_t doc;
+ bson_t storage_doc;
+ bson_t wt_doc;
+ const mongoc_index_opt_geo_t *geo_opt;
+ const mongoc_index_opt_storage_t *storage_opt;
+ const mongoc_index_opt_wt_t *wt_opt;
+ char *alloc_name = NULL;
+ bool ret = false;
+ bool reply_initialized = false;
+ bool has_collation = false;
+ mongoc_server_stream_t *server_stream = NULL;
+ mongoc_cluster_t *cluster;
+
+ ENTRY;
+
+ BSON_ASSERT_PARAM (collection);
+ BSON_ASSERT_PARAM (keys);
+
+ def_opt = mongoc_index_opt_get_default ();
+ opt = opt ? opt : def_opt;
+
+ mongoc_cmd_parts_init (
+ &parts, collection->client, collection->db, MONGOC_QUERY_NONE, &cmd);
+ parts.is_write_command = true;
+
+ if (!_mongoc_create_index_opts_parse (
+ collection->client, opts, &parsed, error)) {
+ GOTO (done);
+ }
+
+ if (!parsed.writeConcern) {
+ parsed.writeConcern = collection->write_concern;
+ parsed.write_concern_owned = false;
+ }
+
+ /*
+ * Generate the key name if it was not provided.
+ */
+ name = (opt->name != def_opt->name) ? opt->name : NULL;
+ if (!name) {
+ alloc_name = mongoc_collection_keys_to_index_string (keys);
+ if (alloc_name) {
+ name = alloc_name;
+ } else {
+ bson_set_error (
+ error,
+ MONGOC_ERROR_BSON,
+ MONGOC_ERROR_BSON_INVALID,
+ "Cannot generate index name from invalid `keys` argument");
+ GOTO (done);
+ }
+ }
+
+ /*
+ * Build our createIndexes command to send to the server.
+ */
+ BSON_ASSERT (
+ BSON_APPEND_UTF8 (&cmd, "createIndexes", collection->collection));
+ bson_append_array_begin (&cmd, "indexes", 7, &ar);
+ bson_append_document_begin (&ar, "0", 1, &doc);
+ BSON_ASSERT (BSON_APPEND_DOCUMENT (&doc, "key", keys));
+ BSON_ASSERT (BSON_APPEND_UTF8 (&doc, "name", name));
+ if (opt->background) {
+ BSON_ASSERT (BSON_APPEND_BOOL (&doc, "background", true));
+ }
+ if (opt->unique) {
+ BSON_ASSERT (BSON_APPEND_BOOL (&doc, "unique", true));
+ }
+ if (opt->drop_dups) {
+ BSON_ASSERT (BSON_APPEND_BOOL (&doc, "dropDups", true));
+ }
+ if (opt->sparse) {
+ BSON_ASSERT (BSON_APPEND_BOOL (&doc, "sparse", true));
+ }
+ if (opt->expire_after_seconds != def_opt->expire_after_seconds) {
+ BSON_ASSERT (BSON_APPEND_INT32 (
+ &doc, "expireAfterSeconds", opt->expire_after_seconds));
+ }
+ if (opt->v != def_opt->v) {
+ BSON_ASSERT (BSON_APPEND_INT32 (&doc, "v", opt->v));
+ }
+ if (opt->weights && (opt->weights != def_opt->weights)) {
+ BSON_ASSERT (BSON_APPEND_DOCUMENT (&doc, "weights", opt->weights));
+ }
+ if (opt->default_language != def_opt->default_language) {
+ BSON_ASSERT (
+ BSON_APPEND_UTF8 (&doc, "default_language", opt->default_language));
+ }
+ if (opt->language_override != def_opt->language_override) {
+ BSON_ASSERT (
+ BSON_APPEND_UTF8 (&doc, "language_override", opt->language_override));
+ }
+ if (opt->partial_filter_expression) {
+ BSON_ASSERT (BSON_APPEND_DOCUMENT (
+ &doc, "partialFilterExpression", opt->partial_filter_expression));
+ }
+ if (opt->collation) {
+ BSON_ASSERT (BSON_APPEND_DOCUMENT (&doc, "collation", opt->collation));
+ has_collation = true;
+ }
+ if (opt->geo_options) {
+ geo_opt = opt->geo_options;
+ def_geo = mongoc_index_opt_geo_get_default ();
+ if (geo_opt->twod_sphere_version != def_geo->twod_sphere_version) {
+ BSON_ASSERT (BSON_APPEND_INT32 (
+ &doc, "2dsphereIndexVersion", geo_opt->twod_sphere_version));
+ }
+ if (geo_opt->twod_bits_precision != def_geo->twod_bits_precision) {
+ BSON_ASSERT (
+ BSON_APPEND_INT32 (&doc, "bits", geo_opt->twod_bits_precision));
+ }
+ if (geo_opt->twod_location_min != def_geo->twod_location_min) {
+ BSON_ASSERT (
+ BSON_APPEND_DOUBLE (&doc, "min", geo_opt->twod_location_min));
+ }
+ if (geo_opt->twod_location_max != def_geo->twod_location_max) {
+ BSON_ASSERT (
+ BSON_APPEND_DOUBLE (&doc, "max", geo_opt->twod_location_max));
+ }
+ if (geo_opt->haystack_bucket_size != def_geo->haystack_bucket_size) {
+ BSON_ASSERT (BSON_APPEND_DOUBLE (
+ &doc, "bucketSize", geo_opt->haystack_bucket_size));
+ }
+ }
+
+ if (opt->storage_options) {
+ storage_opt = opt->storage_options;
+ switch (storage_opt->type) {
+ case MONGOC_INDEX_STORAGE_OPT_WIREDTIGER:
+ wt_opt = (mongoc_index_opt_wt_t *) storage_opt;
+ BSON_APPEND_DOCUMENT_BEGIN (&doc, "storageEngine", &storage_doc);
+ BSON_APPEND_DOCUMENT_BEGIN (&storage_doc, "wiredTiger", &wt_doc);
+ BSON_ASSERT (
+ BSON_APPEND_UTF8 (&wt_doc, "configString", wt_opt->config_str));
+ bson_append_document_end (&storage_doc, &wt_doc);
+ bson_append_document_end (&doc, &storage_doc);
+ break;
+ default:
+ break;
+ }
+ }
+
+ bson_append_document_end (&ar, &doc);
+ bson_append_array_end (&cmd, &ar);
+
+ server_stream = mongoc_cluster_stream_for_writes (
+ &collection->client->cluster, parsed.client_session, reply, error);
+
+ if (!server_stream) {
+ reply_initialized = true;
+ GOTO (done);
+ }
+
+ if (!mongoc_cmd_parts_set_write_concern (&parts,
+ parsed.writeConcern,
+ server_stream->sd->max_wire_version,
+ error)) {
+ GOTO (done);
+ }
+
+ if (has_collation &&
+ server_stream->sd->max_wire_version < WIRE_VERSION_COLLATION) {
+ bson_set_error (error,
+ MONGOC_ERROR_COMMAND,
+ MONGOC_ERROR_PROTOCOL_BAD_WIRE_VERSION,
+ "The selected server does not support collation");
+ GOTO (done);
+ }
+
+ parts.assembled.session = parsed.client_session;
+ if (!bson_concat (&parts.extra, &parsed.extra)) {
+ bson_set_error (error,
+ MONGOC_ERROR_COMMAND,
+ MONGOC_ERROR_COMMAND_INVALID_ARG,
+ "'opts' is too large");
+ GOTO (done);
+ }
+
+ cluster = &collection->client->cluster;
+ if (mongoc_cmd_parts_assemble (&parts, server_stream, error)) {
+ ret = mongoc_cluster_run_command_monitored (
+ cluster, &parts.assembled, reply, error);
+ } else {
+ _mongoc_bson_init_if_set (reply);
+ }
+
+ reply_initialized = true;
+
+ if (ret) {
+ if (reply) {
+ ret = !_mongoc_parse_wc_err (reply, error);
+ }
+ }
+
+done:
+ bson_destroy (&cmd);
+ bson_free (alloc_name);
+ _mongoc_create_index_opts_cleanup (&parsed);
+ mongoc_server_stream_cleanup (server_stream);
+ mongoc_cmd_parts_cleanup (&parts);
+ if (!reply_initialized && reply) {
+ bson_init (reply);
+ }
+
+ RETURN (ret);
+}
+
+
+bool
+mongoc_collection_ensure_index (mongoc_collection_t *collection,
+ const bson_t *keys,
+ const mongoc_index_opt_t *opt,
+ bson_error_t *error)
+{
+ BEGIN_IGNORE_DEPRECATIONS
+ return mongoc_collection_create_index (collection, keys, opt, error);
+ END_IGNORE_DEPRECATIONS
+}
+
+
+mongoc_cursor_t *
+mongoc_collection_find_indexes (mongoc_collection_t *collection,
+ bson_error_t *error)
+{
+ mongoc_cursor_t *cursor;
+
+ cursor = mongoc_collection_find_indexes_with_opts (collection, NULL);
+
+ (void) mongoc_cursor_error (cursor, error);
+
+ return cursor;
+}
+
+
+mongoc_cursor_t *
+mongoc_collection_find_indexes_with_opts (mongoc_collection_t *collection,
+ const bson_t *opts)
+{
+ mongoc_cursor_t *cursor;
+ bson_t cmd = BSON_INITIALIZER;
+ bson_t child;
+ bson_error_t error;
+
+ BSON_ASSERT_PARAM (collection);
+
+ bson_append_utf8 (&cmd,
+ "listIndexes",
+ -1,
+ collection->collection,
+ collection->collectionlen);
+
+ BSON_APPEND_DOCUMENT_BEGIN (&cmd, "cursor", &child);
+ bson_append_document_end (&cmd, &child);
+
+ /* No read preference. Index Enumeration Spec: "run listIndexes on the
+ * primary node in replicaSet mode". */
+ cursor = _mongoc_cursor_cmd_new (
+ collection->client, collection->ns, &cmd, opts, NULL, NULL, NULL);
+
+ if (!mongoc_cursor_error (cursor, &error)) {
+ _mongoc_cursor_prime (cursor);
+ }
+
+ if (mongoc_cursor_error (cursor, &error) &&
+ error.code == MONGOC_ERROR_COLLECTION_DOES_NOT_EXIST) {
+ /* collection does not exist. from spec: return no documents but no err:
+ * https://github.com/mongodb/specifications/blob/master/source/enumerate-indexes.rst#enumeration-getting-index-information
+ */
+ _mongoc_cursor_set_empty (cursor);
+ }
+
+ bson_destroy (&cmd);
+
+ return cursor;
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_collection_insert_bulk --
+ *
+ * Bulk insert documents into a MongoDB collection.
+ *
+ * Parameters:
+ * @collection: A mongoc_collection_t.
+ * @flags: flags for the insert or 0.
+ * @documents: The documents to insert.
+ * @n_documents: The number of documents to insert.
+ * @write_concern: A write concern or NULL.
+ * @error: a location for an error or NULL.
+ *
+ * Returns:
+ * true if successful; otherwise false and @error is set.
+ *
+ * If the write concern does not dictate checking the result of the
+ * insert, then true may be returned even though the document was
+ * not actually inserted on the MongoDB server or cluster.
+ *
+ * Side effects:
+ * @collection->gle is setup, depending on write_concern->w value.
+ * @error may be set upon failure if non-NULL.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+bool
+mongoc_collection_insert_bulk (mongoc_collection_t *collection,
+ mongoc_insert_flags_t flags,
+ const bson_t **documents,
+ uint32_t n_documents,
+ const mongoc_write_concern_t *write_concern,
+ bson_error_t *error)
+{
+ mongoc_write_command_t command;
+ mongoc_write_result_t result;
+ mongoc_bulk_write_flags_t write_flags = MONGOC_BULK_WRITE_FLAGS_INIT;
+ uint32_t i;
+ bool ret;
+
+ BSON_ASSERT_PARAM (collection);
+ BSON_ASSERT_PARAM (documents);
+
+ if (!write_concern) {
+ write_concern = collection->write_concern;
+ }
+
+ if (!(flags & MONGOC_INSERT_NO_VALIDATE)) {
+ for (i = 0; i < n_documents; i++) {
+ if (!_mongoc_validate_new_document (
+ documents[i], _mongoc_default_insert_vflags, error)) {
+ RETURN (false);
+ }
+ }
+ }
+
+ bson_clear (&collection->gle);
+
+ _mongoc_write_result_init (&result);
+
+ write_flags.ordered = !(flags & MONGOC_INSERT_CONTINUE_ON_ERROR);
+
+ _mongoc_write_command_init_insert (
+ &command,
+ NULL,
+ NULL,
+ write_flags,
+ ++collection->client->cluster.operation_id);
+
+ for (i = 0; i < n_documents; i++) {
+ _mongoc_write_command_insert_append (&command, documents[i]);
+ }
+
+ _mongoc_collection_write_command_execute (
+ &command, collection, write_concern, NULL, &result);
+
+ collection->gle = bson_new ();
+ ret = MONGOC_WRITE_RESULT_COMPLETE (&result,
+ collection->client->error_api_version,
+ write_concern,
+ /* no error domain override */
+ (mongoc_error_domain_t) 0,
+ collection->gle,
+ error);
+
+ _mongoc_write_result_destroy (&result);
+ _mongoc_write_command_destroy (&command);
+
+ return ret;
+}
+
+
+bool
+mongoc_collection_insert (mongoc_collection_t *collection,
+ mongoc_insert_flags_t flags,
+ const bson_t *document,
+ const mongoc_write_concern_t *write_concern,
+ bson_error_t *error)
+{
+ bson_t opts = BSON_INITIALIZER;
+ bson_t reply;
+ bool r;
+
+ bson_clear (&collection->gle);
+
+ if (flags & MONGOC_INSERT_NO_VALIDATE) {
+ bson_append_bool (&opts, "validate", 8, false);
+ }
+
+ if (write_concern) {
+ mongoc_write_concern_append ((mongoc_write_concern_t *) write_concern,
+ &opts);
+ }
+
+ r =
+ mongoc_collection_insert_one (collection, document, &opts, &reply, error);
+
+ collection->gle = bson_copy (&reply);
+ bson_destroy (&reply);
+ bson_destroy (&opts);
+
+ return r;
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_collection_insert_one --
+ *
+ * Insert a document into a MongoDB collection.
+ *
+ * Parameters:
+ * @collection: A mongoc_collection_t.
+ * @document: The document to insert.
+ * @opts: Standard command options.
+ * @reply: Optional. Uninitialized doc to receive the update result.
+ * @error: A location for an error or NULL.
+ *
+ * Returns:
+ * true if successful; otherwise false and @error is set.
+ *
+ * If the write concern does not dictate checking the result of the
+ * insert, then true may be returned even though the document was
+ * not actually inserted on the MongoDB server or cluster.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+bool
+mongoc_collection_insert_one (mongoc_collection_t *collection,
+ const bson_t *document,
+ const bson_t *opts,
+ bson_t *reply,
+ bson_error_t *error)
+{
+ mongoc_insert_one_opts_t insert_one_opts;
+ mongoc_write_command_t command;
+ mongoc_write_result_t result;
+ bool ret = false;
+
+ ENTRY;
+
+ BSON_ASSERT_PARAM (collection);
+ BSON_ASSERT_PARAM (document);
+
+ _mongoc_bson_init_if_set (reply);
+
+ if (!_mongoc_insert_one_opts_parse (
+ collection->client, opts, &insert_one_opts, error)) {
+ GOTO (done);
+ }
+
+ if (!_mongoc_validate_new_document (
+ document, insert_one_opts.crud.validate, error)) {
+ GOTO (done);
+ }
+
+ _mongoc_write_result_init (&result);
+ _mongoc_write_command_init_insert_idl (
+ &command,
+ document,
+ &insert_one_opts.extra,
+ ++collection->client->cluster.operation_id);
+
+ command.flags.bypass_document_validation = insert_one_opts.bypass;
+ _mongoc_collection_write_command_execute_idl (
+ &command, collection, &insert_one_opts.crud, &result);
+
+ ret = MONGOC_WRITE_RESULT_COMPLETE (&result,
+ collection->client->error_api_version,
+ insert_one_opts.crud.writeConcern,
+ /* no error domain override */
+ (mongoc_error_domain_t) 0,
+ reply,
+ error,
+ "insertedCount");
+
+ _mongoc_write_result_destroy (&result);
+ _mongoc_write_command_destroy (&command);
+
+done:
+ _mongoc_insert_one_opts_cleanup (&insert_one_opts);
+ RETURN (ret);
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_collection_insert_many --
+ *
+ * Insert documents into a MongoDB collection. Replaces
+ * mongoc_collection_insert_bulk.
+ *
+ * Parameters:
+ * @collection: A mongoc_collection_t.
+ * @documents: The documents to insert.
+ * @n_documents: Length of @documents array.
+ * @opts: Standard command options.
+ * @reply: Optional. Uninitialized doc to receive the update result.
+ * @error: A location for an error or NULL.
+ *
+ * Returns:
+ * true if successful; otherwise false and @error is set.
+ *
+ * If the write concern does not dictate checking the result of the
+ * insert, then true may be returned even though the document was
+ * not actually inserted on the MongoDB server or cluster.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+bool
+mongoc_collection_insert_many (mongoc_collection_t *collection,
+ const bson_t **documents,
+ size_t n_documents,
+ const bson_t *opts,
+ bson_t *reply,
+ bson_error_t *error)
+{
+ mongoc_insert_many_opts_t insert_many_opts;
+ mongoc_write_command_t command;
+ mongoc_write_result_t result;
+ size_t i;
+ bool ret;
+
+ ENTRY;
+
+ BSON_ASSERT_PARAM (collection);
+ BSON_ASSERT_PARAM (documents);
+
+ _mongoc_bson_init_if_set (reply);
+
+ if (!_mongoc_insert_many_opts_parse (
+ collection->client, opts, &insert_many_opts, error)) {
+ _mongoc_insert_many_opts_cleanup (&insert_many_opts);
+ return false;
+ }
+
+ _mongoc_write_result_init (&result);
+ _mongoc_write_command_init_insert_idl (
+ &command,
+ NULL,
+ &insert_many_opts.extra,
+ ++collection->client->cluster.operation_id);
+
+ command.flags.ordered = insert_many_opts.ordered;
+ command.flags.bypass_document_validation = insert_many_opts.bypass;
+
+ for (i = 0; i < n_documents; i++) {
+ if (!_mongoc_validate_new_document (
+ documents[i], insert_many_opts.crud.validate, error)) {
+ ret = false;
+ GOTO (done);
+ }
+
+ _mongoc_write_command_insert_append (&command, documents[i]);
+ }
+
+ _mongoc_collection_write_command_execute_idl (
+ &command, collection, &insert_many_opts.crud, &result);
+
+ ret = MONGOC_WRITE_RESULT_COMPLETE (&result,
+ collection->client->error_api_version,
+ insert_many_opts.crud.writeConcern,
+ /* no error domain override */
+ (mongoc_error_domain_t) 0,
+ reply,
+ error,
+ "insertedCount");
+
+done:
+ _mongoc_write_result_destroy (&result);
+ _mongoc_write_command_destroy (&command);
+ _mongoc_insert_many_opts_cleanup (&insert_many_opts);
+
+ RETURN (ret);
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_collection_update --
+ *
+ * Updates one or more documents matching @selector with @update.
+ *
+ * Parameters:
+ * @collection: A mongoc_collection_t.
+ * @flags: The flags for the update.
+ * @selector: A bson_t containing your selector.
+ * @update: A bson_t containing your update document.
+ * @write_concern: The write concern or NULL.
+ * @error: A location for an error or NULL.
+ *
+ * Returns:
+ * true if successful; otherwise false and @error is set.
+ *
+ * Side effects:
+ * @collection->gle is setup, depending on write_concern->w value.
+ * @error is setup upon failure.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+bool
+mongoc_collection_update (mongoc_collection_t *collection,
+ mongoc_update_flags_t uflags,
+ const bson_t *selector,
+ const bson_t *update,
+ const mongoc_write_concern_t *write_concern,
+ bson_error_t *error)
+{
+ mongoc_bulk_write_flags_t write_flags = MONGOC_BULK_WRITE_FLAGS_INIT;
+ mongoc_write_command_t command;
+ mongoc_write_result_t result;
+ bson_iter_t iter;
+ bool ret;
+ int flags = uflags;
+ bson_t opts;
+
+ ENTRY;
+
+ BSON_ASSERT_PARAM (collection);
+ BSON_ASSERT_PARAM (selector);
+ BSON_ASSERT_PARAM (update);
+
+ bson_clear (&collection->gle);
+
+ if (!write_concern) {
+ write_concern = collection->write_concern;
+ }
+
+ if (!((uint32_t) flags & MONGOC_UPDATE_NO_VALIDATE) &&
+ bson_iter_init (&iter, update) && bson_iter_next (&iter)) {
+ if (bson_iter_key (&iter)[0] == '$') {
+ /* update document, all keys must be $-operators */
+ if (!_mongoc_validate_update (
+ update, _mongoc_default_update_vflags, error)) {
+ return false;
+ }
+ } else {
+ if (!_mongoc_validate_replace (
+ update, _mongoc_default_replace_vflags, error)) {
+ return false;
+ }
+ }
+ }
+
+ bson_init (&opts);
+ BSON_APPEND_BOOL (&opts, "upsert", !!(flags & MONGOC_UPDATE_UPSERT));
+ BSON_APPEND_BOOL (&opts, "multi", !!(flags & MONGOC_UPDATE_MULTI_UPDATE));
+
+ _mongoc_write_result_init (&result);
+ _mongoc_write_command_init_update (
+ &command,
+ selector,
+ update,
+ &opts,
+ write_flags,
+ ++collection->client->cluster.operation_id);
+ bson_destroy (&opts);
+
+ command.flags.has_multi_write = !!(flags & MONGOC_UPDATE_MULTI_UPDATE);
+
+ _mongoc_collection_write_command_execute (
+ &command, collection, write_concern, NULL, &result);
+
+ collection->gle = bson_new ();
+ ret = MONGOC_WRITE_RESULT_COMPLETE (&result,
+ collection->client->error_api_version,
+ write_concern,
+ /* no error domain override */
+ (mongoc_error_domain_t) 0,
+ collection->gle,
+ error);
+
+ _mongoc_write_result_destroy (&result);
+ _mongoc_write_command_destroy (&command);
+
+ RETURN (ret);
+}
+
+static bool
+_mongoc_collection_update_or_replace (mongoc_collection_t *collection,
+ const bson_t *selector,
+ const bson_t *update,
+ mongoc_update_opts_t *update_opts,
+ bool multi,
+ bool bypass,
+ const bson_t *array_filters,
+ bson_t *extra,
+ bson_t *reply,
+ bson_error_t *error)
+{
+ mongoc_write_command_t command;
+ mongoc_write_result_t result;
+ mongoc_server_stream_t *server_stream = NULL;
+ bool reply_initialized = false;
+ bool ret = false;
+
+ ENTRY;
+
+ BSON_ASSERT_PARAM (collection);
+ BSON_ASSERT_PARAM (selector);
+ BSON_ASSERT_PARAM (update);
+
+ if (update_opts->upsert) {
+ bson_append_bool (extra, "upsert", 6, true);
+ }
+
+ if (!bson_empty (&update_opts->collation)) {
+ bson_append_document (extra, "collation", 9, &update_opts->collation);
+ }
+
+ if (update_opts->hint.value_type) {
+ bson_append_value (extra, "hint", 4, &update_opts->hint);
+ }
+
+ if (!bson_empty0 (array_filters)) {
+ bson_append_array (extra, "arrayFilters", 12, array_filters);
+ }
+
+ if (multi) {
+ bson_append_bool (extra, "multi", 5, true);
+ }
+
+ _mongoc_write_result_init (&result);
+ _mongoc_write_command_init_update_idl (
+ &command,
+ selector,
+ update,
+ extra,
+ ++collection->client->cluster.operation_id);
+
+ command.flags.has_multi_write = multi;
+ command.flags.bypass_document_validation = bypass;
+ if (!bson_empty (&update_opts->collation)) {
+ command.flags.has_collation = true;
+ }
+ if (update_opts->hint.value_type) {
+ command.flags.has_update_hint = true;
+ }
+
+ server_stream =
+ mongoc_cluster_stream_for_writes (&collection->client->cluster,
+ update_opts->crud.client_session,
+ reply,
+ error);
+
+ if (!server_stream) {
+ /* mongoc_cluster_stream_for_writes inits reply on error */
+ reply_initialized = true;
+ GOTO (done);
+ }
+
+ if (!bson_empty0 (array_filters)) {
+ if (server_stream->sd->max_wire_version < WIRE_VERSION_ARRAY_FILTERS) {
+ bson_set_error (error,
+ MONGOC_ERROR_COMMAND,
+ MONGOC_ERROR_PROTOCOL_BAD_WIRE_VERSION,
+ "The selected server does not support array filters");
+ GOTO (done);
+ }
+
+ if (!mongoc_write_concern_is_acknowledged (
+ update_opts->crud.writeConcern)) {
+ bson_set_error (error,
+ MONGOC_ERROR_COMMAND,
+ MONGOC_ERROR_PROTOCOL_BAD_WIRE_VERSION,
+ "Cannot use array filters with unacknowledged writes");
+ GOTO (done);
+ }
+ }
+
+ if (_mongoc_client_session_in_txn (update_opts->crud.client_session) &&
+ update_opts->crud.writeConcern) {
+ bson_set_error (error,
+ MONGOC_ERROR_COMMAND,
+ MONGOC_ERROR_COMMAND_INVALID_ARG,
+ "Cannot set write concern after starting transaction");
+ GOTO (done);
+ }
+
+ if (!update_opts->crud.writeConcern &&
+ !_mongoc_client_session_in_txn (update_opts->crud.client_session)) {
+ update_opts->crud.writeConcern = collection->write_concern;
+ update_opts->crud.write_concern_owned = false;
+ }
+
+ _mongoc_write_command_execute_idl (&command,
+ collection->client,
+ server_stream,
+ collection->db,
+ collection->collection,
+ 0 /* offset */,
+ &update_opts->crud,
+ &result);
+
+ _mongoc_bson_init_if_set (reply);
+ reply_initialized = true;
+
+ /* set fields described in CRUD spec for the UpdateResult */
+ ret = MONGOC_WRITE_RESULT_COMPLETE (&result,
+ collection->client->error_api_version,
+ update_opts->crud.writeConcern,
+ /* no error domain override */
+ (mongoc_error_domain_t) 0,
+ reply,
+ error,
+ "modifiedCount",
+ "matchedCount",
+ "upsertedCount",
+ "upsertedId");
+
+done:
+ _mongoc_write_result_destroy (&result);
+ mongoc_server_stream_cleanup (server_stream);
+ _mongoc_write_command_destroy (&command);
+
+ if (!reply_initialized) {
+ _mongoc_bson_init_if_set (reply);
+ }
+
+ RETURN (ret);
+}
+
+bool
+mongoc_collection_update_one (mongoc_collection_t *collection,
+ const bson_t *selector,
+ const bson_t *update,
+ const bson_t *opts,
+ bson_t *reply,
+ bson_error_t *error)
+{
+ mongoc_update_one_opts_t update_one_opts;
+ bool ret;
+
+ ENTRY;
+
+ BSON_ASSERT_PARAM (collection);
+ BSON_ASSERT_PARAM (update);
+
+ if (!_mongoc_update_one_opts_parse (
+ collection->client, opts, &update_one_opts, error)) {
+ _mongoc_update_one_opts_cleanup (&update_one_opts);
+ _mongoc_bson_init_if_set (reply);
+ return false;
+ }
+
+ if (!_mongoc_validate_update (
+ update, update_one_opts.update.crud.validate, error)) {
+ _mongoc_update_one_opts_cleanup (&update_one_opts);
+ _mongoc_bson_init_if_set (reply);
+ return false;
+ }
+
+ ret = _mongoc_collection_update_or_replace (collection,
+ selector,
+ update,
+ &update_one_opts.update,
+ false /* multi */,
+ update_one_opts.update.bypass,
+ &update_one_opts.arrayFilters,
+ &update_one_opts.extra,
+ reply,
+ error);
+
+ _mongoc_update_one_opts_cleanup (&update_one_opts);
+
+ RETURN (ret);
+}
+
+bool
+mongoc_collection_update_many (mongoc_collection_t *collection,
+ const bson_t *selector,
+ const bson_t *update,
+ const bson_t *opts,
+ bson_t *reply,
+ bson_error_t *error)
+{
+ mongoc_update_many_opts_t update_many_opts;
+ bool ret;
+
+ ENTRY;
+
+ BSON_ASSERT_PARAM (collection);
+ BSON_ASSERT_PARAM (update);
+
+ if (!_mongoc_update_many_opts_parse (
+ collection->client, opts, &update_many_opts, error)) {
+ _mongoc_update_many_opts_cleanup (&update_many_opts);
+ _mongoc_bson_init_if_set (reply);
+ return false;
+ }
+
+ if (!_mongoc_validate_update (
+ update, update_many_opts.update.crud.validate, error)) {
+ _mongoc_update_many_opts_cleanup (&update_many_opts);
+ _mongoc_bson_init_if_set (reply);
+ return false;
+ }
+
+ ret = _mongoc_collection_update_or_replace (collection,
+ selector,
+ update,
+ &update_many_opts.update,
+ true /* multi */,
+ update_many_opts.update.bypass,
+ &update_many_opts.arrayFilters,
+ &update_many_opts.extra,
+ reply,
+ error);
+
+ _mongoc_update_many_opts_cleanup (&update_many_opts);
+
+ RETURN (ret);
+}
+
+bool
+mongoc_collection_replace_one (mongoc_collection_t *collection,
+ const bson_t *selector,
+ const bson_t *replacement,
+ const bson_t *opts,
+ bson_t *reply,
+ bson_error_t *error)
+{
+ mongoc_replace_one_opts_t replace_one_opts;
+ bool ret;
+
+ ENTRY;
+
+ BSON_ASSERT_PARAM (collection);
+ BSON_ASSERT_PARAM (replacement);
+
+ if (!_mongoc_replace_one_opts_parse (
+ collection->client, opts, &replace_one_opts, error)) {
+ _mongoc_replace_one_opts_cleanup (&replace_one_opts);
+ _mongoc_bson_init_if_set (reply);
+ return false;
+ }
+
+ if (!_mongoc_validate_replace (
+ replacement, replace_one_opts.update.crud.validate, error)) {
+ _mongoc_replace_one_opts_cleanup (&replace_one_opts);
+ _mongoc_bson_init_if_set (reply);
+ return false;
+ }
+
+ ret = _mongoc_collection_update_or_replace (collection,
+ selector,
+ replacement,
+ &replace_one_opts.update,
+ false /* multi */,
+ replace_one_opts.update.bypass,
+ NULL,
+ &replace_one_opts.extra,
+ reply,
+ error);
+
+ _mongoc_replace_one_opts_cleanup (&replace_one_opts);
+
+ RETURN (ret);
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_collection_save --
+ *
+ * Save @document to @collection.
+ *
+ * If the document has an _id field, it will be updated. Otherwise,
+ * the document will be inserted into the collection.
+ *
+ * Returns:
+ * true if successful; otherwise false and @error is set.
+ *
+ * Side effects:
+ * @error is set upon failure if non-NULL.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+bool
+mongoc_collection_save (mongoc_collection_t *collection,
+ const bson_t *document,
+ const mongoc_write_concern_t *write_concern,
+ bson_error_t *error)
+{
+ bson_iter_t iter;
+ bool ret;
+ bson_t selector;
+
+ BSON_ASSERT_PARAM (collection);
+ BSON_ASSERT_PARAM (document);
+
+ BEGIN_IGNORE_DEPRECATIONS
+ if (!bson_iter_init_find (&iter, document, "_id")) {
+ return mongoc_collection_insert (
+ collection, MONGOC_INSERT_NONE, document, write_concern, error);
+ }
+
+ bson_init (&selector);
+ if (!bson_append_iter (&selector, NULL, 0, &iter)) {
+ bson_set_error (error,
+ MONGOC_ERROR_COMMAND,
+ MONGOC_ERROR_COMMAND_INVALID_ARG,
+ "Failed to append bson to create update.");
+ bson_destroy (&selector);
+ return false;
+ }
+
+ /* this document will be inserted, validate same as for inserts */
+ if (!_mongoc_validate_new_document (
+ document, _mongoc_default_insert_vflags, error)) {
+ return false;
+ }
+
+ ret = mongoc_collection_update (collection,
+ MONGOC_UPDATE_UPSERT |
+ MONGOC_UPDATE_NO_VALIDATE,
+ &selector,
+ document,
+ write_concern,
+ error);
+ END_IGNORE_DEPRECATIONS
+
+ bson_destroy (&selector);
+
+ return ret;
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_collection_remove --
+ *
+ * Delete one or more items from a collection. If you want to
+ * limit to a single delete, provided MONGOC_REMOVE_SINGLE_REMOVE
+ * for @flags.
+ *
+ * Superseded by mongoc_collection_delete_one/many.
+ *
+ * Parameters:
+ * @collection: A mongoc_collection_t.
+ * @flags: the delete flags or 0.
+ * @selector: A selector of documents to delete.
+ * @write_concern: A write concern or NULL. If NULL, the default
+ * write concern for the collection will be used.
+ * @error: A location for an error or NULL.
+ *
+ * Returns:
+ * true if successful; otherwise false and error is set.
+ *
+ * If the write concern does not dictate checking the result, this
+ * function may return true even if it failed.
+ *
+ * Side effects:
+ * @collection->gle is setup, depending on write_concern->w value.
+ * @error is setup upon failure.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+bool
+mongoc_collection_remove (mongoc_collection_t *collection,
+ mongoc_remove_flags_t flags,
+ const bson_t *selector,
+ const mongoc_write_concern_t *write_concern,
+ bson_error_t *error)
+{
+ mongoc_bulk_write_flags_t write_flags = MONGOC_BULK_WRITE_FLAGS_INIT;
+ mongoc_write_command_t command;
+ mongoc_write_result_t result;
+ bson_t opts;
+ bool ret;
+
+ ENTRY;
+
+ BSON_ASSERT_PARAM (collection);
+ BSON_ASSERT_PARAM (selector);
+
+ bson_clear (&collection->gle);
+
+ if (!write_concern) {
+ write_concern = collection->write_concern;
+ }
+
+ bson_init (&opts);
+ BSON_APPEND_INT32 (
+ &opts, "limit", flags & MONGOC_REMOVE_SINGLE_REMOVE ? 1 : 0);
+ _mongoc_write_result_init (&result);
+ ++collection->client->cluster.operation_id;
+ _mongoc_write_command_init_delete (&command,
+ selector,
+ NULL,
+ &opts,
+ write_flags,
+ collection->client->cluster.operation_id);
+ bson_destroy (&opts);
+
+ command.flags.has_multi_write = !(flags & MONGOC_REMOVE_SINGLE_REMOVE);
+
+ _mongoc_collection_write_command_execute (
+ &command, collection, write_concern, NULL, &result);
+
+ collection->gle = bson_new ();
+ ret = MONGOC_WRITE_RESULT_COMPLETE (&result,
+ collection->client->error_api_version,
+ write_concern,
+ 0 /* no error domain override */,
+ collection->gle,
+ error);
+
+ _mongoc_write_result_destroy (&result);
+ _mongoc_write_command_destroy (&command);
+
+ RETURN (ret);
+}
+
+
+bool
+mongoc_collection_delete (mongoc_collection_t *collection,
+ mongoc_delete_flags_t flags,
+ const bson_t *selector,
+ const mongoc_write_concern_t *write_concern,
+ bson_error_t *error)
+{
+ return mongoc_collection_remove (collection,
+ (mongoc_remove_flags_t) flags,
+ selector,
+ write_concern,
+ error);
+}
+
+
+static bool
+_mongoc_delete_one_or_many (mongoc_collection_t *collection,
+ bool multi,
+ const bson_t *selector,
+ mongoc_delete_opts_t *delete_opts,
+ const bson_t *cmd_opts,
+ bson_t *opts,
+ bson_t *reply,
+ bson_error_t *error)
+{
+ mongoc_write_command_t command;
+ mongoc_write_result_t result;
+ bool ret;
+
+ ENTRY;
+
+ BSON_ASSERT_PARAM (collection);
+ BSON_ASSERT_PARAM (selector);
+ BSON_ASSERT (bson_empty0 (reply));
+
+ _mongoc_write_result_init (&result);
+ bson_append_int32 (opts, "limit", 5, multi ? 0 : 1);
+
+ if (!bson_empty (&delete_opts->collation)) {
+ bson_append_document (opts, "collation", 9, &delete_opts->collation);
+ }
+
+ if (delete_opts->hint.value_type) {
+ bson_append_value (opts, "hint", 4, &delete_opts->hint);
+ }
+
+ _mongoc_write_command_init_delete_idl (
+ &command,
+ selector,
+ cmd_opts,
+ opts,
+ ++collection->client->cluster.operation_id);
+
+ command.flags.has_multi_write = multi;
+ if (!bson_empty (&delete_opts->collation)) {
+ command.flags.has_collation = true;
+ }
+ if (delete_opts->hint.value_type) {
+ command.flags.has_delete_hint = true;
+ }
+
+ _mongoc_collection_write_command_execute_idl (
+ &command, collection, &delete_opts->crud, &result);
+
+ /* set field described in CRUD spec for the DeleteResult */
+ ret = MONGOC_WRITE_RESULT_COMPLETE (&result,
+ collection->client->error_api_version,
+ delete_opts->crud.writeConcern,
+ /* no error domain override */
+ (mongoc_error_domain_t) 0,
+ reply,
+ error,
+ "deletedCount");
+
+ _mongoc_write_result_destroy (&result);
+ _mongoc_write_command_destroy (&command);
+
+ RETURN (ret);
+}
+
+
+bool
+mongoc_collection_delete_one (mongoc_collection_t *collection,
+ const bson_t *selector,
+ const bson_t *opts,
+ bson_t *reply,
+ bson_error_t *error)
+{
+ mongoc_delete_one_opts_t delete_one_opts;
+ bson_t limit = BSON_INITIALIZER;
+ bool ret = false;
+
+ ENTRY;
+
+ BSON_ASSERT_PARAM (collection);
+ BSON_ASSERT_PARAM (selector);
+
+ _mongoc_bson_init_if_set (reply);
+ if (!_mongoc_delete_one_opts_parse (
+ collection->client, opts, &delete_one_opts, error)) {
+ GOTO (done);
+ }
+
+ ret = _mongoc_delete_one_or_many (collection,
+ false /* multi */,
+ selector,
+ &delete_one_opts.delete,
+ &delete_one_opts.extra,
+ &limit,
+ reply,
+ error);
+
+done:
+ _mongoc_delete_one_opts_cleanup (&delete_one_opts);
+ bson_destroy (&limit);
+
+ RETURN (ret);
+}
+
+bool
+mongoc_collection_delete_many (mongoc_collection_t *collection,
+ const bson_t *selector,
+ const bson_t *opts,
+ bson_t *reply,
+ bson_error_t *error)
+{
+ mongoc_delete_many_opts_t delete_many_opts;
+ bson_t limit = BSON_INITIALIZER;
+ bool ret = false;
+
+ ENTRY;
+
+ BSON_ASSERT_PARAM (collection);
+ BSON_ASSERT_PARAM (selector);
+
+ _mongoc_bson_init_if_set (reply);
+ if (!_mongoc_delete_many_opts_parse (
+ collection->client, opts, &delete_many_opts, error)) {
+ GOTO (done);
+ }
+
+ ret = _mongoc_delete_one_or_many (collection,
+ true /* multi */,
+ selector,
+ &delete_many_opts.delete,
+ &delete_many_opts.extra,
+ &limit,
+ reply,
+ error);
+
+done:
+ _mongoc_delete_many_opts_cleanup (&delete_many_opts);
+ bson_destroy (&limit);
+
+ RETURN (ret);
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_collection_get_read_prefs --
+ *
+ * Fetch the default read preferences for the collection.
+ *
+ * Returns:
+ * A mongoc_read_prefs_t that should not be modified or freed.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+const mongoc_read_prefs_t *
+mongoc_collection_get_read_prefs (const mongoc_collection_t *collection)
+{
+ BSON_ASSERT_PARAM (collection);
+ return collection->read_prefs;
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_collection_set_read_prefs --
+ *
+ * Sets the default read preferences for the collection instance.
+ *
+ * Returns:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+void
+mongoc_collection_set_read_prefs (mongoc_collection_t *collection,
+ const mongoc_read_prefs_t *read_prefs)
+{
+ BSON_ASSERT_PARAM (collection);
+
+ if (collection->read_prefs) {
+ mongoc_read_prefs_destroy (collection->read_prefs);
+ collection->read_prefs = NULL;
+ }
+
+ if (read_prefs) {
+ collection->read_prefs = mongoc_read_prefs_copy (read_prefs);
+ }
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_collection_get_read_concern --
+ *
+ * Fetches the default read concern for the collection instance.
+ *
+ * Returns:
+ * A mongoc_read_concern_t that should not be modified or freed.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+const mongoc_read_concern_t *
+mongoc_collection_get_read_concern (const mongoc_collection_t *collection)
+{
+ BSON_ASSERT_PARAM (collection);
+
+ return collection->read_concern;
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_collection_set_read_concern --
+ *
+ * Sets the default read concern for the collection instance.
+ *
+ * Returns:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+void
+mongoc_collection_set_read_concern (mongoc_collection_t *collection,
+ const mongoc_read_concern_t *read_concern)
+{
+ BSON_ASSERT_PARAM (collection);
+
+ if (collection->read_concern) {
+ mongoc_read_concern_destroy (collection->read_concern);
+ collection->read_concern = NULL;
+ }
+
+ if (read_concern) {
+ collection->read_concern = mongoc_read_concern_copy (read_concern);
+ }
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_collection_get_write_concern --
+ *
+ * Fetches the default write concern for the collection instance.
+ *
+ * Returns:
+ * A mongoc_write_concern_t that should not be modified or freed.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+const mongoc_write_concern_t *
+mongoc_collection_get_write_concern (const mongoc_collection_t *collection)
+{
+ BSON_ASSERT_PARAM (collection);
+
+ return collection->write_concern;
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_collection_set_write_concern --
+ *
+ * Sets the default write concern for the collection instance.
+ *
+ * Returns:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+void
+mongoc_collection_set_write_concern (
+ mongoc_collection_t *collection, const mongoc_write_concern_t *write_concern)
+{
+ BSON_ASSERT_PARAM (collection);
+
+ if (collection->write_concern) {
+ mongoc_write_concern_destroy (collection->write_concern);
+ collection->write_concern = NULL;
+ }
+
+ if (write_concern) {
+ collection->write_concern = mongoc_write_concern_copy (write_concern);
+ }
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_collection_get_name --
+ *
+ * Returns the name of the collection, excluding the database name.
+ *
+ * Returns:
+ * A string which should not be modified or freed.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+const char *
+mongoc_collection_get_name (mongoc_collection_t *collection)
+{
+ BSON_ASSERT_PARAM (collection);
+
+ return collection->collection;
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_collection_get_last_error --
+ *
+ * Returns a bulk result.
+ *
+ * Returns:
+ * NULL or a bson_t that should not be modified or freed. This value
+ * is not guaranteed to be persistent between calls into the
+ * mongoc_collection_t instance, and therefore must be copied if
+ * you would like to keep it around.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+const bson_t *
+mongoc_collection_get_last_error (
+ const mongoc_collection_t *collection) /* IN */
+{
+ BSON_ASSERT_PARAM (collection);
+
+ return collection->gle;
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_collection_validate --
+ *
+ * Helper to call the validate command on the MongoDB server to
+ * validate the collection.
+ *
+ * Options may be additional options, or NULL.
+ * Currently supported options are:
+ *
+ * "full": Boolean
+ *
+ * If full is true, then perform a more resource intensive
+ * validation.
+ *
+ * The result is stored in reply.
+ *
+ * Returns:
+ * true if successful; otherwise false and @error is set.
+ *
+ * Side effects:
+ * @reply is set if successful.
+ * @error may be set.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+bool
+mongoc_collection_validate (mongoc_collection_t *collection, /* IN */
+ const bson_t *options, /* IN */
+ bson_t *reply, /* OUT */
+ bson_error_t *error) /* IN */
+{
+ bson_iter_t iter;
+ bson_t cmd = BSON_INITIALIZER;
+ bool ret = false;
+ bool reply_initialized = false;
+
+ BSON_ASSERT_PARAM (collection);
+
+ if (options && bson_iter_init_find (&iter, options, "full") &&
+ !BSON_ITER_HOLDS_BOOL (&iter)) {
+ bson_set_error (error,
+ MONGOC_ERROR_BSON,
+ MONGOC_ERROR_BSON_INVALID,
+ "'full' must be a boolean value.");
+ goto cleanup;
+ }
+
+ bson_append_utf8 (
+ &cmd, "validate", 8, collection->collection, collection->collectionlen);
+
+ if (options) {
+ bson_concat (&cmd, options);
+ }
+
+ ret =
+ mongoc_collection_command_simple (collection, &cmd, NULL, reply, error);
+ reply_initialized = true;
+
+cleanup:
+ bson_destroy (&cmd);
+
+ if (reply && !reply_initialized) {
+ bson_init (reply);
+ }
+
+ return ret;
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_collection_rename --
+ *
+ * Rename the collection to @new_name.
+ *
+ * If @new_db is NULL, the same db will be used.
+ *
+ * If @drop_target_before_rename is true, then a collection named
+ * @new_name will be dropped before renaming @collection to
+ * @new_name.
+ *
+ * Returns:
+ * true on success; false on failure and @error is set.
+ *
+ * Side effects:
+ * @error is set on failure.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+bool
+mongoc_collection_rename (mongoc_collection_t *collection,
+ const char *new_db,
+ const char *new_name,
+ bool drop_target_before_rename,
+ bson_error_t *error)
+{
+ return mongoc_collection_rename_with_opts (
+ collection, new_db, new_name, drop_target_before_rename, NULL, error);
+}
+
+
+bool
+mongoc_collection_rename_with_opts (mongoc_collection_t *collection,
+ const char *new_db,
+ const char *new_name,
+ bool drop_target_before_rename,
+ const bson_t *opts,
+ bson_error_t *error)
+{
+ bson_t cmd = BSON_INITIALIZER;
+ char *newns;
+ bool ret;
+
+ BSON_ASSERT_PARAM (collection);
+ BSON_ASSERT_PARAM (new_name);
+
+ if (strchr (new_name, '$')) {
+ bson_set_error (error,
+ MONGOC_ERROR_NAMESPACE,
+ MONGOC_ERROR_NAMESPACE_INVALID,
+ "\"%s\" is an invalid collection name.",
+ new_name);
+ return false;
+ }
+
+ newns =
+ bson_strdup_printf ("%s.%s", new_db ? new_db : collection->db, new_name);
+
+ BSON_APPEND_UTF8 (&cmd, "renameCollection", collection->ns);
+ BSON_APPEND_UTF8 (&cmd, "to", newns);
+
+ if (drop_target_before_rename) {
+ BSON_APPEND_BOOL (&cmd, "dropTarget", true);
+ }
+
+ ret = _mongoc_client_command_with_opts (collection->client,
+ "admin",
+ &cmd,
+ MONGOC_CMD_WRITE,
+ opts,
+ MONGOC_QUERY_NONE,
+ NULL, /* user prefs */
+ collection->read_prefs,
+ collection->read_concern,
+ collection->write_concern,
+ NULL, /* reply */
+ error);
+
+ if (ret) {
+ if (new_db) {
+ bson_free (collection->db);
+ collection->db = bson_strdup (new_db);
+ }
+
+ bson_free (collection->collection);
+ collection->collection = bson_strdup (new_name);
+ collection->collectionlen = (int) strlen (collection->collection);
+
+ bson_free (collection->ns);
+ collection->ns = bson_strdup_printf ("%s.%s", collection->db, new_name);
+ collection->nslen = (int) strlen (collection->ns);
+ }
+
+ bson_free (newns);
+ bson_destroy (&cmd);
+
+ return ret;
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_collection_stats --
+ *
+ * Fetches statistics about the collection.
+ *
+ * The result is stored in @stats, which should NOT be an initialized
+ * bson_t or a leak will occur.
+ *
+ * @stats, @options, and @error are optional.
+ *
+ * Returns:
+ * true on success and @stats is set.
+ * false on failure and @error is set.
+ *
+ * Side effects:
+ * @stats and @error.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+bool
+mongoc_collection_stats (mongoc_collection_t *collection,
+ const bson_t *options,
+ bson_t *stats,
+ bson_error_t *error)
+{
+ bson_iter_t iter;
+ bson_t cmd = BSON_INITIALIZER;
+ bool ret;
+
+ BSON_ASSERT_PARAM (collection);
+
+ if (options && bson_iter_init_find (&iter, options, "scale") &&
+ !BSON_ITER_HOLDS_INT32 (&iter)) {
+ bson_set_error (error,
+ MONGOC_ERROR_BSON,
+ MONGOC_ERROR_BSON_INVALID,
+ "'scale' must be an int32 value.");
+ return false;
+ }
+
+ BSON_APPEND_UTF8 (&cmd, "collStats", collection->collection);
+
+ if (options) {
+ bson_concat (&cmd, options);
+ }
+
+ /* Server Selection Spec: "may-use-secondary" commands SHOULD take a read
+ * preference argument and otherwise MUST use the default read preference
+ * from client, database or collection configuration. */
+ ret = mongoc_collection_command_simple (
+ collection, &cmd, collection->read_prefs, stats, error);
+
+ bson_destroy (&cmd);
+
+ return ret;
+}
+
+
+mongoc_bulk_operation_t *
+mongoc_collection_create_bulk_operation (
+ mongoc_collection_t *collection,
+ bool ordered,
+ const mongoc_write_concern_t *write_concern)
+{
+ bson_t opts = BSON_INITIALIZER;
+ mongoc_bulk_operation_t *bulk;
+ bool wc_ok = true;
+
+ bson_append_bool (&opts, "ordered", 7, ordered);
+ if (write_concern) {
+ wc_ok = mongoc_write_concern_append (
+ (mongoc_write_concern_t *) write_concern, &opts);
+ }
+
+ bulk = mongoc_collection_create_bulk_operation_with_opts (collection, &opts);
+
+ bson_destroy (&opts);
+
+ if (!wc_ok) {
+ bson_set_error (&bulk->result.error,
+ MONGOC_ERROR_COMMAND,
+ MONGOC_ERROR_COMMAND_INVALID_ARG,
+ "invalid writeConcern");
+ }
+
+ return bulk;
+}
+
+
+mongoc_bulk_operation_t *
+mongoc_collection_create_bulk_operation_with_opts (
+ mongoc_collection_t *collection, const bson_t *opts)
+{
+ mongoc_bulk_opts_t bulk_opts;
+ mongoc_bulk_write_flags_t write_flags = MONGOC_BULK_WRITE_FLAGS_INIT;
+ mongoc_write_concern_t *wc = NULL;
+ mongoc_bulk_operation_t *bulk;
+ bson_error_t err = {0};
+
+ BSON_ASSERT_PARAM (collection);
+
+ (void) _mongoc_bulk_opts_parse (collection->client, opts, &bulk_opts, &err);
+ if (!_mongoc_client_session_in_txn (bulk_opts.client_session)) {
+ wc = COALESCE (bulk_opts.writeConcern, collection->write_concern);
+ }
+ write_flags.ordered = bulk_opts.ordered;
+ bulk = _mongoc_bulk_operation_new (collection->client,
+ collection->db,
+ collection->collection,
+ write_flags,
+ wc);
+
+ bulk->session = bulk_opts.client_session;
+ if (err.domain) {
+ /* _mongoc_bulk_opts_parse failed, above */
+ memcpy (&bulk->result.error, &err, sizeof (bson_error_t));
+ } else if (_mongoc_client_session_in_txn (bulk_opts.client_session) &&
+ !mongoc_write_concern_is_default (bulk_opts.writeConcern)) {
+ bson_set_error (&bulk->result.error,
+ MONGOC_ERROR_COMMAND,
+ MONGOC_ERROR_COMMAND_INVALID_ARG,
+ "Cannot set write concern after starting transaction");
+ }
+
+ _mongoc_bulk_opts_cleanup (&bulk_opts);
+
+ return bulk;
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_collection_find_and_modify_with_opts --
+ *
+ * Find a document in @collection matching @query, applying @opts.
+ *
+ * If @reply is not NULL, then the result document will be placed
+ * in reply and should be released with bson_destroy().
+ *
+ * See http://docs.mongodb.org/manual/reference/command/findAndModify/
+ * for more information.
+ *
+ * Returns:
+ * true on success; false on failure.
+ *
+ * Side effects:
+ * reply is initialized.
+ * error is set if false is returned.
+ *
+ *--------------------------------------------------------------------------
+ */
+bool
+mongoc_collection_find_and_modify_with_opts (
+ mongoc_collection_t *collection,
+ const bson_t *query,
+ const mongoc_find_and_modify_opts_t *opts,
+ bson_t *reply,
+ bson_error_t *error)
+{
+ mongoc_cluster_t *cluster;
+ mongoc_cmd_parts_t parts;
+ bool is_retryable;
+ bson_iter_t iter;
+ bson_iter_t inner;
+ const char *name;
+ bson_t ss_reply;
+ bson_t reply_local;
+ bson_t *reply_ptr;
+ bool ret = false;
+ bson_t command = BSON_INITIALIZER;
+ mongoc_server_stream_t *server_stream = NULL;
+ mongoc_server_stream_t *retry_server_stream = NULL;
+ mongoc_find_and_modify_appended_opts_t appended_opts;
+ mongoc_write_concern_t *write_concern = NULL;
+
+ ENTRY;
+
+ BSON_ASSERT_PARAM (collection);
+ BSON_ASSERT_PARAM (query);
+ BSON_ASSERT_PARAM (opts);
+
+ reply_ptr = reply ? reply : &reply_local;
+ cluster = &collection->client->cluster;
+
+ mongoc_cmd_parts_init (
+ &parts, collection->client, collection->db, MONGOC_QUERY_NONE, &command);
+ parts.is_read_command = true;
+ parts.is_write_command = true;
+
+ bson_init (reply_ptr);
+
+ if (!_mongoc_find_and_modify_appended_opts_parse (
+ cluster->client, &opts->extra, &appended_opts, error)) {
+ GOTO (done);
+ }
+
+ server_stream = mongoc_cluster_stream_for_writes (
+ cluster, appended_opts.client_session, &ss_reply, error);
+
+ if (!server_stream) {
+ bson_concat (reply_ptr, &ss_reply);
+ bson_destroy (&ss_reply);
+ GOTO (done);
+ }
+
+ name = mongoc_collection_get_name (collection);
+ BSON_APPEND_UTF8 (&command, "findAndModify", name);
+ BSON_APPEND_DOCUMENT (&command, "query", query);
+
+ if (opts->sort) {
+ BSON_APPEND_DOCUMENT (&command, "sort", opts->sort);
+ }
+
+ if (opts->update) {
+ if (_mongoc_document_is_pipeline (opts->update)) {
+ BSON_APPEND_ARRAY (&command, "update", opts->update);
+ } else {
+ BSON_APPEND_DOCUMENT (&command, "update", opts->update);
+ }
+ }
+
+ if (opts->fields) {
+ BSON_APPEND_DOCUMENT (&command, "fields", opts->fields);
+ }
+
+ if (opts->flags & MONGOC_FIND_AND_MODIFY_REMOVE) {
+ BSON_APPEND_BOOL (&command, "remove", true);
+ }
+
+ if (opts->flags & MONGOC_FIND_AND_MODIFY_UPSERT) {
+ BSON_APPEND_BOOL (&command, "upsert", true);
+ }
+
+ if (opts->flags & MONGOC_FIND_AND_MODIFY_RETURN_NEW) {
+ BSON_APPEND_BOOL (&command, "new", true);
+ }
+
+ if (opts->bypass_document_validation) {
+ BSON_APPEND_BOOL (&command,
+ "bypassDocumentValidation",
+ opts->bypass_document_validation);
+ }
+
+ if (opts->max_time_ms > 0) {
+ BSON_APPEND_INT32 (&command, "maxTimeMS", opts->max_time_ms);
+ }
+
+ /* Some options set via mongoc_find_and_modify_opts_append were parsed. Set
+ * them on the command parts. */
+ if (appended_opts.client_session) {
+ mongoc_cmd_parts_set_session (&parts, appended_opts.client_session);
+ }
+
+ if (appended_opts.writeConcern) {
+ if (_mongoc_client_session_in_txn (parts.assembled.session)) {
+ bson_set_error (error,
+ MONGOC_ERROR_COMMAND,
+ MONGOC_ERROR_COMMAND_INVALID_ARG,
+ "Cannot set write concern after starting transaction");
+ GOTO (done);
+ }
+
+ write_concern = appended_opts.writeConcern;
+ }
+ /* inherit write concern from collection if not in transaction */
+ else if (server_stream->sd->max_wire_version >=
+ WIRE_VERSION_FAM_WRITE_CONCERN &&
+ !_mongoc_client_session_in_txn (parts.assembled.session)) {
+ if (!mongoc_write_concern_is_valid (collection->write_concern)) {
+ bson_set_error (error,
+ MONGOC_ERROR_COMMAND,
+ MONGOC_ERROR_COMMAND_INVALID_ARG,
+ "The write concern is invalid.");
+ GOTO (done);
+ }
+
+ write_concern = collection->write_concern;
+ }
+
+ if (appended_opts.hint.value_type) {
+ int max_wire_version =
+ mongoc_write_concern_is_acknowledged (write_concern)
+ ? WIRE_VERSION_FIND_AND_MODIFY_HINT_SERVER_SIDE_ERROR
+ : WIRE_VERSION_FIND_AND_MODIFY_HINT;
+
+ if (server_stream->sd->max_wire_version < max_wire_version) {
+ bson_set_error (
+ error,
+ MONGOC_ERROR_COMMAND,
+ MONGOC_ERROR_PROTOCOL_BAD_WIRE_VERSION,
+ "selected server does not support hint on findAndModify");
+ GOTO (done);
+ }
+
+ bson_append_value (&parts.extra, "hint", 4, &appended_opts.hint);
+ }
+
+ /* Append any remaining unparsed options set via
+ * mongoc_find_and_modify_opts_append to the command part. */
+ if (bson_iter_init (&iter, &appended_opts.extra)) {
+ bool ok = mongoc_cmd_parts_append_opts (
+ &parts, &iter, server_stream->sd->max_wire_version, error);
+ if (!ok) {
+ GOTO (done);
+ }
+ }
+
+ /* An empty write concern amounts to a no-op, so there's no need to guard
+ * against it. */
+ if (!mongoc_cmd_parts_set_write_concern (
+ &parts, write_concern, server_stream->sd->max_wire_version, error)) {
+ GOTO (done);
+ }
+
+ parts.assembled.operation_id = ++cluster->operation_id;
+ if (!mongoc_cmd_parts_assemble (&parts, server_stream, error)) {
+ GOTO (done);
+ }
+
+ is_retryable = parts.is_retryable_write;
+
+ /* increment the transaction number for the first attempt of each retryable
+ * write command */
+ if (is_retryable) {
+ bson_iter_t txn_number_iter;
+ BSON_ASSERT (bson_iter_init_find (
+ &txn_number_iter, parts.assembled.command, "txnNumber"));
+ bson_iter_overwrite_int64 (
+ &txn_number_iter,
+ ++parts.assembled.session->server_session->txn_number);
+ }
+retry:
+ bson_destroy (reply_ptr);
+ ret = mongoc_cluster_run_command_monitored (
+ cluster, &parts.assembled, reply_ptr, error);
+
+ if (parts.is_retryable_write) {
+ _mongoc_write_error_handle_labels (
+ ret, error, reply_ptr, server_stream->sd->max_wire_version);
+ }
+
+ if (is_retryable) {
+ _mongoc_write_error_update_if_unsupported_storage_engine (
+ ret, error, reply_ptr);
+ }
+
+ /* If a retryable error is encountered and the write is retryable, select
+ * a new writable stream and retry. If server selection fails or the selected
+ * server does not support retryable writes, fall through and allow the
+ * original error to be reported. */
+ if (is_retryable &&
+ _mongoc_write_error_get_type (reply_ptr) == MONGOC_WRITE_ERR_RETRY) {
+ bson_error_t ignored_error;
+
+ /* each write command may be retried at most once */
+ is_retryable = false;
+ retry_server_stream = mongoc_cluster_stream_for_writes (
+ cluster, parts.assembled.session, NULL /* reply */, &ignored_error);
+
+ if (retry_server_stream && retry_server_stream->sd->max_wire_version >=
+ WIRE_VERSION_RETRY_WRITES) {
+ parts.assembled.server_stream = retry_server_stream;
+ GOTO (retry);
+ }
+ }
+
+ if (bson_iter_init_find (&iter, reply_ptr, "writeConcernError") &&
+ BSON_ITER_HOLDS_DOCUMENT (&iter)) {
+ const char *errmsg = NULL;
+ int32_t code = 0;
+
+ BSON_ASSERT (bson_iter_recurse (&iter, &inner));
+ while (bson_iter_next (&inner)) {
+ if (BSON_ITER_IS_KEY (&inner, "code")) {
+ code = (uint32_t) bson_iter_as_int64 (&inner);
+ } else if (BSON_ITER_IS_KEY (&inner, "errmsg")) {
+ errmsg = bson_iter_utf8 (&inner, NULL);
+ }
+ }
+ bson_set_error (error,
+ MONGOC_ERROR_WRITE_CONCERN,
+ code,
+ "Write Concern error: %s",
+ errmsg);
+ ret = false;
+ }
+
+
+done:
+ mongoc_server_stream_cleanup (server_stream);
+ mongoc_server_stream_cleanup (retry_server_stream);
+
+ if (ret && error) {
+ /* if a retry succeeded, clear the initial error */
+ memset (error, 0, sizeof (bson_error_t));
+ }
+ mongoc_cmd_parts_cleanup (&parts);
+ bson_destroy (&command);
+ if (&reply_local == reply_ptr) {
+ bson_destroy (&reply_local);
+ }
+ _mongoc_find_and_modify_appended_opts_cleanup (&appended_opts);
+ RETURN (ret);
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_collection_find_and_modify --
+ *
+ * Find a document in @collection matching @query and update it with
+ * the update document @update.
+ *
+ * If @reply is not NULL, then the result document will be placed
+ * in reply and should be released with bson_destroy().
+ *
+ * If @remove is true, then the matching documents will be removed.
+ *
+ * If @fields is not NULL, it will be used to select the desired
+ * resulting fields.
+ *
+ * If @_new is true, then the new version of the document is returned
+ * instead of the old document.
+ *
+ * See http://docs.mongodb.org/manual/reference/command/findAndModify/
+ * for more information.
+ *
+ * Returns:
+ * true on success; false on failure.
+ *
+ * Side effects:
+ * reply is initialized.
+ * error is set if false is returned.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+bool
+mongoc_collection_find_and_modify (mongoc_collection_t *collection,
+ const bson_t *query,
+ const bson_t *sort,
+ const bson_t *update,
+ const bson_t *fields,
+ bool _remove,
+ bool upsert,
+ bool _new,
+ bson_t *reply,
+ bson_error_t *error)
+{
+ mongoc_find_and_modify_opts_t *opts;
+ int flags = 0;
+ bool ret;
+
+ ENTRY;
+
+ BSON_ASSERT_PARAM (collection);
+ BSON_ASSERT_PARAM (query);
+ BSON_ASSERT (update || _remove);
+
+
+ if (_remove) {
+ flags |= MONGOC_FIND_AND_MODIFY_REMOVE;
+ }
+ if (upsert) {
+ flags |= MONGOC_FIND_AND_MODIFY_UPSERT;
+ }
+ if (_new) {
+ flags |= MONGOC_FIND_AND_MODIFY_RETURN_NEW;
+ }
+
+ opts = mongoc_find_and_modify_opts_new ();
+
+ mongoc_find_and_modify_opts_set_sort (opts, sort);
+ mongoc_find_and_modify_opts_set_update (opts, update);
+ mongoc_find_and_modify_opts_set_fields (opts, fields);
+ mongoc_find_and_modify_opts_set_flags (opts, flags);
+
+ ret = mongoc_collection_find_and_modify_with_opts (
+ collection, query, opts, reply, error);
+ mongoc_find_and_modify_opts_destroy (opts);
+
+ return ret;
+}
+
+mongoc_change_stream_t *
+mongoc_collection_watch (const mongoc_collection_t *coll,
+ const bson_t *pipeline,
+ const bson_t *opts)
+{
+ return _mongoc_change_stream_new_from_collection (coll, pipeline, opts);
+}
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-collection.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-collection.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-collection.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-collection.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-compression-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-compression-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-compression-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-compression-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-compression.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-compression.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-compression.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-compression.c
diff --git a/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-config.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-config.h
new file mode 100644
index 00000000..4a645849
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-config.h
@@ -0,0 +1,423 @@
+/*
+ * Copyright 2013 MongoDB Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if !defined(MONGOC_INSIDE) && !defined(MONGOC_COMPILATION)
+#error "Only <mongoc/mongoc.h> can be included directly."
+#endif
+
+
+#ifndef MONGOC_CONFIG_H
+#define MONGOC_CONFIG_H
+
+/* clang-format off */
+
+/*
+ * NOTICE:
+ * If you're about to update this file and add a config flag, make sure to
+ * update:
+ * o The bitfield in mongoc-handshake-private.h
+ * o _mongoc_handshake_get_config_hex_string() in mongoc-handshake.c
+ * o examples/parse_handshake_cfg.py
+ * o test_handshake_config_string in test-mongoc-handshake.c
+ */
+
+/* MONGOC_USER_SET_CFLAGS is set from config based on what compiler flags were
+ * used to compile mongoc */
+#define MONGOC_USER_SET_CFLAGS ""
+
+#define MONGOC_USER_SET_LDFLAGS ""
+
+/* MONGOC_CC is used to determine what C compiler was used to compile mongoc */
+#define MONGOC_CC "cc"
+
+/*
+ * MONGOC_ENABLE_SSL_SECURE_CHANNEL is set from configure to determine if we are
+ * compiled with Native SSL support on Windows
+ */
+#define MONGOC_ENABLE_SSL_SECURE_CHANNEL 0
+
+#if MONGOC_ENABLE_SSL_SECURE_CHANNEL != 1
+# undef MONGOC_ENABLE_SSL_SECURE_CHANNEL
+#endif
+
+
+/*
+ * MONGOC_ENABLE_CRYPTO_CNG is set from configure to determine if we are
+ * compiled with Native Crypto support on Windows
+ */
+#define MONGOC_ENABLE_CRYPTO_CNG 0
+
+#if MONGOC_ENABLE_CRYPTO_CNG != 1
+# undef MONGOC_ENABLE_CRYPTO_CNG
+#endif
+
+
+/*
+ * MONGOC_ENABLE_SSL_SECURE_TRANSPORT is set from configure to determine if we are
+ * compiled with Native SSL support on Darwin
+ */
+#define MONGOC_ENABLE_SSL_SECURE_TRANSPORT 0
+
+#if MONGOC_ENABLE_SSL_SECURE_TRANSPORT != 1
+# undef MONGOC_ENABLE_SSL_SECURE_TRANSPORT
+#endif
+
+
+/*
+ * MONGOC_ENABLE_CRYPTO_COMMON_CRYPTO is set from configure to determine if we are
+ * compiled with Native Crypto support on Darwin
+ */
+#define MONGOC_ENABLE_CRYPTO_COMMON_CRYPTO 0
+
+#if MONGOC_ENABLE_CRYPTO_COMMON_CRYPTO != 1
+# undef MONGOC_ENABLE_CRYPTO_COMMON_CRYPTO
+#endif
+
+
+/*
+ * MONGOC_ENABLE_SSL_LIBRESSL is set from configure to determine if we are
+ * compiled with LibreSSL support.
+ */
+#define MONGOC_ENABLE_SSL_LIBRESSL 0
+
+#if MONGOC_ENABLE_SSL_LIBRESSL != 1
+# undef MONGOC_ENABLE_SSL_LIBRESSL
+#endif
+
+
+/*
+ * MONGOC_ENABLE_SSL_OPENSSL is set from configure to determine if we are
+ * compiled with OpenSSL support.
+ */
+#define MONGOC_ENABLE_SSL_OPENSSL 1
+
+#if MONGOC_ENABLE_SSL_OPENSSL != 1
+# undef MONGOC_ENABLE_SSL_OPENSSL
+#endif
+
+
+/*
+ * MONGOC_ENABLE_CRYPTO_LIBCRYPTO is set from configure to determine if we are
+ * compiled with OpenSSL support.
+ */
+#define MONGOC_ENABLE_CRYPTO_LIBCRYPTO 1
+
+#if MONGOC_ENABLE_CRYPTO_LIBCRYPTO != 1
+# undef MONGOC_ENABLE_CRYPTO_LIBCRYPTO
+#endif
+
+
+/*
+ * MONGOC_ENABLE_SSL is set from configure to determine if we are
+ * compiled with any SSL support.
+ */
+#define MONGOC_ENABLE_SSL 1
+
+#if MONGOC_ENABLE_SSL != 1
+# undef MONGOC_ENABLE_SSL
+#endif
+
+
+/*
+ * MONGOC_ENABLE_CRYPTO is set from configure to determine if we are
+ * compiled with any crypto support.
+ */
+#define MONGOC_ENABLE_CRYPTO 1
+
+#if MONGOC_ENABLE_CRYPTO != 1
+# undef MONGOC_ENABLE_CRYPTO
+#endif
+
+
+/*
+ * Use system crypto profile
+ */
+#define MONGOC_ENABLE_CRYPTO_SYSTEM_PROFILE 0
+
+#if MONGOC_ENABLE_CRYPTO_SYSTEM_PROFILE != 1
+# undef MONGOC_ENABLE_CRYPTO_SYSTEM_PROFILE
+#endif
+
+
+/*
+ * Use ASN1_STRING_get0_data () rather than the deprecated ASN1_STRING_data
+ */
+#define MONGOC_HAVE_ASN1_STRING_GET0_DATA 1
+
+#if MONGOC_HAVE_ASN1_STRING_GET0_DATA != 1
+# undef MONGOC_HAVE_ASN1_STRING_GET0_DATA
+#endif
+
+
+/*
+ * MONGOC_ENABLE_SASL is set from configure to determine if we are
+ * compiled with SASL support.
+ */
+#define MONGOC_ENABLE_SASL 1
+
+#if MONGOC_ENABLE_SASL != 1
+# undef MONGOC_ENABLE_SASL
+#endif
+
+
+/*
+ * MONGOC_ENABLE_SASL_CYRUS is set from configure to determine if we are
+ * compiled with Cyrus SASL support.
+ */
+#define MONGOC_ENABLE_SASL_CYRUS 1
+
+#if MONGOC_ENABLE_SASL_CYRUS != 1
+# undef MONGOC_ENABLE_SASL_CYRUS
+#endif
+
+
+/*
+ * MONGOC_ENABLE_SASL_SSPI is set from configure to determine if we are
+ * compiled with SSPI support.
+ */
+#define MONGOC_ENABLE_SASL_SSPI 0
+
+#if MONGOC_ENABLE_SASL_SSPI != 1
+# undef MONGOC_ENABLE_SASL_SSPI
+#endif
+
+/*
+ * MONGOC_HAVE_SASL_CLIENT_DONE is set from configure to determine if we
+ * have SASL and its version is new enough to use sasl_client_done (),
+ * which supersedes sasl_done ().
+ */
+#define MONGOC_HAVE_SASL_CLIENT_DONE 1
+
+#if MONGOC_HAVE_SASL_CLIENT_DONE != 1
+# undef MONGOC_HAVE_SASL_CLIENT_DONE
+#endif
+
+
+/*
+ * Disable automatic calls to mongoc_init() and mongoc_cleanup()
+ * before main() is called, and after exit() (respectively).
+ */
+#define MONGOC_NO_AUTOMATIC_GLOBALS 1
+
+#if MONGOC_NO_AUTOMATIC_GLOBALS != 1
+# undef MONGOC_NO_AUTOMATIC_GLOBALS
+#endif
+
+/*
+ * MONGOC_HAVE_SOCKLEN is set from configure to determine if we
+ * need to emulate the type.
+ */
+#define MONGOC_HAVE_SOCKLEN 1
+
+#if MONGOC_HAVE_SOCKLEN != 1
+# undef MONGOC_HAVE_SOCKLEN
+#endif
+
+
+/*
+ * MONGOC_HAVE_DNSAPI is set from configure to determine if we should use the
+ * Windows dnsapi for SRV record lookups.
+ */
+#define MONGOC_HAVE_DNSAPI 0
+
+#if MONGOC_HAVE_DNSAPI != 1
+# undef MONGOC_HAVE_DNSAPI
+#endif
+
+
+/*
+ * MONGOC_HAVE_RES_NSEARCH is set from configure to determine if we
+ * have thread-safe res_nsearch().
+ */
+#define MONGOC_HAVE_RES_NSEARCH 1
+
+#if MONGOC_HAVE_RES_NSEARCH != 1
+# undef MONGOC_HAVE_RES_NSEARCH
+#endif
+
+
+/*
+ * MONGOC_HAVE_RES_NDESTROY is set from configure to determine if we
+ * have BSD / Darwin's res_ndestroy().
+ */
+#define MONGOC_HAVE_RES_NDESTROY 0
+
+#if MONGOC_HAVE_RES_NDESTROY != 1
+# undef MONGOC_HAVE_RES_NDESTROY
+#endif
+
+
+/*
+ * MONGOC_HAVE_RES_NCLOSE is set from configure to determine if we
+ * have Linux's res_nclose().
+ */
+#define MONGOC_HAVE_RES_NCLOSE 1
+
+#if MONGOC_HAVE_RES_NCLOSE != 1
+# undef MONGOC_HAVE_RES_NCLOSE
+#endif
+
+
+/*
+ * MONGOC_HAVE_RES_SEARCH is set from configure to determine if we
+ * have thread-unsafe res_search(). It's unset if we have the preferred
+ * res_nsearch().
+ */
+#define MONGOC_HAVE_RES_SEARCH 0
+
+#if MONGOC_HAVE_RES_SEARCH != 1
+# undef MONGOC_HAVE_RES_SEARCH
+#endif
+
+
+/*
+ * Set from configure, see
+ * https://curl.haxx.se/mail/lib-2009-04/0287.html
+ */
+#define MONGOC_SOCKET_ARG2 struct sockaddr
+#define MONGOC_SOCKET_ARG3 socklen_t
+
+/*
+ * Enable wire protocol compression negotiation
+ *
+ */
+#define MONGOC_ENABLE_COMPRESSION 1
+
+#if MONGOC_ENABLE_COMPRESSION != 1
+# undef MONGOC_ENABLE_COMPRESSION
+#endif
+
+/*
+ * Set if we have snappy compression support
+ *
+ */
+#define MONGOC_ENABLE_COMPRESSION_SNAPPY 1
+
+#if MONGOC_ENABLE_COMPRESSION_SNAPPY != 1
+# undef MONGOC_ENABLE_COMPRESSION_SNAPPY
+#endif
+
+
+/*
+ * Set if we have zlib compression support
+ *
+ */
+#define MONGOC_ENABLE_COMPRESSION_ZLIB 1
+
+#if MONGOC_ENABLE_COMPRESSION_ZLIB != 1
+# undef MONGOC_ENABLE_COMPRESSION_ZLIB
+#endif
+
+/*
+ * Set if we have zstd compression support
+ *
+ */
+#define MONGOC_ENABLE_COMPRESSION_ZSTD 1
+
+#if MONGOC_ENABLE_COMPRESSION_ZSTD != 1
+# undef MONGOC_ENABLE_COMPRESSION_ZSTD
+#endif
+
+/*
+ * Set if performance counters are available and not disabled.
+ *
+ */
+#define MONGOC_ENABLE_SHM_COUNTERS 0
+
+#if MONGOC_ENABLE_SHM_COUNTERS != 1
+# undef MONGOC_ENABLE_SHM_COUNTERS
+#endif
+
+/*
+ * Set if we have enabled fast counters on Intel using the RDTSCP instruction
+ *
+ */
+#define MONGOC_ENABLE_RDTSCP 0
+
+#if MONGOC_ENABLE_RDTSCP != 1
+# undef MONGOC_ENABLE_RDTSCP
+#endif
+
+
+/*
+ * Set if we have the sched_getcpu() function for use with counters
+ *
+ */
+#define MONGOC_HAVE_SCHED_GETCPU 1
+
+#if MONGOC_HAVE_SCHED_GETCPU != 1
+# undef MONGOC_HAVE_SCHED_GETCPU
+#endif
+
+/*
+ * Set if tracing is enabled. Logs things like network communication and
+ * entry/exit of certain functions.
+ */
+#define MONGOC_TRACE 1
+
+enum {
+ /**
+ * @brief Compile-time constant determining whether the mongoc library was
+ * compiled with tracing enabled.
+ *
+ * Can be controlled with the 'ENABLE_TRACING" configure-time boolean option
+ */
+ MONGOC_TRACE_ENABLED = MONGOC_TRACE
+};
+
+/*
+ * Set if we have ICU support.
+ */
+#define MONGOC_ENABLE_ICU 1
+
+#if MONGOC_ENABLE_ICU != 1
+# undef MONGOC_ENABLE_ICU
+#endif
+
+
+/*
+ * Set if we have Client Side Encryption support.
+ */
+
+#define MONGOC_ENABLE_CLIENT_SIDE_ENCRYPTION 1
+
+#if MONGOC_ENABLE_CLIENT_SIDE_ENCRYPTION != 1
+# undef MONGOC_ENABLE_CLIENT_SIDE_ENCRYPTION
+#endif
+
+
+/*
+ * Set if struct sockaddr_storage has __ss_family (instead of ss_family)
+ */
+
+#define MONGOC_HAVE_SS_FAMILY 1
+
+#if MONGOC_HAVE_SS_FAMILY != 1
+# undef MONGOC_HAVE_SS_FAMILY
+#endif
+
+/*
+ * Set if building with AWS IAM support.
+ */
+#define MONGOC_ENABLE_MONGODB_AWS_AUTH 1
+
+#if MONGOC_ENABLE_MONGODB_AWS_AUTH != 1
+# undef MONGOC_ENABLE_MONGODB_AWS_AUTH
+#endif
+
+/* clang-format on */
+
+#endif /* MONGOC_CONFIG_H */
diff --git a/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-config.h.in b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-config.h.in
new file mode 100644
index 00000000..29882211
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-config.h.in
@@ -0,0 +1,423 @@
+/*
+ * Copyright 2013 MongoDB Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if !defined(MONGOC_INSIDE) && !defined(MONGOC_COMPILATION)
+#error "Only <mongoc/mongoc.h> can be included directly."
+#endif
+
+
+#ifndef MONGOC_CONFIG_H
+#define MONGOC_CONFIG_H
+
+/* clang-format off */
+
+/*
+ * NOTICE:
+ * If you're about to update this file and add a config flag, make sure to
+ * update:
+ * o The bitfield in mongoc-handshake-private.h
+ * o _mongoc_handshake_get_config_hex_string() in mongoc-handshake.c
+ * o examples/parse_handshake_cfg.py
+ * o test_handshake_config_string in test-mongoc-handshake.c
+ */
+
+/* MONGOC_USER_SET_CFLAGS is set from config based on what compiler flags were
+ * used to compile mongoc */
+#define MONGOC_USER_SET_CFLAGS "@MONGOC_USER_SET_CFLAGS@"
+
+#define MONGOC_USER_SET_LDFLAGS "@MONGOC_USER_SET_LDFLAGS@"
+
+/* MONGOC_CC is used to determine what C compiler was used to compile mongoc */
+#define MONGOC_CC "@MONGOC_CC@"
+
+/*
+ * MONGOC_ENABLE_SSL_SECURE_CHANNEL is set from configure to determine if we are
+ * compiled with Native SSL support on Windows
+ */
+#define MONGOC_ENABLE_SSL_SECURE_CHANNEL @MONGOC_ENABLE_SSL_SECURE_CHANNEL@
+
+#if MONGOC_ENABLE_SSL_SECURE_CHANNEL != 1
+# undef MONGOC_ENABLE_SSL_SECURE_CHANNEL
+#endif
+
+
+/*
+ * MONGOC_ENABLE_CRYPTO_CNG is set from configure to determine if we are
+ * compiled with Native Crypto support on Windows
+ */
+#define MONGOC_ENABLE_CRYPTO_CNG @MONGOC_ENABLE_CRYPTO_CNG@
+
+#if MONGOC_ENABLE_CRYPTO_CNG != 1
+# undef MONGOC_ENABLE_CRYPTO_CNG
+#endif
+
+
+/*
+ * MONGOC_ENABLE_SSL_SECURE_TRANSPORT is set from configure to determine if we are
+ * compiled with Native SSL support on Darwin
+ */
+#define MONGOC_ENABLE_SSL_SECURE_TRANSPORT @MONGOC_ENABLE_SSL_SECURE_TRANSPORT@
+
+#if MONGOC_ENABLE_SSL_SECURE_TRANSPORT != 1
+# undef MONGOC_ENABLE_SSL_SECURE_TRANSPORT
+#endif
+
+
+/*
+ * MONGOC_ENABLE_CRYPTO_COMMON_CRYPTO is set from configure to determine if we are
+ * compiled with Native Crypto support on Darwin
+ */
+#define MONGOC_ENABLE_CRYPTO_COMMON_CRYPTO @MONGOC_ENABLE_CRYPTO_COMMON_CRYPTO@
+
+#if MONGOC_ENABLE_CRYPTO_COMMON_CRYPTO != 1
+# undef MONGOC_ENABLE_CRYPTO_COMMON_CRYPTO
+#endif
+
+
+/*
+ * MONGOC_ENABLE_SSL_LIBRESSL is set from configure to determine if we are
+ * compiled with LibreSSL support.
+ */
+#define MONGOC_ENABLE_SSL_LIBRESSL @MONGOC_ENABLE_SSL_LIBRESSL@
+
+#if MONGOC_ENABLE_SSL_LIBRESSL != 1
+# undef MONGOC_ENABLE_SSL_LIBRESSL
+#endif
+
+
+/*
+ * MONGOC_ENABLE_SSL_OPENSSL is set from configure to determine if we are
+ * compiled with OpenSSL support.
+ */
+#define MONGOC_ENABLE_SSL_OPENSSL @MONGOC_ENABLE_SSL_OPENSSL@
+
+#if MONGOC_ENABLE_SSL_OPENSSL != 1
+# undef MONGOC_ENABLE_SSL_OPENSSL
+#endif
+
+
+/*
+ * MONGOC_ENABLE_CRYPTO_LIBCRYPTO is set from configure to determine if we are
+ * compiled with OpenSSL support.
+ */
+#define MONGOC_ENABLE_CRYPTO_LIBCRYPTO @MONGOC_ENABLE_CRYPTO_LIBCRYPTO@
+
+#if MONGOC_ENABLE_CRYPTO_LIBCRYPTO != 1
+# undef MONGOC_ENABLE_CRYPTO_LIBCRYPTO
+#endif
+
+
+/*
+ * MONGOC_ENABLE_SSL is set from configure to determine if we are
+ * compiled with any SSL support.
+ */
+#define MONGOC_ENABLE_SSL @MONGOC_ENABLE_SSL@
+
+#if MONGOC_ENABLE_SSL != 1
+# undef MONGOC_ENABLE_SSL
+#endif
+
+
+/*
+ * MONGOC_ENABLE_CRYPTO is set from configure to determine if we are
+ * compiled with any crypto support.
+ */
+#define MONGOC_ENABLE_CRYPTO @MONGOC_ENABLE_CRYPTO@
+
+#if MONGOC_ENABLE_CRYPTO != 1
+# undef MONGOC_ENABLE_CRYPTO
+#endif
+
+
+/*
+ * Use system crypto profile
+ */
+#define MONGOC_ENABLE_CRYPTO_SYSTEM_PROFILE @MONGOC_ENABLE_CRYPTO_SYSTEM_PROFILE@
+
+#if MONGOC_ENABLE_CRYPTO_SYSTEM_PROFILE != 1
+# undef MONGOC_ENABLE_CRYPTO_SYSTEM_PROFILE
+#endif
+
+
+/*
+ * Use ASN1_STRING_get0_data () rather than the deprecated ASN1_STRING_data
+ */
+#define MONGOC_HAVE_ASN1_STRING_GET0_DATA @MONGOC_HAVE_ASN1_STRING_GET0_DATA@
+
+#if MONGOC_HAVE_ASN1_STRING_GET0_DATA != 1
+# undef MONGOC_HAVE_ASN1_STRING_GET0_DATA
+#endif
+
+
+/*
+ * MONGOC_ENABLE_SASL is set from configure to determine if we are
+ * compiled with SASL support.
+ */
+#define MONGOC_ENABLE_SASL @MONGOC_ENABLE_SASL@
+
+#if MONGOC_ENABLE_SASL != 1
+# undef MONGOC_ENABLE_SASL
+#endif
+
+
+/*
+ * MONGOC_ENABLE_SASL_CYRUS is set from configure to determine if we are
+ * compiled with Cyrus SASL support.
+ */
+#define MONGOC_ENABLE_SASL_CYRUS @MONGOC_ENABLE_SASL_CYRUS@
+
+#if MONGOC_ENABLE_SASL_CYRUS != 1
+# undef MONGOC_ENABLE_SASL_CYRUS
+#endif
+
+
+/*
+ * MONGOC_ENABLE_SASL_SSPI is set from configure to determine if we are
+ * compiled with SSPI support.
+ */
+#define MONGOC_ENABLE_SASL_SSPI @MONGOC_ENABLE_SASL_SSPI@
+
+#if MONGOC_ENABLE_SASL_SSPI != 1
+# undef MONGOC_ENABLE_SASL_SSPI
+#endif
+
+/*
+ * MONGOC_HAVE_SASL_CLIENT_DONE is set from configure to determine if we
+ * have SASL and its version is new enough to use sasl_client_done (),
+ * which supersedes sasl_done ().
+ */
+#define MONGOC_HAVE_SASL_CLIENT_DONE @MONGOC_HAVE_SASL_CLIENT_DONE@
+
+#if MONGOC_HAVE_SASL_CLIENT_DONE != 1
+# undef MONGOC_HAVE_SASL_CLIENT_DONE
+#endif
+
+
+/*
+ * Disable automatic calls to mongoc_init() and mongoc_cleanup()
+ * before main() is called, and after exit() (respectively).
+ */
+#define MONGOC_NO_AUTOMATIC_GLOBALS @MONGOC_NO_AUTOMATIC_GLOBALS@
+
+#if MONGOC_NO_AUTOMATIC_GLOBALS != 1
+# undef MONGOC_NO_AUTOMATIC_GLOBALS
+#endif
+
+/*
+ * MONGOC_HAVE_SOCKLEN is set from configure to determine if we
+ * need to emulate the type.
+ */
+#define MONGOC_HAVE_SOCKLEN @MONGOC_HAVE_SOCKLEN@
+
+#if MONGOC_HAVE_SOCKLEN != 1
+# undef MONGOC_HAVE_SOCKLEN
+#endif
+
+
+/*
+ * MONGOC_HAVE_DNSAPI is set from configure to determine if we should use the
+ * Windows dnsapi for SRV record lookups.
+ */
+#define MONGOC_HAVE_DNSAPI @MONGOC_HAVE_DNSAPI@
+
+#if MONGOC_HAVE_DNSAPI != 1
+# undef MONGOC_HAVE_DNSAPI
+#endif
+
+
+/*
+ * MONGOC_HAVE_RES_NSEARCH is set from configure to determine if we
+ * have thread-safe res_nsearch().
+ */
+#define MONGOC_HAVE_RES_NSEARCH @MONGOC_HAVE_RES_NSEARCH@
+
+#if MONGOC_HAVE_RES_NSEARCH != 1
+# undef MONGOC_HAVE_RES_NSEARCH
+#endif
+
+
+/*
+ * MONGOC_HAVE_RES_NDESTROY is set from configure to determine if we
+ * have BSD / Darwin's res_ndestroy().
+ */
+#define MONGOC_HAVE_RES_NDESTROY @MONGOC_HAVE_RES_NDESTROY@
+
+#if MONGOC_HAVE_RES_NDESTROY != 1
+# undef MONGOC_HAVE_RES_NDESTROY
+#endif
+
+
+/*
+ * MONGOC_HAVE_RES_NCLOSE is set from configure to determine if we
+ * have Linux's res_nclose().
+ */
+#define MONGOC_HAVE_RES_NCLOSE @MONGOC_HAVE_RES_NCLOSE@
+
+#if MONGOC_HAVE_RES_NCLOSE != 1
+# undef MONGOC_HAVE_RES_NCLOSE
+#endif
+
+
+/*
+ * MONGOC_HAVE_RES_SEARCH is set from configure to determine if we
+ * have thread-unsafe res_search(). It's unset if we have the preferred
+ * res_nsearch().
+ */
+#define MONGOC_HAVE_RES_SEARCH @MONGOC_HAVE_RES_SEARCH@
+
+#if MONGOC_HAVE_RES_SEARCH != 1
+# undef MONGOC_HAVE_RES_SEARCH
+#endif
+
+
+/*
+ * Set from configure, see
+ * https://curl.haxx.se/mail/lib-2009-04/0287.html
+ */
+#define MONGOC_SOCKET_ARG2 @MONGOC_SOCKET_ARG2@
+#define MONGOC_SOCKET_ARG3 @MONGOC_SOCKET_ARG3@
+
+/*
+ * Enable wire protocol compression negotiation
+ *
+ */
+#define MONGOC_ENABLE_COMPRESSION @MONGOC_ENABLE_COMPRESSION@
+
+#if MONGOC_ENABLE_COMPRESSION != 1
+# undef MONGOC_ENABLE_COMPRESSION
+#endif
+
+/*
+ * Set if we have snappy compression support
+ *
+ */
+#define MONGOC_ENABLE_COMPRESSION_SNAPPY @MONGOC_ENABLE_COMPRESSION_SNAPPY@
+
+#if MONGOC_ENABLE_COMPRESSION_SNAPPY != 1
+# undef MONGOC_ENABLE_COMPRESSION_SNAPPY
+#endif
+
+
+/*
+ * Set if we have zlib compression support
+ *
+ */
+#define MONGOC_ENABLE_COMPRESSION_ZLIB @MONGOC_ENABLE_COMPRESSION_ZLIB@
+
+#if MONGOC_ENABLE_COMPRESSION_ZLIB != 1
+# undef MONGOC_ENABLE_COMPRESSION_ZLIB
+#endif
+
+/*
+ * Set if we have zstd compression support
+ *
+ */
+#define MONGOC_ENABLE_COMPRESSION_ZSTD @MONGOC_ENABLE_COMPRESSION_ZSTD@
+
+#if MONGOC_ENABLE_COMPRESSION_ZSTD != 1
+# undef MONGOC_ENABLE_COMPRESSION_ZSTD
+#endif
+
+/*
+ * Set if performance counters are available and not disabled.
+ *
+ */
+#define MONGOC_ENABLE_SHM_COUNTERS @MONGOC_ENABLE_SHM_COUNTERS@
+
+#if MONGOC_ENABLE_SHM_COUNTERS != 1
+# undef MONGOC_ENABLE_SHM_COUNTERS
+#endif
+
+/*
+ * Set if we have enabled fast counters on Intel using the RDTSCP instruction
+ *
+ */
+#define MONGOC_ENABLE_RDTSCP @MONGOC_ENABLE_RDTSCP@
+
+#if MONGOC_ENABLE_RDTSCP != 1
+# undef MONGOC_ENABLE_RDTSCP
+#endif
+
+
+/*
+ * Set if we have the sched_getcpu() function for use with counters
+ *
+ */
+#define MONGOC_HAVE_SCHED_GETCPU @MONGOC_HAVE_SCHED_GETCPU@
+
+#if MONGOC_HAVE_SCHED_GETCPU != 1
+# undef MONGOC_HAVE_SCHED_GETCPU
+#endif
+
+/*
+ * Set if tracing is enabled. Logs things like network communication and
+ * entry/exit of certain functions.
+ */
+#define MONGOC_TRACE @MONGOC_TRACE@
+
+enum {
+ /**
+ * @brief Compile-time constant determining whether the mongoc library was
+ * compiled with tracing enabled.
+ *
+ * Can be controlled with the 'ENABLE_TRACING" configure-time boolean option
+ */
+ MONGOC_TRACE_ENABLED = MONGOC_TRACE
+};
+
+/*
+ * Set if we have ICU support.
+ */
+#define MONGOC_ENABLE_ICU @MONGOC_ENABLE_ICU@
+
+#if MONGOC_ENABLE_ICU != 1
+# undef MONGOC_ENABLE_ICU
+#endif
+
+
+/*
+ * Set if we have Client Side Encryption support.
+ */
+
+#define MONGOC_ENABLE_CLIENT_SIDE_ENCRYPTION @MONGOC_ENABLE_CLIENT_SIDE_ENCRYPTION@
+
+#if MONGOC_ENABLE_CLIENT_SIDE_ENCRYPTION != 1
+# undef MONGOC_ENABLE_CLIENT_SIDE_ENCRYPTION
+#endif
+
+
+/*
+ * Set if struct sockaddr_storage has __ss_family (instead of ss_family)
+ */
+
+#define MONGOC_HAVE_SS_FAMILY @MONGOC_HAVE_SS_FAMILY@
+
+#if MONGOC_HAVE_SS_FAMILY != 1
+# undef MONGOC_HAVE_SS_FAMILY
+#endif
+
+/*
+ * Set if building with AWS IAM support.
+ */
+#define MONGOC_ENABLE_MONGODB_AWS_AUTH @MONGOC_ENABLE_MONGODB_AWS_AUTH@
+
+#if MONGOC_ENABLE_MONGODB_AWS_AUTH != 1
+# undef MONGOC_ENABLE_MONGODB_AWS_AUTH
+#endif
+
+/* clang-format on */
+
+#endif /* MONGOC_CONFIG_H */
diff --git a/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-counters-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-counters-private.h
new file mode 100644
index 00000000..3a84ff64
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-counters-private.h
@@ -0,0 +1,202 @@
+/*
+ * Copyright 2013 MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mongoc-prelude.h"
+
+#ifndef MONGOC_COUNTERS_PRIVATE_H
+#define MONGOC_COUNTERS_PRIVATE_H
+
+#include <bson/bson.h>
+
+#include "mongoc.h"
+
+#ifdef __linux__
+#include <sched.h>
+#include <sys/sysinfo.h>
+#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || \
+ defined(__OpenBSD__)
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#include <sys/param.h>
+#elif defined(__hpux__)
+#include <sys/pstat.h>
+#endif
+
+
+BSON_BEGIN_DECLS
+
+
+void
+_mongoc_counters_init (void);
+void
+_mongoc_counters_cleanup (void);
+
+
+static BSON_INLINE unsigned
+_mongoc_get_cpu_count (void)
+{
+#if defined(__linux__)
+ return get_nprocs ();
+#elif defined(__hpux__)
+ struct pst_dynamic psd;
+
+ if (pstat_getdynamic (&psd, sizeof (psd), (size_t) 1, 0) != -1) {
+ return psd.psd_max_proc_cnt;
+ }
+ return 1;
+#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || \
+ defined(__OpenBSD__)
+ int mib[2];
+ int maxproc;
+ size_t len;
+
+ mib[0] = CTL_HW;
+ mib[1] = HW_NCPU;
+ len = sizeof (maxproc);
+
+ if (-1 == sysctl (mib, 2, &maxproc, &len, NULL, 0)) {
+ return 1;
+ }
+
+ return len;
+#elif defined(__APPLE__) || defined(__sun) || defined(_AIX)
+ int ncpu;
+
+ ncpu = (int) sysconf (_SC_NPROCESSORS_ONLN);
+ return (ncpu > 0) ? ncpu : 1;
+#elif defined(_MSC_VER) || defined(_WIN32)
+ SYSTEM_INFO si;
+ GetSystemInfo (&si);
+ return si.dwNumberOfProcessors;
+#else
+#warning "_mongoc_get_cpu_count() not supported, defaulting to 1."
+ return 1;
+#endif
+}
+
+
+#if defined(MONGOC_ENABLE_RDTSCP)
+static BSON_INLINE unsigned
+_mongoc_sched_getcpu (void)
+{
+ volatile uint32_t rax, rdx, rcx;
+ __asm__ volatile("rdtscp\n" : "=a"(rax), "=d"(rdx), "=c"(rcx) : :);
+ unsigned node_id, core_id;
+ // node_id = (rcx & 0xFFF000)>>12; // node_id is unused
+ core_id = rcx & 0xFFF;
+ return core_id;
+}
+#elif defined(MONGOC_HAVE_SCHED_GETCPU)
+#define _mongoc_sched_getcpu sched_getcpu
+#elif defined(__APPLE__) && defined(__aarch64__)
+static BSON_INLINE unsigned
+_mongoc_sched_getcpu (void)
+{
+ uintptr_t tls;
+ unsigned core_id;
+ /* Get the current thread ID, not the core ID.
+ * Getting the core ID requires privileged execution. */
+ __asm__ volatile("mrs %x0, tpidrro_el0" : "=r"(tls));
+ /* In ARM, only 8 cores are manageable. */
+ core_id = tls & 0x07u;
+ return core_id;
+}
+#else
+#define _mongoc_sched_getcpu() (0)
+#endif
+
+
+#ifndef SLOTS_PER_CACHELINE
+#define SLOTS_PER_CACHELINE 8
+#endif
+
+
+typedef struct {
+ int64_t slots[SLOTS_PER_CACHELINE];
+} mongoc_counter_slots_t;
+
+
+typedef struct {
+ mongoc_counter_slots_t *cpus;
+} mongoc_counter_t;
+
+
+#define COUNTER(ident, Category, Name, Description) \
+ extern mongoc_counter_t __mongoc_counter_##ident;
+#include "mongoc-counters.defs"
+#undef COUNTER
+
+
+enum {
+#define COUNTER(ident, Category, Name, Description) COUNTER_##ident,
+#include "mongoc-counters.defs"
+#undef COUNTER
+ LAST_COUNTER
+};
+
+#ifdef MONGOC_ENABLE_SHM_COUNTERS
+#define COUNTER(ident, Category, Name, Description) \
+ static BSON_INLINE void mongoc_counter_##ident##_add (int64_t val) \
+ { \
+ int64_t *counter = \
+ &BSON_CONCAT (__mongoc_counter_, ident) \
+ .cpus[_mongoc_sched_getcpu ()] \
+ .slots[BSON_CONCAT (COUNTER_, ident) % SLOTS_PER_CACHELINE]; \
+ bson_atomic_int64_fetch_add (counter, val, bson_memory_order_seq_cst); \
+ } \
+ static BSON_INLINE void mongoc_counter_##ident##_inc (void) \
+ { \
+ mongoc_counter_##ident##_add (1); \
+ } \
+ static BSON_INLINE void mongoc_counter_##ident##_dec (void) \
+ { \
+ mongoc_counter_##ident##_add (-1); \
+ } \
+ static BSON_INLINE void mongoc_counter_##ident##_reset (void) \
+ { \
+ uint32_t i; \
+ for (i = 0; i < _mongoc_get_cpu_count (); i++) { \
+ int64_t *counter = &__mongoc_counter_##ident.cpus[i] \
+ .slots[COUNTER_##ident % SLOTS_PER_CACHELINE]; \
+ bson_atomic_int64_exchange (counter, 0, bson_memory_order_seq_cst); \
+ } \
+ bson_atomic_thread_fence (); \
+ }
+#include "mongoc-counters.defs"
+#undef COUNTER
+#else
+/* when counters are disabled, these functions are no-ops */
+#define COUNTER(ident, Category, Name, Description) \
+ static BSON_INLINE void mongoc_counter_##ident##_add (int64_t val) \
+ { \
+ } \
+ static BSON_INLINE void mongoc_counter_##ident##_inc (void) \
+ { \
+ } \
+ static BSON_INLINE void mongoc_counter_##ident##_dec (void) \
+ { \
+ } \
+ static BSON_INLINE void mongoc_counter_##ident##_reset (void) \
+ { \
+ }
+#include "mongoc-counters.defs"
+#undef COUNTER
+#endif
+
+BSON_END_DECLS
+
+
+#endif /* MONGOC_COUNTERS_PRIVATE_H */
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-counters.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-counters.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-counters.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-counters.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-counters.defs b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-counters.defs
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-counters.defs
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-counters.defs
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-crypt-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-crypt-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-crypt-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-crypt-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-crypt.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-crypt.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-crypt.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-crypt.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-crypto-cng-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-crypto-cng-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-crypto-cng-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-crypto-cng-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-crypto-cng.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-crypto-cng.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-crypto-cng.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-crypto-cng.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-crypto-common-crypto-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-crypto-common-crypto-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-crypto-common-crypto-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-crypto-common-crypto-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-crypto-common-crypto.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-crypto-common-crypto.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-crypto-common-crypto.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-crypto-common-crypto.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-crypto-openssl-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-crypto-openssl-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-crypto-openssl-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-crypto-openssl-private.h
diff --git a/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-crypto-openssl.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-crypto-openssl.c
new file mode 100644
index 00000000..f48c5355
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-crypto-openssl.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2016 MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mongoc-config.h"
+#include <bson/bson.h>
+
+#ifdef MONGOC_ENABLE_CRYPTO_LIBCRYPTO
+#include "mongoc-crypto-openssl-private.h"
+#include "mongoc-crypto-private.h"
+
+#include <openssl/sha.h>
+#include <openssl/evp.h>
+#include <openssl/hmac.h>
+
+
+void
+mongoc_crypto_openssl_hmac_sha1 (mongoc_crypto_t *crypto,
+ const void *key,
+ int key_len,
+ const unsigned char *data,
+ int data_len,
+ unsigned char *hmac_out)
+{
+ /* U1 = HMAC(input, salt + 0001) */
+ HMAC (EVP_sha1 (), key, key_len, data, data_len, hmac_out, NULL);
+}
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000L)
+static EVP_MD_CTX *
+EVP_MD_CTX_new (void)
+{
+ return bson_malloc0 (sizeof (EVP_MD_CTX));
+}
+
+static void
+EVP_MD_CTX_free (EVP_MD_CTX *ctx)
+{
+ EVP_MD_CTX_cleanup (ctx);
+ bson_free (ctx);
+}
+#endif
+
+bool
+mongoc_crypto_openssl_sha1 (mongoc_crypto_t *crypto,
+ const unsigned char *input,
+ const size_t input_len,
+ unsigned char *hash_out)
+{
+ EVP_MD_CTX *digest_ctxp = EVP_MD_CTX_new ();
+ bool rval = false;
+
+ if (1 != EVP_DigestInit_ex (digest_ctxp, EVP_sha1 (), NULL)) {
+ goto cleanup;
+ }
+
+ if (1 != EVP_DigestUpdate (digest_ctxp, input, input_len)) {
+ goto cleanup;
+ }
+
+ rval = (1 == EVP_DigestFinal_ex (digest_ctxp, hash_out, NULL));
+
+cleanup:
+ EVP_MD_CTX_free (digest_ctxp);
+
+ return rval;
+}
+
+void
+mongoc_crypto_openssl_hmac_sha256 (mongoc_crypto_t *crypto,
+ const void *key,
+ int key_len,
+ const unsigned char *data,
+ int data_len,
+ unsigned char *hmac_out)
+{
+ /* U1 = HMAC(input, salt + 0001) */
+ HMAC (EVP_sha256 (), key, key_len, data, data_len, hmac_out, NULL);
+}
+
+bool
+mongoc_crypto_openssl_sha256 (mongoc_crypto_t *crypto,
+ const unsigned char *input,
+ const size_t input_len,
+ unsigned char *hash_out)
+{
+ EVP_MD_CTX *digest_ctxp = EVP_MD_CTX_new ();
+ bool rval = false;
+
+ if (1 != EVP_DigestInit_ex (digest_ctxp, EVP_sha256 (), NULL)) {
+ goto cleanup;
+ }
+
+ if (1 != EVP_DigestUpdate (digest_ctxp, input, input_len)) {
+ goto cleanup;
+ }
+
+ rval = (1 == EVP_DigestFinal_ex (digest_ctxp, hash_out, NULL));
+
+cleanup:
+ EVP_MD_CTX_free (digest_ctxp);
+
+ return rval;
+}
+
+#endif
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-crypto-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-crypto-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-crypto-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-crypto-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-crypto.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-crypto.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-crypto.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-crypto.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor-array.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor-array.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor-array.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor-array.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor-change-stream.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor-change-stream.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor-change-stream.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor-change-stream.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor-cmd-deprecated.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor-cmd-deprecated.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor-cmd-deprecated.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor-cmd-deprecated.c
diff --git a/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor-cmd.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor-cmd.c
new file mode 100644
index 00000000..b8308a19
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor-cmd.c
@@ -0,0 +1,217 @@
+/*
+ * Copyright 2018-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "mongoc.h"
+#include "mongoc-cursor-private.h"
+#include "mongoc-client-private.h"
+
+typedef enum { NONE, CMD_RESPONSE, OP_GETMORE_RESPONSE } reading_from_t;
+typedef enum { UNKNOWN, GETMORE_CMD, OP_GETMORE } getmore_type_t;
+typedef struct _data_cmd_t {
+ /* Two paths:
+ * - Mongo 3.2+, sent "getMore" cmd, we're reading reply's "nextBatch" array
+ * - Mongo 2.6 to 3, after "aggregate" or similar command we sent OP_GETMORE,
+ * we're reading the raw reply from a stream
+ */
+ mongoc_cursor_response_t response;
+ mongoc_cursor_response_legacy_t response_legacy;
+ reading_from_t reading_from;
+ getmore_type_t getmore_type; /* cache after first getmore. */
+ bson_t cmd;
+} data_cmd_t;
+
+
+static getmore_type_t
+_getmore_type (mongoc_cursor_t *cursor)
+{
+ mongoc_server_stream_t *server_stream;
+ int32_t wire_version;
+ data_cmd_t *data = (data_cmd_t *) cursor->impl.data;
+ if (data->getmore_type != UNKNOWN) {
+ return data->getmore_type;
+ }
+ server_stream = _mongoc_cursor_fetch_stream (cursor);
+ if (!server_stream) {
+ return UNKNOWN;
+ }
+ wire_version = server_stream->sd->max_wire_version;
+ mongoc_server_stream_cleanup (server_stream);
+
+ if (
+ /* Server version 5.1 and newer do not support OP_GETMORE. */
+ wire_version > WIRE_VERSION_5_0 ||
+ /* Fallback to legacy OP_GETMORE wire protocol messages if exhaust cursor
+ requested with server version 3.6 or newer . */
+ (wire_version >= WIRE_VERSION_FIND_CMD &&
+ !_mongoc_cursor_get_opt_bool (cursor, MONGOC_CURSOR_EXHAUST))) {
+ data->getmore_type = GETMORE_CMD;
+ } else {
+ data->getmore_type = OP_GETMORE;
+ }
+
+ return data->getmore_type;
+}
+
+
+static mongoc_cursor_state_t
+_prime (mongoc_cursor_t *cursor)
+{
+ data_cmd_t *data = (data_cmd_t *) cursor->impl.data;
+ bson_t copied_opts;
+ bson_init (&copied_opts);
+
+ cursor->operation_id = ++cursor->client->cluster.operation_id;
+ /* commands like agg have a cursor field, so copy opts without "batchSize" */
+ bson_copy_to_excluding_noinit (
+ &cursor->opts, &copied_opts, "batchSize", "tailable", NULL);
+
+ /* server replies to aggregate/listIndexes/listCollections with:
+ * {cursor: {id: N, firstBatch: []}} */
+ _mongoc_cursor_response_refresh (
+ cursor, &data->cmd, &copied_opts, &data->response);
+ data->reading_from = CMD_RESPONSE;
+ bson_destroy (&copied_opts);
+ return IN_BATCH;
+}
+
+
+static mongoc_cursor_state_t
+_pop_from_batch (mongoc_cursor_t *cursor)
+{
+ data_cmd_t *data = (data_cmd_t *) cursor->impl.data;
+
+ switch (data->reading_from) {
+ case CMD_RESPONSE:
+ _mongoc_cursor_response_read (cursor, &data->response, &cursor->current);
+ break;
+ case OP_GETMORE_RESPONSE:
+ cursor->current = bson_reader_read (data->response_legacy.reader, NULL);
+ break;
+ case NONE:
+ default:
+ fprintf (stderr, "trying to pop from an uninitialized cursor reader.\n");
+ BSON_ASSERT (false);
+ }
+ if (cursor->current) {
+ return IN_BATCH;
+ } else {
+ return cursor->cursor_id ? END_OF_BATCH : DONE;
+ }
+}
+
+
+static mongoc_cursor_state_t
+_get_next_batch (mongoc_cursor_t *cursor)
+{
+ data_cmd_t *data = (data_cmd_t *) cursor->impl.data;
+ bson_t getmore_cmd;
+ getmore_type_t getmore_type = _getmore_type (cursor);
+
+ switch (getmore_type) {
+ case GETMORE_CMD:
+ _mongoc_cursor_prepare_getmore_command (cursor, &getmore_cmd);
+ _mongoc_cursor_response_refresh (
+ cursor, &getmore_cmd, NULL /* opts */, &data->response);
+ bson_destroy (&getmore_cmd);
+ data->reading_from = CMD_RESPONSE;
+ return IN_BATCH;
+ case OP_GETMORE:
+ _mongoc_cursor_op_getmore (cursor, &data->response_legacy);
+ data->reading_from = OP_GETMORE_RESPONSE;
+ return IN_BATCH;
+ case UNKNOWN:
+ default:
+ return DONE;
+ }
+}
+
+
+static void
+_destroy (mongoc_cursor_impl_t *impl)
+{
+ data_cmd_t *data = (data_cmd_t *) impl->data;
+ bson_destroy (&data->response.reply);
+ bson_destroy (&data->cmd);
+ _mongoc_cursor_response_legacy_destroy (&data->response_legacy);
+ bson_free (data);
+}
+
+
+static void
+_clone (mongoc_cursor_impl_t *dst, const mongoc_cursor_impl_t *src)
+{
+ data_cmd_t *data_src = (data_cmd_t *) src->data;
+ data_cmd_t *data_dst = bson_malloc0 (sizeof (data_cmd_t));
+ bson_init (&data_dst->response.reply);
+ _mongoc_cursor_response_legacy_init (&data_dst->response_legacy);
+ bson_copy_to (&data_src->cmd, &data_dst->cmd);
+ dst->data = data_dst;
+}
+
+
+mongoc_cursor_t *
+_mongoc_cursor_cmd_new (mongoc_client_t *client,
+ const char *db_and_coll,
+ const bson_t *cmd,
+ const bson_t *opts,
+ const mongoc_read_prefs_t *user_prefs,
+ const mongoc_read_prefs_t *default_prefs,
+ const mongoc_read_concern_t *read_concern)
+{
+ mongoc_cursor_t *cursor;
+ data_cmd_t *data = bson_malloc0 (sizeof (*data));
+
+ cursor = _mongoc_cursor_new_with_opts (
+ client, db_and_coll, opts, user_prefs, default_prefs, read_concern);
+ _mongoc_cursor_response_legacy_init (&data->response_legacy);
+ _mongoc_cursor_check_and_copy_to (cursor, "command", cmd, &data->cmd);
+ bson_init (&data->response.reply);
+ cursor->impl.prime = _prime;
+ cursor->impl.pop_from_batch = _pop_from_batch;
+ cursor->impl.get_next_batch = _get_next_batch;
+ cursor->impl.destroy = _destroy;
+ cursor->impl.clone = _clone;
+ cursor->impl.data = (void *) data;
+ return cursor;
+}
+
+
+mongoc_cursor_t *
+_mongoc_cursor_cmd_new_from_reply (mongoc_client_t *client,
+ const bson_t *cmd,
+ const bson_t *opts,
+ bson_t *reply)
+{
+ mongoc_cursor_t *cursor =
+ _mongoc_cursor_cmd_new (client, NULL, cmd, opts, NULL, NULL, NULL);
+ data_cmd_t *data = (data_cmd_t *) cursor->impl.data;
+
+ data->reading_from = CMD_RESPONSE;
+ cursor->state = IN_BATCH;
+
+ bson_destroy (&data->response.reply);
+ if (!bson_steal (&data->response.reply, reply)) {
+ bson_destroy (&data->response.reply);
+ BSON_ASSERT (bson_steal (&data->response.reply, bson_copy (reply)));
+ }
+
+ if (!_mongoc_cursor_start_reading_response (cursor, &data->response)) {
+ bson_set_error (&cursor->error,
+ MONGOC_ERROR_CURSOR,
+ MONGOC_ERROR_CURSOR_INVALID_CURSOR,
+ "Couldn't parse cursor document");
+ }
+ return cursor;
+}
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor-find-cmd.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor-find-cmd.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor-find-cmd.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor-find-cmd.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor-find-opquery.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor-find-opquery.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor-find-opquery.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor-find-opquery.c
diff --git a/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor-find.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor-find.c
new file mode 100644
index 00000000..48fb5c58
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor-find.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2018-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mongoc.h"
+#include "mongoc-cursor-private.h"
+#include "mongoc-client-private.h"
+
+typedef struct _data_find_t {
+ bson_t filter;
+} data_find_t;
+
+
+extern void
+_mongoc_cursor_impl_find_cmd_init (mongoc_cursor_t *cursor, bson_t *filter);
+extern void
+_mongoc_cursor_impl_find_opquery_init (mongoc_cursor_t *cursor, bson_t *filter);
+
+
+static mongoc_cursor_state_t
+_prime (mongoc_cursor_t *cursor)
+{
+ int32_t wire_version;
+ mongoc_server_stream_t *server_stream;
+ data_find_t *data = (data_find_t *) cursor->impl.data;
+
+ /* determine if this should be a command or op_query cursor. */
+ server_stream = _mongoc_cursor_fetch_stream (cursor);
+ if (!server_stream) {
+ return DONE;
+ }
+ wire_version = server_stream->sd->max_wire_version;
+ mongoc_server_stream_cleanup (server_stream);
+
+ /* set all mongoc_impl_t function pointers. */
+ if (
+ /* Server version 5.1 and newer do not support OP_QUERY. */
+ wire_version > WIRE_VERSION_5_0 ||
+ /* Fallback to legacy OP_QUERY wire protocol messages if exhaust cursor
+ requested with server version 3.6 or newer. */
+ (wire_version >= WIRE_VERSION_FIND_CMD &&
+ !_mongoc_cursor_get_opt_bool (cursor, MONGOC_CURSOR_EXHAUST))) {
+ _mongoc_cursor_impl_find_cmd_init (cursor, &data->filter /* stolen */);
+ } else {
+ _mongoc_cursor_impl_find_opquery_init (cursor,
+ &data->filter /* stolen */);
+ }
+ /* destroy this impl data since impl functions have been replaced. */
+ bson_free (data);
+ /* prime with the new implementation. */
+ return cursor->impl.prime (cursor);
+}
+
+
+static void
+_clone (mongoc_cursor_impl_t *dst, const mongoc_cursor_impl_t *src)
+{
+ data_find_t *data_dst = bson_malloc0 (sizeof (data_find_t));
+ data_find_t *data_src = (data_find_t *) src->data;
+ bson_copy_to (&data_src->filter, &data_dst->filter);
+ dst->data = data_dst;
+}
+
+
+static void
+_destroy (mongoc_cursor_impl_t *impl)
+{
+ data_find_t *data = (data_find_t *) impl->data;
+ bson_destroy (&data->filter);
+ bson_free (data);
+}
+
+
+mongoc_cursor_t *
+_mongoc_cursor_find_new (mongoc_client_t *client,
+ const char *db_and_coll,
+ const bson_t *filter,
+ const bson_t *opts,
+ const mongoc_read_prefs_t *user_prefs,
+ const mongoc_read_prefs_t *default_prefs,
+ const mongoc_read_concern_t *read_concern)
+{
+ mongoc_cursor_t *cursor;
+ data_find_t *data = bson_malloc0 (sizeof (data_find_t));
+ cursor = _mongoc_cursor_new_with_opts (
+ client, db_and_coll, opts, user_prefs, default_prefs, read_concern);
+ _mongoc_cursor_check_and_copy_to (cursor, "filter", filter, &data->filter);
+ cursor->impl.prime = _prime;
+ cursor->impl.clone = _clone;
+ cursor->impl.destroy = _destroy;
+ cursor->impl.data = data;
+ return cursor;
+}
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor-legacy.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor-legacy.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor-legacy.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor-legacy.c
diff --git a/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor-private.h
new file mode 100644
index 00000000..b4196249
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor-private.h
@@ -0,0 +1,337 @@
+/*
+ * Copyright 2013 MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mongoc-prelude.h"
+
+#ifndef MONGOC_CURSOR_PRIVATE_H
+#define MONGOC_CURSOR_PRIVATE_H
+
+#include <bson/bson.h>
+
+#include "mongoc-client.h"
+#include "mongoc-buffer-private.h"
+#include "mongoc-rpc-private.h"
+#include "mongoc-server-stream-private.h"
+#include "mongoc-cluster-private.h"
+
+
+BSON_BEGIN_DECLS
+
+#define MONGOC_CURSOR_ALLOW_PARTIAL_RESULTS "allowPartialResults"
+#define MONGOC_CURSOR_ALLOW_PARTIAL_RESULTS_LEN 19
+#define MONGOC_CURSOR_AWAIT_DATA "awaitData"
+#define MONGOC_CURSOR_AWAIT_DATA_LEN 9
+#define MONGOC_CURSOR_BATCH_SIZE "batchSize"
+#define MONGOC_CURSOR_BATCH_SIZE_LEN 9
+#define MONGOC_CURSOR_COLLATION "collation"
+#define MONGOC_CURSOR_COLLATION_LEN 9
+#define MONGOC_CURSOR_COMMENT "comment"
+#define MONGOC_CURSOR_COMMENT_LEN 7
+#define MONGOC_CURSOR_EXHAUST "exhaust"
+#define MONGOC_CURSOR_EXHAUST_LEN 7
+#define MONGOC_CURSOR_FILTER "filter"
+#define MONGOC_CURSOR_FILTER_LEN 6
+#define MONGOC_CURSOR_FIND "find"
+#define MONGOC_CURSOR_FIND_LEN 4
+#define MONGOC_CURSOR_HINT "hint"
+#define MONGOC_CURSOR_HINT_LEN 4
+#define MONGOC_CURSOR_LIMIT "limit"
+#define MONGOC_CURSOR_LIMIT_LEN 5
+#define MONGOC_CURSOR_MAX "max"
+#define MONGOC_CURSOR_MAX_LEN 3
+#define MONGOC_CURSOR_MAX_AWAIT_TIME_MS "maxAwaitTimeMS"
+#define MONGOC_CURSOR_MAX_AWAIT_TIME_MS_LEN 14
+#define MONGOC_CURSOR_MAX_SCAN "maxScan"
+#define MONGOC_CURSOR_MAX_SCAN_LEN 7
+#define MONGOC_CURSOR_MAX_TIME_MS "maxTimeMS"
+#define MONGOC_CURSOR_MAX_TIME_MS_LEN 9
+#define MONGOC_CURSOR_MIN "min"
+#define MONGOC_CURSOR_MIN_LEN 3
+#define MONGOC_CURSOR_NO_CURSOR_TIMEOUT "noCursorTimeout"
+#define MONGOC_CURSOR_NO_CURSOR_TIMEOUT_LEN 15
+#define MONGOC_CURSOR_OPLOG_REPLAY "oplogReplay"
+#define MONGOC_CURSOR_OPLOG_REPLAY_LEN 11
+#define MONGOC_CURSOR_ORDERBY "orderby"
+#define MONGOC_CURSOR_ORDERBY_LEN 7
+#define MONGOC_CURSOR_PROJECTION "projection"
+#define MONGOC_CURSOR_PROJECTION_LEN 10
+#define MONGOC_CURSOR_QUERY "query"
+#define MONGOC_CURSOR_QUERY_LEN 5
+#define MONGOC_CURSOR_READ_CONCERN "readConcern"
+#define MONGOC_CURSOR_READ_CONCERN_LEN 11
+#define MONGOC_CURSOR_RETURN_KEY "returnKey"
+#define MONGOC_CURSOR_RETURN_KEY_LEN 9
+#define MONGOC_CURSOR_SHOW_DISK_LOC "showDiskLoc"
+#define MONGOC_CURSOR_SHOW_DISK_LOC_LEN 11
+#define MONGOC_CURSOR_SHOW_RECORD_ID "showRecordId"
+#define MONGOC_CURSOR_SHOW_RECORD_ID_LEN 12
+#define MONGOC_CURSOR_SINGLE_BATCH "singleBatch"
+#define MONGOC_CURSOR_SINGLE_BATCH_LEN 11
+#define MONGOC_CURSOR_SKIP "skip"
+#define MONGOC_CURSOR_SKIP_LEN 4
+#define MONGOC_CURSOR_SNAPSHOT "snapshot"
+#define MONGOC_CURSOR_SNAPSHOT_LEN 8
+#define MONGOC_CURSOR_SORT "sort"
+#define MONGOC_CURSOR_SORT_LEN 4
+#define MONGOC_CURSOR_TAILABLE "tailable"
+#define MONGOC_CURSOR_TAILABLE_LEN 8
+
+typedef struct _mongoc_cursor_impl_t mongoc_cursor_impl_t;
+typedef enum { UNPRIMED, IN_BATCH, END_OF_BATCH, DONE } mongoc_cursor_state_t;
+typedef mongoc_cursor_state_t (*_mongoc_cursor_impl_transition_t) (
+ mongoc_cursor_t *cursor);
+struct _mongoc_cursor_impl_t {
+ void (*clone) (mongoc_cursor_impl_t *dst, const mongoc_cursor_impl_t *src);
+ void (*destroy) (mongoc_cursor_impl_t *ctx);
+ _mongoc_cursor_impl_transition_t prime;
+ _mongoc_cursor_impl_transition_t pop_from_batch;
+ _mongoc_cursor_impl_transition_t get_next_batch;
+ void *data;
+};
+
+/* pre-3.2 and exhaust cursor responses -- read documents from stream. */
+typedef struct _mongoc_cursor_response_legacy {
+ mongoc_rpc_t rpc;
+ mongoc_buffer_t buffer;
+ bson_reader_t *reader;
+} mongoc_cursor_response_legacy_t;
+
+/* 3.2+ responses -- read batch docs like {cursor:{id: 123, firstBatch: []}} */
+typedef struct _mongoc_cursor_response_t {
+ bson_t reply; /* the entire command reply */
+ bson_iter_t batch_iter; /* iterates over the batch array */
+ bson_t current_doc; /* the current doc inside the batch array */
+} mongoc_cursor_response_t;
+
+struct _mongoc_cursor_t {
+ mongoc_client_t *client;
+ uint32_t client_generation;
+
+ uint32_t server_id;
+ bool secondary_ok;
+
+ mongoc_cursor_state_t state;
+ bool in_exhaust;
+
+ bson_t opts;
+
+ mongoc_read_concern_t *read_concern;
+ mongoc_read_prefs_t *read_prefs;
+ mongoc_write_concern_t *write_concern;
+
+ /** If the cursor was created for an operation that might have overridden the
+ * user's read preferences' read mode, then server selection forced the
+ * cursor to use a read preference mode of 'primary' server. Whether this
+ * force occurred is stored here: */
+ bool must_use_primary;
+
+ /** Whether this cursor corresponds to an aggregate command that contains a
+ * writing-stage */
+ bool is_aggr_with_write_stage;
+
+ bool explicit_session;
+ mongoc_client_session_t *client_session;
+
+ uint32_t count;
+
+ char *ns;
+ uint32_t nslen;
+ uint32_t dblen;
+
+ bson_error_t error;
+ bson_t error_doc; /* always initialized, and set with server errors. */
+
+ const bson_t *current;
+
+ mongoc_cursor_impl_t impl;
+
+ int64_t operation_id;
+ int64_t cursor_id;
+};
+
+int32_t
+_mongoc_n_return (mongoc_cursor_t *cursor);
+void
+_mongoc_set_cursor_ns (mongoc_cursor_t *cursor, const char *ns, uint32_t nslen);
+bool
+_mongoc_cursor_get_opt_bool (const mongoc_cursor_t *cursor, const char *option);
+void
+_mongoc_cursor_flags_to_opts (mongoc_query_flags_t qflags,
+ bson_t *opts,
+ bool *secondary_ok);
+bool
+_mongoc_cursor_translate_dollar_query_opts (const bson_t *query,
+ bson_t *opts,
+ bson_t *unwrapped,
+ bson_error_t *error);
+mongoc_server_stream_t *
+_mongoc_cursor_fetch_stream (mongoc_cursor_t *cursor);
+void
+_mongoc_cursor_collection (const mongoc_cursor_t *cursor,
+ const char **collection,
+ int *collection_len);
+bool
+_mongoc_cursor_run_command (mongoc_cursor_t *cursor,
+ const bson_t *command,
+ const bson_t *opts,
+ bson_t *reply,
+ bool retry_prohibited);
+bool
+_mongoc_cursor_more (mongoc_cursor_t *cursor);
+
+bool
+_mongoc_cursor_set_opt_int64 (mongoc_cursor_t *cursor,
+ const char *option,
+ int64_t value);
+void
+_mongoc_cursor_monitor_failed (mongoc_cursor_t *cursor,
+ int64_t duration,
+ mongoc_server_stream_t *stream,
+ const char *cmd_name);
+bool
+_mongoc_cursor_monitor_command (mongoc_cursor_t *cursor,
+ mongoc_server_stream_t *server_stream,
+ const bson_t *cmd,
+ const char *cmd_name);
+void
+_mongoc_cursor_prepare_find_command (mongoc_cursor_t *cursor,
+ const bson_t *filter,
+ bson_t *command);
+const bson_t *
+_mongoc_cursor_initial_query (mongoc_cursor_t *cursor);
+const bson_t *
+_mongoc_cursor_get_more (mongoc_cursor_t *cursor);
+bool
+_mongoc_cursor_opts_to_flags (mongoc_cursor_t *cursor,
+ mongoc_server_stream_t *stream,
+ mongoc_query_flags_t *flags /* OUT */);
+void
+_mongoc_cursor_monitor_succeeded (mongoc_cursor_t *cursor,
+ mongoc_cursor_response_legacy_t *response,
+ int64_t duration,
+ bool first_batch,
+ mongoc_server_stream_t *stream,
+ const char *cmd_name);
+/* start iterating a reply like
+ * {cursor: {id: 1234, ns: "db.collection", firstBatch: [...]}} or
+ * {cursor: {id: 1234, ns: "db.collection", nextBatch: [...]}} */
+void
+_mongoc_cursor_response_refresh (mongoc_cursor_t *cursor,
+ const bson_t *command,
+ const bson_t *opts,
+ mongoc_cursor_response_t *response);
+bool
+_mongoc_cursor_start_reading_response (mongoc_cursor_t *cursor,
+ mongoc_cursor_response_t *response);
+void
+_mongoc_cursor_response_read (mongoc_cursor_t *cursor,
+ mongoc_cursor_response_t *response,
+ const bson_t **bson);
+void
+_mongoc_cursor_prepare_getmore_command (mongoc_cursor_t *cursor,
+ bson_t *command);
+void
+_mongoc_cursor_set_empty (mongoc_cursor_t *cursor);
+bool
+_mongoc_cursor_check_and_copy_to (mongoc_cursor_t *cursor,
+ const char *err_prefix,
+ const bson_t *src,
+ bson_t *dst);
+void
+_mongoc_cursor_prime (mongoc_cursor_t *cursor);
+/* legacy functions defined in mongoc-cursor-legacy.c */
+bool
+_mongoc_cursor_next (mongoc_cursor_t *cursor, const bson_t **bson);
+bool
+_mongoc_cursor_op_query_find (mongoc_cursor_t *cursor,
+ bson_t *filter,
+ mongoc_cursor_response_legacy_t *response);
+void
+_mongoc_cursor_op_getmore (mongoc_cursor_t *cursor,
+ mongoc_cursor_response_legacy_t *response);
+mongoc_cursor_t *
+_mongoc_cursor_new_with_opts (mongoc_client_t *client,
+ const char *db_and_collection,
+ const bson_t *opts,
+ const mongoc_read_prefs_t *user_prefs,
+ const mongoc_read_prefs_t *default_prefs,
+ const mongoc_read_concern_t *read_concern);
+void
+_mongoc_cursor_response_legacy_init (mongoc_cursor_response_legacy_t *response);
+void
+_mongoc_cursor_response_legacy_destroy (
+ mongoc_cursor_response_legacy_t *response);
+/* cursor constructors. */
+mongoc_cursor_t *
+_mongoc_cursor_find_new (mongoc_client_t *client,
+ const char *db_and_coll,
+ const bson_t *filter,
+ const bson_t *opts,
+ const mongoc_read_prefs_t *user_prefs,
+ const mongoc_read_prefs_t *default_prefs,
+ const mongoc_read_concern_t *read_concern);
+
+mongoc_cursor_t *
+_mongoc_cursor_cmd_new (mongoc_client_t *client,
+ const char *db_and_coll,
+ const bson_t *cmd,
+ const bson_t *opts,
+ const mongoc_read_prefs_t *user_prefs,
+ const mongoc_read_prefs_t *default_prefs,
+ const mongoc_read_concern_t *read_concern);
+
+mongoc_cursor_t *
+_mongoc_cursor_cmd_new_from_reply (mongoc_client_t *client,
+ const bson_t *cmd,
+ const bson_t *opts,
+ bson_t *reply);
+
+mongoc_cursor_t *
+_mongoc_cursor_cmd_deprecated_new (mongoc_client_t *client,
+ const char *db_and_coll,
+ const bson_t *cmd,
+ const mongoc_read_prefs_t *read_prefs);
+
+mongoc_cursor_t *
+_mongoc_cursor_array_new (mongoc_client_t *client,
+ const char *db_and_coll,
+ const bson_t *cmd,
+ const bson_t *opts,
+ const char *field_name);
+
+mongoc_cursor_t *
+_mongoc_cursor_change_stream_new (mongoc_client_t *client,
+ bson_t *reply,
+ const bson_t *opts);
+
+bool
+_mongoc_cursor_change_stream_end_of_batch (mongoc_cursor_t *cursor);
+
+const bson_t *
+_mongoc_cursor_change_stream_get_post_batch_resume_token (
+ mongoc_cursor_t *cursor);
+
+bool
+_mongoc_cursor_change_stream_has_post_batch_resume_token (
+ mongoc_cursor_t *cursor);
+
+const bson_t *
+_mongoc_cursor_change_stream_get_reply (mongoc_cursor_t *cursor);
+
+BSON_END_DECLS
+
+
+#endif /* MONGOC_CURSOR_PRIVATE_H */
diff --git a/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor.c
new file mode 100644
index 00000000..2aa8164c
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor.c
@@ -0,0 +1,1791 @@
+/*
+ * Copyright 2013 MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include "mongoc-cursor.h"
+#include "mongoc-cursor-private.h"
+#include "mongoc-client-private.h"
+#include "mongoc-client-session-private.h"
+#include "mongoc-counters-private.h"
+#include "mongoc-error.h"
+#include "mongoc-error-private.h"
+#include "mongoc-log.h"
+#include "mongoc-trace-private.h"
+#include "mongoc-read-concern-private.h"
+#include "mongoc-util-private.h"
+#include "mongoc-write-concern-private.h"
+#include "mongoc-read-prefs-private.h"
+#include "mongoc-aggregate-private.h"
+
+#undef MONGOC_LOG_DOMAIN
+#define MONGOC_LOG_DOMAIN "cursor"
+
+
+#define CURSOR_FAILED(cursor_) ((cursor_)->error.domain != 0)
+
+static bool
+_translate_query_opt (const char *query_field,
+ const char **cmd_field,
+ int *len);
+
+
+bool
+_mongoc_cursor_set_opt_int64 (mongoc_cursor_t *cursor,
+ const char *option,
+ int64_t value)
+{
+ bson_iter_t iter;
+
+ if (bson_iter_init_find (&iter, &cursor->opts, option)) {
+ if (!BSON_ITER_HOLDS_INT64 (&iter)) {
+ return false;
+ }
+
+ bson_iter_overwrite_int64 (&iter, value);
+ return true;
+ }
+
+ return BSON_APPEND_INT64 (&cursor->opts, option, value);
+}
+
+
+static int64_t
+_mongoc_cursor_get_opt_int64 (const mongoc_cursor_t *cursor,
+ const char *option,
+ int64_t default_value)
+{
+ bson_iter_t iter;
+
+ if (bson_iter_init_find (&iter, &cursor->opts, option)) {
+ return bson_iter_as_int64 (&iter);
+ }
+
+ return default_value;
+}
+
+
+static bool
+_mongoc_cursor_set_opt_bool (mongoc_cursor_t *cursor,
+ const char *option,
+ bool value)
+{
+ bson_iter_t iter;
+
+ if (bson_iter_init_find (&iter, &cursor->opts, option)) {
+ if (!BSON_ITER_HOLDS_BOOL (&iter)) {
+ return false;
+ }
+
+ bson_iter_overwrite_bool (&iter, value);
+ return true;
+ }
+
+ return BSON_APPEND_BOOL (&cursor->opts, option, value);
+}
+
+
+bool
+_mongoc_cursor_get_opt_bool (const mongoc_cursor_t *cursor, const char *option)
+{
+ bson_iter_t iter;
+
+ if (bson_iter_init_find (&iter, &cursor->opts, option)) {
+ return bson_iter_as_bool (&iter);
+ }
+
+ return false;
+}
+
+
+int32_t
+_mongoc_n_return (mongoc_cursor_t *cursor)
+{
+ int64_t limit;
+ int64_t batch_size;
+ int64_t n_return;
+
+ /* calculate numberToReturn according to:
+ * https://github.com/mongodb/specifications/blob/master/source/crud/crud.rst#combining-limit-and-batch-size-for-the-wire-protocol
+ */
+ limit = mongoc_cursor_get_limit (cursor);
+ batch_size = mongoc_cursor_get_batch_size (cursor);
+
+ if (limit < 0) {
+ n_return = limit;
+ } else if (limit == 0) {
+ n_return = batch_size;
+ } else if (batch_size == 0) {
+ n_return = limit;
+ } else if (limit < batch_size) {
+ n_return = limit;
+ } else {
+ n_return = batch_size;
+ }
+
+ /* if a specified limit exists, account for documents already returned. */
+ if (limit > 0 && cursor->count) {
+ int64_t remaining = limit - cursor->count;
+ /* remaining can be 0 if we have retrieved "limit" documents, but still
+ * have a cursor id: SERVER-21086. use nonzero batchSize to fetch final
+ * empty batch and trigger server to close cursor. */
+ if (remaining <= 0) {
+ return 1;
+ }
+
+ n_return = BSON_MIN (n_return, remaining);
+ }
+
+ /* check boundary conditions */
+ if (n_return < INT32_MIN) {
+ return INT32_MIN;
+ } else if (n_return > INT32_MAX) {
+ return INT32_MAX;
+ } else {
+ return (int32_t) n_return;
+ }
+}
+
+
+void
+_mongoc_set_cursor_ns (mongoc_cursor_t *cursor, const char *ns, uint32_t nslen)
+{
+ const char *dot;
+
+ bson_free (cursor->ns);
+ cursor->ns = bson_strndup (ns, nslen);
+ cursor->nslen = nslen;
+ dot = strstr (cursor->ns, ".");
+
+ if (dot) {
+ cursor->dblen = (uint32_t) (dot - cursor->ns);
+ } else {
+ /* a database name with no collection name */
+ cursor->dblen = cursor->nslen;
+ }
+}
+
+
+/* return first key beginning with $, or NULL. precondition: bson is valid. */
+static const char *
+_first_dollar_field (const bson_t *bson)
+{
+ bson_iter_t iter;
+ const char *key;
+
+ BSON_ASSERT (bson_iter_init (&iter, bson));
+ while (bson_iter_next (&iter)) {
+ key = bson_iter_key (&iter);
+
+ if (key[0] == '$') {
+ return key;
+ }
+ }
+
+ return NULL;
+}
+
+
+/* if src is non-NULL, it is validated and copied to dst. returns false and
+ * sets the cursor error if validation fails. */
+bool
+_mongoc_cursor_check_and_copy_to (mongoc_cursor_t *cursor,
+ const char *err_prefix,
+ const bson_t *src,
+ bson_t *dst)
+{
+ bson_error_t validate_err;
+ bson_init (dst);
+ if (src) {
+ if (!bson_validate_with_error (
+ src, BSON_VALIDATE_EMPTY_KEYS, &validate_err)) {
+ bson_set_error (&cursor->error,
+ MONGOC_ERROR_CURSOR,
+ MONGOC_ERROR_CURSOR_INVALID_CURSOR,
+ "Invalid %s: %s",
+ err_prefix,
+ validate_err.message);
+ return false;
+ }
+
+ bson_destroy (dst);
+ bson_copy_to (src, dst);
+ }
+ return true;
+}
+
+
+mongoc_cursor_t *
+_mongoc_cursor_new_with_opts (mongoc_client_t *client,
+ const char *db_and_collection,
+ const bson_t *opts,
+ const mongoc_read_prefs_t *user_prefs,
+ const mongoc_read_prefs_t *default_prefs,
+ const mongoc_read_concern_t *read_concern)
+{
+ mongoc_cursor_t *cursor;
+ mongoc_topology_description_type_t td_type;
+ uint32_t server_id;
+ mongoc_read_concern_t *read_concern_local = NULL;
+ bson_error_t validate_err;
+ const char *dollar_field;
+ bson_iter_t iter;
+
+ ENTRY;
+
+ BSON_ASSERT (client);
+
+ cursor = (mongoc_cursor_t *) bson_malloc0 (sizeof *cursor);
+ cursor->client = client;
+ cursor->state = UNPRIMED;
+ cursor->client_generation = client->generation;
+ cursor->is_aggr_with_write_stage = false;
+
+ bson_init (&cursor->opts);
+ bson_init (&cursor->error_doc);
+
+ if (opts) {
+ if (!bson_validate_with_error (
+ opts, BSON_VALIDATE_EMPTY_KEYS, &validate_err)) {
+ bson_set_error (&cursor->error,
+ MONGOC_ERROR_CURSOR,
+ MONGOC_ERROR_CURSOR_INVALID_CURSOR,
+ "Invalid opts: %s",
+ validate_err.message);
+ GOTO (finish);
+ }
+
+ dollar_field = _first_dollar_field (opts);
+ if (dollar_field) {
+ bson_set_error (&cursor->error,
+ MONGOC_ERROR_CURSOR,
+ MONGOC_ERROR_CURSOR_INVALID_CURSOR,
+ "Cannot use $-modifiers in opts: \"%s\"",
+ dollar_field);
+ GOTO (finish);
+ }
+
+ if (bson_iter_init_find (&iter, opts, "sessionId")) {
+ if (!_mongoc_client_session_from_iter (
+ client, &iter, &cursor->client_session, &cursor->error)) {
+ GOTO (finish);
+ }
+
+ cursor->explicit_session = true;
+ }
+
+ if (bson_iter_init_find (&iter, opts, "readConcern")) {
+ read_concern_local =
+ _mongoc_read_concern_new_from_iter (&iter, &cursor->error);
+
+ if (!read_concern_local) {
+ /* invalid read concern */
+ GOTO (finish);
+ }
+
+ read_concern = read_concern_local;
+ }
+
+ /* true if there's a valid serverId or no serverId, false on err */
+ if (!_mongoc_get_server_id_from_opts (opts,
+ MONGOC_ERROR_CURSOR,
+ MONGOC_ERROR_CURSOR_INVALID_CURSOR,
+ &server_id,
+ &cursor->error)) {
+ GOTO (finish);
+ }
+
+ if (server_id) {
+ (void) mongoc_cursor_set_hint (cursor, server_id);
+ }
+
+ bson_copy_to_excluding_noinit (opts,
+ &cursor->opts,
+ "serverId",
+ "sessionId",
+ "bypassDocumentValidation",
+ NULL);
+
+
+ /* only include bypassDocumentValidation if it's true */
+ if (bson_iter_init_find (&iter, opts, "bypassDocumentValidation") &&
+ bson_iter_as_bool (&iter)) {
+ BSON_APPEND_BOOL (&cursor->opts, "bypassDocumentValidation", true);
+ }
+ }
+
+ if (_mongoc_client_session_in_txn (cursor->client_session)) {
+ if (!IS_PREF_PRIMARY (user_prefs)) {
+ bson_set_error (&cursor->error,
+ MONGOC_ERROR_CURSOR,
+ MONGOC_ERROR_CURSOR_INVALID_CURSOR,
+ "Read preference in a transaction must be primary");
+ GOTO (finish);
+ }
+
+ cursor->read_prefs =
+ mongoc_read_prefs_copy (cursor->client_session->txn.opts.read_prefs);
+
+ if (bson_has_field (opts, "readConcern")) {
+ bson_set_error (&cursor->error,
+ MONGOC_ERROR_CURSOR,
+ MONGOC_ERROR_CURSOR_INVALID_CURSOR,
+ "Cannot set read concern after starting transaction");
+ GOTO (finish);
+ }
+ } else if (user_prefs) {
+ cursor->read_prefs = mongoc_read_prefs_copy (user_prefs);
+ } else if (default_prefs) {
+ cursor->read_prefs = mongoc_read_prefs_copy (default_prefs);
+ } else {
+ cursor->read_prefs = mongoc_read_prefs_new (MONGOC_READ_PRIMARY);
+ }
+
+ cursor->read_concern = read_concern ? mongoc_read_concern_copy (read_concern)
+ : mongoc_read_concern_new ();
+
+ if (db_and_collection) {
+ _mongoc_set_cursor_ns (
+ cursor, db_and_collection, (uint32_t) strlen (db_and_collection));
+ }
+
+ if (_mongoc_cursor_get_opt_bool (cursor, MONGOC_CURSOR_EXHAUST)) {
+ if (_mongoc_cursor_get_opt_int64 (cursor, MONGOC_CURSOR_LIMIT, 0)) {
+ bson_set_error (&cursor->error,
+ MONGOC_ERROR_CURSOR,
+ MONGOC_ERROR_CURSOR_INVALID_CURSOR,
+ "Cannot specify both 'exhaust' and 'limit'.");
+ GOTO (finish);
+ }
+
+ td_type = _mongoc_topology_get_type (client->topology);
+
+ if (td_type == MONGOC_TOPOLOGY_SHARDED) {
+ bson_set_error (&cursor->error,
+ MONGOC_ERROR_CURSOR,
+ MONGOC_ERROR_CURSOR_INVALID_CURSOR,
+ "Cannot use exhaust cursor with sharded cluster.");
+ GOTO (finish);
+ }
+ }
+
+ (void) _mongoc_read_prefs_validate (cursor->read_prefs, &cursor->error);
+
+finish:
+ mongoc_read_concern_destroy (read_concern_local);
+ mongoc_counter_cursors_active_inc ();
+
+ RETURN (cursor);
+}
+
+
+static bool
+_translate_query_opt (const char *query_field, const char **cmd_field, int *len)
+{
+ if (query_field[0] != '$') {
+ *cmd_field = query_field;
+ *len = -1;
+ return true;
+ }
+
+ /* strip the leading '$' */
+ query_field++;
+
+ if (!strcmp (MONGOC_CURSOR_ORDERBY, query_field)) {
+ *cmd_field = MONGOC_CURSOR_SORT;
+ *len = MONGOC_CURSOR_SORT_LEN;
+ } else if (!strcmp (MONGOC_CURSOR_SHOW_DISK_LOC,
+ query_field)) { /* <= MongoDb 3.0 */
+ *cmd_field = MONGOC_CURSOR_SHOW_RECORD_ID;
+ *len = MONGOC_CURSOR_SHOW_RECORD_ID_LEN;
+ } else if (!strcmp (MONGOC_CURSOR_HINT, query_field)) {
+ *cmd_field = MONGOC_CURSOR_HINT;
+ *len = MONGOC_CURSOR_HINT_LEN;
+ } else if (!strcmp (MONGOC_CURSOR_COMMENT, query_field)) {
+ *cmd_field = MONGOC_CURSOR_COMMENT;
+ *len = MONGOC_CURSOR_COMMENT_LEN;
+ } else if (!strcmp (MONGOC_CURSOR_MAX_SCAN, query_field)) {
+ *cmd_field = MONGOC_CURSOR_MAX_SCAN;
+ *len = MONGOC_CURSOR_MAX_SCAN_LEN;
+ } else if (!strcmp (MONGOC_CURSOR_MAX_TIME_MS, query_field)) {
+ *cmd_field = MONGOC_CURSOR_MAX_TIME_MS;
+ *len = MONGOC_CURSOR_MAX_TIME_MS_LEN;
+ } else if (!strcmp (MONGOC_CURSOR_MAX, query_field)) {
+ *cmd_field = MONGOC_CURSOR_MAX;
+ *len = MONGOC_CURSOR_MAX_LEN;
+ } else if (!strcmp (MONGOC_CURSOR_MIN, query_field)) {
+ *cmd_field = MONGOC_CURSOR_MIN;
+ *len = MONGOC_CURSOR_MIN_LEN;
+ } else if (!strcmp (MONGOC_CURSOR_RETURN_KEY, query_field)) {
+ *cmd_field = MONGOC_CURSOR_RETURN_KEY;
+ *len = MONGOC_CURSOR_RETURN_KEY_LEN;
+ } else if (!strcmp (MONGOC_CURSOR_SNAPSHOT, query_field)) {
+ *cmd_field = MONGOC_CURSOR_SNAPSHOT;
+ *len = MONGOC_CURSOR_SNAPSHOT_LEN;
+ } else {
+ /* not a special command field, must be a query operator like $or */
+ return false;
+ }
+
+ return true;
+}
+
+
+/* set up a new opt bson from older ways of specifying options.
+ * secondary_ok may be NULL.
+ * error may be NULL.
+ */
+void
+_mongoc_cursor_flags_to_opts (mongoc_query_flags_t qflags,
+ bson_t *opts, /* IN/OUT */
+ bool *secondary_ok /* OUT */)
+{
+ ENTRY;
+ BSON_ASSERT (opts);
+
+ if (secondary_ok) {
+ *secondary_ok = !!(qflags & MONGOC_QUERY_SECONDARY_OK);
+ }
+
+ if (qflags & MONGOC_QUERY_TAILABLE_CURSOR) {
+ bson_append_bool (
+ opts, MONGOC_CURSOR_TAILABLE, MONGOC_CURSOR_TAILABLE_LEN, true);
+ }
+
+ if (qflags & MONGOC_QUERY_OPLOG_REPLAY) {
+ bson_append_bool (opts,
+ MONGOC_CURSOR_OPLOG_REPLAY,
+ MONGOC_CURSOR_OPLOG_REPLAY_LEN,
+ true);
+ }
+
+ if (qflags & MONGOC_QUERY_NO_CURSOR_TIMEOUT) {
+ bson_append_bool (opts,
+ MONGOC_CURSOR_NO_CURSOR_TIMEOUT,
+ MONGOC_CURSOR_NO_CURSOR_TIMEOUT_LEN,
+ true);
+ }
+
+ if (qflags & MONGOC_QUERY_AWAIT_DATA) {
+ bson_append_bool (
+ opts, MONGOC_CURSOR_AWAIT_DATA, MONGOC_CURSOR_AWAIT_DATA_LEN, true);
+ }
+
+ if (qflags & MONGOC_QUERY_EXHAUST) {
+ bson_append_bool (
+ opts, MONGOC_CURSOR_EXHAUST, MONGOC_CURSOR_EXHAUST_LEN, true);
+ }
+
+ if (qflags & MONGOC_QUERY_PARTIAL) {
+ bson_append_bool (opts,
+ MONGOC_CURSOR_ALLOW_PARTIAL_RESULTS,
+ MONGOC_CURSOR_ALLOW_PARTIAL_RESULTS_LEN,
+ true);
+ }
+}
+
+/* Checks if the passed query was wrapped in a $query, and if so, parses the
+ * query modifiers:
+ * https://docs.mongodb.com/manual/reference/operator/query-modifier/
+ * and translates them to find command options:
+ * https://docs.mongodb.com/manual/reference/command/find/
+ * opts must be initialized, and may already have options set.
+ * unwrapped must be uninitialized, and will be initialized at return.
+ * Returns true if query was unwrapped. */
+bool
+_mongoc_cursor_translate_dollar_query_opts (const bson_t *query,
+ bson_t *opts,
+ bson_t *unwrapped,
+ bson_error_t *error)
+{
+ bool has_filter = false;
+ const char *key;
+ bson_iter_t iter;
+ const char *opt_key;
+ int len;
+ uint32_t data_len;
+ const uint8_t *data;
+ bson_error_t error_local = {0};
+
+ ENTRY;
+ BSON_ASSERT (query);
+ BSON_ASSERT (opts);
+ /* If the query is explicitly specified wrapped in $query, unwrap it and
+ * translate the options to new options. */
+ if (bson_has_field (query, "$query")) {
+ /* like "{$query: {a: 1}, $orderby: {b: 1}, $otherModifier: true}" */
+ if (!bson_iter_init (&iter, query)) {
+ bson_set_error (&error_local,
+ MONGOC_ERROR_BSON,
+ MONGOC_ERROR_BSON_INVALID,
+ "Invalid BSON in query document");
+ GOTO (done);
+ }
+ while (bson_iter_next (&iter)) {
+ key = bson_iter_key (&iter);
+ if (key[0] != '$') {
+ bson_set_error (&error_local,
+ MONGOC_ERROR_CURSOR,
+ MONGOC_ERROR_CURSOR_INVALID_CURSOR,
+ "Cannot mix $query with non-dollar field '%s'",
+ key);
+ GOTO (done);
+ }
+ if (!strcmp (key, "$query")) {
+ /* set "filter" to the incoming document's "$query" */
+ bson_iter_document (&iter, &data_len, &data);
+ if (!bson_init_static (unwrapped, data, (size_t) data_len)) {
+ bson_set_error (&error_local,
+ MONGOC_ERROR_BSON,
+ MONGOC_ERROR_BSON_INVALID,
+ "Invalid BSON in $query subdocument");
+ GOTO (done);
+ }
+ has_filter = true;
+ } else if (_translate_query_opt (key, &opt_key, &len)) {
+ /* "$orderby" becomes "sort", etc., "$unknown" -> "unknown" */
+ if (!bson_append_iter (opts, opt_key, len, &iter)) {
+ bson_set_error (&error_local,
+ MONGOC_ERROR_BSON,
+ MONGOC_ERROR_BSON_INVALID,
+ "Error adding \"%s\" to query",
+ opt_key);
+ }
+ } else {
+ /* strip leading "$" */
+ if (!bson_append_iter (opts, key + 1, -1, &iter)) {
+ bson_set_error (&error_local,
+ MONGOC_ERROR_BSON,
+ MONGOC_ERROR_BSON_INVALID,
+ "Error adding \"%s\" to query",
+ key);
+ }
+ }
+ }
+ }
+done:
+ if (error) {
+ memcpy (error, &error_local, sizeof (bson_error_t));
+ }
+ if (!has_filter) {
+ bson_init (unwrapped);
+ }
+ RETURN (has_filter);
+}
+
+
+void
+mongoc_cursor_destroy (mongoc_cursor_t *cursor)
+{
+ char *db;
+ ENTRY;
+
+ if (!cursor) {
+ EXIT;
+ }
+
+ if (cursor->impl.destroy) {
+ cursor->impl.destroy (&cursor->impl);
+ }
+
+ /* Always close the socket for an exhaust cursor, even if the client was
+ * reset with mongoc_client_reset. That prevents further use of that socket.
+ */
+ if (cursor->in_exhaust) {
+ cursor->client->in_exhaust = false;
+ if (cursor->state != DONE) {
+ /* The only way to stop an exhaust cursor is to kill the connection
+ */
+ mongoc_cluster_disconnect_node (&cursor->client->cluster,
+ cursor->server_id);
+ }
+ } else if (cursor->client_generation == cursor->client->generation) {
+ if (cursor->cursor_id) {
+ db = bson_strndup (cursor->ns, cursor->dblen);
+
+ _mongoc_client_kill_cursor (cursor->client,
+ cursor->server_id,
+ cursor->cursor_id,
+ cursor->operation_id,
+ db,
+ cursor->ns + cursor->dblen + 1,
+ cursor->client_session);
+ bson_free (db);
+ }
+ }
+
+ if (cursor->client_session && !cursor->explicit_session) {
+ mongoc_client_session_destroy (cursor->client_session);
+ }
+
+ mongoc_read_prefs_destroy (cursor->read_prefs);
+ mongoc_read_concern_destroy (cursor->read_concern);
+ mongoc_write_concern_destroy (cursor->write_concern);
+
+ bson_destroy (&cursor->opts);
+ bson_destroy (&cursor->error_doc);
+ bson_free (cursor->ns);
+ bson_free (cursor);
+
+ mongoc_counter_cursors_active_dec ();
+ mongoc_counter_cursors_disposed_inc ();
+
+ EXIT;
+}
+
+
+mongoc_server_stream_t *
+_mongoc_cursor_fetch_stream (mongoc_cursor_t *cursor)
+{
+ mongoc_server_stream_t *server_stream;
+ bson_t reply;
+
+ ENTRY;
+
+ if (cursor->server_id) {
+ /* We already did server selection once before. Reuse the prior
+ * selection to create a new stream on the same server. */
+ server_stream =
+ mongoc_cluster_stream_for_server (&cursor->client->cluster,
+ cursor->server_id,
+ true /* reconnect_ok */,
+ cursor->client_session,
+ &reply,
+ &cursor->error);
+ if (server_stream) {
+ /* Also restore whether primary read preference was forced by server
+ * selection */
+ server_stream->must_use_primary = cursor->must_use_primary;
+ }
+ } else {
+ server_stream =
+ mongoc_cluster_stream_for_reads (&cursor->client->cluster,
+ cursor->read_prefs,
+ cursor->client_session,
+ &reply,
+ cursor->is_aggr_with_write_stage,
+ &cursor->error);
+
+ if (server_stream) {
+ /* Remember the selected server_id and whether primary read mode was
+ * forced so that we can re-create an equivalent server_stream at a
+ * later time */
+ cursor->server_id = server_stream->sd->id;
+ cursor->must_use_primary = server_stream->must_use_primary;
+ }
+ }
+
+ if (!server_stream) {
+ bson_destroy (&cursor->error_doc);
+ bson_copy_to (&reply, &cursor->error_doc);
+ bson_destroy (&reply);
+ }
+
+ RETURN (server_stream);
+}
+
+
+bool
+_mongoc_cursor_monitor_command (mongoc_cursor_t *cursor,
+ mongoc_server_stream_t *server_stream,
+ const bson_t *cmd,
+ const char *cmd_name)
+{
+ mongoc_client_t *client;
+ mongoc_apm_command_started_t event;
+ char *db;
+
+ ENTRY;
+
+ client = cursor->client;
+ if (!client->apm_callbacks.started) {
+ /* successful */
+ RETURN (true);
+ }
+
+ db = bson_strndup (cursor->ns, cursor->dblen);
+
+ mongoc_apm_command_started_init (&event,
+ cmd,
+ db,
+ cmd_name,
+ client->cluster.request_id,
+ cursor->operation_id,
+ &server_stream->sd->host,
+ server_stream->sd->id,
+ &server_stream->sd->service_id,
+ NULL,
+ client->apm_context);
+
+ client->apm_callbacks.started (&event);
+ mongoc_apm_command_started_cleanup (&event);
+ bson_free (db);
+
+ RETURN (true);
+}
+
+
+/* append array of docs from current cursor batch */
+static void
+_mongoc_cursor_append_docs_array (mongoc_cursor_t *cursor,
+ bson_t *docs,
+ mongoc_cursor_response_legacy_t *response)
+{
+ bool eof = false;
+ char str[16];
+ const char *key;
+ uint32_t i = 0;
+ size_t keylen;
+ const bson_t *doc;
+
+ while ((doc = bson_reader_read (response->reader, &eof))) {
+ keylen = bson_uint32_to_string (i, &key, str, sizeof str);
+ bson_append_document (docs, key, (int) keylen, doc);
+ }
+
+ bson_reader_reset (response->reader);
+}
+
+
+void
+_mongoc_cursor_monitor_succeeded (mongoc_cursor_t *cursor,
+ mongoc_cursor_response_legacy_t *response,
+ int64_t duration,
+ bool first_batch,
+ mongoc_server_stream_t *stream,
+ const char *cmd_name)
+{
+ bson_t docs_array;
+ mongoc_apm_command_succeeded_t event;
+ mongoc_client_t *client;
+ bson_t reply;
+ bson_t reply_cursor;
+
+ ENTRY;
+
+ client = cursor->client;
+
+ if (!client->apm_callbacks.succeeded) {
+ EXIT;
+ }
+
+ /* we sent OP_QUERY/OP_GETMORE, fake a reply to find/getMore command:
+ * {ok: 1, cursor: {id: 17, ns: "...", first/nextBatch: [ ... docs ... ]}}
+ */
+ bson_init (&docs_array);
+ _mongoc_cursor_append_docs_array (cursor, &docs_array, response);
+
+ bson_init (&reply);
+ bson_append_int32 (&reply, "ok", 2, 1);
+ bson_append_document_begin (&reply, "cursor", 6, &reply_cursor);
+ bson_append_int64 (&reply_cursor, "id", 2, mongoc_cursor_get_id (cursor));
+ bson_append_utf8 (&reply_cursor, "ns", 2, cursor->ns, cursor->nslen);
+ bson_append_array (&reply_cursor,
+ first_batch ? "firstBatch" : "nextBatch",
+ first_batch ? 10 : 9,
+ &docs_array);
+ bson_append_document_end (&reply, &reply_cursor);
+ bson_destroy (&docs_array);
+
+ mongoc_apm_command_succeeded_init (&event,
+ duration,
+ &reply,
+ cmd_name,
+ client->cluster.request_id,
+ cursor->operation_id,
+ &stream->sd->host,
+ stream->sd->id,
+ &stream->sd->service_id,
+ false,
+ client->apm_context);
+
+ client->apm_callbacks.succeeded (&event);
+
+ mongoc_apm_command_succeeded_cleanup (&event);
+ bson_destroy (&reply);
+
+ EXIT;
+}
+
+
+void
+_mongoc_cursor_monitor_failed (mongoc_cursor_t *cursor,
+ int64_t duration,
+ mongoc_server_stream_t *stream,
+ const char *cmd_name)
+{
+ mongoc_apm_command_failed_t event;
+ mongoc_client_t *client;
+ bson_t reply;
+
+ ENTRY;
+
+ client = cursor->client;
+
+ if (!client->apm_callbacks.failed) {
+ EXIT;
+ }
+
+ /* we sent OP_QUERY/OP_GETMORE, fake a reply to find/getMore command:
+ * {ok: 0}
+ */
+ bson_init (&reply);
+ bson_append_int32 (&reply, "ok", 2, 0);
+
+ mongoc_apm_command_failed_init (&event,
+ duration,
+ cmd_name,
+ &cursor->error,
+ &reply,
+ client->cluster.request_id,
+ cursor->operation_id,
+ &stream->sd->host,
+ stream->sd->id,
+ &stream->sd->service_id,
+ false,
+ client->apm_context);
+
+ client->apm_callbacks.failed (&event);
+
+ mongoc_apm_command_failed_cleanup (&event);
+ bson_destroy (&reply);
+
+ EXIT;
+}
+
+
+#define ADD_FLAG(_flags, _value) \
+ do { \
+ if (!BSON_ITER_HOLDS_BOOL (&iter)) { \
+ bson_set_error (&cursor->error, \
+ MONGOC_ERROR_COMMAND, \
+ MONGOC_ERROR_COMMAND_INVALID_ARG, \
+ "invalid option %s, should be type bool", \
+ key); \
+ return false; \
+ } \
+ if (bson_iter_as_bool (&iter)) { \
+ *_flags |= _value; \
+ } \
+ } while (false);
+
+bool
+_mongoc_cursor_opts_to_flags (mongoc_cursor_t *cursor,
+ mongoc_server_stream_t *stream,
+ mongoc_query_flags_t *flags /* OUT */)
+{
+ bson_iter_t iter;
+ const char *key;
+
+ *flags = MONGOC_QUERY_NONE;
+
+ if (!bson_iter_init (&iter, &cursor->opts)) {
+ bson_set_error (&cursor->error,
+ MONGOC_ERROR_BSON,
+ MONGOC_ERROR_BSON_INVALID,
+ "Invalid 'opts' parameter.");
+ return false;
+ }
+
+ while (bson_iter_next (&iter)) {
+ key = bson_iter_key (&iter);
+
+ if (!strcmp (key, MONGOC_CURSOR_ALLOW_PARTIAL_RESULTS)) {
+ ADD_FLAG (flags, MONGOC_QUERY_PARTIAL);
+ } else if (!strcmp (key, MONGOC_CURSOR_AWAIT_DATA)) {
+ ADD_FLAG (flags, MONGOC_QUERY_AWAIT_DATA);
+ } else if (!strcmp (key, MONGOC_CURSOR_EXHAUST)) {
+ ADD_FLAG (flags, MONGOC_QUERY_EXHAUST);
+ } else if (!strcmp (key, MONGOC_CURSOR_NO_CURSOR_TIMEOUT)) {
+ ADD_FLAG (flags, MONGOC_QUERY_NO_CURSOR_TIMEOUT);
+ } else if (!strcmp (key, MONGOC_CURSOR_OPLOG_REPLAY)) {
+ ADD_FLAG (flags, MONGOC_QUERY_OPLOG_REPLAY);
+ } else if (!strcmp (key, MONGOC_CURSOR_TAILABLE)) {
+ ADD_FLAG (flags, MONGOC_QUERY_TAILABLE_CURSOR);
+ }
+ }
+
+ if (cursor->secondary_ok) {
+ *flags |= MONGOC_QUERY_SECONDARY_OK;
+ } else if (cursor->server_id &&
+ (stream->topology_type == MONGOC_TOPOLOGY_RS_WITH_PRIMARY ||
+ stream->topology_type == MONGOC_TOPOLOGY_RS_NO_PRIMARY) &&
+ stream->sd->type != MONGOC_SERVER_RS_PRIMARY) {
+ *flags |= MONGOC_QUERY_SECONDARY_OK;
+ }
+
+ return true;
+}
+
+bool
+_mongoc_cursor_run_command (mongoc_cursor_t *cursor,
+ const bson_t *command,
+ const bson_t *opts,
+ bson_t *reply,
+ bool retry_prohibited)
+{
+ mongoc_server_stream_t *server_stream;
+ bson_iter_t iter;
+ mongoc_cmd_parts_t parts;
+ const char *cmd_name;
+ bool is_primary;
+ mongoc_read_prefs_t *prefs = NULL;
+ char *db = NULL;
+ mongoc_session_opt_t *session_opts;
+ bool ret = false;
+ bool is_retryable = true;
+
+ ENTRY;
+
+ mongoc_cmd_parts_init (
+ &parts, cursor->client, db, MONGOC_QUERY_NONE, command);
+ parts.is_read_command = true;
+ parts.read_prefs = cursor->read_prefs;
+ parts.assembled.operation_id = cursor->operation_id;
+ server_stream = _mongoc_cursor_fetch_stream (cursor);
+
+ if (!server_stream) {
+ _mongoc_bson_init_if_set (reply);
+ GOTO (done);
+ }
+
+ if (opts) {
+ if (!bson_iter_init (&iter, opts)) {
+ _mongoc_bson_init_if_set (reply);
+ bson_set_error (&cursor->error,
+ MONGOC_ERROR_BSON,
+ MONGOC_ERROR_BSON_INVALID,
+ "Invalid BSON in opts document");
+ GOTO (done);
+ }
+ if (!mongoc_cmd_parts_append_opts (&parts,
+ &iter,
+ server_stream->sd->max_wire_version,
+ &cursor->error)) {
+ _mongoc_bson_init_if_set (reply);
+ GOTO (done);
+ }
+ if (_mongoc_cursor_get_opt_bool (cursor, MONGOC_CURSOR_EXHAUST)) {
+ MONGOC_WARNING (
+ "exhaust cursors not supported with OP_MSG, using normal "
+ "cursor instead");
+ }
+ }
+
+ if (parts.assembled.session) {
+ /* initial query/aggregate/etc, and opts contains "sessionId" */
+ BSON_ASSERT (!cursor->client_session);
+ BSON_ASSERT (!cursor->explicit_session);
+ cursor->client_session = parts.assembled.session;
+ cursor->explicit_session = true;
+ } else if (cursor->client_session) {
+ /* a getMore with implicit or explicit session already acquired */
+ mongoc_cmd_parts_set_session (&parts, cursor->client_session);
+ } else {
+ /* try to create an implicit session. not causally consistent. we keep
+ * the session but leave cursor->explicit_session as 0, so we use the
+ * same lsid for getMores but destroy the session when the cursor dies.
+ */
+ session_opts = mongoc_session_opts_new ();
+ mongoc_session_opts_set_causal_consistency (session_opts, false);
+ /* returns NULL if sessions aren't supported. ignore errors. */
+ cursor->client_session =
+ mongoc_client_start_session (cursor->client, session_opts, NULL);
+ mongoc_cmd_parts_set_session (&parts, cursor->client_session);
+ mongoc_session_opts_destroy (session_opts);
+ }
+
+ if (!mongoc_cmd_parts_set_read_concern (&parts,
+ cursor->read_concern,
+ server_stream->sd->max_wire_version,
+ &cursor->error)) {
+ _mongoc_bson_init_if_set (reply);
+ GOTO (done);
+ }
+
+ db = bson_strndup (cursor->ns, cursor->dblen);
+ parts.assembled.db_name = db;
+
+ if (!_mongoc_cursor_opts_to_flags (
+ cursor, server_stream, &parts.user_query_flags)) {
+ _mongoc_bson_init_if_set (reply);
+ GOTO (done);
+ }
+
+ /* Exhaust cursors with OP_MSG not yet supported; fallback to normal cursor.
+ * user_query_flags is unused in OP_MSG, so this technically has no effect,
+ * but is done anyways to ensure the query flags match handling of options.
+ */
+ if (parts.user_query_flags & MONGOC_QUERY_EXHAUST) {
+ parts.user_query_flags ^= MONGOC_QUERY_EXHAUST;
+ }
+
+ /* we might use mongoc_cursor_set_hint to target a secondary but have no
+ * read preference, so the secondary rejects the read. same if we have a
+ * direct connection to a secondary (topology type "single"). with
+ * OP_QUERY we handle this by setting secondaryOk. here we use
+ * $readPreference.
+ */
+ cmd_name = _mongoc_get_command_name (command);
+ is_primary =
+ !cursor->read_prefs || cursor->read_prefs->mode == MONGOC_READ_PRIMARY;
+
+ if (strcmp (cmd_name, "getMore") != 0 &&
+ server_stream->sd->max_wire_version >= WIRE_VERSION_OP_MSG &&
+ is_primary && parts.user_query_flags & MONGOC_QUERY_SECONDARY_OK) {
+ parts.read_prefs = prefs =
+ mongoc_read_prefs_new (MONGOC_READ_PRIMARY_PREFERRED);
+ } else {
+ parts.read_prefs = cursor->read_prefs;
+ }
+
+ is_retryable = _is_retryable_read (&parts, server_stream);
+ if (!strcmp (cmd_name, "getMore")) {
+ is_retryable = false;
+ }
+ if (!strcmp (cmd_name, "aggregate")) {
+ bson_iter_t pipeline_iter;
+ if (bson_iter_init_find (&pipeline_iter, command, "pipeline") &&
+ BSON_ITER_HOLDS_ARRAY (&pipeline_iter) &&
+ bson_iter_recurse (&pipeline_iter, &pipeline_iter)) {
+ if (_has_write_key (&pipeline_iter)) {
+ is_retryable = false;
+ }
+ }
+ }
+ if (is_retryable && retry_prohibited) {
+ is_retryable = false;
+ }
+
+ if (cursor->write_concern &&
+ !mongoc_write_concern_is_default (cursor->write_concern) &&
+ server_stream->sd->max_wire_version >= WIRE_VERSION_CMD_WRITE_CONCERN) {
+ parts.assembled.is_acknowledged =
+ mongoc_write_concern_is_acknowledged (cursor->write_concern);
+ mongoc_write_concern_append (cursor->write_concern, &parts.extra);
+ }
+
+ if (!mongoc_cmd_parts_assemble (&parts, server_stream, &cursor->error)) {
+ _mongoc_bson_init_if_set (reply);
+ GOTO (done);
+ }
+
+retry:
+ ret = mongoc_cluster_run_command_monitored (
+ &cursor->client->cluster, &parts.assembled, reply, &cursor->error);
+
+ if (ret) {
+ memset (&cursor->error, 0, sizeof (bson_error_t));
+ }
+
+ if (is_retryable &&
+ _mongoc_read_error_get_type (ret, &cursor->error, reply) ==
+ MONGOC_READ_ERR_RETRY) {
+ is_retryable = false;
+
+ mongoc_server_stream_cleanup (server_stream);
+
+ BSON_ASSERT (!cursor->is_aggr_with_write_stage &&
+ "Cannot attempt a retry on an aggregate operation that "
+ "contains write stages");
+ server_stream =
+ mongoc_cluster_stream_for_reads (&cursor->client->cluster,
+ cursor->read_prefs,
+ cursor->client_session,
+ reply,
+ /* Not aggregate-with-write */ false,
+ &cursor->error);
+
+ if (server_stream &&
+ server_stream->sd->max_wire_version >= WIRE_VERSION_RETRY_READS) {
+ cursor->server_id = server_stream->sd->id;
+ parts.assembled.server_stream = server_stream;
+ bson_destroy (reply);
+ GOTO (retry);
+ }
+ }
+
+ if (cursor->error.domain) {
+ bson_destroy (&cursor->error_doc);
+ bson_copy_to (reply, &cursor->error_doc);
+ }
+
+ /* Read and Write Concern Spec: "Drivers SHOULD parse server replies for a
+ * "writeConcernError" field and report the error only in command-specific
+ * helper methods that take a separate write concern parameter or an options
+ * parameter that may contain a write concern option.
+ *
+ * Only command helpers with names like "_with_write_concern" can create
+ * cursors with a non-NULL write_concern field.
+ */
+ if (ret && cursor->write_concern) {
+ ret = !_mongoc_parse_wc_err (reply, &cursor->error);
+ }
+
+done:
+ mongoc_server_stream_cleanup (server_stream);
+ mongoc_cmd_parts_cleanup (&parts);
+ mongoc_read_prefs_destroy (prefs);
+ bson_free (db);
+
+ return ret;
+}
+
+
+void
+_mongoc_cursor_collection (const mongoc_cursor_t *cursor,
+ const char **collection,
+ int *collection_len)
+{
+ /* ns is like "db.collection". Collection name is located past the ".". */
+ *collection = cursor->ns + (cursor->dblen + 1);
+ /* Collection name's length is ns length, minus length of db name and ".". */
+ *collection_len = cursor->nslen - cursor->dblen - 1;
+
+ BSON_ASSERT (*collection_len > 0);
+}
+
+
+void
+_mongoc_cursor_prepare_find_command (mongoc_cursor_t *cursor,
+ const bson_t *filter,
+ bson_t *command)
+{
+ const char *collection;
+ int collection_len;
+
+ _mongoc_cursor_collection (cursor, &collection, &collection_len);
+ bson_append_utf8 (command,
+ MONGOC_CURSOR_FIND,
+ MONGOC_CURSOR_FIND_LEN,
+ collection,
+ collection_len);
+ bson_append_document (
+ command, MONGOC_CURSOR_FILTER, MONGOC_CURSOR_FILTER_LEN, filter);
+}
+
+
+bool
+mongoc_cursor_error (mongoc_cursor_t *cursor, bson_error_t *error)
+{
+ ENTRY;
+
+ RETURN (mongoc_cursor_error_document (cursor, error, NULL));
+}
+
+
+bool
+mongoc_cursor_error_document (mongoc_cursor_t *cursor,
+ bson_error_t *error,
+ const bson_t **doc)
+{
+ ENTRY;
+
+ BSON_ASSERT (cursor);
+
+ if (BSON_UNLIKELY (CURSOR_FAILED (cursor))) {
+ bson_set_error (error,
+ cursor->error.domain,
+ cursor->error.code,
+ "%s",
+ cursor->error.message);
+
+ if (doc) {
+ *doc = &cursor->error_doc;
+ }
+
+ RETURN (true);
+ }
+
+ if (doc) {
+ *doc = NULL;
+ }
+
+ RETURN (false);
+}
+
+
+static mongoc_cursor_state_t
+_call_transition (mongoc_cursor_t *cursor)
+{
+ mongoc_cursor_state_t state = cursor->state;
+ _mongoc_cursor_impl_transition_t fn = NULL;
+ switch (state) {
+ case UNPRIMED:
+ fn = cursor->impl.prime;
+ break;
+ case IN_BATCH:
+ fn = cursor->impl.pop_from_batch;
+ break;
+ case END_OF_BATCH:
+ fn = cursor->impl.get_next_batch;
+ break;
+ case DONE:
+ default:
+ fn = NULL;
+ break;
+ }
+ if (!fn) {
+ return DONE;
+ }
+ state = fn (cursor);
+ if (cursor->error.domain) {
+ state = DONE;
+ }
+ return state;
+}
+
+
+bool
+mongoc_cursor_next (mongoc_cursor_t *cursor, const bson_t **bson)
+{
+ bool ret = false;
+ bool attempted_refresh = false;
+
+ ENTRY;
+
+ BSON_ASSERT (cursor);
+ BSON_ASSERT (bson);
+
+ TRACE ("cursor_id(%" PRId64 ")", cursor->cursor_id);
+
+ if (cursor->client_generation != cursor->client->generation) {
+ bson_set_error (&cursor->error,
+ MONGOC_ERROR_CURSOR,
+ MONGOC_ERROR_CURSOR_INVALID_CURSOR,
+ "Cannot advance cursor after client reset");
+ RETURN (false);
+ }
+
+ if (bson) {
+ *bson = NULL;
+ }
+
+ if (CURSOR_FAILED (cursor)) {
+ RETURN (false);
+ }
+
+ if (cursor->state == DONE) {
+ bson_set_error (&cursor->error,
+ MONGOC_ERROR_CURSOR,
+ MONGOC_ERROR_CURSOR_INVALID_CURSOR,
+ "Cannot advance a completed or failed cursor.");
+ RETURN (false);
+ }
+
+ /*
+ * We cannot proceed if another cursor is receiving results in exhaust mode.
+ */
+ if (cursor->client->in_exhaust && !cursor->in_exhaust) {
+ bson_set_error (&cursor->error,
+ MONGOC_ERROR_CLIENT,
+ MONGOC_ERROR_CLIENT_IN_EXHAUST,
+ "Another cursor derived from this client is in exhaust.");
+ RETURN (false);
+ }
+
+ cursor->current = NULL;
+
+ /* if an error was set on this cursor before calling next, transition to DONE
+ * immediately. */
+ if (cursor->error.domain) {
+ cursor->state = DONE;
+ GOTO (done);
+ }
+
+ while (cursor->state != DONE) {
+ /* even when there is no data to return, some cursors remain open and
+ * continue sending empty batches (e.g. a tailable or change stream
+ * cursor). in that case, do not attempt to get another batch. */
+ if (cursor->state == END_OF_BATCH) {
+ if (attempted_refresh) {
+ RETURN (false);
+ }
+ attempted_refresh = true;
+ }
+
+ cursor->state = _call_transition (cursor);
+
+ /* check if we received a document. */
+ if (cursor->current) {
+ *bson = cursor->current;
+ ret = true;
+ GOTO (done);
+ }
+
+ if (cursor->state == DONE) {
+ GOTO (done);
+ }
+ }
+
+done:
+ cursor->count++;
+ RETURN (ret);
+}
+
+
+bool
+mongoc_cursor_more (mongoc_cursor_t *cursor)
+{
+ ENTRY;
+
+ BSON_ASSERT (cursor);
+
+ if (CURSOR_FAILED (cursor)) {
+ RETURN (false);
+ }
+
+ RETURN (cursor->state != DONE);
+}
+
+
+void
+mongoc_cursor_get_host (mongoc_cursor_t *cursor, mongoc_host_list_t *host)
+{
+ mongoc_server_description_t const *description;
+ mc_shared_tpld td;
+
+ BSON_ASSERT (cursor);
+ BSON_ASSERT (host);
+
+ memset (host, 0, sizeof *host);
+
+ if (!cursor->server_id) {
+ MONGOC_WARNING ("%s(): Must send query before fetching peer.", BSON_FUNC);
+ return;
+ }
+
+ td = mc_tpld_take_ref (cursor->client->topology);
+ description = mongoc_topology_description_server_by_id_const (
+ td.ptr, cursor->server_id, &cursor->error);
+ mc_tpld_drop_ref (&td);
+ if (!description) {
+ return;
+ }
+
+ *host = description->host;
+
+ EXIT;
+}
+
+
+mongoc_cursor_t *
+mongoc_cursor_clone (const mongoc_cursor_t *cursor)
+{
+ mongoc_cursor_t *_clone;
+
+ BSON_ASSERT (cursor);
+
+ _clone = (mongoc_cursor_t *) bson_malloc0 (sizeof *_clone);
+
+ _clone->client = cursor->client;
+ _clone->nslen = cursor->nslen;
+ _clone->dblen = cursor->dblen;
+ _clone->explicit_session = cursor->explicit_session;
+
+ if (cursor->read_prefs) {
+ _clone->read_prefs = mongoc_read_prefs_copy (cursor->read_prefs);
+ }
+
+ if (cursor->read_concern) {
+ _clone->read_concern = mongoc_read_concern_copy (cursor->read_concern);
+ }
+
+ if (cursor->write_concern) {
+ _clone->write_concern = mongoc_write_concern_copy (cursor->write_concern);
+ }
+
+ if (cursor->explicit_session) {
+ _clone->client_session = cursor->client_session;
+ }
+
+ bson_copy_to (&cursor->opts, &_clone->opts);
+ bson_init (&_clone->error_doc);
+
+ _clone->ns = bson_strdup (cursor->ns);
+
+ /* copy the context functions by default. */
+ memcpy (&_clone->impl, &cursor->impl, sizeof (cursor->impl));
+ if (cursor->impl.clone) {
+ cursor->impl.clone (&_clone->impl, &cursor->impl);
+ }
+
+ mongoc_counter_cursors_active_inc ();
+
+ RETURN (_clone);
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_cursor_is_alive --
+ *
+ * Deprecated for mongoc_cursor_more.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+bool
+mongoc_cursor_is_alive (const mongoc_cursor_t *cursor) /* IN */
+{
+ return mongoc_cursor_more ((mongoc_cursor_t *) cursor);
+}
+
+
+const bson_t *
+mongoc_cursor_current (const mongoc_cursor_t *cursor) /* IN */
+{
+ BSON_ASSERT (cursor);
+
+ return cursor->current;
+}
+
+
+void
+mongoc_cursor_set_batch_size (mongoc_cursor_t *cursor, uint32_t batch_size)
+{
+ BSON_ASSERT (cursor);
+
+ _mongoc_cursor_set_opt_int64 (
+ cursor, MONGOC_CURSOR_BATCH_SIZE, (int64_t) batch_size);
+}
+
+
+uint32_t
+mongoc_cursor_get_batch_size (const mongoc_cursor_t *cursor)
+{
+ BSON_ASSERT (cursor);
+
+ return (uint32_t) _mongoc_cursor_get_opt_int64 (
+ cursor, MONGOC_CURSOR_BATCH_SIZE, 0);
+}
+
+
+bool
+mongoc_cursor_set_limit (mongoc_cursor_t *cursor, int64_t limit)
+{
+ BSON_ASSERT (cursor);
+
+ if (cursor->state == UNPRIMED) {
+ if (limit < 0) {
+ return _mongoc_cursor_set_opt_int64 (
+ cursor, MONGOC_CURSOR_LIMIT, -limit) &&
+ _mongoc_cursor_set_opt_bool (
+ cursor, MONGOC_CURSOR_SINGLE_BATCH, true);
+ } else {
+ return _mongoc_cursor_set_opt_int64 (
+ cursor, MONGOC_CURSOR_LIMIT, limit);
+ }
+ } else {
+ return false;
+ }
+}
+
+
+int64_t
+mongoc_cursor_get_limit (const mongoc_cursor_t *cursor)
+{
+ int64_t limit;
+ bool single_batch;
+
+ BSON_ASSERT (cursor);
+
+ limit = _mongoc_cursor_get_opt_int64 (cursor, MONGOC_CURSOR_LIMIT, 0);
+ single_batch =
+ _mongoc_cursor_get_opt_bool (cursor, MONGOC_CURSOR_SINGLE_BATCH);
+
+ if (limit > 0 && single_batch) {
+ limit = -limit;
+ }
+
+ return limit;
+}
+
+
+bool
+mongoc_cursor_set_hint (mongoc_cursor_t *cursor, uint32_t server_id)
+{
+ BSON_ASSERT (cursor);
+
+ if (cursor->server_id) {
+ MONGOC_ERROR ("mongoc_cursor_set_hint: server_id already set");
+ return false;
+ }
+
+ if (!server_id) {
+ MONGOC_ERROR ("mongoc_cursor_set_hint: cannot set server_id to 0");
+ return false;
+ }
+
+ cursor->server_id = server_id;
+
+ return true;
+}
+
+
+uint32_t
+mongoc_cursor_get_hint (const mongoc_cursor_t *cursor)
+{
+ BSON_ASSERT (cursor);
+
+ return cursor->server_id;
+}
+
+
+int64_t
+mongoc_cursor_get_id (const mongoc_cursor_t *cursor)
+{
+ BSON_ASSERT (cursor);
+
+ return cursor->cursor_id;
+}
+
+
+void
+mongoc_cursor_set_max_await_time_ms (mongoc_cursor_t *cursor,
+ uint32_t max_await_time_ms)
+{
+ BSON_ASSERT (cursor);
+
+ if (cursor->state == UNPRIMED) {
+ _mongoc_cursor_set_opt_int64 (
+ cursor, MONGOC_CURSOR_MAX_AWAIT_TIME_MS, (int64_t) max_await_time_ms);
+ }
+}
+
+
+uint32_t
+mongoc_cursor_get_max_await_time_ms (const mongoc_cursor_t *cursor)
+{
+ bson_iter_t iter;
+
+ BSON_ASSERT (cursor);
+
+ if (bson_iter_init_find (
+ &iter, &cursor->opts, MONGOC_CURSOR_MAX_AWAIT_TIME_MS)) {
+ return (uint32_t) bson_iter_as_int64 (&iter);
+ }
+
+ return 0;
+}
+
+
+/* deprecated for mongoc_cursor_new_from_command_reply_with_opts */
+mongoc_cursor_t *
+mongoc_cursor_new_from_command_reply (mongoc_client_t *client,
+ bson_t *reply,
+ uint32_t server_id)
+{
+ mongoc_cursor_t *cursor;
+ bson_t cmd = BSON_INITIALIZER;
+ bson_t opts = BSON_INITIALIZER;
+
+ BSON_ASSERT (client);
+ BSON_ASSERT (reply);
+ /* options are passed through by adding them to reply. */
+ bson_copy_to_excluding_noinit (reply,
+ &opts,
+ "cursor",
+ "ok",
+ "operationTime",
+ "$clusterTime",
+ "$gleStats",
+ NULL);
+
+ if (server_id) {
+ bson_append_int64 (&opts, "serverId", 8, server_id);
+ }
+
+ cursor = _mongoc_cursor_cmd_new_from_reply (client, &cmd, &opts, reply);
+ bson_destroy (&cmd);
+ bson_destroy (&opts);
+
+ return cursor;
+}
+
+
+mongoc_cursor_t *
+mongoc_cursor_new_from_command_reply_with_opts (mongoc_client_t *client,
+ bson_t *reply,
+ const bson_t *opts)
+{
+ mongoc_cursor_t *cursor;
+ bson_t cmd = BSON_INITIALIZER;
+
+ BSON_ASSERT (client);
+ BSON_ASSERT (reply);
+
+ cursor = _mongoc_cursor_cmd_new_from_reply (client, &cmd, opts, reply);
+ bson_destroy (&cmd);
+
+ return cursor;
+}
+
+
+bool
+_mongoc_cursor_start_reading_response (mongoc_cursor_t *cursor,
+ mongoc_cursor_response_t *response)
+{
+ bson_iter_t iter;
+ bson_iter_t child;
+ const char *ns;
+ uint32_t nslen;
+ bool in_batch = false;
+
+ if (bson_iter_init_find (&iter, &response->reply, "cursor") &&
+ BSON_ITER_HOLDS_DOCUMENT (&iter) && bson_iter_recurse (&iter, &child)) {
+ while (bson_iter_next (&child)) {
+ if (BSON_ITER_IS_KEY (&child, "id")) {
+ cursor->cursor_id = bson_iter_as_int64 (&child);
+ } else if (BSON_ITER_IS_KEY (&child, "ns")) {
+ ns = bson_iter_utf8 (&child, &nslen);
+ _mongoc_set_cursor_ns (cursor, ns, nslen);
+ } else if (BSON_ITER_IS_KEY (&child, "firstBatch") ||
+ BSON_ITER_IS_KEY (&child, "nextBatch")) {
+ if (BSON_ITER_HOLDS_ARRAY (&child) &&
+ bson_iter_recurse (&child, &response->batch_iter)) {
+ in_batch = true;
+ }
+ }
+ }
+ }
+
+ /* Driver Sessions Spec: "When an implicit session is associated with a
+ * cursor for use with getMore operations, the session MUST be returned to
+ * the pool immediately following a getMore operation that indicates that the
+ * cursor has been exhausted." */
+ if (cursor->cursor_id == 0 && cursor->client_session &&
+ !cursor->explicit_session) {
+ mongoc_client_session_destroy (cursor->client_session);
+ cursor->client_session = NULL;
+ }
+
+ return in_batch;
+}
+
+
+void
+_mongoc_cursor_response_read (mongoc_cursor_t *cursor,
+ mongoc_cursor_response_t *response,
+ const bson_t **bson)
+{
+ const uint8_t *data = NULL;
+ uint32_t data_len = 0;
+
+ ENTRY;
+
+ if (bson_iter_next (&response->batch_iter) &&
+ BSON_ITER_HOLDS_DOCUMENT (&response->batch_iter)) {
+ bson_iter_document (&response->batch_iter, &data_len, &data);
+
+ /* bson_iter_next guarantees valid BSON, so this must succeed */
+ BSON_ASSERT (bson_init_static (&response->current_doc, data, data_len));
+ *bson = &response->current_doc;
+ }
+}
+
+/* sets cursor error if could not get the next batch. */
+void
+_mongoc_cursor_response_refresh (mongoc_cursor_t *cursor,
+ const bson_t *command,
+ const bson_t *opts,
+ mongoc_cursor_response_t *response)
+{
+ ENTRY;
+
+ bson_destroy (&response->reply);
+
+ /* server replies to find / aggregate with {cursor: {id: N, firstBatch: []}},
+ * to getMore command with {cursor: {id: N, nextBatch: []}}. */
+ if (_mongoc_cursor_run_command (
+ cursor, command, opts, &response->reply, false) &&
+ _mongoc_cursor_start_reading_response (cursor, response)) {
+ return;
+ }
+ if (!cursor->error.domain) {
+ bson_set_error (&cursor->error,
+ MONGOC_ERROR_PROTOCOL,
+ MONGOC_ERROR_PROTOCOL_INVALID_REPLY,
+ "Invalid reply to %s command.",
+ _mongoc_get_command_name (command));
+ }
+}
+
+void
+_mongoc_cursor_prepare_getmore_command (mongoc_cursor_t *cursor,
+ bson_t *command)
+{
+ const char *collection;
+ int collection_len;
+ int64_t batch_size;
+ bool await_data;
+ int64_t max_await_time_ms;
+
+ ENTRY;
+
+ _mongoc_cursor_collection (cursor, &collection, &collection_len);
+
+ bson_init (command);
+ bson_append_int64 (command, "getMore", 7, mongoc_cursor_get_id (cursor));
+ bson_append_utf8 (command, "collection", 10, collection, collection_len);
+
+ batch_size = mongoc_cursor_get_batch_size (cursor);
+
+ /* See find, getMore, and killCursors Spec for batchSize rules */
+ if (batch_size) {
+ bson_append_int64 (command,
+ MONGOC_CURSOR_BATCH_SIZE,
+ MONGOC_CURSOR_BATCH_SIZE_LEN,
+ abs (_mongoc_n_return (cursor)));
+ }
+
+ /* Find, getMore And killCursors Commands Spec: "In the case of a tailable
+ cursor with awaitData == true the driver MUST provide a Cursor level
+ option named maxAwaitTimeMS (See CRUD specification for details). The
+ maxTimeMS option on the getMore command MUST be set to the value of the
+ option maxAwaitTimeMS. If no maxAwaitTimeMS is specified, the driver
+ SHOULD not set maxTimeMS on the getMore command."
+ */
+ await_data = _mongoc_cursor_get_opt_bool (cursor, MONGOC_CURSOR_TAILABLE) &&
+ _mongoc_cursor_get_opt_bool (cursor, MONGOC_CURSOR_AWAIT_DATA);
+
+ if (await_data) {
+ max_await_time_ms = _mongoc_cursor_get_opt_int64 (
+ cursor, MONGOC_CURSOR_MAX_AWAIT_TIME_MS, 0);
+ if (max_await_time_ms) {
+ bson_append_int64 (command,
+ MONGOC_CURSOR_MAX_TIME_MS,
+ MONGOC_CURSOR_MAX_TIME_MS_LEN,
+ max_await_time_ms);
+ }
+ }
+}
+
+/* sets the cursor to be empty so it returns NULL on the first call to
+ * cursor_next but does not return an error. */
+void
+_mongoc_cursor_set_empty (mongoc_cursor_t *cursor)
+{
+ memset (&cursor->error, 0, sizeof (bson_error_t));
+ bson_reinit (&cursor->error_doc);
+ cursor->state = IN_BATCH;
+}
+
+void
+_mongoc_cursor_prime (mongoc_cursor_t *cursor)
+{
+ cursor->state = cursor->impl.prime (cursor);
+}
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cyrus-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cyrus-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cyrus-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cyrus-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cyrus.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cyrus.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cyrus.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-cyrus.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-database-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-database-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-database-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-database-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-database.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-database.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-database.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-database.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-database.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-database.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-database.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-database.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-errno-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-errno-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-errno-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-errno-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-error-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-error-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-error-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-error-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-error.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-error.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-error.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-error.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-error.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-error.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-error.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-error.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-find-and-modify-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-find-and-modify-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-find-and-modify-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-find-and-modify-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-find-and-modify.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-find-and-modify.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-find-and-modify.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-find-and-modify.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-find-and-modify.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-find-and-modify.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-find-and-modify.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-find-and-modify.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-flags-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-flags-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-flags-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-flags-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-flags.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-flags.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-flags.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-flags.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-generation-map-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-generation-map-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-generation-map-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-generation-map-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-generation-map.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-generation-map.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-generation-map.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-generation-map.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-bucket-file-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-bucket-file-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-bucket-file-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-bucket-file-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-bucket-file.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-bucket-file.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-bucket-file.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-bucket-file.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-bucket-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-bucket-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-bucket-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-bucket-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-bucket.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-bucket.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-bucket.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-bucket.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-bucket.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-bucket.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-bucket.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-bucket.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-file-list-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-file-list-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-file-list-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-file-list-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-file-list.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-file-list.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-file-list.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-file-list.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-file-list.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-file-list.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-file-list.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-file-list.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-file-page-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-file-page-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-file-page-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-file-page-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-file-page.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-file-page.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-file-page.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-file-page.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-file-page.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-file-page.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-file-page.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-file-page.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-file-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-file-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-file-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-file-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-file.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-file.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-file.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-file.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-file.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-file.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-file.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-file.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-handshake-compiler-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-handshake-compiler-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-handshake-compiler-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-handshake-compiler-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-handshake-os-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-handshake-os-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-handshake-os-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-handshake-os-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-handshake-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-handshake-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-handshake-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-handshake-private.h
diff --git a/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-handshake.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-handshake.c
new file mode 100644
index 00000000..fc08285c
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-handshake.c
@@ -0,0 +1,712 @@
+/*
+ * Copyright 2016-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <bson/bson.h>
+
+#ifdef _POSIX_VERSION
+#include <sys/utsname.h>
+#endif
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+#include "mongoc-linux-distro-scanner-private.h"
+#include "mongoc-handshake.h"
+#include "mongoc-handshake-compiler-private.h"
+#include "mongoc-handshake-os-private.h"
+#include "mongoc-handshake-private.h"
+#include "mongoc-client.h"
+#include "mongoc-client-private.h"
+#include "mongoc-error.h"
+#include "mongoc-log.h"
+#include "mongoc-version.h"
+#include "mongoc-util-private.h"
+
+/*
+ * Global handshake data instance. Initialized at startup from mongoc_init
+ *
+ * Can be modified by calls to mongoc_handshake_data_append
+ */
+static mongoc_handshake_t gMongocHandshake;
+
+/*
+ * Used for thread-safety in mongoc_handshake_data_append
+ */
+static bson_mutex_t gHandshakeLock;
+
+static void
+_set_bit (uint8_t *bf, uint32_t byte_count, uint32_t bit)
+{
+ uint32_t byte = bit / 8;
+ uint32_t bit_of_byte = (bit) % 8;
+ /* byte 0 is the last location in bf. */
+ bf[(byte_count - 1) - byte] |= 1u << bit_of_byte;
+}
+
+/* returns a hex string for all config flag bits, which must be freed. */
+char *
+_mongoc_handshake_get_config_hex_string (void)
+{
+ uint32_t byte_count;
+ uint8_t *bf;
+ bson_string_t *str;
+ int i;
+
+ byte_count = (LAST_MONGOC_MD_FLAG + 7) / 8; /* ceil (num_bits / 8) */
+ /* allocate enough bytes to fit all config bits. */
+ bf = (uint8_t *) bson_malloc0 (byte_count);
+
+#ifdef MONGOC_ENABLE_SSL_SECURE_CHANNEL
+ _set_bit (bf, byte_count, MONGOC_ENABLE_SSL_SECURE_CHANNEL);
+#endif
+
+#ifdef MONGOC_ENABLE_CRYPTO_CNG
+ _set_bit (bf, byte_count, MONGOC_ENABLE_CRYPTO_CNG);
+#endif
+
+#ifdef MONGOC_ENABLE_SSL_SECURE_TRANSPORT
+ _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_SSL_SECURE_TRANSPORT);
+#endif
+
+#ifdef MONGOC_ENABLE_CRYPTO_COMMON_CRYPTO
+ _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_CRYPTO_COMMON_CRYPTO);
+#endif
+
+#ifdef MONGOC_ENABLE_SSL_OPENSSL
+ _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_SSL_OPENSSL);
+#endif
+
+#ifdef MONGOC_ENABLE_CRYPTO_LIBCRYPTO
+ _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_CRYPTO_LIBCRYPTO);
+#endif
+
+#ifdef MONGOC_ENABLE_SSL
+ _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_SSL);
+#endif
+
+#ifdef MONGOC_ENABLE_CRYPTO
+ _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_CRYPTO);
+#endif
+
+#ifdef MONGOC_ENABLE_CRYPTO_SYSTEM_PROFILE
+ _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_CRYPTO_SYSTEM_PROFILE);
+#endif
+
+#ifdef MONGOC_ENABLE_SASL
+ _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_SASL);
+#endif
+
+#ifdef MONGOC_HAVE_SASL_CLIENT_DONE
+ _set_bit (bf, byte_count, MONGOC_MD_FLAG_HAVE_SASL_CLIENT_DONE);
+#endif
+
+#ifdef MONGOC_NO_AUTOMATIC_GLOBALS
+ _set_bit (bf, byte_count, MONGOC_MD_FLAG_NO_AUTOMATIC_GLOBALS);
+#endif
+
+#ifdef MONGOC_EXPERIMENTAL_FEATURES
+ _set_bit (bf, byte_count, MONGOC_MD_FLAG_EXPERIMENTAL_FEATURES);
+#endif
+
+#ifdef MONGOC_ENABLE_SSL_LIBRESSL
+ _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_SSL_LIBRESSL);
+#endif
+
+#ifdef MONGOC_ENABLE_SASL_CYRUS
+ _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_SASL_CYRUS);
+#endif
+
+#ifdef MONGOC_ENABLE_SASL_SSPI
+ _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_SASL_SSPI);
+#endif
+
+#ifdef MONGOC_HAVE_SOCKLEN
+ _set_bit (bf, byte_count, MONGOC_MD_FLAG_HAVE_SOCKLEN);
+#endif
+
+#ifdef MONGOC_ENABLE_COMPRESSION
+ _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_COMPRESSION);
+#endif
+
+#ifdef MONGOC_ENABLE_COMPRESSION_SNAPPY
+ _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_COMPRESSION_SNAPPY);
+#endif
+
+#ifdef MONGOC_ENABLE_COMPRESSION_ZLIB
+ _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_COMPRESSION_ZLIB);
+#endif
+
+#ifdef MONGOC_HAVE_RES_NSEARCH
+ _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_RES_NSEARCH);
+#endif
+
+#ifdef MONGOC_HAVE_RES_NDESTROY
+ _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_RES_NDESTROY);
+#endif
+
+#ifdef MONGOC_HAVE_RES_NCLOSE
+ _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_RES_NCLOSE);
+#endif
+
+#ifdef MONGOC_HAVE_RES_SEARCH
+ _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_RES_SEARCH);
+#endif
+
+#ifdef MONGOC_HAVE_DNSAPI
+ _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_DNSAPI);
+#endif
+
+#ifdef MONGOC_HAVE_RDTSCP
+ _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_RDTSCP);
+#endif
+
+#ifdef MONGOC_HAVE_SCHED_GETCPU
+ _set_bit (bf, byte_count, MONGOC_MD_FLAG_HAVE_SCHED_GETCPU);
+#endif
+
+#ifdef MONGOC_ENABLE_SHM_COUNTERS
+ _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_SHM_COUNTERS);
+#endif
+
+ if (MONGOC_TRACE_ENABLED) {
+ _set_bit (bf, byte_count, MONGOC_MD_FLAG_TRACE);
+ }
+
+#ifdef MONGOC_ENABLE_ICU
+ _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_ICU);
+#endif
+
+#ifdef MONGOC_ENABLE_CLIENT_SIDE_ENCRYPTION
+ _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_CLIENT_SIDE_ENCRYPTION);
+#endif
+
+#ifdef MONGOC_ENABLE_MONGODB_AWS_AUTH
+ _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_MONGODB_AWS_AUTH);
+#endif
+
+ str = bson_string_new ("0x");
+ for (i = 0; i < byte_count; i++) {
+ bson_string_append_printf (str, "%02x", bf[i]);
+ }
+ bson_free (bf);
+ /* free the bson_string_t, but keep the underlying char* alive. */
+ return bson_string_free (str, false);
+}
+
+static char *
+_get_os_type (void)
+{
+#ifdef MONGOC_OS_TYPE
+ return bson_strndup (MONGOC_OS_TYPE, HANDSHAKE_OS_TYPE_MAX);
+#else
+ return bson_strndup ("unknown", HANDSHAKE_OS_TYPE_MAX);
+#endif
+}
+
+static char *
+_get_os_architecture (void)
+{
+ const char *ret = NULL;
+
+#ifdef _WIN32
+ SYSTEM_INFO system_info;
+ DWORD arch;
+ GetSystemInfo (&system_info);
+
+ arch = system_info.wProcessorArchitecture;
+
+ switch (arch) {
+ case PROCESSOR_ARCHITECTURE_AMD64:
+ ret = "x86_64";
+ break;
+ case PROCESSOR_ARCHITECTURE_ARM:
+ ret = "ARM";
+ break;
+ case PROCESSOR_ARCHITECTURE_IA64:
+ ret = "IA64";
+ break;
+ case PROCESSOR_ARCHITECTURE_INTEL:
+ ret = "x86";
+ break;
+ case PROCESSOR_ARCHITECTURE_UNKNOWN:
+ ret = "Unknown";
+ break;
+ default:
+ ret = "Other";
+ break;
+ }
+
+#elif defined(_POSIX_VERSION)
+ struct utsname system_info;
+
+ if (uname (&system_info) >= 0) {
+ ret = system_info.machine;
+ }
+
+#endif
+
+ if (ret) {
+ return bson_strndup (ret, HANDSHAKE_OS_ARCHITECTURE_MAX);
+ }
+
+ return NULL;
+}
+
+#ifndef MONGOC_OS_IS_LINUX
+static char *
+_get_os_name (void)
+{
+#ifdef MONGOC_OS_NAME
+ return bson_strndup (MONGOC_OS_NAME, HANDSHAKE_OS_NAME_MAX);
+#elif defined(_POSIX_VERSION)
+ struct utsname system_info;
+
+ if (uname (&system_info) >= 0) {
+ return bson_strndup (system_info.sysname, HANDSHAKE_OS_NAME_MAX);
+ }
+
+#endif
+
+ return NULL;
+}
+
+static char *
+_get_os_version (void)
+{
+ char *ret = bson_malloc (HANDSHAKE_OS_VERSION_MAX);
+ bool found = false;
+
+#ifdef _WIN32
+ OSVERSIONINFO osvi;
+ ZeroMemory (&osvi, sizeof (OSVERSIONINFO));
+ osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
+
+ if (GetVersionEx (&osvi)) {
+ bson_snprintf (ret,
+ HANDSHAKE_OS_VERSION_MAX,
+ "%lu.%lu (%lu)",
+ osvi.dwMajorVersion,
+ osvi.dwMinorVersion,
+ osvi.dwBuildNumber);
+ found = true;
+ } else {
+ MONGOC_WARNING ("Error with GetVersionEx(): %lu", GetLastError ());
+ }
+
+#elif defined(_POSIX_VERSION)
+ struct utsname system_info;
+
+ if (uname (&system_info) >= 0) {
+ bson_strncpy (ret, system_info.release, HANDSHAKE_OS_VERSION_MAX);
+ found = true;
+ } else {
+ MONGOC_WARNING ("Error with uname(): %d", errno);
+ }
+
+#endif
+
+ if (!found) {
+ bson_free (ret);
+ ret = NULL;
+ }
+
+ return ret;
+}
+#endif
+
+static void
+_get_system_info (mongoc_handshake_t *handshake)
+{
+ handshake->os_type = _get_os_type ();
+
+#ifdef MONGOC_OS_IS_LINUX
+ _mongoc_linux_distro_scanner_get_distro (&handshake->os_name,
+ &handshake->os_version);
+#else
+ handshake->os_name = _get_os_name ();
+ handshake->os_version = _get_os_version ();
+#endif
+
+ handshake->os_architecture = _get_os_architecture ();
+}
+
+static void
+_free_system_info (mongoc_handshake_t *handshake)
+{
+ bson_free (handshake->os_type);
+ bson_free (handshake->os_name);
+ bson_free (handshake->os_version);
+ bson_free (handshake->os_architecture);
+}
+
+static void
+_get_driver_info (mongoc_handshake_t *handshake)
+{
+ handshake->driver_name = bson_strndup ("mongoc", HANDSHAKE_DRIVER_NAME_MAX);
+ handshake->driver_version =
+ bson_strndup (MONGOC_VERSION_S, HANDSHAKE_DRIVER_VERSION_MAX);
+}
+
+static void
+_free_driver_info (mongoc_handshake_t *handshake)
+{
+ bson_free (handshake->driver_name);
+ bson_free (handshake->driver_version);
+}
+
+static void
+_set_platform_string (mongoc_handshake_t *handshake)
+{
+ bson_string_t *str;
+
+ str = bson_string_new ("");
+
+ handshake->platform = bson_string_free (str, false);
+}
+
+static void
+_set_compiler_info (mongoc_handshake_t *handshake)
+{
+ bson_string_t *str;
+ char *config_str;
+
+ str = bson_string_new ("");
+
+ config_str = _mongoc_handshake_get_config_hex_string ();
+ bson_string_append_printf (str, "cfg=%s", config_str);
+ bson_free (config_str);
+
+#ifdef _POSIX_VERSION
+ bson_string_append_printf (str, " posix=%ld", _POSIX_VERSION);
+#endif
+
+#ifdef __STDC_VERSION__
+ bson_string_append_printf (str, " stdc=%ld", __STDC_VERSION__);
+#endif
+
+ bson_string_append_printf (str, " CC=%s", MONGOC_COMPILER);
+
+#ifdef MONGOC_COMPILER_VERSION
+ bson_string_append_printf (str, " %s", MONGOC_COMPILER_VERSION);
+#endif
+ handshake->compiler_info = bson_string_free (str, false);
+}
+
+static void
+_set_flags (mongoc_handshake_t *handshake)
+{
+ bson_string_t *str;
+
+ str = bson_string_new ("");
+
+ if (strlen (MONGOC_EVALUATE_STR (MONGOC_USER_SET_CFLAGS)) > 0) {
+ bson_string_append_printf (
+ str, " CFLAGS=%s", MONGOC_EVALUATE_STR (MONGOC_USER_SET_CFLAGS));
+ }
+
+ if (strlen (MONGOC_EVALUATE_STR (MONGOC_USER_SET_LDFLAGS)) > 0) {
+ bson_string_append_printf (
+ str, " LDFLAGS=%s", MONGOC_EVALUATE_STR (MONGOC_USER_SET_LDFLAGS));
+ }
+
+ handshake->flags = bson_string_free (str, false);
+}
+
+static void
+_free_platform_string (mongoc_handshake_t *handshake)
+{
+ bson_free (handshake->platform);
+ bson_free (handshake->compiler_info);
+ bson_free (handshake->flags);
+}
+
+void
+_mongoc_handshake_init (void)
+{
+ _get_system_info (_mongoc_handshake_get ());
+ _get_driver_info (_mongoc_handshake_get ());
+ _set_platform_string (_mongoc_handshake_get ());
+ _set_compiler_info (_mongoc_handshake_get ());
+ _set_flags (_mongoc_handshake_get ());
+
+ _mongoc_handshake_get ()->frozen = false;
+ bson_mutex_init (&gHandshakeLock);
+}
+
+void
+_mongoc_handshake_cleanup (void)
+{
+ _free_system_info (_mongoc_handshake_get ());
+ _free_driver_info (_mongoc_handshake_get ());
+ _free_platform_string (_mongoc_handshake_get ());
+
+ bson_mutex_destroy (&gHandshakeLock);
+}
+
+static void
+_append_platform_field (bson_t *doc, const char *platform)
+{
+ int max_platform_str_size;
+
+ char *compiler_info = _mongoc_handshake_get ()->compiler_info;
+ char *flags = _mongoc_handshake_get ()->flags;
+ bson_string_t *combined_platform = bson_string_new (platform);
+
+ /* Compute space left for platform field */
+ max_platform_str_size =
+ HANDSHAKE_MAX_SIZE - ((int) doc->len +
+ /* 1 byte for utf8 tag */
+ 1 +
+
+ /* key size */
+ (int) strlen (HANDSHAKE_PLATFORM_FIELD) + 1 +
+
+ /* 4 bytes for length of string */
+ 4);
+
+ if (max_platform_str_size <= 0) {
+ bson_string_free (combined_platform, true);
+ return;
+ }
+
+ /* We opt to drop compiler info and flags if they can't fit, while the
+ * platform information is truncated
+ * Try to drop flags first, and if there is still not enough space also drop
+ * compiler info */
+ if (max_platform_str_size >
+ combined_platform->len + strlen (compiler_info) + 1) {
+ bson_string_append (combined_platform, compiler_info);
+ }
+ if (max_platform_str_size > combined_platform->len + strlen (flags) + 1) {
+ bson_string_append (combined_platform, flags);
+ }
+
+ /* We use the flags_index field to check if the CLAGS/LDFLAGS need to be
+ * truncated, and if so we drop them altogether */
+ bson_append_utf8 (
+ doc,
+ HANDSHAKE_PLATFORM_FIELD,
+ -1,
+ combined_platform->str,
+ BSON_MIN (max_platform_str_size - 1, combined_platform->len));
+
+ bson_string_free (combined_platform, true);
+ BSON_ASSERT (doc->len <= HANDSHAKE_MAX_SIZE);
+}
+
+/*
+ * Return true if we build the document, and it's not too big
+ * false if there's no way to prevent the doc from being too big. In this
+ * case, the caller shouldn't include it with hello
+ */
+bool
+_mongoc_handshake_build_doc_with_application (bson_t *doc, const char *appname)
+{
+ const mongoc_handshake_t *md = _mongoc_handshake_get ();
+ bson_t child;
+
+ if (appname) {
+ BSON_APPEND_DOCUMENT_BEGIN (doc, "application", &child);
+ BSON_APPEND_UTF8 (&child, "name", appname);
+ bson_append_document_end (doc, &child);
+ }
+
+ BSON_APPEND_DOCUMENT_BEGIN (doc, "driver", &child);
+ BSON_APPEND_UTF8 (&child, "name", md->driver_name);
+ BSON_APPEND_UTF8 (&child, "version", md->driver_version);
+ bson_append_document_end (doc, &child);
+
+ BSON_APPEND_DOCUMENT_BEGIN (doc, "os", &child);
+
+ BSON_ASSERT (md->os_type);
+ BSON_APPEND_UTF8 (&child, "type", md->os_type);
+
+ if (md->os_name) {
+ BSON_APPEND_UTF8 (&child, "name", md->os_name);
+ }
+
+ if (md->os_version) {
+ BSON_APPEND_UTF8 (&child, "version", md->os_version);
+ }
+
+ if (md->os_architecture) {
+ BSON_APPEND_UTF8 (&child, "architecture", md->os_architecture);
+ }
+
+ bson_append_document_end (doc, &child);
+
+ if (doc->len > HANDSHAKE_MAX_SIZE) {
+ /* We've done all we can possibly do to ensure the current
+ * document is below the maxsize, so if it overflows there is
+ * nothing else we can do, so we fail */
+ return false;
+ }
+
+ if (md->platform) {
+ _append_platform_field (doc, md->platform);
+ }
+
+ return true;
+}
+
+void
+_mongoc_handshake_freeze (void)
+{
+ _mongoc_handshake_get ()->frozen = true;
+}
+
+/*
+ * free (*s) and make *s point to *s concated with suffix.
+ * If *s is NULL it's treated like it's an empty string.
+ */
+static void
+_append_and_truncate (char **s, const char *suffix, int max_len)
+{
+ char *old_str = *s;
+ char *prefix;
+ const int delim_len = (int) strlen (" / ");
+ int space_for_suffix;
+
+ BSON_ASSERT_PARAM (s);
+ BSON_ASSERT_PARAM (suffix);
+
+ prefix = old_str ? old_str : "";
+
+ space_for_suffix = max_len - (int) strlen (prefix) - delim_len;
+
+ if (space_for_suffix <= 0) {
+ /* the old string already takes the whole allotted space */
+ return;
+ }
+
+ *s = bson_strdup_printf ("%s / %.*s", prefix, space_for_suffix, suffix);
+ BSON_ASSERT (strlen (*s) <= max_len);
+
+ bson_free (old_str);
+}
+
+
+/*
+ * Set some values in our global handshake struct. These values will be sent
+ * to the server as part of the initial connection handshake (hello).
+ * If this function is called more than once, or after we've connected to a
+ * mongod, then it will do nothing and return false. It will return true if it
+ * successfully sets the values.
+ *
+ * All arguments are optional.
+ */
+bool
+mongoc_handshake_data_append (const char *driver_name,
+ const char *driver_version,
+ const char *platform)
+{
+ int platform_space;
+
+ bson_mutex_lock (&gHandshakeLock);
+
+ if (_mongoc_handshake_get ()->frozen) {
+ bson_mutex_unlock (&gHandshakeLock);
+ return false;
+ }
+
+ BSON_ASSERT (_mongoc_handshake_get ()->platform);
+
+ /* allow practically any size for "platform", we'll trim it down in
+ * _mongoc_handshake_build_doc_with_application */
+ platform_space =
+ HANDSHAKE_MAX_SIZE - (int) strlen (_mongoc_handshake_get ()->platform);
+
+ if (platform) {
+ /* we check for an empty string as a special case to avoid an unnecessary
+ * delimiter being added in front of the string by _append_and_truncate */
+ if (_mongoc_handshake_get ()->platform[0] == '\0') {
+ bson_free (_mongoc_handshake_get ()->platform);
+ _mongoc_handshake_get ()->platform =
+ bson_strdup_printf ("%.*s", platform_space, platform);
+ } else {
+ _append_and_truncate (
+ &_mongoc_handshake_get ()->platform, platform, HANDSHAKE_MAX_SIZE);
+ }
+ }
+
+ if (driver_name) {
+ _append_and_truncate (&_mongoc_handshake_get ()->driver_name,
+ driver_name,
+ HANDSHAKE_DRIVER_NAME_MAX);
+ }
+
+ if (driver_version) {
+ _append_and_truncate (&_mongoc_handshake_get ()->driver_version,
+ driver_version,
+ HANDSHAKE_DRIVER_VERSION_MAX);
+ }
+
+ _mongoc_handshake_freeze ();
+ bson_mutex_unlock (&gHandshakeLock);
+
+ return true;
+}
+
+mongoc_handshake_t *
+_mongoc_handshake_get (void)
+{
+ return &gMongocHandshake;
+}
+
+bool
+_mongoc_handshake_appname_is_valid (const char *appname)
+{
+ return strlen (appname) <= MONGOC_HANDSHAKE_APPNAME_MAX;
+}
+
+void
+_mongoc_handshake_append_sasl_supported_mechs (const mongoc_uri_t *uri,
+ bson_t *cmd)
+{
+ const char *username;
+ char *db_user;
+ username = mongoc_uri_get_username (uri);
+ db_user =
+ bson_strdup_printf ("%s.%s", mongoc_uri_get_auth_source (uri), username);
+ bson_append_utf8 (cmd, "saslSupportedMechs", 18, db_user, -1);
+ bson_free (db_user);
+}
+
+void
+_mongoc_handshake_parse_sasl_supported_mechs (
+ const bson_t *hello,
+ mongoc_handshake_sasl_supported_mechs_t *sasl_supported_mechs)
+{
+ bson_iter_t iter;
+ memset (sasl_supported_mechs, 0, sizeof (*sasl_supported_mechs));
+ if (bson_iter_init_find (&iter, hello, "saslSupportedMechs")) {
+ bson_iter_t array_iter;
+ if (BSON_ITER_HOLDS_ARRAY (&iter) &&
+ bson_iter_recurse (&iter, &array_iter)) {
+ while (bson_iter_next (&array_iter)) {
+ if (BSON_ITER_HOLDS_UTF8 (&array_iter)) {
+ const char *mechanism_name = bson_iter_utf8 (&array_iter, NULL);
+ if (0 == strcmp (mechanism_name, "SCRAM-SHA-256")) {
+ sasl_supported_mechs->scram_sha_256 = true;
+ } else if (0 == strcmp (mechanism_name, "SCRAM-SHA-1")) {
+ sasl_supported_mechs->scram_sha_1 = true;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-handshake.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-handshake.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-handshake.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-handshake.h
diff --git a/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-host-list-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-host-list-private.h
new file mode 100644
index 00000000..a64cec5d
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-host-list-private.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2013 MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mongoc-prelude.h"
+
+#ifndef MONGOC_HOST_LIST_PRIVATE_H
+#define MONGOC_HOST_LIST_PRIVATE_H
+
+#include "mongoc-host-list.h"
+
+
+BSON_BEGIN_DECLS
+
+mongoc_host_list_t *
+_mongoc_host_list_push (const char *host,
+ uint16_t port,
+ int family,
+ mongoc_host_list_t *next);
+
+void
+_mongoc_host_list_upsert (mongoc_host_list_t **list,
+ const mongoc_host_list_t *new_host);
+
+mongoc_host_list_t *
+_mongoc_host_list_copy_all (const mongoc_host_list_t *src);
+
+bool
+_mongoc_host_list_from_string (mongoc_host_list_t *host_list,
+ const char *host_and_port);
+
+bool
+_mongoc_host_list_from_string_with_err (mongoc_host_list_t *host_list,
+ const char *host_and_port,
+ bson_error_t *error);
+
+bool
+_mongoc_host_list_from_hostport_with_err (mongoc_host_list_t *host_list,
+ const char *host,
+ uint16_t port,
+ bson_error_t *error);
+
+int
+_mongoc_host_list_length (const mongoc_host_list_t *list);
+
+bool
+_mongoc_host_list_compare_one (const mongoc_host_list_t *host_a,
+ const mongoc_host_list_t *host_b);
+
+void
+_mongoc_host_list_remove_host (mongoc_host_list_t **phosts,
+ const char *host,
+ uint16_t port);
+
+void
+_mongoc_host_list_destroy_all (mongoc_host_list_t *host);
+
+bool
+_mongoc_host_list_contains_one (mongoc_host_list_t *host_list,
+ mongoc_host_list_t *host);
+
+BSON_END_DECLS
+
+
+#endif /* MONGOC_HOST_LIST_PRIVATE_H */
diff --git a/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-host-list.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-host-list.c
new file mode 100644
index 00000000..becef5cb
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-host-list.c
@@ -0,0 +1,393 @@
+/*
+ * Copyright 2015 MongoDB Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mongoc-host-list-private.h"
+/* strcasecmp on windows */
+#include "mongoc-util-private.h"
+#include "utlist.h"
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_host_list_push --
+ *
+ * Add a host to the front of the list and return it.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+mongoc_host_list_t *
+_mongoc_host_list_push (const char *host,
+ uint16_t port,
+ int family,
+ mongoc_host_list_t *next)
+{
+ mongoc_host_list_t *h;
+
+ BSON_ASSERT (host);
+
+ h = bson_malloc0 (sizeof (mongoc_host_list_t));
+ bson_strncpy (h->host, host, sizeof h->host);
+ h->port = port;
+ bson_snprintf (
+ h->host_and_port, sizeof h->host_and_port, "%s:%hu", host, port);
+
+ h->family = family;
+ h->next = next;
+
+ return h;
+}
+
+static mongoc_host_list_t *
+_mongoc_host_list_find_host_and_port (mongoc_host_list_t *hosts,
+ const char *host_and_port)
+{
+ mongoc_host_list_t *iter;
+ LL_FOREACH (hosts, iter)
+ {
+ BSON_ASSERT (iter);
+
+ if (strcasecmp (iter->host_and_port, host_and_port) == 0) {
+ return iter;
+ }
+ }
+
+ return NULL;
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_host_list_upsert --
+ *
+ * If new_host is not already in list, copy and add it to the end of list.
+ * If *list == NULL, then it will be set to a new host.
+ *
+ * Returns:
+ * Nothing.
+ *
+ *--------------------------------------------------------------------------
+ */
+void
+_mongoc_host_list_upsert (mongoc_host_list_t **list,
+ const mongoc_host_list_t *new_host)
+{
+ mongoc_host_list_t *link = NULL;
+ mongoc_host_list_t *next_link = NULL;
+
+ BSON_ASSERT (list);
+ if (!new_host) {
+ return;
+ }
+
+ link = _mongoc_host_list_find_host_and_port (*list, new_host->host_and_port);
+
+ if (!link) {
+ link = bson_malloc0 (sizeof (mongoc_host_list_t));
+ LL_APPEND (*list, link);
+ } else {
+ /* Make sure linking is preserved when copying data into final. */
+ next_link = link->next;
+ }
+
+ memcpy (link, new_host, sizeof (mongoc_host_list_t));
+ link->next = next_link;
+}
+
+
+/* Duplicates a host list.
+ */
+mongoc_host_list_t *
+_mongoc_host_list_copy_all (const mongoc_host_list_t *src)
+{
+ mongoc_host_list_t *tail = NULL;
+ const mongoc_host_list_t *src_iter;
+ mongoc_host_list_t *head = NULL;
+
+ LL_FOREACH (src, src_iter)
+ {
+ tail = bson_malloc0 (sizeof (mongoc_host_list_t));
+ memcpy (tail, src_iter, sizeof (mongoc_host_list_t));
+
+ LL_PREPEND (head, tail);
+ }
+
+ return head;
+}
+
+int
+_mongoc_host_list_length (const mongoc_host_list_t *list)
+{
+ const mongoc_host_list_t *tmp;
+ int counter = 0;
+
+ tmp = list;
+ while (tmp) {
+ tmp = tmp->next;
+ counter++;
+ }
+
+ return counter;
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_host_list_compare_one --
+ *
+ * Check two hosts have the same domain (case-insensitive), port,
+ * and address family.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+bool
+_mongoc_host_list_compare_one (const mongoc_host_list_t *host_a,
+ const mongoc_host_list_t *host_b)
+{
+ return (0 == strcasecmp (host_a->host_and_port, host_b->host_and_port) &&
+ host_a->family == host_b->family);
+}
+
+bool
+_mongoc_host_list_contains_one (mongoc_host_list_t *host_list,
+ mongoc_host_list_t *host)
+{
+ return NULL !=
+ _mongoc_host_list_find_host_and_port (host_list, host->host_and_port);
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_host_list_destroy_all --
+ *
+ * Destroy whole linked list of hosts.
+ *
+ *--------------------------------------------------------------------------
+ */
+void
+_mongoc_host_list_destroy_all (mongoc_host_list_t *host)
+{
+ mongoc_host_list_t *tmp;
+
+ while (host) {
+ tmp = host->next;
+ bson_free (host);
+ host = tmp;
+ }
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_host_list_from_string --
+ *
+ * Populate a mongoc_host_list_t from a fully qualified address
+ *
+ *--------------------------------------------------------------------------
+ */
+bool
+_mongoc_host_list_from_string (mongoc_host_list_t *link_, const char *address)
+{
+ bson_error_t error = {0};
+ bool r = _mongoc_host_list_from_string_with_err (link_, address, &error);
+ if (!r) {
+ MONGOC_ERROR ("Could not parse address %s: %s", address, error.message);
+ return false;
+ }
+ return true;
+}
+
+bool
+_mongoc_host_list_from_string_with_err (mongoc_host_list_t *link_,
+ const char *address,
+ bson_error_t *error)
+{
+ char *close_bracket;
+ char *sport;
+ uint16_t port;
+ char *host;
+ bool ret;
+ bool ipv6 = false;
+
+ close_bracket = strchr (address, ']');
+
+ /* if this is an ipv6 address. */
+ if (close_bracket) {
+ /* if present, the port should immediately follow after ] */
+ sport = strchr (close_bracket, ':');
+ if (sport > close_bracket + 1) {
+ bson_set_error (error,
+ MONGOC_ERROR_COMMAND,
+ MONGOC_ERROR_COMMAND_INVALID_ARG,
+ "If present, port should immediately follow the \"]\""
+ "in an IPv6 address");
+ return false;
+ }
+
+ /* otherwise ] should be the last char. */
+ if (!sport && *(close_bracket + 1) != '\0') {
+ bson_set_error (error,
+ MONGOC_ERROR_COMMAND,
+ MONGOC_ERROR_COMMAND_INVALID_ARG,
+ "If port is not supplied, \"[\" should be the last"
+ "character");
+ return false;
+ }
+
+ if (*address != '[') {
+ bson_set_error (error,
+ MONGOC_ERROR_COMMAND,
+ MONGOC_ERROR_COMMAND_INVALID_ARG,
+ "Missing matching bracket \"[\"");
+ return false;
+ }
+
+ ipv6 = true;
+ }
+ /* otherwise, just find the first : */
+ else {
+ sport = strchr (address, ':');
+ }
+
+ /* like "example.com:27019" or "[fe80::1]:27019", but not "[fe80::1]" */
+ if (sport) {
+ if (sport == address) {
+ /* bad address like ":27017" */
+ bson_set_error (error,
+ MONGOC_ERROR_COMMAND,
+ MONGOC_ERROR_COMMAND_INVALID_ARG,
+ "Bad address, \":\" should not be first character");
+ return false;
+ }
+
+ if (!mongoc_parse_port (&port, sport + 1)) {
+ bson_set_error (error,
+ MONGOC_ERROR_COMMAND,
+ MONGOC_ERROR_COMMAND_INVALID_ARG,
+ "Port could not be parsed");
+ return false;
+ }
+
+ /* if this is an ipv6 address, strip the [ and ] */
+ if (ipv6) {
+ host = bson_strndup (address + 1, close_bracket - address - 1);
+ } else {
+ host = bson_strndup (address, sport - address);
+ }
+ } else {
+ /* if this is an ipv6 address, strip the [ and ] */
+ if (ipv6) {
+ host = bson_strndup (address + 1, close_bracket - address - 1);
+ } else {
+ host = bson_strdup (address);
+ }
+ port = MONGOC_DEFAULT_PORT;
+ }
+
+ ret = _mongoc_host_list_from_hostport_with_err (link_, host, port, error);
+
+ bson_free (host);
+
+ return ret;
+}
+
+bool
+_mongoc_host_list_from_hostport_with_err (mongoc_host_list_t *link_,
+ const char *host,
+ uint16_t port,
+ bson_error_t *error)
+{
+ size_t host_len = strlen (host);
+ link_->port = port;
+
+ if (host_len == 0) {
+ bson_set_error (error,
+ MONGOC_ERROR_STREAM,
+ MONGOC_ERROR_STREAM_NAME_RESOLUTION,
+ "Empty hostname in URI");
+ return false;
+ }
+
+ if (host_len > BSON_HOST_NAME_MAX) {
+ bson_set_error (error,
+ MONGOC_ERROR_STREAM,
+ MONGOC_ERROR_STREAM_NAME_RESOLUTION,
+ "Hostname provided in URI is too long, max is %d chars",
+ BSON_HOST_NAME_MAX);
+ return false;
+ }
+
+ bson_strncpy (link_->host, host, host_len + 1);
+
+ /* like "fe80::1" or "::1" */
+ if (strchr (host, ':')) {
+ link_->family = AF_INET6;
+
+ mongoc_lowercase (link_->host, link_->host);
+ bson_snprintf (link_->host_and_port,
+ sizeof link_->host_and_port,
+ "[%s]:%hu",
+ link_->host,
+ link_->port);
+
+ } else if (strchr (host, '/') && strstr (host, ".sock")) {
+ link_->family = AF_UNIX;
+ bson_strncpy (link_->host_and_port, link_->host, host_len + 1);
+ } else {
+ /* This is either an IPv4 or hostname. */
+ link_->family = AF_UNSPEC;
+
+ mongoc_lowercase (link_->host, link_->host);
+ bson_snprintf (link_->host_and_port,
+ sizeof link_->host_and_port,
+ "%s:%hu",
+ link_->host,
+ link_->port);
+ }
+
+ link_->next = NULL;
+ return true;
+}
+
+void
+_mongoc_host_list_remove_host (mongoc_host_list_t **hosts,
+ const char *host,
+ uint16_t port)
+{
+ mongoc_host_list_t *current;
+ mongoc_host_list_t *prev = NULL;
+
+ for (current = *hosts; current; prev = current, current = current->next) {
+ if ((current->port == port) && (strcmp (current->host, host) == 0)) {
+ /* Node found, unlink. */
+ if (prev) {
+ prev->next = current->next;
+ } else {
+ /* No previous, unlinking at head. */
+ *hosts = current->next;
+ }
+ bson_free (current);
+ break;
+ }
+ }
+}
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-host-list.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-host-list.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-host-list.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-host-list.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-http-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-http-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-http-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-http-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-http.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-http.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-http.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-http.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-index.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-index.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-index.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-index.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-index.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-index.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-index.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-index.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-init.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-init.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-init.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-init.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-init.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-init.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-init.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-init.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-interrupt-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-interrupt-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-interrupt-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-interrupt-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-interrupt.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-interrupt.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-interrupt.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-interrupt.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-iovec.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-iovec.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-iovec.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-iovec.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-libressl-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-libressl-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-libressl-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-libressl-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-libressl.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-libressl.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-libressl.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-libressl.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-linux-distro-scanner-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-linux-distro-scanner-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-linux-distro-scanner-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-linux-distro-scanner-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-linux-distro-scanner.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-linux-distro-scanner.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-linux-distro-scanner.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-linux-distro-scanner.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-list-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-list-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-list-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-list-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-list.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-list.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-list.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-list.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-log-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-log-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-log-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-log-private.h
diff --git a/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-log.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-log.c
new file mode 100644
index 00000000..74848ab3
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-log.c
@@ -0,0 +1,330 @@
+/*
+ * Copyright 2013 MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#if defined(__linux__)
+#include <sys/syscall.h>
+#elif defined(_WIN32)
+#include <process.h>
+#elif defined(__APPLE__)
+#include <pthread.h>
+#elif defined(__FreeBSD__)
+#include <sys/thr.h>
+#elif defined(__NetBSD__)
+#include <lwp.h>
+#else
+#include <unistd.h>
+#endif
+#include <stdarg.h>
+#include <time.h>
+
+#include "mongoc-log.h"
+#include "mongoc-log-private.h"
+#include "mongoc-thread-private.h"
+
+
+static bson_once_t once = BSON_ONCE_INIT;
+static bson_mutex_t gLogMutex;
+static mongoc_log_func_t gLogFunc = mongoc_log_default_handler;
+static bool gLogTrace = MONGOC_TRACE_ENABLED;
+static void *gLogData;
+
+static BSON_ONCE_FUN (_mongoc_ensure_mutex_once)
+{
+ bson_mutex_init (&gLogMutex);
+
+ BSON_ONCE_RETURN;
+}
+
+void
+mongoc_log_set_handler (mongoc_log_func_t log_func, void *user_data)
+{
+ bson_once (&once, &_mongoc_ensure_mutex_once);
+
+ bson_mutex_lock (&gLogMutex);
+ gLogFunc = log_func;
+ gLogData = user_data;
+ bson_mutex_unlock (&gLogMutex);
+}
+
+bool
+_mongoc_log_trace_is_enabled (void)
+{
+ return gLogTrace && MONGOC_TRACE_ENABLED;
+}
+
+void
+mongoc_log_trace_enable (void)
+{
+ /* Enable trace logging if-and-only-if tracing is enabled at configure-time,
+ * otherwise tracing remains disabled.
+ */
+ gLogTrace = MONGOC_TRACE_ENABLED;
+}
+
+void
+mongoc_log_trace_disable (void)
+{
+ gLogTrace = false;
+}
+
+/* just for testing */
+void
+_mongoc_log_get_handler (mongoc_log_func_t *log_func, void **user_data)
+{
+ *log_func = gLogFunc;
+ *user_data = gLogData;
+}
+
+
+void
+mongoc_log (mongoc_log_level_t log_level,
+ const char *log_domain,
+ const char *format,
+ ...)
+{
+ va_list args;
+ char *message;
+ int stop_logging;
+
+ bson_once (&once, &_mongoc_ensure_mutex_once);
+
+ stop_logging = !gLogFunc;
+ stop_logging = stop_logging || (log_level == MONGOC_LOG_LEVEL_TRACE &&
+ !_mongoc_log_trace_is_enabled ());
+ if (stop_logging) {
+ return;
+ }
+
+ BSON_ASSERT (format);
+
+ va_start (args, format);
+ message = bson_strdupv_printf (format, args);
+ va_end (args);
+
+ bson_mutex_lock (&gLogMutex);
+ gLogFunc (log_level, log_domain, message, gLogData);
+ bson_mutex_unlock (&gLogMutex);
+
+ bson_free (message);
+}
+
+
+const char *
+mongoc_log_level_str (mongoc_log_level_t log_level)
+{
+ switch (log_level) {
+ case MONGOC_LOG_LEVEL_ERROR:
+ return "ERROR";
+ case MONGOC_LOG_LEVEL_CRITICAL:
+ return "CRITICAL";
+ case MONGOC_LOG_LEVEL_WARNING:
+ return "WARNING";
+ case MONGOC_LOG_LEVEL_MESSAGE:
+ return "MESSAGE";
+ case MONGOC_LOG_LEVEL_INFO:
+ return "INFO";
+ case MONGOC_LOG_LEVEL_DEBUG:
+ return "DEBUG";
+ case MONGOC_LOG_LEVEL_TRACE:
+ return "TRACE";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+
+void
+mongoc_log_default_handler (mongoc_log_level_t log_level,
+ const char *log_domain,
+ const char *message,
+ void *user_data)
+{
+ struct timeval tv;
+ struct tm tt;
+ time_t t;
+ FILE *stream;
+ char nowstr[32];
+ int pid;
+
+ bson_gettimeofday (&tv);
+ t = tv.tv_sec;
+
+#ifdef _WIN32
+#ifdef _MSC_VER
+ localtime_s (&tt, &t);
+#else
+ tt = *(localtime (&t));
+#endif
+#else
+ localtime_r (&t, &tt);
+#endif
+
+ strftime (nowstr, sizeof nowstr, "%Y/%m/%d %H:%M:%S", &tt);
+
+ switch (log_level) {
+ case MONGOC_LOG_LEVEL_ERROR:
+ case MONGOC_LOG_LEVEL_CRITICAL:
+ case MONGOC_LOG_LEVEL_WARNING:
+ stream = stderr;
+ break;
+ case MONGOC_LOG_LEVEL_MESSAGE:
+ case MONGOC_LOG_LEVEL_INFO:
+ case MONGOC_LOG_LEVEL_DEBUG:
+ case MONGOC_LOG_LEVEL_TRACE:
+ default:
+ stream = stdout;
+ }
+
+#ifdef __linux__
+ pid = syscall (SYS_gettid);
+#elif defined(_WIN32)
+ pid = (int) _getpid ();
+#elif defined(__FreeBSD__)
+ long tid;
+ thr_self (&tid);
+ pid = (int) tid;
+#elif defined(__OpenBSD__)
+ pid = (int) getthrid ();
+#elif defined(__NetBSD__)
+ pid = (int) _lwp_self ();
+#elif defined(__APPLE__)
+ uint64_t tid;
+ pthread_threadid_np (0, &tid);
+ pid = (int) tid;
+#else
+ pid = (int) getpid ();
+#endif
+
+ fprintf (stream,
+ "%s.%04ld: [%5d]: %8s: %12s: %s\n",
+ nowstr,
+ tv.tv_usec / 1000L,
+ pid,
+ mongoc_log_level_str (log_level),
+ log_domain,
+ message);
+}
+
+void
+mongoc_log_trace_bytes (const char *domain, const uint8_t *_b, size_t _l)
+{
+ bson_string_t *str, *astr;
+ int32_t _i;
+ uint8_t _v;
+
+ if (!_mongoc_log_trace_is_enabled ()) {
+ return;
+ }
+
+ str = bson_string_new (NULL);
+ astr = bson_string_new (NULL);
+ for (_i = 0; _i < _l; _i++) {
+ _v = *(_b + _i);
+
+ if ((_i % 16) == 0) {
+ bson_string_append_printf (str, "%05x: ", _i);
+ }
+
+ bson_string_append_printf (str, " %02x", _v);
+ if (isprint (_v)) {
+ bson_string_append_printf (astr, " %c", _v);
+ } else {
+ bson_string_append (astr, " .");
+ }
+
+ if ((_i % 16) == 15) {
+ mongoc_log (
+ MONGOC_LOG_LEVEL_TRACE, domain, "%s %s", str->str, astr->str);
+ bson_string_truncate (str, 0);
+ bson_string_truncate (astr, 0);
+ } else if ((_i % 16) == 7) {
+ bson_string_append (str, " ");
+ bson_string_append (astr, " ");
+ }
+ }
+
+ if (_i != 16) {
+ mongoc_log (
+ MONGOC_LOG_LEVEL_TRACE, domain, "%-56s %s", str->str, astr->str);
+ }
+
+ bson_string_free (str, true);
+ bson_string_free (astr, true);
+}
+
+void
+mongoc_log_trace_iovec (const char *domain,
+ const mongoc_iovec_t *_iov,
+ size_t _iovcnt)
+{
+ bson_string_t *str, *astr;
+ const char *_b;
+ unsigned _i = 0;
+ unsigned _j = 0;
+ unsigned _k = 0;
+ size_t _l = 0;
+ uint8_t _v;
+
+ if (!_mongoc_log_trace_is_enabled ()) {
+ return;
+ }
+
+ for (_i = 0; _i < _iovcnt; _i++) {
+ _l += _iov[_i].iov_len;
+ }
+
+ _i = 0;
+ str = bson_string_new (NULL);
+ astr = bson_string_new (NULL);
+
+ for (_j = 0; _j < _iovcnt; _j++) {
+ _b = (char *) _iov[_j].iov_base;
+ _l = _iov[_j].iov_len;
+
+ for (_k = 0; _k < _l; _k++, _i++) {
+ _v = *(_b + _k);
+ if ((_i % 16) == 0) {
+ bson_string_append_printf (str, "%05x: ", _i);
+ }
+
+ bson_string_append_printf (str, " %02x", _v);
+ if (isprint (_v)) {
+ bson_string_append_printf (astr, " %c", _v);
+ } else {
+ bson_string_append (astr, " .");
+ }
+
+ if ((_i % 16) == 15) {
+ mongoc_log (
+ MONGOC_LOG_LEVEL_TRACE, domain, "%s %s", str->str, astr->str);
+ bson_string_truncate (str, 0);
+ bson_string_truncate (astr, 0);
+ } else if ((_i % 16) == 7) {
+ bson_string_append (str, " ");
+ bson_string_append (astr, " ");
+ }
+ }
+ }
+
+ if (_i != 16) {
+ mongoc_log (
+ MONGOC_LOG_LEVEL_TRACE, domain, "%-56s %s", str->str, astr->str);
+ }
+
+ bson_string_free (str, true);
+ bson_string_free (astr, true);
+}
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-log.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-log.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-log.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-log.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-macros.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-macros.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-macros.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-macros.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-matcher-op-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-matcher-op-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-matcher-op-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-matcher-op-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-matcher-op.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-matcher-op.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-matcher-op.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-matcher-op.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-matcher-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-matcher-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-matcher-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-matcher-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-matcher.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-matcher.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-matcher.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-matcher.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-matcher.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-matcher.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-matcher.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-matcher.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-memcmp-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-memcmp-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-memcmp-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-memcmp-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-memcmp.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-memcmp.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-memcmp.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-memcmp.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-ocsp-cache-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-ocsp-cache-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-ocsp-cache-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-ocsp-cache-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-ocsp-cache.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-ocsp-cache.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-ocsp-cache.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-ocsp-cache.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-opcode.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-opcode.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-opcode.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-opcode.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-openssl-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-openssl-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-openssl-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-openssl-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-openssl.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-openssl.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-openssl.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-openssl.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-optional.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-optional.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-optional.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-optional.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-optional.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-optional.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-optional.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-optional.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-opts-helpers-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-opts-helpers-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-opts-helpers-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-opts-helpers-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-opts-helpers.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-opts-helpers.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-opts-helpers.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-opts-helpers.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-opts-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-opts-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-opts-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-opts-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-opts.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-opts.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-opts.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-opts.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-prelude.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-prelude.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-prelude.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-prelude.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-queue-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-queue-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-queue-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-queue-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-queue.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-queue.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-queue.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-queue.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-rand-cng.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-rand-cng.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-rand-cng.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-rand-cng.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-rand-common-crypto.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-rand-common-crypto.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-rand-common-crypto.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-rand-common-crypto.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-rand-openssl.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-rand-openssl.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-rand-openssl.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-rand-openssl.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-rand-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-rand-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-rand-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-rand-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-rand.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-rand.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-rand.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-rand.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-read-concern-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-read-concern-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-read-concern-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-read-concern-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-read-concern.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-read-concern.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-read-concern.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-read-concern.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-read-concern.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-read-concern.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-read-concern.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-read-concern.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-read-prefs-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-read-prefs-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-read-prefs-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-read-prefs-private.h
diff --git a/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-read-prefs.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-read-prefs.c
new file mode 100644
index 00000000..7a250bdf
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-read-prefs.c
@@ -0,0 +1,423 @@
+/*
+ * Copyright 2013 MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include "mongoc-error.h"
+#include "mongoc-read-prefs-private.h"
+#include "mongoc-trace-private.h"
+
+
+mongoc_read_prefs_t *
+mongoc_read_prefs_new (mongoc_read_mode_t mode)
+{
+ mongoc_read_prefs_t *read_prefs;
+
+ read_prefs = (mongoc_read_prefs_t *) bson_malloc0 (sizeof *read_prefs);
+ read_prefs->mode = mode;
+ bson_init (&read_prefs->tags);
+ read_prefs->max_staleness_seconds = MONGOC_NO_MAX_STALENESS;
+ bson_init (&read_prefs->hedge);
+
+ return read_prefs;
+}
+
+
+mongoc_read_mode_t
+mongoc_read_prefs_get_mode (const mongoc_read_prefs_t *read_prefs)
+{
+ return read_prefs ? read_prefs->mode : MONGOC_READ_PRIMARY;
+}
+
+
+void
+mongoc_read_prefs_set_mode (mongoc_read_prefs_t *read_prefs,
+ mongoc_read_mode_t mode)
+{
+ BSON_ASSERT (read_prefs);
+ BSON_ASSERT (mode <= MONGOC_READ_NEAREST);
+
+ read_prefs->mode = mode;
+}
+
+
+const bson_t *
+mongoc_read_prefs_get_tags (const mongoc_read_prefs_t *read_prefs)
+{
+ BSON_ASSERT (read_prefs);
+ return &read_prefs->tags;
+}
+
+
+void
+mongoc_read_prefs_set_tags (mongoc_read_prefs_t *read_prefs, const bson_t *tags)
+{
+ BSON_ASSERT (read_prefs);
+
+ bson_destroy (&read_prefs->tags);
+
+ if (tags) {
+ bson_copy_to (tags, &read_prefs->tags);
+ } else {
+ bson_init (&read_prefs->tags);
+ }
+}
+
+
+void
+mongoc_read_prefs_add_tag (mongoc_read_prefs_t *read_prefs, const bson_t *tag)
+{
+ bson_t empty = BSON_INITIALIZER;
+ char str[16];
+ int key;
+
+ BSON_ASSERT (read_prefs);
+
+ key = bson_count_keys (&read_prefs->tags);
+ bson_snprintf (str, sizeof str, "%d", key);
+
+ if (tag) {
+ bson_append_document (&read_prefs->tags, str, -1, tag);
+ } else {
+ bson_append_document (&read_prefs->tags, str, -1, &empty);
+ }
+
+ bson_destroy (&empty);
+}
+
+
+int64_t
+mongoc_read_prefs_get_max_staleness_seconds (
+ const mongoc_read_prefs_t *read_prefs)
+{
+ BSON_ASSERT (read_prefs);
+
+ return read_prefs->max_staleness_seconds;
+}
+
+
+void
+mongoc_read_prefs_set_max_staleness_seconds (mongoc_read_prefs_t *read_prefs,
+ int64_t max_staleness_seconds)
+{
+ BSON_ASSERT (read_prefs);
+
+ read_prefs->max_staleness_seconds = max_staleness_seconds;
+}
+
+
+const bson_t *
+mongoc_read_prefs_get_hedge (const mongoc_read_prefs_t *read_prefs)
+{
+ BSON_ASSERT (read_prefs);
+
+ return &read_prefs->hedge;
+}
+
+
+void
+mongoc_read_prefs_set_hedge (mongoc_read_prefs_t *read_prefs,
+ const bson_t *hedge)
+{
+ BSON_ASSERT (read_prefs);
+
+ bson_destroy (&read_prefs->hedge);
+
+ if (hedge) {
+ bson_copy_to (hedge, &read_prefs->hedge);
+ } else {
+ bson_init (&read_prefs->hedge);
+ }
+}
+
+
+bool
+mongoc_read_prefs_is_valid (const mongoc_read_prefs_t *read_prefs)
+{
+ BSON_ASSERT (read_prefs);
+
+ /*
+ * Tags, maxStalenessSeconds, and hedge are not supported with PRIMARY mode.
+ */
+ if (read_prefs->mode == MONGOC_READ_PRIMARY) {
+ if (!bson_empty (&read_prefs->tags) ||
+ read_prefs->max_staleness_seconds != MONGOC_NO_MAX_STALENESS ||
+ !bson_empty (&read_prefs->hedge)) {
+ return false;
+ }
+ }
+
+ if (read_prefs->max_staleness_seconds != MONGOC_NO_MAX_STALENESS &&
+ read_prefs->max_staleness_seconds <= 0) {
+ return false;
+ }
+
+
+ return true;
+}
+
+
+void
+mongoc_read_prefs_destroy (mongoc_read_prefs_t *read_prefs)
+{
+ if (read_prefs) {
+ bson_destroy (&read_prefs->tags);
+ bson_destroy (&read_prefs->hedge);
+ bson_free (read_prefs);
+ }
+}
+
+
+mongoc_read_prefs_t *
+mongoc_read_prefs_copy (const mongoc_read_prefs_t *read_prefs)
+{
+ mongoc_read_prefs_t *ret = NULL;
+
+ if (read_prefs) {
+ ret = mongoc_read_prefs_new (read_prefs->mode);
+ bson_destroy (&ret->tags);
+ bson_copy_to (&read_prefs->tags, &ret->tags);
+ ret->max_staleness_seconds = read_prefs->max_staleness_seconds;
+ bson_destroy (&ret->hedge);
+ bson_copy_to (&read_prefs->hedge, &ret->hedge);
+ }
+
+ return ret;
+}
+
+
+const char *
+_mongoc_read_mode_as_str (mongoc_read_mode_t mode)
+{
+ switch (mode) {
+ case MONGOC_READ_PRIMARY:
+ return "primary";
+ case MONGOC_READ_PRIMARY_PREFERRED:
+ return "primaryPreferred";
+ case MONGOC_READ_SECONDARY:
+ return "secondary";
+ case MONGOC_READ_SECONDARY_PREFERRED:
+ return "secondaryPreferred";
+ case MONGOC_READ_NEAREST:
+ return "nearest";
+ default:
+ return "";
+ }
+}
+
+
+/* Update result with the read prefs, following Server Selection Spec.
+ * The driver must have discovered the server is a mongos.
+ */
+static void
+_apply_read_preferences_mongos (
+ const mongoc_read_prefs_t *read_prefs,
+ const bson_t *query_bson,
+ mongoc_assemble_query_result_t *result /* OUT */)
+{
+ mongoc_read_mode_t mode;
+ const bson_t *tags = NULL;
+ bson_t child;
+ const char *mode_str;
+ int64_t max_staleness_seconds = MONGOC_NO_MAX_STALENESS;
+ const bson_t *hedge = NULL;
+
+ mode = mongoc_read_prefs_get_mode (read_prefs);
+ if (read_prefs) {
+ max_staleness_seconds =
+ mongoc_read_prefs_get_max_staleness_seconds (read_prefs);
+
+ tags = mongoc_read_prefs_get_tags (read_prefs);
+ hedge = mongoc_read_prefs_get_hedge (read_prefs);
+ }
+
+ /* Server Selection Spec says:
+ *
+ * For mode 'primary', drivers MUST NOT set the secondaryOk wire protocol flag
+ * and MUST NOT use $readPreference
+ *
+ * For mode 'secondary', drivers MUST set the secondaryOk wire protocol flag and
+ * MUST also use $readPreference
+ *
+ * For mode 'primaryPreferred', drivers MUST set the secondaryOk wire protocol
+ * flag and MUST also use $readPreference
+ *
+ * For mode 'secondaryPreferred', drivers MUST set the secondaryOk wire protocol
+ * flag. If the read preference contains a non-empty tag_sets parameter,
+ * maxStalenessSeconds is a positive integer, or the hedge parameter is
+ * non-empty, drivers MUST use $readPreference; otherwise, drivers MUST NOT
+ * use $readPreference
+ *
+ * For mode 'nearest', drivers MUST set the secondaryOk wire protocol flag and
+ * MUST also use $readPreference
+ */
+ if (mode == MONGOC_READ_SECONDARY_PREFERRED &&
+ (bson_empty0 (tags) && max_staleness_seconds <= 0 && bson_empty0 (hedge))) {
+ result->flags |= MONGOC_QUERY_SECONDARY_OK;
+
+ } else if (mode != MONGOC_READ_PRIMARY) {
+ result->flags |= MONGOC_QUERY_SECONDARY_OK;
+
+ /* Server Selection Spec: "When any $ modifier is used, including the
+ * $readPreference modifier, the query MUST be provided using the $query
+ * modifier".
+ *
+ * This applies to commands, too.
+ */
+ result->assembled_query = bson_new ();
+ result->query_owned = true;
+
+ if (bson_has_field (query_bson, "$query")) {
+ bson_concat (result->assembled_query, query_bson);
+ } else {
+ bson_append_document (
+ result->assembled_query, "$query", 6, query_bson);
+ }
+
+ bson_append_document_begin (
+ result->assembled_query, "$readPreference", 15, &child);
+ mode_str = _mongoc_read_mode_as_str (mode);
+ bson_append_utf8 (&child, "mode", 4, mode_str, -1);
+ if (!bson_empty0 (tags)) {
+ bson_append_array (&child, "tags", 4, tags);
+ }
+
+ if (max_staleness_seconds != MONGOC_NO_MAX_STALENESS) {
+ bson_append_int64 (
+ &child, "maxStalenessSeconds", 19, max_staleness_seconds);
+ }
+
+ if (!bson_empty0 (hedge)) {
+ bson_append_document (&child, "hedge", 5, hedge);
+ }
+
+ bson_append_document_end (result->assembled_query, &child);
+ }
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * assemble_query --
+ *
+ * Update @result based on @read_prefs, following the Server Selection
+ * Spec.
+ *
+ * Side effects:
+ * Sets @result->assembled_query and @result->flags.
+ *
+ * Note:
+ * This function, the mongoc_assemble_query_result_t struct, and all
+ * related functions are only used for find operations with OP_QUERY.
+ * Remove them once we have implemented exhaust cursors with OP_MSG in
+ * the server, and all previous server versions are EOL.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+void
+assemble_query (const mongoc_read_prefs_t *read_prefs,
+ const mongoc_server_stream_t *server_stream,
+ const bson_t *query_bson,
+ mongoc_query_flags_t initial_flags,
+ mongoc_assemble_query_result_t *result /* OUT */)
+{
+ mongoc_server_description_type_t server_type;
+
+ ENTRY;
+
+ BSON_ASSERT (server_stream);
+ BSON_ASSERT (query_bson);
+ BSON_ASSERT (result);
+
+ /* default values */
+ result->assembled_query = (bson_t *) query_bson;
+ result->query_owned = false;
+ result->flags = initial_flags;
+
+ server_type = server_stream->sd->type;
+
+ switch (server_stream->topology_type) {
+ case MONGOC_TOPOLOGY_SINGLE:
+ if (server_type == MONGOC_SERVER_MONGOS) {
+ _apply_read_preferences_mongos (read_prefs, query_bson, result);
+ } else {
+ /* Server Selection Spec: for topology type single and server types
+ * besides mongos, "clients MUST always set the secondaryOk wire protocol
+ * flag on reads to ensure that any server type can handle the
+ * request."
+ */
+ result->flags |= MONGOC_QUERY_SECONDARY_OK;
+ }
+
+ break;
+
+ case MONGOC_TOPOLOGY_RS_NO_PRIMARY:
+ case MONGOC_TOPOLOGY_RS_WITH_PRIMARY:
+ /* Server Selection Spec: for RS topology types, "For all read
+ * preferences modes except primary, clients MUST set the secondaryOk wire
+ * protocol flag to ensure that any suitable server can handle the
+ * request. Clients MUST NOT set the secondaryOk wire protocol flag if the
+ * read preference mode is primary.
+ */
+ if (read_prefs && read_prefs->mode != MONGOC_READ_PRIMARY) {
+ result->flags |= MONGOC_QUERY_SECONDARY_OK;
+ }
+
+ break;
+
+ case MONGOC_TOPOLOGY_SHARDED:
+ case MONGOC_TOPOLOGY_LOAD_BALANCED:
+ _apply_read_preferences_mongos (read_prefs, query_bson, result);
+ break;
+
+ case MONGOC_TOPOLOGY_UNKNOWN:
+ case MONGOC_TOPOLOGY_DESCRIPTION_TYPES:
+ default:
+ /* must not call _apply_read_preferences with unknown topology type */
+ BSON_ASSERT (false);
+ }
+
+ EXIT;
+}
+
+
+void
+assemble_query_result_cleanup (mongoc_assemble_query_result_t *result)
+{
+ ENTRY;
+
+ BSON_ASSERT (result);
+
+ if (result->query_owned) {
+ bson_destroy (result->assembled_query);
+ }
+
+ EXIT;
+}
+
+bool
+_mongoc_read_prefs_validate (const mongoc_read_prefs_t *read_prefs,
+ bson_error_t *error)
+{
+ if (read_prefs && !mongoc_read_prefs_is_valid (read_prefs)) {
+ bson_set_error (error,
+ MONGOC_ERROR_COMMAND,
+ MONGOC_ERROR_COMMAND_INVALID_ARG,
+ "Invalid mongoc_read_prefs_t");
+ return false;
+ }
+ return true;
+}
diff --git a/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-read-prefs.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-read-prefs.h
new file mode 100644
index 00000000..c378adbe
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-read-prefs.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2013 MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mongoc-prelude.h"
+
+#ifndef MONGOC_READ_PREFS_H
+#define MONGOC_READ_PREFS_H
+
+#include <bson/bson.h>
+
+#include "mongoc-macros.h"
+#include "mongoc-config.h"
+
+BSON_BEGIN_DECLS
+
+
+#define MONGOC_NO_MAX_STALENESS -1
+#define MONGOC_SMALLEST_MAX_STALENESS_SECONDS 90
+
+typedef struct _mongoc_read_prefs_t mongoc_read_prefs_t;
+
+
+typedef enum {
+ /** Represents $readPreference.mode of 'primary' */
+ MONGOC_READ_PRIMARY = (1 << 0),
+ /** Represents $readPreference.mode of 'secondary' */
+ MONGOC_READ_SECONDARY = (1 << 1),
+ /** Represents $readPreference.mode of 'primaryPreferred' */
+ MONGOC_READ_PRIMARY_PREFERRED = (1 << 2) | MONGOC_READ_PRIMARY,
+ /** Represents $readPreference.mode of 'secondaryPreferred' */
+ MONGOC_READ_SECONDARY_PREFERRED = (1 << 2) | MONGOC_READ_SECONDARY,
+ /** Represents $readPreference.mode of 'nearest' */
+ MONGOC_READ_NEAREST = (1 << 3) | MONGOC_READ_SECONDARY,
+} mongoc_read_mode_t;
+
+
+MONGOC_EXPORT (mongoc_read_prefs_t *)
+mongoc_read_prefs_new (mongoc_read_mode_t read_mode)
+ BSON_GNUC_WARN_UNUSED_RESULT;
+MONGOC_EXPORT (mongoc_read_prefs_t *)
+mongoc_read_prefs_copy (const mongoc_read_prefs_t *read_prefs)
+ BSON_GNUC_WARN_UNUSED_RESULT;
+MONGOC_EXPORT (void)
+mongoc_read_prefs_destroy (mongoc_read_prefs_t *read_prefs);
+MONGOC_EXPORT (mongoc_read_mode_t)
+mongoc_read_prefs_get_mode (const mongoc_read_prefs_t *read_prefs);
+MONGOC_EXPORT (void)
+mongoc_read_prefs_set_mode (mongoc_read_prefs_t *read_prefs,
+ mongoc_read_mode_t mode);
+MONGOC_EXPORT (const bson_t *)
+mongoc_read_prefs_get_tags (const mongoc_read_prefs_t *read_prefs);
+MONGOC_EXPORT (void)
+mongoc_read_prefs_set_tags (mongoc_read_prefs_t *read_prefs,
+ const bson_t *tags);
+MONGOC_EXPORT (void)
+mongoc_read_prefs_add_tag (mongoc_read_prefs_t *read_prefs, const bson_t *tag);
+MONGOC_EXPORT (int64_t)
+mongoc_read_prefs_get_max_staleness_seconds (
+ const mongoc_read_prefs_t *read_prefs);
+MONGOC_EXPORT (void)
+mongoc_read_prefs_set_max_staleness_seconds (mongoc_read_prefs_t *read_prefs,
+ int64_t max_staleness_seconds);
+MONGOC_EXPORT (const bson_t *)
+mongoc_read_prefs_get_hedge (const mongoc_read_prefs_t *read_prefs);
+MONGOC_EXPORT (void)
+mongoc_read_prefs_set_hedge (mongoc_read_prefs_t *read_prefs,
+ const bson_t *hedge);
+MONGOC_EXPORT (bool)
+mongoc_read_prefs_is_valid (const mongoc_read_prefs_t *read_prefs);
+
+
+BSON_END_DECLS
+
+
+#endif /* MONGOC_READ_PREFS_H */
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-rpc-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-rpc-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-rpc-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-rpc-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-rpc.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-rpc.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-rpc.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-rpc.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-sasl-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-sasl-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-sasl-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-sasl-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-sasl.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-sasl.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-sasl.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-sasl.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-scram-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-scram-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-scram-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-scram-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-scram.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-scram.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-scram.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-scram.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-secure-channel-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-secure-channel-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-secure-channel-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-secure-channel-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-secure-channel.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-secure-channel.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-secure-channel.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-secure-channel.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-secure-transport-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-secure-transport-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-secure-transport-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-secure-transport-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-secure-transport.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-secure-transport.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-secure-transport.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-secure-transport.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-api-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-api-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-api-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-api-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-api.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-api.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-api.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-api.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-api.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-api.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-api.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-api.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-description-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-description-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-description-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-description-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-description.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-description.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-description.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-description.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-description.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-description.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-description.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-description.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-monitor-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-monitor-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-monitor-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-monitor-private.h
diff --git a/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-monitor.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-monitor.c
new file mode 100644
index 00000000..69a7dc2c
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-monitor.c
@@ -0,0 +1,1273 @@
+/*
+ * Copyright 2020-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "common-thread-private.h"
+#include "mongoc-server-monitor-private.h"
+
+#include "mongoc/mongoc-client-private.h"
+#include "mongoc/mongoc-error-private.h"
+#include "mongoc/mongoc-flags-private.h"
+#include "mongoc/mongoc-ssl-private.h"
+#include "mongoc/mongoc-stream-private.h"
+#include "mongoc/mongoc-topology-background-monitoring-private.h"
+#include "mongoc/mongoc-topology-private.h"
+#include "mongoc/mongoc-trace-private.h"
+
+#undef MONGOC_LOG_DOMAIN
+#define MONGOC_LOG_DOMAIN "monitor"
+
+typedef enum {
+ MONGOC_THREAD_OFF = 0,
+ MONGOC_THREAD_RUNNING,
+ MONGOC_THREAD_SHUTTING_DOWN,
+ MONGOC_THREAD_JOINABLE
+} thread_state_t;
+
+/* Use a signed and wide return type for timeouts as long as you can. Cast only
+ * when you know what you're doing with it. */
+static int64_t
+_now_us (void)
+{
+ return bson_get_monotonic_time ();
+}
+
+static int64_t
+_now_ms (void)
+{
+ return _now_us () / 1000;
+}
+
+struct _mongoc_server_monitor_t {
+ mongoc_topology_t *topology;
+ bson_thread_t thread;
+
+ /* State accessed from multiple threads. */
+ struct {
+ bson_mutex_t mutex;
+ mongoc_cond_t cond;
+ thread_state_t state;
+ bool scan_requested;
+ bool cancel_requested;
+ } shared;
+
+ /* Default time to sleep between hello checks (reduced when a scan is
+ * requested) */
+ uint64_t heartbeat_frequency_ms;
+ /* The minimum time to sleep between hello checks. */
+ uint64_t min_heartbeat_frequency_ms;
+ int64_t connect_timeout_ms;
+ bool use_tls;
+#ifdef MONGOC_ENABLE_SSL
+ mongoc_ssl_opt_t *ssl_opts;
+#endif
+ mongoc_uri_t *uri;
+ /* A custom initiator may be set if a user provides overrides to create a
+ * stream. */
+ mongoc_stream_initiator_t initiator;
+ void *initiator_context;
+ int64_t request_id;
+ mongoc_apm_callbacks_t apm_callbacks;
+ void *apm_context;
+
+ mongoc_stream_t *stream;
+ bool more_to_come;
+ mongoc_server_description_t *description;
+ uint32_t server_id;
+ bool is_rtt;
+};
+
+static BSON_GNUC_PRINTF (3, 4) void _server_monitor_log (
+ mongoc_server_monitor_t *server_monitor,
+ mongoc_log_level_t level,
+ const char *format,
+ ...)
+{
+ va_list ap;
+ char *msg;
+
+ va_start (ap, format);
+ msg = bson_strdupv_printf (format, ap);
+ va_end (ap);
+
+ mongoc_log (level,
+ MONGOC_LOG_DOMAIN,
+ "[%s%s] %s",
+ server_monitor->description->host.host_and_port,
+ server_monitor->is_rtt ? "-RTT" : "",
+ msg);
+ bson_free (msg);
+}
+
+#define MONITOR_LOG(sm, ...) \
+ do { \
+ if (MONGOC_TRACE_ENABLED) { \
+ _server_monitor_log (sm, MONGOC_LOG_LEVEL_TRACE, __VA_ARGS__); \
+ } \
+ } while (0)
+
+/* TODO CDRIVER-3710 use MONGOC_LOG_LEVEL_ERROR */
+#define MONITOR_LOG_ERROR(sm, ...) \
+ _server_monitor_log (sm, MONGOC_LOG_LEVEL_DEBUG, __VA_ARGS__)
+/* TODO CDRIVER-3710 use MONGOC_LOG_LEVEL_WARNING */
+#define MONITOR_LOG_WARNING(sm, ...) \
+ _server_monitor_log (sm, MONGOC_LOG_LEVEL_DEBUG, __VA_ARGS__)
+
+static void
+_server_monitor_heartbeat_started (mongoc_server_monitor_t *server_monitor,
+ bool awaited)
+{
+ mongoc_apm_server_heartbeat_started_t event;
+ MONGOC_DEBUG_ASSERT (
+ !COMMON_PREFIX (mutex_is_locked) (&server_monitor->topology->apm_mutex));
+
+ if (!server_monitor->apm_callbacks.server_heartbeat_started) {
+ return;
+ }
+
+ event.host = &server_monitor->description->host;
+ event.context = server_monitor->apm_context;
+ MONITOR_LOG (server_monitor,
+ "%s heartbeat started",
+ awaited ? "awaitable" : "regular");
+ event.awaited = awaited;
+ bson_mutex_lock (&server_monitor->topology->apm_mutex);
+ server_monitor->apm_callbacks.server_heartbeat_started (&event);
+ bson_mutex_unlock (&server_monitor->topology->apm_mutex);
+}
+
+static void
+_server_monitor_heartbeat_succeeded (mongoc_server_monitor_t *server_monitor,
+ const bson_t *reply,
+ int64_t duration_usec,
+ bool awaited)
+{
+ mongoc_apm_server_heartbeat_succeeded_t event;
+
+ if (!server_monitor->apm_callbacks.server_heartbeat_succeeded) {
+ return;
+ }
+
+ event.host = &server_monitor->description->host;
+ event.context = server_monitor->apm_context;
+ event.reply = reply;
+ event.duration_usec = duration_usec;
+ MONITOR_LOG (server_monitor,
+ "%s heartbeat succeeded",
+ awaited ? "awaitable" : "regular");
+ event.awaited = awaited;
+ bson_mutex_lock (&server_monitor->topology->apm_mutex);
+ server_monitor->apm_callbacks.server_heartbeat_succeeded (&event);
+ bson_mutex_unlock (&server_monitor->topology->apm_mutex);
+}
+
+static void
+_server_monitor_heartbeat_failed (mongoc_server_monitor_t *server_monitor,
+ const bson_error_t *error,
+ int64_t duration_usec,
+ bool awaited)
+{
+ mongoc_apm_server_heartbeat_failed_t event;
+
+ if (!server_monitor->apm_callbacks.server_heartbeat_failed) {
+ return;
+ }
+
+ event.host = &server_monitor->description->host;
+ event.context = server_monitor->apm_context;
+ event.error = error;
+ event.duration_usec = duration_usec;
+ MONITOR_LOG (
+ server_monitor, "%s heartbeat failed", awaited ? "awaitable" : "regular");
+ event.awaited = awaited;
+ bson_mutex_lock (&server_monitor->topology->apm_mutex);
+ server_monitor->apm_callbacks.server_heartbeat_failed (&event);
+ bson_mutex_unlock (&server_monitor->topology->apm_mutex);
+}
+
+static void
+_server_monitor_append_cluster_time (mongoc_server_monitor_t *server_monitor,
+ bson_t *cmd)
+{
+ mc_shared_tpld td =
+ mc_tpld_take_ref (BSON_ASSERT_PTR_INLINE (server_monitor)->topology);
+
+ /* Cluster time is updated on every reply. */
+ if (!bson_empty (&td.ptr->cluster_time)) {
+ bson_append_document (cmd, "$clusterTime", 12, &td.ptr->cluster_time);
+ }
+ mc_tpld_drop_ref (&td);
+}
+
+static bool
+_server_monitor_send_and_recv_opquery (mongoc_server_monitor_t *server_monitor,
+ const bson_t *cmd,
+ bson_t *reply,
+ bson_error_t *error)
+{
+ mongoc_rpc_t rpc;
+ mongoc_array_t array_to_write;
+ mongoc_iovec_t *iovec;
+ int niovec;
+ mongoc_buffer_t buffer;
+ uint32_t reply_len;
+ bson_t temp_reply;
+ bool ret = false;
+
+ rpc.header.msg_len = 0;
+ rpc.header.request_id = server_monitor->request_id++;
+ rpc.header.response_to = 0;
+ rpc.header.opcode = MONGOC_OPCODE_QUERY;
+ rpc.query.flags = MONGOC_QUERY_SECONDARY_OK;
+ rpc.query.collection = "admin.$cmd";
+ rpc.query.skip = 0;
+ rpc.query.n_return = -1;
+ rpc.query.query = bson_get_data (cmd);
+ rpc.query.fields = NULL;
+
+ _mongoc_buffer_init (&buffer, NULL, 0, NULL, NULL);
+ _mongoc_array_init (&array_to_write, sizeof (mongoc_iovec_t));
+ _mongoc_rpc_gather (&rpc, &array_to_write);
+ iovec = (mongoc_iovec_t *) array_to_write.data;
+ niovec = array_to_write.len;
+ _mongoc_rpc_swab_to_le (&rpc);
+
+ if (!_mongoc_stream_writev_full (server_monitor->stream,
+ iovec,
+ niovec,
+ server_monitor->connect_timeout_ms,
+ error)) {
+ GOTO (fail);
+ }
+
+ if (!_mongoc_buffer_append_from_stream (&buffer,
+ server_monitor->stream,
+ 4,
+ server_monitor->connect_timeout_ms,
+ error)) {
+ GOTO (fail);
+ }
+
+ memcpy (&reply_len, buffer.data, 4);
+ reply_len = BSON_UINT32_FROM_LE (reply_len);
+
+ if (!_mongoc_buffer_append_from_stream (&buffer,
+ server_monitor->stream,
+ reply_len - buffer.len,
+ server_monitor->connect_timeout_ms,
+ error)) {
+ GOTO (fail);
+ }
+
+ if (!_mongoc_rpc_scatter (&rpc, buffer.data, buffer.len)) {
+ bson_set_error (error,
+ MONGOC_ERROR_PROTOCOL,
+ MONGOC_ERROR_PROTOCOL_INVALID_REPLY,
+ "Invalid reply from server.");
+
+ GOTO (fail);
+ }
+
+ if (!_mongoc_rpc_decompress_if_necessary (&rpc, &buffer, error)) {
+ GOTO (fail);
+ }
+ _mongoc_rpc_swab_from_le (&rpc);
+
+ if (!_mongoc_rpc_get_first_document (&rpc, &temp_reply)) {
+ bson_set_error (error,
+ MONGOC_ERROR_PROTOCOL,
+ MONGOC_ERROR_PROTOCOL_INVALID_REPLY,
+ "Invalid reply from server");
+ GOTO (fail);
+ }
+ bson_copy_to (&temp_reply, reply);
+
+ ret = true;
+fail:
+ if (!ret) {
+ bson_init (reply);
+ }
+ _mongoc_array_destroy (&array_to_write);
+ _mongoc_buffer_destroy (&buffer);
+ return ret;
+}
+
+static bool
+_server_monitor_polling_hello (mongoc_server_monitor_t *server_monitor,
+ bool hello_ok,
+ bson_t *hello_response,
+ bson_error_t *error)
+{
+ bson_t cmd;
+ const bson_t *hello;
+ bool ret;
+
+ hello = _mongoc_topology_scanner_get_monitoring_cmd (
+ server_monitor->topology->scanner, hello_ok);
+ bson_copy_to (hello, &cmd);
+
+ _server_monitor_append_cluster_time (server_monitor, &cmd);
+ ret = _server_monitor_send_and_recv_opquery (
+ server_monitor, &cmd, hello_response, error);
+ bson_destroy (&cmd);
+ return ret;
+}
+
+static bool
+_server_monitor_awaitable_hello_send (mongoc_server_monitor_t *server_monitor,
+ bson_t *cmd,
+ bson_error_t *error)
+{
+ mongoc_rpc_t rpc = {0};
+ mongoc_array_t array_to_write;
+ mongoc_iovec_t *iovec;
+ int niovec;
+
+ rpc.header.msg_len = 0;
+ rpc.header.request_id = server_monitor->request_id++;
+ rpc.header.response_to = 0;
+ rpc.header.opcode = MONGOC_OPCODE_MSG;
+ rpc.msg.flags = MONGOC_MSG_EXHAUST_ALLOWED;
+ rpc.msg.n_sections = 1;
+ rpc.msg.sections[0].payload_type = 0;
+ rpc.msg.sections[0].payload.bson_document = bson_get_data (cmd);
+
+ _mongoc_array_init (&array_to_write, sizeof (mongoc_iovec_t));
+ _mongoc_rpc_gather (&rpc, &array_to_write);
+
+ iovec = (mongoc_iovec_t *) array_to_write.data;
+ niovec = array_to_write.len;
+ _mongoc_rpc_swab_to_le (&rpc);
+
+ MONITOR_LOG (server_monitor,
+ "sending with timeout %" PRId64,
+ server_monitor->connect_timeout_ms);
+
+ if (!_mongoc_stream_writev_full (server_monitor->stream,
+ iovec,
+ niovec,
+ server_monitor->connect_timeout_ms,
+ error)) {
+ MONITOR_LOG_ERROR (
+ server_monitor, "failed to write awaitable hello: %s", error->message);
+ _mongoc_array_destroy (&array_to_write);
+ return false;
+ }
+ _mongoc_array_destroy (&array_to_write);
+ return true;
+}
+
+/* Poll the server monitor stream for reading. Allows cancellation.
+ *
+ * Called only from server monitor thread.
+ * Locks server monitor mutex.
+ * Returns true if stream is readable. False on error or cancellation.
+ * On cancellation, no error is set, but cancelled is set to true.
+ */
+static bool
+_server_monitor_poll_with_interrupt (mongoc_server_monitor_t *server_monitor,
+ int64_t expire_at_ms,
+ bool *cancelled,
+ bson_error_t *error)
+{
+ /* How many milliseconds we should poll for on each tick.
+ * On every tick, check whether the awaitable hello was cancelled. */
+ const int32_t monitor_tick_ms = MONGOC_TOPOLOGY_MIN_HEARTBEAT_FREQUENCY_MS;
+ int64_t timeleft_ms;
+
+ while ((timeleft_ms = expire_at_ms - _now_ms ()) > 0) {
+ ssize_t ret;
+ mongoc_stream_poll_t poller[1];
+
+ MONITOR_LOG (server_monitor,
+ "_server_monitor_poll_with_interrupt expires in: %" PRIu64
+ "ms",
+ timeleft_ms);
+ poller[0].stream = server_monitor->stream;
+ poller[0].events =
+ POLLIN; /* POLLERR and POLLHUP are added in mongoc_socket_poll. */
+ poller[0].revents = 0;
+
+ MONITOR_LOG (
+ server_monitor,
+ "polling for awaitable hello reply with timeleft_ms: %" PRId64,
+ timeleft_ms);
+ ret = mongoc_stream_poll (
+ poller, 1, (int32_t) BSON_MIN (timeleft_ms, monitor_tick_ms));
+ if (ret == -1) {
+ MONITOR_LOG (server_monitor, "mongoc_stream_poll error");
+ bson_set_error (error,
+ MONGOC_ERROR_STREAM,
+ MONGOC_ERROR_STREAM_SOCKET,
+ "poll error");
+ return false;
+ }
+
+ if (poller[0].revents & (POLLERR | POLLHUP)) {
+ bson_set_error (error,
+ MONGOC_ERROR_STREAM,
+ MONGOC_ERROR_STREAM_SOCKET,
+ "connection closed while polling");
+ return false;
+ }
+
+ /* Check for cancellation. */
+ bson_mutex_lock (&server_monitor->shared.mutex);
+ *cancelled = server_monitor->shared.cancel_requested;
+ server_monitor->shared.cancel_requested = false;
+ bson_mutex_unlock (&server_monitor->shared.mutex);
+
+ if (*cancelled) {
+ MONITOR_LOG (server_monitor, "polling cancelled");
+ return false;
+ }
+
+ if (poller[0].revents & POLLIN) {
+ MONITOR_LOG (server_monitor, "mongoc_stream_poll ready to read");
+ return true;
+ }
+ }
+ bson_set_error (error,
+ MONGOC_ERROR_STREAM,
+ MONGOC_ERROR_STREAM_SOCKET,
+ "connection timeout while polling");
+ return false;
+}
+
+/* Calculate the timeout between the current time and an absolute expiration
+ * time in milliseconds.
+ *
+ * Returns 0 and sets error if time expired.
+ */
+int64_t
+_get_timeout_ms (int64_t expire_at_ms, bson_error_t *error)
+{
+ int64_t timeout_ms;
+
+ timeout_ms = expire_at_ms - _now_ms ();
+ if (timeout_ms <= 0) {
+ bson_set_error (error,
+ MONGOC_ERROR_STREAM,
+ MONGOC_ERROR_STREAM_SOCKET,
+ "connection timed out reading message length");
+ return 0;
+ }
+ return timeout_ms;
+}
+
+/* Receive an awaitable hello reply.
+ *
+ * May be used to receive additional replies when moreToCome is set.
+ * Called only from server monitor thread.
+ * May lock server monitor mutex in functions that are called.
+ * May block for up to heartbeatFrequencyMS + connectTimeoutMS waiting for
+ * reply.
+ * Returns true if a reply was received. False on error or cancellation.
+ * On cancellation, no error is set, but cancelled is set to true.
+ */
+static bool
+_server_monitor_awaitable_hello_recv (mongoc_server_monitor_t *server_monitor,
+ bson_t *hello_response,
+ bool *cancelled,
+ bson_error_t *error)
+{
+ bool ret = false;
+ mongoc_buffer_t buffer;
+ int32_t msg_len;
+ mongoc_rpc_t rpc;
+ bson_t reply_local;
+ int64_t expire_at_ms;
+ int64_t timeout_ms;
+
+ expire_at_ms = _now_ms () + server_monitor->heartbeat_frequency_ms +
+ server_monitor->connect_timeout_ms;
+ _mongoc_buffer_init (&buffer, NULL, 0, NULL, NULL);
+ if (!_server_monitor_poll_with_interrupt (
+ server_monitor, expire_at_ms, cancelled, error)) {
+ GOTO (fail);
+ }
+
+ timeout_ms = _get_timeout_ms (expire_at_ms, error);
+ if (!timeout_ms) {
+ GOTO (fail);
+ }
+ MONITOR_LOG (server_monitor,
+ "reading first 4 bytes with timeout: %" PRId64,
+ timeout_ms);
+ if (!_mongoc_buffer_append_from_stream (
+ &buffer, server_monitor->stream, 4, (int32_t) timeout_ms, error)) {
+ GOTO (fail);
+ }
+
+ BSON_ASSERT (buffer.len == 4);
+ memcpy (&msg_len, buffer.data, 4);
+ msg_len = BSON_UINT32_FROM_LE (msg_len);
+
+ if ((msg_len < 16) ||
+ (msg_len > server_monitor->description->max_msg_size)) {
+ bson_set_error (
+ error,
+ MONGOC_ERROR_PROTOCOL,
+ MONGOC_ERROR_PROTOCOL_INVALID_REPLY,
+ "Message size %d is not within expected range 16-%d bytes",
+ msg_len,
+ server_monitor->description->max_msg_size);
+ GOTO (fail);
+ }
+
+ timeout_ms = _get_timeout_ms (expire_at_ms, error);
+ if (!timeout_ms) {
+ GOTO (fail);
+ }
+ MONITOR_LOG (server_monitor,
+ "reading remaining %d bytes. Timeout %" PRId64,
+ (int) (msg_len - 4),
+ timeout_ms);
+ if (!_mongoc_buffer_append_from_stream (
+ &buffer, server_monitor->stream, msg_len - 4, timeout_ms, error)) {
+ GOTO (fail);
+ }
+
+ if (!_mongoc_rpc_scatter (&rpc, buffer.data, buffer.len)) {
+ bson_set_error (error,
+ MONGOC_ERROR_PROTOCOL,
+ MONGOC_ERROR_PROTOCOL_INVALID_REPLY,
+ "Malformed message from server");
+ GOTO (fail);
+ }
+
+ if (!_mongoc_rpc_decompress_if_necessary (&rpc, &buffer, error)) {
+ GOTO (fail);
+ }
+
+ _mongoc_rpc_swab_from_le (&rpc);
+ memcpy (&msg_len, rpc.msg.sections[0].payload.bson_document, 4);
+ msg_len = BSON_UINT32_FROM_LE (msg_len);
+ if (!bson_init_static (
+ &reply_local, rpc.msg.sections[0].payload.bson_document, msg_len)) {
+ bson_set_error (error,
+ MONGOC_ERROR_PROTOCOL,
+ MONGOC_ERROR_PROTOCOL_INVALID_REPLY,
+ "Malformed BSON payload from server");
+ GOTO (fail);
+ }
+
+ bson_copy_to (&reply_local, hello_response);
+ server_monitor->more_to_come =
+ (rpc.msg.flags & MONGOC_MSG_MORE_TO_COME) != 0;
+
+ ret = true;
+fail:
+ if (!ret) {
+ bson_init (hello_response);
+ }
+ _mongoc_buffer_destroy (&buffer);
+ return ret;
+}
+
+/* Send and receive an awaitable hello.
+ *
+ * Called only from server monitor thread.
+ * May lock server monitor mutex in functions that are called.
+ * May block for up to heartbeatFrequencyMS waiting for reply.
+ */
+static bool
+_server_monitor_awaitable_hello (mongoc_server_monitor_t *server_monitor,
+ const mongoc_server_description_t *description,
+ bson_t *hello_response,
+ bool *cancelled,
+ bson_error_t *error)
+{
+ bson_t cmd;
+ const bson_t *hello;
+ bool ret = false;
+
+ hello = _mongoc_topology_scanner_get_monitoring_cmd (
+ server_monitor->topology->scanner, description->hello_ok);
+ bson_copy_to (hello, &cmd);
+
+ _server_monitor_append_cluster_time (server_monitor, &cmd);
+ bson_append_document (
+ &cmd, "topologyVersion", 15, &description->topology_version);
+ bson_append_int32 (
+ &cmd, "maxAwaitTimeMS", 14, server_monitor->heartbeat_frequency_ms);
+ bson_append_utf8 (&cmd, "$db", 3, "admin", 5);
+
+ if (!_server_monitor_awaitable_hello_send (server_monitor, &cmd, error)) {
+ GOTO (fail);
+ }
+
+ if (!_server_monitor_awaitable_hello_recv (
+ server_monitor, hello_response, cancelled, error)) {
+ bson_destroy (hello_response);
+ GOTO (fail);
+ }
+
+ ret = true;
+fail:
+ if (!ret) {
+ bson_init (hello_response);
+ }
+ bson_destroy (&cmd);
+ return ret;
+}
+
+/* Update the topology description with a reply or an error.
+ *
+ * Called only from server monitor thread.
+ * Caller must hold no locks.
+ * Locks server monitor mutex.
+ */
+static void
+_update_topology_description (mongoc_server_monitor_t *server_monitor,
+ mongoc_server_description_t *description)
+{
+ mongoc_topology_t *topology;
+ bson_t *hello_response = NULL;
+ mc_tpld_modification tdmod;
+
+ topology = server_monitor->topology;
+ if (description->has_hello_response) {
+ hello_response = &description->last_hello_response;
+ }
+
+ if (hello_response) {
+ _mongoc_topology_update_cluster_time (topology, hello_response);
+ }
+
+ if (bson_atomic_int_fetch (&topology->scanner_state,
+ bson_memory_order_relaxed) ==
+ MONGOC_TOPOLOGY_SCANNER_SHUTTING_DOWN) {
+ return;
+ }
+
+ tdmod = mc_tpld_modify_begin (topology);
+ bson_mutex_lock (&server_monitor->shared.mutex);
+ server_monitor->shared.scan_requested = false;
+ bson_mutex_unlock (&server_monitor->shared.mutex);
+ mongoc_topology_description_handle_hello (tdmod.new_td,
+ server_monitor->server_id,
+ hello_response,
+ description->round_trip_time_msec,
+ &description->error);
+ /* Reconcile server monitors. */
+ _mongoc_topology_background_monitoring_reconcile (topology, tdmod.new_td);
+ /* Wake threads performing server selection. */
+ mongoc_cond_broadcast (&server_monitor->topology->cond_client);
+ mc_tpld_modify_commit (tdmod);
+}
+
+/* Create a new server monitor.
+ *
+ * Called during reconcile.
+ * Caller must hold topology lock.
+ */
+mongoc_server_monitor_t *
+mongoc_server_monitor_new (mongoc_topology_t *topology,
+ mongoc_topology_description_t *td,
+ mongoc_server_description_t *init_description)
+{
+ mongoc_server_monitor_t *server_monitor =
+ bson_malloc0 (sizeof (*server_monitor));
+ server_monitor->description =
+ mongoc_server_description_new_copy (init_description);
+ server_monitor->server_id = init_description->id;
+ server_monitor->topology = topology;
+ server_monitor->heartbeat_frequency_ms = td->heartbeat_msec;
+ server_monitor->min_heartbeat_frequency_ms =
+ topology->min_heartbeat_frequency_msec;
+ server_monitor->connect_timeout_ms = topology->connect_timeout_msec;
+ server_monitor->uri = mongoc_uri_copy (topology->uri);
+/* TODO CDRIVER-3682: Do not retrieve ssl opts from topology scanner. They
+ * should be stored somewhere else. */
+#ifdef MONGOC_ENABLE_SSL
+ if (topology->scanner->ssl_opts) {
+ server_monitor->ssl_opts = bson_malloc0 (sizeof (mongoc_ssl_opt_t));
+
+ _mongoc_ssl_opts_copy_to (
+ topology->scanner->ssl_opts, server_monitor->ssl_opts, true);
+ }
+#endif
+ memcpy (&server_monitor->apm_callbacks,
+ &td->apm_callbacks,
+ sizeof (mongoc_apm_callbacks_t));
+ server_monitor->apm_context = td->apm_context;
+ server_monitor->initiator = topology->scanner->initiator;
+ server_monitor->initiator_context = topology->scanner->initiator_context;
+ mongoc_cond_init (&server_monitor->shared.cond);
+ bson_mutex_init (&server_monitor->shared.mutex);
+ return server_monitor;
+}
+
+/* Creates a stream and performs the initial hello handshake.
+ *
+ * Called only by server monitor thread.
+ * Returns true if both connection and handshake succeeds.
+ * Returns false and sets error otherwise.
+ * hello_response is always initialized.
+ */
+static bool
+_server_monitor_setup_connection (mongoc_server_monitor_t *server_monitor,
+ bson_t *hello_response,
+ int64_t *start_us,
+ bson_error_t *error)
+{
+ bson_t cmd = BSON_INITIALIZER;
+ bool ret = false;
+
+ ENTRY;
+
+ BSON_ASSERT (!server_monitor->stream);
+ bson_init (hello_response);
+
+ server_monitor->more_to_come = false;
+
+ /* Using an initiator isn't really necessary. Users can't set them on
+ * pools. But it is used for tests. */
+ if (server_monitor->initiator) {
+ server_monitor->stream =
+ server_monitor->initiator (server_monitor->uri,
+ &server_monitor->description->host,
+ server_monitor->initiator_context,
+ error);
+ } else {
+ void *ssl_opts_void = NULL;
+
+#ifdef MONGOC_ENABLE_SSL
+ ssl_opts_void = server_monitor->ssl_opts;
+#endif
+ server_monitor->stream =
+ mongoc_client_connect (false,
+ ssl_opts_void != NULL,
+ ssl_opts_void,
+ server_monitor->uri,
+ &server_monitor->description->host,
+ error);
+ }
+
+ if (!server_monitor->stream) {
+ GOTO (fail);
+ }
+
+ /* Update the start time just before the handshake. */
+ *start_us = _now_us ();
+ /* Perform handshake. */
+ bson_destroy (&cmd);
+ _mongoc_topology_dup_handshake_cmd (server_monitor->topology, &cmd);
+ _server_monitor_append_cluster_time (server_monitor, &cmd);
+ bson_destroy (hello_response);
+ if (!_server_monitor_send_and_recv_opquery (
+ server_monitor, &cmd, hello_response, error)) {
+ GOTO (fail);
+ }
+
+ ret = true;
+fail:
+ bson_destroy (&cmd);
+ RETURN (ret);
+}
+
+/**
+ * @brief Perform a hello check on a server
+ *
+ * @param server_monitor The server monitor for this server.
+ * @param previous_description The most recent view of the description of this
+ * server.
+ * @param cancelled Output parameter: Whether the monitor check is cancelled.
+ * @return mongoc_server_description_t* The newly created updated server
+ * description.
+ *
+ * @note May update the topology description associated with the server monitor.
+ *
+ * @note In case of error, returns a new server description with the error
+ * information, but with no hello reply.
+ */
+static mongoc_server_description_t *
+_server_monitor_check_server (
+ mongoc_server_monitor_t *server_monitor,
+ const mongoc_server_description_t *previous_description,
+ bool *cancelled)
+{
+ bool ret = false;
+ bson_error_t error;
+ bson_t hello_response;
+ int64_t duration_us;
+ int64_t start_us;
+ bool command_or_network_error = false;
+ bool awaited = false;
+ mongoc_server_description_t *description;
+ mc_tpld_modification tdmod;
+
+ ENTRY;
+
+ *cancelled = false;
+ memset (&error, 0, sizeof (bson_error_t));
+ description = bson_malloc0 (sizeof (mongoc_server_description_t));
+ mongoc_server_description_init (
+ description,
+ server_monitor->description->connection_address,
+ server_monitor->description->id);
+ start_us = _now_us ();
+
+ if (!server_monitor->stream) {
+ MONITOR_LOG (server_monitor, "setting up connection");
+ awaited = false;
+ _server_monitor_heartbeat_started (server_monitor, awaited);
+ ret = _server_monitor_setup_connection (
+ server_monitor, &hello_response, &start_us, &error);
+ GOTO (exit);
+ }
+
+ if (server_monitor->more_to_come) {
+ awaited = true;
+ /* Publish a heartbeat started for each additional response read. */
+ _server_monitor_heartbeat_started (server_monitor, awaited);
+ MONITOR_LOG (server_monitor, "more to come");
+ ret = _server_monitor_awaitable_hello_recv (
+ server_monitor, &hello_response, cancelled, &error);
+ GOTO (exit);
+ }
+
+ if (!bson_empty (&previous_description->topology_version)) {
+ awaited = true;
+ _server_monitor_heartbeat_started (server_monitor, awaited);
+ MONITOR_LOG (server_monitor, "awaitable hello");
+ ret = _server_monitor_awaitable_hello (server_monitor,
+ previous_description,
+ &hello_response,
+ cancelled,
+ &error);
+ GOTO (exit);
+ }
+
+ MONITOR_LOG (server_monitor, "polling hello");
+ awaited = false;
+ _server_monitor_heartbeat_started (server_monitor, awaited);
+ ret = _server_monitor_polling_hello (
+ server_monitor, previous_description->hello_ok, &hello_response, &error);
+
+exit:
+ duration_us = _now_us () - start_us;
+ MONITOR_LOG (
+ server_monitor, "server check duration (us): %" PRId64, duration_us);
+
+ /* If ret is true, we have a reply. Check if "ok": 1. */
+ if (ret && _mongoc_cmd_check_ok (
+ &hello_response, MONGOC_ERROR_API_VERSION_2, &error)) {
+ int64_t rtt_ms = MONGOC_RTT_UNSET;
+
+ /* rtt remains MONGOC_RTT_UNSET if awaited. */
+ if (!awaited) {
+ rtt_ms = duration_us / 1000;
+ }
+
+ mongoc_server_description_handle_hello (
+ description, &hello_response, rtt_ms, NULL);
+ /* If the hello reply could not be parsed, consider this a command
+ * error. */
+ if (description->error.code) {
+ MONITOR_LOG_ERROR (server_monitor,
+ "error parsing server reply: %s",
+ description->error.message);
+ command_or_network_error = true;
+ _server_monitor_heartbeat_failed (
+ server_monitor, &description->error, duration_us, awaited);
+ } else {
+ _server_monitor_heartbeat_succeeded (
+ server_monitor, &hello_response, duration_us, awaited);
+ }
+ } else if (*cancelled) {
+ MONITOR_LOG (server_monitor, "server monitor cancelled");
+ if (server_monitor->stream) {
+ mongoc_stream_destroy (server_monitor->stream);
+ }
+ server_monitor->stream = NULL;
+ server_monitor->more_to_come = false;
+ _server_monitor_heartbeat_failed (
+ server_monitor, &description->error, duration_us, awaited);
+ } else {
+ /* The hello reply had "ok":0 or a network error occurred. */
+ MONITOR_LOG_ERROR (server_monitor,
+ "command or network error occurred: %s",
+ error.message);
+ command_or_network_error = true;
+ mongoc_server_description_handle_hello (
+ description, NULL, MONGOC_RTT_UNSET, &error);
+ _server_monitor_heartbeat_failed (
+ server_monitor, &description->error, duration_us, awaited);
+ }
+
+ if (command_or_network_error) {
+ if (server_monitor->stream) {
+ mongoc_stream_failed (server_monitor->stream);
+ }
+ server_monitor->stream = NULL;
+ server_monitor->more_to_come = false;
+ tdmod = mc_tpld_modify_begin (server_monitor->topology);
+ /* clear_connection_pool() is a no-op if 'description->id' was already
+ * removed. */
+ _mongoc_topology_description_clear_connection_pool (
+ tdmod.new_td,
+ server_monitor->description->id,
+ &server_monitor->description->service_id);
+ mc_tpld_modify_commit (tdmod);
+ }
+
+ bson_destroy (&hello_response);
+ return description;
+}
+
+/* Request scan of a single server.
+ *
+ * Locks server monitor mutex to deliver scan_requested.
+ */
+void
+mongoc_server_monitor_request_scan (mongoc_server_monitor_t *server_monitor)
+{
+ MONITOR_LOG (server_monitor, "requesting scan");
+ bson_mutex_lock (&server_monitor->shared.mutex);
+ server_monitor->shared.scan_requested = true;
+ mongoc_cond_signal (&server_monitor->shared.cond);
+ bson_mutex_unlock (&server_monitor->shared.mutex);
+}
+
+/* Request cancellation of an in progress awaitable hello.
+ *
+ * Called from app threads on network errors and during shutdown.
+ * Locks server monitor mutex.
+ */
+void
+mongoc_server_monitor_request_cancel (mongoc_server_monitor_t *server_monitor)
+{
+ MONITOR_LOG (server_monitor, "requesting cancel");
+ bson_mutex_lock (&server_monitor->shared.mutex);
+ server_monitor->shared.cancel_requested = true;
+ mongoc_cond_signal (&server_monitor->shared.cond);
+ bson_mutex_unlock (&server_monitor->shared.mutex);
+}
+
+/* Wait for heartbeatFrequencyMS or minHeartbeatFrequencyMS if a scan is
+ * requested.
+ *
+ * Locks server monitor mutex.
+ */
+void
+mongoc_server_monitor_wait (mongoc_server_monitor_t *server_monitor)
+{
+ int64_t start_ms;
+ int64_t scan_due_ms;
+
+ start_ms = _now_ms ();
+ scan_due_ms = start_ms + server_monitor->heartbeat_frequency_ms;
+
+ bson_mutex_lock (&server_monitor->shared.mutex);
+ while (true) {
+ int64_t sleep_duration_ms;
+ int cond_ret;
+
+ if (server_monitor->shared.state != MONGOC_THREAD_RUNNING) {
+ break;
+ }
+
+ if (server_monitor->shared.scan_requested) {
+ server_monitor->shared.scan_requested = false;
+ scan_due_ms = start_ms + server_monitor->min_heartbeat_frequency_ms;
+ }
+
+ sleep_duration_ms = scan_due_ms - _now_ms ();
+
+ if (sleep_duration_ms <= 0) {
+ break;
+ }
+
+ MONITOR_LOG (server_monitor, "sleeping for %" PRId64, sleep_duration_ms);
+ cond_ret = mongoc_cond_timedwait (&server_monitor->shared.cond,
+ &server_monitor->shared.mutex,
+ sleep_duration_ms);
+ if (mongo_cond_ret_is_timedout (cond_ret)) {
+ break;
+ }
+ }
+ bson_mutex_unlock (&server_monitor->shared.mutex);
+}
+
+/* The server monitor thread function.
+ *
+ * Server monitor must be in state MONGOC_THREAD_OFF.
+ */
+static BSON_THREAD_FUN (_server_monitor_thread, server_monitor_void)
+{
+ mongoc_server_monitor_t *server_monitor;
+ mongoc_server_description_t *description;
+ mongoc_server_description_t *previous_description;
+
+ server_monitor = (mongoc_server_monitor_t *) server_monitor_void;
+ description =
+ mongoc_server_description_new_copy (server_monitor->description);
+ previous_description = NULL;
+
+ while (true) {
+ bool cancelled = false;
+
+ bson_mutex_lock (&server_monitor->shared.mutex);
+ if (server_monitor->shared.state != MONGOC_THREAD_RUNNING) {
+ bson_mutex_unlock (&server_monitor->shared.mutex);
+ break;
+ }
+ bson_mutex_unlock (&server_monitor->shared.mutex);
+
+ mongoc_server_description_destroy (previous_description);
+ previous_description = mongoc_server_description_new_copy (description);
+ mongoc_server_description_destroy (description);
+ description = _server_monitor_check_server (
+ server_monitor, previous_description, &cancelled);
+
+ if (cancelled) {
+ mongoc_server_monitor_wait (server_monitor);
+ continue;
+ }
+
+ _update_topology_description (server_monitor, description);
+
+ /* Immediately proceed to the next check if the previous response was
+ * successful and included the topologyVersion field. */
+ if (description->type != MONGOC_SERVER_UNKNOWN &&
+ !bson_empty (&description->topology_version)) {
+ MONITOR_LOG (server_monitor,
+ "immediately proceeding due to topologyVersion");
+ continue;
+ }
+
+ /* ... or the previous response included the moreToCome flag */
+ if (server_monitor->more_to_come) {
+ MONITOR_LOG (server_monitor,
+ "immediately proceeding due to moreToCome");
+ continue;
+ }
+
+ /* ... or the server has just transitioned to Unknown due to a network
+ * error. */
+ if (_mongoc_error_is_network (&description->error) &&
+ previous_description->type != MONGOC_SERVER_UNKNOWN) {
+ MONITOR_LOG (server_monitor,
+ "immediately proceeding due to network error");
+ continue;
+ }
+
+ mongoc_server_monitor_wait (server_monitor);
+ }
+
+ bson_mutex_lock (&server_monitor->shared.mutex);
+ server_monitor->shared.state = MONGOC_THREAD_JOINABLE;
+ bson_mutex_unlock (&server_monitor->shared.mutex);
+ mongoc_server_description_destroy (previous_description);
+ mongoc_server_description_destroy (description);
+ BSON_THREAD_RETURN;
+}
+
+static bool
+_server_monitor_ping_server (mongoc_server_monitor_t *server_monitor,
+ bool hello_ok,
+ int64_t *rtt_ms)
+{
+ bool ret = false;
+ int64_t start_us = _now_us ();
+ bson_t hello_response;
+ bson_error_t error;
+
+ *rtt_ms = MONGOC_RTT_UNSET;
+
+ if (!server_monitor->stream) {
+ MONITOR_LOG (server_monitor, "rtt setting up connection");
+ ret = _server_monitor_setup_connection (
+ server_monitor, &hello_response, &start_us, &error);
+ bson_destroy (&hello_response);
+ }
+
+ if (server_monitor->stream) {
+ MONITOR_LOG (server_monitor, "rtt polling hello");
+ ret = _server_monitor_polling_hello (
+ server_monitor, hello_ok, &hello_response, &error);
+ if (ret) {
+ *rtt_ms = (_now_us () - start_us) / 1000;
+ }
+ bson_destroy (&hello_response);
+ }
+ return ret;
+}
+
+/* The RTT monitor thread function.
+ *
+ * Server monitor must be in state MONGOC_THREAD_OFF.
+ */
+static BSON_THREAD_FUN (_server_monitor_rtt_thread, server_monitor_void)
+{
+ mongoc_server_monitor_t *server_monitor = server_monitor_void;
+
+ while (true) {
+ int64_t rtt_ms;
+ bson_error_t error;
+ bool hello_ok;
+
+ bson_mutex_lock (&server_monitor->shared.mutex);
+ if (server_monitor->shared.state != MONGOC_THREAD_RUNNING) {
+ bson_mutex_unlock (&server_monitor->shared.mutex);
+ break;
+ }
+ bson_mutex_unlock (&server_monitor->shared.mutex);
+
+ {
+ mc_shared_tpld td = mc_tpld_take_ref (server_monitor->topology);
+ const mongoc_server_description_t *sd =
+ mongoc_topology_description_server_by_id_const (
+ td.ptr, server_monitor->description->id, &error);
+ hello_ok = sd ? sd->hello_ok : false;
+ mc_tpld_drop_ref (&td);
+ }
+
+ _server_monitor_ping_server (server_monitor, hello_ok, &rtt_ms);
+ if (rtt_ms != MONGOC_RTT_UNSET) {
+ mc_tpld_modification tdmod =
+ mc_tpld_modify_begin (server_monitor->topology);
+ mongoc_server_description_t *const mut_sd =
+ mongoc_topology_description_server_by_id (
+ tdmod.new_td, server_monitor->description->id, &error);
+ if (mut_sd) {
+ mongoc_server_description_update_rtt (mut_sd, rtt_ms);
+ mc_tpld_modify_commit (tdmod);
+ } else {
+ /* If the server description has been removed, the RTT thread will
+ * be terminated by background monitoring soon, so we have nothing
+ * to do but wait until we are about to be stopped. */
+ mc_tpld_modify_drop (tdmod);
+ }
+ }
+ mongoc_server_monitor_wait (server_monitor);
+ }
+
+ bson_mutex_lock (&server_monitor->shared.mutex);
+ server_monitor->shared.state = MONGOC_THREAD_JOINABLE;
+ bson_mutex_unlock (&server_monitor->shared.mutex);
+ BSON_THREAD_RETURN;
+}
+
+void
+mongoc_server_monitor_run (mongoc_server_monitor_t *server_monitor)
+{
+ bson_mutex_lock (&server_monitor->shared.mutex);
+ if (server_monitor->shared.state == MONGOC_THREAD_OFF) {
+ server_monitor->is_rtt = false;
+ server_monitor->shared.state = MONGOC_THREAD_RUNNING;
+ COMMON_PREFIX (thread_create)
+ (&server_monitor->thread, _server_monitor_thread, server_monitor);
+ }
+ bson_mutex_unlock (&server_monitor->shared.mutex);
+}
+
+void
+mongoc_server_monitor_run_as_rtt (mongoc_server_monitor_t *server_monitor)
+{
+ bson_mutex_lock (&server_monitor->shared.mutex);
+ if (server_monitor->shared.state == MONGOC_THREAD_OFF) {
+ server_monitor->is_rtt = true;
+ server_monitor->shared.state = MONGOC_THREAD_RUNNING;
+ COMMON_PREFIX (thread_create)
+ (&server_monitor->thread, _server_monitor_rtt_thread, server_monitor);
+ }
+ bson_mutex_unlock (&server_monitor->shared.mutex);
+}
+
+/* Request thread shutdown.
+ *
+ * Returns true if in state MONGOC_THREAD_OFF and the server monitor can be
+ * safely destroyed.
+ * Called during topology description reconcile.
+ * Locks server monitor mutex.
+ */
+bool
+mongoc_server_monitor_request_shutdown (mongoc_server_monitor_t *server_monitor)
+{
+ bool off = false;
+
+ bson_mutex_lock (&server_monitor->shared.mutex);
+ if (server_monitor->shared.state == MONGOC_THREAD_RUNNING) {
+ server_monitor->shared.state = MONGOC_THREAD_SHUTTING_DOWN;
+ }
+ if (server_monitor->shared.state == MONGOC_THREAD_JOINABLE) {
+ COMMON_PREFIX (thread_join) (server_monitor->thread);
+ server_monitor->shared.state = MONGOC_THREAD_OFF;
+ }
+ if (server_monitor->shared.state == MONGOC_THREAD_OFF) {
+ off = true;
+ }
+ mongoc_cond_signal (&server_monitor->shared.cond);
+ bson_mutex_unlock (&server_monitor->shared.mutex);
+ /* Cancel an in-progress hello check. */
+ if (!off) {
+ mongoc_server_monitor_request_cancel (server_monitor);
+ }
+ return off;
+}
+
+/* Request thread shutdown and block until the server monitor thread terminates.
+ *
+ * Called by one thread.
+ * Locks the server monitor mutex.
+ */
+void
+mongoc_server_monitor_wait_for_shutdown (
+ mongoc_server_monitor_t *server_monitor)
+{
+ if (mongoc_server_monitor_request_shutdown (server_monitor)) {
+ return;
+ }
+
+ /* Shutdown requested, but thread is not yet off. Wait. */
+ COMMON_PREFIX (thread_join) (server_monitor->thread);
+ bson_mutex_lock (&server_monitor->shared.mutex);
+ server_monitor->shared.state = MONGOC_THREAD_OFF;
+ bson_mutex_unlock (&server_monitor->shared.mutex);
+}
+
+/* Destroy a server monitor.
+ *
+ * Called only by one thread.
+ * Caller must not hold server monitor lock.
+ * Server monitor thread is in state MONGOC_THREAD_OFF.
+ */
+void
+mongoc_server_monitor_destroy (mongoc_server_monitor_t *server_monitor)
+{
+ if (!server_monitor) {
+ return;
+ }
+
+ /* Locking not necessary since this is only called by one thread, and server
+ * monitor thread is no longer running. */
+ BSON_ASSERT (server_monitor->shared.state == MONGOC_THREAD_OFF);
+
+ mongoc_server_description_destroy (server_monitor->description);
+ mongoc_stream_destroy (server_monitor->stream);
+ mongoc_uri_destroy (server_monitor->uri);
+ mongoc_cond_destroy (&server_monitor->shared.cond);
+ bson_mutex_destroy (&server_monitor->shared.mutex);
+#ifdef MONGOC_ENABLE_SSL
+ if (server_monitor->ssl_opts) {
+ _mongoc_ssl_opts_cleanup (server_monitor->ssl_opts, true);
+ bson_free (server_monitor->ssl_opts);
+ }
+#endif
+ bson_free (server_monitor);
+}
diff --git a/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-stream-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-stream-private.h
new file mode 100644
index 00000000..29109dc0
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-stream-private.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2015 MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mongoc-prelude.h"
+
+#ifndef MONGOC_SERVER_STREAM_H
+#define MONGOC_SERVER_STREAM_H
+
+#include "mongoc-config.h"
+
+#include <bson/bson.h>
+
+#include "mongoc-topology-description-private.h"
+#include "mongoc-server-description-private.h"
+#include "mongoc-stream.h"
+
+BSON_BEGIN_DECLS
+
+typedef struct _mongoc_server_stream_t {
+ mongoc_topology_description_type_t topology_type;
+ mongoc_server_description_t *sd; /* owned */
+ bson_t cluster_time; /* owned */
+ mongoc_stream_t *stream; /* borrowed */
+ /** If the stream was created in a way that may have overwritten the user's
+ * readPreference, we need to know if server selection forced that change. */
+ bool must_use_primary;
+} mongoc_server_stream_t;
+
+
+mongoc_server_stream_t *
+mongoc_server_stream_new (const mongoc_topology_description_t *td,
+ mongoc_server_description_t *sd,
+ mongoc_stream_t *stream);
+
+int32_t
+mongoc_server_stream_max_bson_obj_size (mongoc_server_stream_t *server_stream);
+
+int32_t
+mongoc_server_stream_max_msg_size (mongoc_server_stream_t *server_stream);
+
+int32_t
+mongoc_server_stream_max_write_batch_size (
+ mongoc_server_stream_t *server_stream);
+
+void
+mongoc_server_stream_cleanup (mongoc_server_stream_t *server_stream);
+
+BSON_END_DECLS
+
+
+#endif /* MONGOC_SERVER_STREAM_H */
diff --git a/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-stream.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-stream.c
new file mode 100644
index 00000000..84f21a36
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-stream.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2015 MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include "mongoc-cluster-private.h"
+#include "mongoc-server-stream-private.h"
+#include "mongoc-util-private.h"
+
+#undef MONGOC_LOG_DOMAIN
+#define MONGOC_LOG_DOMAIN "server-stream"
+
+mongoc_server_stream_t *
+mongoc_server_stream_new (const mongoc_topology_description_t *td,
+ mongoc_server_description_t *sd,
+ mongoc_stream_t *stream)
+{
+ mongoc_server_stream_t *server_stream;
+
+ BSON_ASSERT (sd);
+ BSON_ASSERT (stream);
+
+ server_stream = bson_malloc (sizeof (mongoc_server_stream_t));
+ server_stream->topology_type = td->type;
+ bson_copy_to (&td->cluster_time, &server_stream->cluster_time);
+ server_stream->sd = sd; /* becomes owned */
+ server_stream->stream = stream; /* merely borrowed */
+ server_stream->must_use_primary = false;
+
+ return server_stream;
+}
+
+void
+mongoc_server_stream_cleanup (mongoc_server_stream_t *server_stream)
+{
+ if (server_stream) {
+ mongoc_server_description_destroy (server_stream->sd);
+ bson_destroy (&server_stream->cluster_time);
+ bson_free (server_stream);
+ }
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_server_stream_max_bson_obj_size --
+ *
+ * Return the max bson object size for the given server stream.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+int32_t
+mongoc_server_stream_max_bson_obj_size (mongoc_server_stream_t *server_stream)
+{
+ return COALESCE (server_stream->sd->max_bson_obj_size,
+ MONGOC_DEFAULT_BSON_OBJ_SIZE);
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_server_stream_max_msg_size --
+ *
+ * Return the max message size for the given server stream.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+int32_t
+mongoc_server_stream_max_msg_size (mongoc_server_stream_t *server_stream)
+{
+ return COALESCE (server_stream->sd->max_msg_size,
+ MONGOC_DEFAULT_MAX_MSG_SIZE);
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_server_stream_max_write_batch_size --
+ *
+ * Return the max write batch size for the given server stream.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+int32_t
+mongoc_server_stream_max_write_batch_size (
+ mongoc_server_stream_t *server_stream)
+{
+ return COALESCE (server_stream->sd->max_write_batch_size,
+ MONGOC_DEFAULT_WRITE_BATCH_SIZE);
+}
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-set-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-set-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-set-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-set-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-set.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-set.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-set.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-set.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-shared-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-shared-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-shared-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-shared-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-shared.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-shared.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-shared.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-shared.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-socket-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-socket-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-socket-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-socket-private.h
diff --git a/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-socket.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-socket.c
new file mode 100644
index 00000000..e085adba
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-socket.c
@@ -0,0 +1,1578 @@
+/*
+ * Copyright 2014 MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include <errno.h>
+#include <string.h>
+
+#include "mongoc-counters-private.h"
+#include "mongoc-errno-private.h"
+#include "mongoc-socket-private.h"
+#include "mongoc-host-list.h"
+#include "mongoc-socket-private.h"
+#include "mongoc-trace-private.h"
+#ifdef _WIN32
+#include <Mstcpip.h>
+#include <process.h>
+#endif
+
+#undef MONGOC_LOG_DOMAIN
+#define MONGOC_LOG_DOMAIN "socket"
+
+
+#define OPERATION_EXPIRED(expire_at) \
+ ((expire_at >= 0) && (expire_at < (bson_get_monotonic_time ())))
+
+
+/* either struct sockaddr or void, depending on platform */
+typedef MONGOC_SOCKET_ARG2 mongoc_sockaddr_t;
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_socket_capture_errno --
+ *
+ * Save the errno state for contextual use.
+ *
+ * Returns:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+static void
+_mongoc_socket_capture_errno (mongoc_socket_t *sock) /* IN */
+{
+#ifdef _WIN32
+ errno = sock->errno_ = WSAGetLastError ();
+#else
+ sock->errno_ = errno;
+#endif
+ TRACE ("setting errno: %d %s", sock->errno_, strerror (sock->errno_));
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_socket_setflags --
+ *
+ * A helper to set socket flags. Sets to nonblocking mode. On
+ * POSIX sets closeonexec.
+ *
+ *
+ * Returns:
+ * true if successful; otherwise false.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+static bool
+#ifdef _WIN32
+_mongoc_socket_setflags (SOCKET sd)
+#else
+_mongoc_socket_setflags (int sd)
+#endif
+{
+#ifdef _WIN32
+ u_long io_mode = 1;
+ return (NO_ERROR == ioctlsocket (sd, FIONBIO, &io_mode));
+#else
+ int flags;
+
+ flags = fcntl (sd, F_GETFL);
+
+ if (-1 == fcntl (sd, F_SETFL, (flags | O_NONBLOCK))) {
+ return false;
+ }
+
+#ifdef FD_CLOEXEC
+ flags = fcntl (sd, F_GETFD);
+ if (-1 == fcntl (sd, F_SETFD, (flags | FD_CLOEXEC))) {
+ return false;
+ }
+#endif
+ return true;
+#endif
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_socket_wait --
+ *
+ * A single socket poll helper.
+ *
+ * @events: in most cases should be POLLIN or POLLOUT.
+ *
+ * @expire_at should be an absolute time at which to expire using
+ * the monotonic clock (bson_get_monotonic_time(), which is in
+ * microseconds). Or zero to not block at all. Or -1 to block
+ * forever.
+ *
+ * Returns:
+ * true if an event matched. otherwise false.
+ * a timeout will return false.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+static bool
+_mongoc_socket_wait (mongoc_socket_t *sock, /* IN */
+ int events, /* IN */
+ int64_t expire_at) /* IN */
+{
+#ifdef _WIN32
+ fd_set read_fds;
+ fd_set write_fds;
+ fd_set error_fds;
+ struct timeval timeout_tv;
+#else
+ struct pollfd pfd;
+#endif
+ int ret;
+ int timeout;
+ int64_t now;
+
+ ENTRY;
+
+ BSON_ASSERT (sock);
+ BSON_ASSERT (events);
+
+#ifdef _WIN32
+ FD_ZERO (&read_fds);
+ FD_ZERO (&write_fds);
+ FD_ZERO (&error_fds);
+
+ if (events & POLLIN) {
+ FD_SET (sock->sd, &read_fds);
+ }
+
+ if (events & POLLOUT) {
+ FD_SET (sock->sd, &write_fds);
+ }
+
+ FD_SET (sock->sd, &error_fds);
+#else
+ pfd.fd = sock->sd;
+ pfd.events = events | POLLERR | POLLHUP;
+ pfd.revents = 0;
+#endif
+ now = bson_get_monotonic_time ();
+
+ for (;;) {
+ if (expire_at < 0) {
+ timeout = -1;
+ } else if (expire_at == 0) {
+ timeout = 0;
+ } else {
+ timeout = (int) ((expire_at - now) / 1000L);
+ if (timeout < 0) {
+ timeout = 0;
+ }
+ }
+
+#ifdef _WIN32
+ if (timeout == -1) {
+ /* not WSAPoll: daniel.haxx.se/blog/2012/10/10/wsapoll-is-broken */
+ ret = select (0 /*unused*/, &read_fds, &write_fds, &error_fds, NULL);
+ } else {
+ timeout_tv.tv_sec = timeout / 1000;
+ timeout_tv.tv_usec = (timeout % 1000) * 1000;
+ ret = select (
+ 0 /*unused*/, &read_fds, &write_fds, &error_fds, &timeout_tv);
+ }
+ if (ret == SOCKET_ERROR) {
+ _mongoc_socket_capture_errno (sock);
+ ret = -1;
+ } else if (FD_ISSET (sock->sd, &error_fds)) {
+ errno = WSAECONNRESET;
+ ret = -1;
+ }
+#else
+ ret = poll (&pfd, 1, timeout);
+#endif
+
+ if (ret > 0) {
+/* Something happened, so return that */
+#ifdef _WIN32
+ return (FD_ISSET (sock->sd, &read_fds) ||
+ FD_ISSET (sock->sd, &write_fds));
+#else
+ RETURN (0 != (pfd.revents & events));
+#endif
+ } else if (ret < 0) {
+ /* poll itself failed */
+
+ TRACE ("errno is: %d", errno);
+ if (MONGOC_ERRNO_IS_AGAIN (errno)) {
+ if (OPERATION_EXPIRED (expire_at)) {
+ _mongoc_socket_capture_errno (sock);
+ RETURN (false);
+ } else {
+ continue;
+ }
+ } else {
+ /* poll failed for some non-transient reason */
+ _mongoc_socket_capture_errno (sock);
+ RETURN (false);
+ }
+ } else {
+ /* ret == 0, poll timed out */
+ if (timeout) {
+ mongoc_counter_streams_timeout_inc ();
+ }
+#ifdef _WIN32
+ sock->errno_ = timeout ? WSAETIMEDOUT : EAGAIN;
+#else
+ sock->errno_ = timeout ? ETIMEDOUT : EAGAIN;
+#endif
+ RETURN (false);
+ }
+ }
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_socket_poll --
+ *
+ * A multi-socket poll helper.
+ *
+ * @expire_at should be an absolute time at which to expire using
+ * the monotonic clock (bson_get_monotonic_time(), which is in
+ * microseconds). Or zero to not block at all. Or -1 to block
+ * forever.
+ *
+ * Returns:
+ * The number of sockets ready.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+ssize_t
+mongoc_socket_poll (mongoc_socket_poll_t *sds, /* IN */
+ size_t nsds, /* IN */
+ int32_t timeout) /* IN */
+{
+#ifdef _WIN32
+ fd_set read_fds;
+ fd_set write_fds;
+ fd_set error_fds;
+ struct timeval timeout_tv;
+#else
+ struct pollfd *pfds;
+#endif
+ int ret;
+ int i;
+
+ ENTRY;
+
+ BSON_ASSERT (sds);
+
+#ifdef _WIN32
+ FD_ZERO (&read_fds);
+ FD_ZERO (&write_fds);
+ FD_ZERO (&error_fds);
+
+ for (i = 0; i < nsds; i++) {
+ if (sds[i].events & POLLIN) {
+ FD_SET (sds[i].socket->sd, &read_fds);
+ }
+
+ if (sds[i].events & POLLOUT) {
+ FD_SET (sds[i].socket->sd, &write_fds);
+ }
+
+ FD_SET (sds[i].socket->sd, &error_fds);
+ }
+
+ timeout_tv.tv_sec = timeout / 1000;
+ timeout_tv.tv_usec = (timeout % 1000) * 1000;
+
+ /* not WSAPoll: daniel.haxx.se/blog/2012/10/10/wsapoll-is-broken */
+ ret = select (0 /*unused*/, &read_fds, &write_fds, &error_fds, &timeout_tv);
+ if (ret == SOCKET_ERROR) {
+ errno = WSAGetLastError ();
+ return -1;
+ }
+
+ for (i = 0; i < nsds; i++) {
+ if (FD_ISSET (sds[i].socket->sd, &read_fds)) {
+ sds[i].revents = POLLIN;
+ } else if (FD_ISSET (sds[i].socket->sd, &write_fds)) {
+ sds[i].revents = POLLOUT;
+ } else if (FD_ISSET (sds[i].socket->sd, &error_fds)) {
+ sds[i].revents = POLLHUP;
+ } else {
+ sds[i].revents = 0;
+ }
+ }
+#else
+ pfds = (struct pollfd *) bson_malloc (sizeof (*pfds) * nsds);
+
+ for (i = 0; i < nsds; i++) {
+ pfds[i].fd = sds[i].socket->sd;
+ pfds[i].events = sds[i].events | POLLERR | POLLHUP;
+ pfds[i].revents = 0;
+ }
+
+ ret = poll (pfds, nsds, timeout);
+ for (i = 0; i < nsds; i++) {
+ sds[i].revents = pfds[i].revents;
+ }
+
+ bson_free (pfds);
+#endif
+
+ return ret;
+}
+
+
+/* https://jira.mongodb.org/browse/CDRIVER-2176 */
+#define MONGODB_KEEPALIVEINTVL 10
+#define MONGODB_KEEPIDLE 120
+#define MONGODB_KEEPALIVECNT 9
+
+#ifdef _WIN32
+static void
+_mongoc_socket_setkeepalive_windows (SOCKET sd)
+{
+ struct tcp_keepalive keepalive;
+ DWORD lpcbBytesReturned = 0;
+ HKEY hKey;
+ DWORD type;
+ DWORD data;
+ DWORD data_size = sizeof data;
+ const char *reg_key =
+ "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters";
+ keepalive.onoff = true;
+ keepalive.keepalivetime = MONGODB_KEEPIDLE * 1000;
+ keepalive.keepaliveinterval = MONGODB_KEEPALIVEINTVL * 1000;
+ /*
+ * Windows hardcodes probes to 10:
+ * https://msdn.microsoft.com/en-us/library/windows/desktop/dd877220(v=vs.85).aspx
+ * "On Windows Vista and later, the number of keep-alive probes (data
+ * retransmissions) is set to 10 and cannot be changed."
+ *
+ * Note that win2k (and seeminly all versions thereafter) do not set the
+ * registry value by default so there is no way to derive the default value
+ * programmatically. It is however listed in the docs. A user can however
+ * change the default value by setting the registry values.
+ */
+
+ if (RegOpenKeyExA (HKEY_LOCAL_MACHINE, reg_key, 0, KEY_QUERY_VALUE, &hKey) ==
+ ERROR_SUCCESS) {
+ /* https://technet.microsoft.com/en-us/library/cc957549.aspx */
+ DWORD default_keepalivetime = 7200000; /* 2 hours */
+ /* https://technet.microsoft.com/en-us/library/cc957548.aspx */
+ DWORD default_keepaliveinterval = 1000; /* 1 second */
+
+ if (RegQueryValueEx (
+ hKey, "KeepAliveTime", NULL, &type, (LPBYTE) &data, &data_size) ==
+ ERROR_SUCCESS) {
+ if (type == REG_DWORD && data < keepalive.keepalivetime) {
+ keepalive.keepalivetime = data;
+ }
+ } else if (default_keepalivetime < keepalive.keepalivetime) {
+ keepalive.keepalivetime = default_keepalivetime;
+ }
+
+ if (RegQueryValueEx (hKey,
+ "KeepAliveInterval",
+ NULL,
+ &type,
+ (LPBYTE) &data,
+ &data_size) == ERROR_SUCCESS) {
+ if (type == REG_DWORD && data < keepalive.keepaliveinterval) {
+ keepalive.keepaliveinterval = data;
+ }
+ } else if (default_keepaliveinterval < keepalive.keepaliveinterval) {
+ keepalive.keepaliveinterval = default_keepaliveinterval;
+ }
+ RegCloseKey (hKey);
+ }
+ if (WSAIoctl (sd,
+ SIO_KEEPALIVE_VALS,
+ &keepalive,
+ sizeof keepalive,
+ NULL,
+ 0,
+ &lpcbBytesReturned,
+ NULL,
+ NULL) == SOCKET_ERROR) {
+ TRACE ("%s", "Could not set keepalive values");
+ } else {
+ TRACE ("%s", "KeepAlive values updated");
+ TRACE ("KeepAliveTime: %d", keepalive.keepalivetime);
+ TRACE ("KeepAliveInterval: %d", keepalive.keepaliveinterval);
+ }
+}
+#else
+
+static const char *
+_mongoc_socket_sockopt_value_to_name (int value)
+{
+ switch (value) {
+#ifdef TCP_KEEPIDLE
+ case TCP_KEEPIDLE:
+ return "TCP_KEEPIDLE";
+#endif
+#ifdef TCP_KEEPALIVE
+ case TCP_KEEPALIVE:
+ return "TCP_KEEPALIVE";
+#endif
+#ifdef TCP_KEEPINTVL
+ case TCP_KEEPINTVL:
+ return "TCP_KEEPINTVL";
+#endif
+#ifdef TCP_KEEPCNT
+ case TCP_KEEPCNT:
+ return "TCP_KEEPCNT";
+#endif
+ default:
+ MONGOC_WARNING ("Don't know what socketopt %d is", value);
+ return "Unknown option name";
+ }
+}
+
+static void
+_mongoc_socket_set_sockopt_if_less (int sd, int name, int value)
+{
+ int optval = 1;
+ mongoc_socklen_t optlen;
+
+ optlen = sizeof optval;
+ if (getsockopt (sd, IPPROTO_TCP, name, (char *) &optval, &optlen)) {
+ TRACE ("Getting '%s' failed, errno: %d",
+ _mongoc_socket_sockopt_value_to_name (name),
+ errno);
+ } else {
+ TRACE ("'%s' is %d, target value is %d",
+ _mongoc_socket_sockopt_value_to_name (name),
+ optval,
+ value);
+ if (optval > value) {
+ optval = value;
+ if (setsockopt (
+ sd, IPPROTO_TCP, name, (char *) &optval, sizeof optval)) {
+ TRACE ("Setting '%s' failed, errno: %d",
+ _mongoc_socket_sockopt_value_to_name (name),
+ errno);
+ } else {
+ TRACE ("'%s' value changed to %d",
+ _mongoc_socket_sockopt_value_to_name (name),
+ optval);
+ }
+ }
+ }
+}
+
+static void
+_mongoc_socket_setkeepalive_nix (int sd)
+{
+#if defined(TCP_KEEPIDLE)
+ _mongoc_socket_set_sockopt_if_less (sd, TCP_KEEPIDLE, MONGODB_KEEPIDLE);
+#elif defined(TCP_KEEPALIVE)
+ _mongoc_socket_set_sockopt_if_less (sd, TCP_KEEPALIVE, MONGODB_KEEPIDLE);
+#else
+ TRACE ("%s", "Neither TCP_KEEPIDLE nor TCP_KEEPALIVE available");
+#endif
+
+#ifdef TCP_KEEPINTVL
+ _mongoc_socket_set_sockopt_if_less (
+ sd, TCP_KEEPINTVL, MONGODB_KEEPALIVEINTVL);
+#else
+ TRACE ("%s", "TCP_KEEPINTVL not available");
+#endif
+
+#ifdef TCP_KEEPCNT
+ _mongoc_socket_set_sockopt_if_less (sd, TCP_KEEPCNT, MONGODB_KEEPALIVECNT);
+#else
+ TRACE ("%s", "TCP_KEEPCNT not available");
+#endif
+}
+
+#endif
+static void
+#ifdef _WIN32
+_mongoc_socket_setkeepalive (SOCKET sd) /* IN */
+#else
+_mongoc_socket_setkeepalive (int sd) /* IN */
+#endif
+{
+#ifdef SO_KEEPALIVE
+ int optval = 1;
+
+ ENTRY;
+#ifdef SO_KEEPALIVE
+ if (!setsockopt (
+ sd, SOL_SOCKET, SO_KEEPALIVE, (char *) &optval, sizeof optval)) {
+ TRACE ("%s", "Setting SO_KEEPALIVE");
+#ifdef _WIN32
+ _mongoc_socket_setkeepalive_windows (sd);
+#else
+ _mongoc_socket_setkeepalive_nix (sd);
+#endif
+ } else {
+ TRACE ("%s", "Failed setting SO_KEEPALIVE");
+ }
+#else
+ TRACE ("%s", "SO_KEEPALIVE not available");
+#endif
+ EXIT;
+#endif
+}
+
+
+static bool
+#ifdef _WIN32
+_mongoc_socket_setnodelay (SOCKET sd) /* IN */
+#else
+_mongoc_socket_setnodelay (int sd) /* IN */
+#endif
+{
+#ifdef _WIN32
+ BOOL optval = 1;
+#else
+ int optval = 1;
+#endif
+ int ret;
+
+ ENTRY;
+
+ errno = 0;
+ ret = setsockopt (
+ sd, IPPROTO_TCP, TCP_NODELAY, (char *) &optval, sizeof optval);
+
+#ifdef _WIN32
+ if (ret == SOCKET_ERROR) {
+ MONGOC_WARNING ("WSAGetLastError(): %d", (int) WSAGetLastError ());
+ }
+#endif
+
+ RETURN (ret == 0);
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_socket_errno --
+ *
+ * Returns the last error on the socket.
+ *
+ * Returns:
+ * An integer errno, or 0 on no error.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+int
+mongoc_socket_errno (mongoc_socket_t *sock) /* IN */
+{
+ BSON_ASSERT (sock);
+ TRACE ("Current errno: %d", sock->errno_);
+ return sock->errno_;
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_socket_errno_is_again --
+ *
+ * Check to see if we should attempt to make further progress
+ * based on the error of the last operation.
+ *
+ * Returns:
+ * true if we should try again. otherwise false.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+static bool
+_mongoc_socket_errno_is_again (mongoc_socket_t *sock) /* IN */
+{
+ TRACE ("errno is: %d", sock->errno_);
+ return MONGOC_ERRNO_IS_AGAIN (sock->errno_);
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_socket_accept --
+ *
+ * Wrapper for BSD socket accept(). Handles portability between
+ * BSD sockets and WinSock2 on Windows Vista and newer.
+ *
+ * Returns:
+ * NULL upon failure to accept or timeout.
+ * A newly allocated mongoc_socket_t on success.
+ *
+ * Side effects:
+ * *port contains the client port number.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+mongoc_socket_t *
+mongoc_socket_accept (mongoc_socket_t *sock, /* IN */
+ int64_t expire_at) /* IN */
+{
+ return mongoc_socket_accept_ex (sock, expire_at, NULL);
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_socket_accept_ex --
+ *
+ * Private synonym for mongoc_socket_accept, returning client port.
+ *
+ * Returns:
+ * NULL upon failure to accept or timeout.
+ * A newly allocated mongoc_socket_t on success.
+ *
+ * Side effects:
+ * *port contains the client port number.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+mongoc_socket_t *
+mongoc_socket_accept_ex (mongoc_socket_t *sock, /* IN */
+ int64_t expire_at, /* IN */
+ uint16_t *port) /* OUT */
+{
+ mongoc_socket_t *client;
+ struct sockaddr_storage addr = {0};
+ mongoc_socklen_t addrlen = sizeof addr;
+ bool try_again = false;
+ bool failed = false;
+#ifdef _WIN32
+ SOCKET sd;
+#else
+ int sd;
+#endif
+
+ ENTRY;
+
+ BSON_ASSERT (sock);
+
+again:
+ errno = 0;
+ sd = accept (sock->sd, (mongoc_sockaddr_t *) &addr, &addrlen);
+
+ _mongoc_socket_capture_errno (sock);
+#ifdef _WIN32
+ failed = (sd == INVALID_SOCKET);
+#else
+ failed = (sd == -1);
+#endif
+ try_again = (failed && _mongoc_socket_errno_is_again (sock));
+
+ if (failed && try_again) {
+ if (_mongoc_socket_wait (sock, POLLIN, expire_at)) {
+ GOTO (again);
+ }
+ RETURN (NULL);
+ } else if (failed) {
+ RETURN (NULL);
+ } else if (!_mongoc_socket_setflags (sd)) {
+#ifdef _WIN32
+ closesocket (sd);
+#else
+ close (sd);
+#endif
+ RETURN (NULL);
+ }
+
+ client = (mongoc_socket_t *) bson_malloc0 (sizeof *client);
+ client->sd = sd;
+
+ if (port) {
+ if (addr.ss_family == AF_INET) {
+ struct sockaddr_in *tmp = (struct sockaddr_in *) &addr;
+ *port = ntohs (tmp->sin_port);
+ } else {
+ struct sockaddr_in6 *tmp = (struct sockaddr_in6 *) &addr;
+ *port = ntohs (tmp->sin6_port);
+ }
+ }
+
+ if (!_mongoc_socket_setnodelay (client->sd)) {
+ MONGOC_WARNING ("Failed to enable TCP_NODELAY.");
+ }
+
+ RETURN (client);
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongo_socket_bind --
+ *
+ * A wrapper around bind().
+ *
+ * Returns:
+ * 0 on success, -1 on failure and errno is set.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+int
+mongoc_socket_bind (mongoc_socket_t *sock, /* IN */
+ const struct sockaddr *addr, /* IN */
+ mongoc_socklen_t addrlen) /* IN */
+{
+ int ret;
+
+ ENTRY;
+
+ BSON_ASSERT (sock);
+ BSON_ASSERT (addr);
+ BSON_ASSERT (addrlen);
+
+ ret = bind (sock->sd, addr, addrlen);
+
+ _mongoc_socket_capture_errno (sock);
+
+ RETURN (ret);
+}
+
+
+int
+mongoc_socket_close (mongoc_socket_t *sock) /* IN */
+{
+ bool owned;
+
+ ENTRY;
+
+ BSON_ASSERT (sock);
+
+#ifdef _WIN32
+ owned = (sock->pid == (int) _getpid ());
+
+ if (sock->sd != INVALID_SOCKET) {
+ if (owned) {
+ shutdown (sock->sd, SD_BOTH);
+ }
+
+ if (0 == closesocket (sock->sd)) {
+ sock->sd = INVALID_SOCKET;
+ } else {
+ _mongoc_socket_capture_errno (sock);
+ RETURN (-1);
+ }
+ }
+ RETURN (0);
+#else
+ owned = (sock->pid == (int) getpid ());
+
+ if (sock->sd != -1) {
+ if (owned) {
+ shutdown (sock->sd, SHUT_RDWR);
+ }
+
+ if (0 == close (sock->sd)) {
+ sock->sd = -1;
+ } else {
+ _mongoc_socket_capture_errno (sock);
+ RETURN (-1);
+ }
+ }
+ RETURN (0);
+#endif
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_socket_connect --
+ *
+ * Performs a socket connection but will fail if @expire_at is
+ * reached by the monotonic clock.
+ *
+ * Returns:
+ * 0 if success, otherwise -1 and errno is set.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+int
+mongoc_socket_connect (mongoc_socket_t *sock, /* IN */
+ const struct sockaddr *addr, /* IN */
+ mongoc_socklen_t addrlen, /* IN */
+ int64_t expire_at) /* IN */
+{
+ bool try_again = false;
+ bool failed = false;
+ int ret;
+ int optval;
+ /* getsockopt parameter types vary, we check in CheckCompiler.m4 */
+ mongoc_socklen_t optlen = (mongoc_socklen_t) sizeof optval;
+
+ ENTRY;
+
+ BSON_ASSERT (sock);
+ BSON_ASSERT (addr);
+ BSON_ASSERT (addrlen);
+
+ ret = connect (sock->sd, addr, addrlen);
+
+#ifdef _WIN32
+ if (ret == SOCKET_ERROR) {
+#else
+ if (ret == -1) {
+#endif
+ _mongoc_socket_capture_errno (sock);
+
+ failed = true;
+ try_again = _mongoc_socket_errno_is_again (sock);
+ }
+
+ if (failed && try_again) {
+ if (_mongoc_socket_wait (sock, POLLOUT, expire_at)) {
+ optval = -1;
+ ret = getsockopt (
+ sock->sd, SOL_SOCKET, SO_ERROR, (char *) &optval, &optlen);
+ if ((ret == 0) && (optval == 0)) {
+ RETURN (0);
+ } else {
+ errno = sock->errno_ = optval;
+ }
+ }
+ RETURN (-1);
+ } else if (failed) {
+ RETURN (-1);
+ } else {
+ RETURN (0);
+ }
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_socket_destroy --
+ *
+ * Cleanup after a mongoc_socket_t structure, possibly closing
+ * underlying sockets.
+ *
+ * Returns:
+ * None.
+ *
+ * Side effects:
+ * @sock is freed and should be considered invalid.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+void
+mongoc_socket_destroy (mongoc_socket_t *sock) /* IN */
+{
+ if (sock) {
+ mongoc_socket_close (sock);
+ bson_free (sock);
+ }
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_socket_listen --
+ *
+ * Listen for incoming requests with a backlog up to @backlog.
+ *
+ * If @backlog is zero, a sensible default will be chosen.
+ *
+ * Returns:
+ * true if successful; otherwise false.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+int
+mongoc_socket_listen (mongoc_socket_t *sock, /* IN */
+ unsigned int backlog) /* IN */
+{
+ int ret;
+
+ ENTRY;
+
+ BSON_ASSERT (sock);
+
+ if (backlog == 0) {
+ backlog = 10;
+ }
+
+ ret = listen (sock->sd, backlog);
+
+ _mongoc_socket_capture_errno (sock);
+
+ RETURN (ret);
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_socket_new --
+ *
+ * Create a new socket and store the current process id on it.
+ *
+ * Free the result with mongoc_socket_destroy().
+ *
+ * Returns:
+ * A newly allocated socket.
+ * NULL on failure.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+mongoc_socket_t *
+mongoc_socket_new (int domain, /* IN */
+ int type, /* IN */
+ int protocol) /* IN */
+{
+ mongoc_socket_t *sock;
+#ifdef _WIN32
+ SOCKET sd;
+#else
+ int sd;
+#endif
+#ifdef SO_NOSIGPIPE
+ int on = 1;
+#endif
+
+ ENTRY;
+
+ sd = socket (domain, type, protocol);
+
+#ifdef _WIN32
+ if (sd == INVALID_SOCKET) {
+#else
+ if (sd == -1) {
+#endif
+ RETURN (NULL);
+ }
+
+ if (!_mongoc_socket_setflags (sd)) {
+ GOTO (fail);
+ }
+
+ if (domain != AF_UNIX) {
+ if (!_mongoc_socket_setnodelay (sd)) {
+ MONGOC_WARNING ("Failed to enable TCP_NODELAY.");
+ }
+ _mongoc_socket_setkeepalive (sd);
+ }
+
+ /* Set SO_NOSIGPIPE, to ignore SIGPIPE on writes for platforms where
+ setting MSG_NOSIGNAL on writes is not supported (primarily OSX). */
+#ifdef SO_NOSIGPIPE
+ setsockopt(sd, SOL_SOCKET, SO_NOSIGPIPE, &on, sizeof(on));
+#endif
+
+ sock = (mongoc_socket_t *) bson_malloc0 (sizeof *sock);
+ sock->sd = sd;
+ sock->domain = domain;
+#ifdef _WIN32
+ sock->pid = (int) _getpid ();
+#else
+ sock->pid = (int) getpid ();
+#endif
+
+ RETURN (sock);
+
+fail:
+#ifdef _WIN32
+ closesocket (sd);
+#else
+ close (sd);
+#endif
+
+ RETURN (NULL);
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_socket_recv --
+ *
+ * A portable wrapper around recv() that also respects an absolute
+ * timeout.
+ *
+ * @expire_at is 0 for no blocking, -1 for infinite blocking,
+ * or a time using the monotonic clock to expire. Calculate this
+ * using bson_get_monotonic_time() + N_MICROSECONDS.
+ *
+ * Returns:
+ * The number of bytes received on success.
+ * 0 on end of stream.
+ * -1 on failure.
+ *
+ * Side effects:
+ * @buf will be read into.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+ssize_t
+mongoc_socket_recv (mongoc_socket_t *sock, /* IN */
+ void *buf, /* OUT */
+ size_t buflen, /* IN */
+ int flags, /* IN */
+ int64_t expire_at) /* IN */
+{
+ ssize_t ret = 0;
+ bool failed = false;
+
+ ENTRY;
+
+ BSON_ASSERT (sock);
+ BSON_ASSERT (buf);
+ BSON_ASSERT (buflen);
+
+again:
+ sock->errno_ = 0;
+#ifdef _WIN32
+ ret = recv (sock->sd, (char *) buf, (int) buflen, flags);
+ failed = (ret == SOCKET_ERROR);
+#else
+ ret = recv (sock->sd, buf, buflen, flags);
+ failed = (ret == -1);
+#endif
+ if (failed) {
+ _mongoc_socket_capture_errno (sock);
+ if (_mongoc_socket_errno_is_again (sock) &&
+ _mongoc_socket_wait (sock, POLLIN, expire_at)) {
+ GOTO (again);
+ }
+ }
+
+ if (failed) {
+ RETURN (-1);
+ }
+
+ mongoc_counter_streams_ingress_add (ret);
+
+ RETURN (ret);
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_socket_setsockopt --
+ *
+ * A wrapper around setsockopt().
+ *
+ * Returns:
+ * 0 on success, -1 on failure.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+int
+mongoc_socket_setsockopt (mongoc_socket_t *sock, /* IN */
+ int level, /* IN */
+ int optname, /* IN */
+ const void *optval, /* IN */
+ mongoc_socklen_t optlen) /* IN */
+{
+ int ret;
+
+ ENTRY;
+
+ BSON_ASSERT (sock);
+
+ ret = setsockopt (sock->sd, level, optname, optval, optlen);
+
+ _mongoc_socket_capture_errno (sock);
+
+ RETURN (ret);
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_socket_send --
+ *
+ * A simplified wrapper around mongoc_socket_sendv().
+ *
+ * @expire_at is 0 for no blocking, -1 for infinite blocking,
+ * or a time using the monotonic clock to expire. Calculate this
+ * using bson_get_monotonic_time() + N_MICROSECONDS.
+ *
+ * Returns:
+ * -1 on failure. number of bytes written on success.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+ssize_t
+mongoc_socket_send (mongoc_socket_t *sock, /* IN */
+ const void *buf, /* IN */
+ size_t buflen, /* IN */
+ int64_t expire_at) /* IN */
+{
+ mongoc_iovec_t iov;
+
+ BSON_ASSERT (sock);
+ BSON_ASSERT (buf);
+ BSON_ASSERT (buflen);
+
+ iov.iov_base = (void *) buf;
+ iov.iov_len = buflen;
+
+ return mongoc_socket_sendv (sock, &iov, 1, expire_at);
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_socket_try_sendv_slow --
+ *
+ * A slow variant of _mongoc_socket_try_sendv() that sends each
+ * iovec entry one by one. This can happen if we hit EMSGSIZE
+ * with sendmsg() on various POSIX systems or WSASend()+WSAEMSGSIZE
+ * on Windows.
+ *
+ * Returns:
+ * the number of bytes sent or -1 and errno is set.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+static ssize_t
+_mongoc_socket_try_sendv_slow (mongoc_socket_t *sock, /* IN */
+ mongoc_iovec_t *iov, /* IN */
+ size_t iovcnt) /* IN */
+{
+ ssize_t ret = 0;
+ size_t i;
+ ssize_t wrote;
+
+ ENTRY;
+
+ BSON_ASSERT (sock);
+ BSON_ASSERT (iov);
+ BSON_ASSERT (iovcnt);
+
+ for (i = 0; i < iovcnt; i++) {
+ wrote = send (sock->sd, iov[i].iov_base, iov[i].iov_len, 0);
+#ifdef _WIN32
+ if (wrote == SOCKET_ERROR) {
+#else
+ if (wrote == -1) {
+#endif
+ _mongoc_socket_capture_errno (sock);
+
+ if (!_mongoc_socket_errno_is_again (sock)) {
+ RETURN (-1);
+ }
+ RETURN (ret ? ret : -1);
+ }
+
+ ret += wrote;
+
+ if (wrote != iov[i].iov_len) {
+ RETURN (ret);
+ }
+ }
+
+ RETURN (ret);
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_socket_try_sendv --
+ *
+ * Helper used by mongoc_socket_sendv() to try to write as many
+ * bytes to the underlying socket until the socket buffer is full.
+ *
+ * This is performed in a non-blocking fashion.
+ *
+ * Returns:
+ * -1 on failure. the number of bytes written on success.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+static ssize_t
+_mongoc_socket_try_sendv (mongoc_socket_t *sock, /* IN */
+ mongoc_iovec_t *iov, /* IN */
+ size_t iovcnt) /* IN */
+{
+#ifdef _WIN32
+ DWORD dwNumberofBytesSent = 0;
+ int ret;
+#else
+ struct msghdr msg;
+ ssize_t ret;
+#endif
+
+ ENTRY;
+
+ BSON_ASSERT (sock);
+ BSON_ASSERT (iov);
+ BSON_ASSERT (iovcnt);
+
+ DUMP_IOVEC (sendbuf, iov, iovcnt);
+
+#ifdef _WIN32
+ ret = WSASend (
+ sock->sd, (LPWSABUF) iov, iovcnt, &dwNumberofBytesSent, 0, NULL, NULL);
+ TRACE ("WSASend sent: %ld (out of: %ld), ret: %d",
+ dwNumberofBytesSent,
+ iov->iov_len,
+ ret);
+#else
+ memset (&msg, 0, sizeof msg);
+ msg.msg_iov = iov;
+ msg.msg_iovlen = (int) iovcnt;
+ ret = sendmsg (sock->sd,
+ &msg,
+#ifdef MSG_NOSIGNAL
+ MSG_NOSIGNAL);
+#else
+ 0);
+#endif
+ TRACE ("Send %ld out of %ld bytes", ret, iov->iov_len);
+#endif
+
+
+#ifdef _WIN32
+ if (ret == SOCKET_ERROR) {
+#else
+ if (ret == -1) {
+#endif
+ _mongoc_socket_capture_errno (sock);
+
+/*
+ * Check to see if we have sent an iovec too large for sendmsg to
+ * complete. If so, we need to fallback to the slow path of multiple
+ * send() commands.
+ */
+#ifdef _WIN32
+ if (mongoc_socket_errno (sock) == WSAEMSGSIZE) {
+#else
+ if (mongoc_socket_errno (sock) == EMSGSIZE) {
+#endif
+ RETURN (_mongoc_socket_try_sendv_slow (sock, iov, iovcnt));
+ }
+
+ RETURN (-1);
+ }
+
+#ifdef _WIN32
+ RETURN (dwNumberofBytesSent);
+#else
+ RETURN (ret);
+#endif
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_socket_sendv --
+ *
+ * A wrapper around using sendmsg() to send an iovec.
+ * This also deals with the structure differences between
+ * WSABUF and struct iovec.
+ *
+ * @expire_at is 0 for no blocking, -1 for infinite blocking,
+ * or a time using the monotonic clock to expire. Calculate this
+ * using bson_get_monotonic_time() + N_MICROSECONDS.
+ *
+ * Returns:
+ * -1 on failure.
+ * the number of bytes written on success.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+ssize_t
+mongoc_socket_sendv (mongoc_socket_t *sock, /* IN */
+ mongoc_iovec_t *in_iov, /* IN */
+ size_t iovcnt, /* IN */
+ int64_t expire_at) /* IN */
+{
+ ssize_t ret = 0;
+ ssize_t sent;
+ size_t cur = 0;
+ mongoc_iovec_t *iov;
+
+ ENTRY;
+
+ BSON_ASSERT (sock);
+ BSON_ASSERT (in_iov);
+ BSON_ASSERT (iovcnt);
+
+ iov = bson_malloc (sizeof (*iov) * iovcnt);
+ memcpy (iov, in_iov, sizeof (*iov) * iovcnt);
+
+ for (;;) {
+ sent = _mongoc_socket_try_sendv (sock, &iov[cur], iovcnt - cur);
+ TRACE (
+ "Sent %ld (of %ld) out of iovcnt=%ld", sent, iov[cur].iov_len, iovcnt);
+
+ /*
+ * If we failed with anything other than EAGAIN or EWOULDBLOCK,
+ * we should fail immediately as there is another issue with the
+ * underlying socket.
+ */
+ if (sent == -1) {
+ if (!_mongoc_socket_errno_is_again (sock)) {
+ ret = -1;
+ GOTO (CLEANUP);
+ }
+ }
+
+ /*
+ * Update internal stream counters.
+ */
+ if (sent > 0) {
+ ret += sent;
+ mongoc_counter_streams_egress_add (sent);
+
+ /*
+ * Subtract the sent amount from what we still need to send.
+ */
+ while ((cur < iovcnt) && (sent >= (ssize_t) iov[cur].iov_len)) {
+ TRACE ("still got bytes left: sent -= iov_len: %ld -= %ld",
+ sent,
+ iov[cur].iov_len);
+ sent -= iov[cur++].iov_len;
+ }
+
+ /*
+ * Check if that made us finish all of the iovecs. If so, we are done
+ * sending data over the socket.
+ */
+ if (cur == iovcnt) {
+ TRACE ("%s", "Finished the iovecs");
+ break;
+ }
+
+ /*
+ * Increment the current iovec buffer to its proper offset and adjust
+ * the number of bytes to write.
+ */
+ TRACE ("Seeked io_base+%ld", sent);
+ TRACE (
+ "Subtracting iov_len -= sent; %ld -= %ld", iov[cur].iov_len, sent);
+ iov[cur].iov_base = ((char *) iov[cur].iov_base) + sent;
+ iov[cur].iov_len -= sent;
+ TRACE ("iov_len remaining %ld", iov[cur].iov_len);
+
+ BSON_ASSERT (iovcnt - cur);
+ BSON_ASSERT (iov[cur].iov_len);
+ } else if (OPERATION_EXPIRED (expire_at)) {
+ if (expire_at > 0) {
+ mongoc_counter_streams_timeout_inc ();
+ }
+ GOTO (CLEANUP);
+ }
+
+ /*
+ * Block on poll() until our desired condition is met.
+ */
+ if (!_mongoc_socket_wait (sock, POLLOUT, expire_at)) {
+ GOTO (CLEANUP);
+ }
+ }
+
+CLEANUP:
+ bson_free (iov);
+
+ RETURN (ret);
+}
+
+
+int
+mongoc_socket_getsockname (mongoc_socket_t *sock, /* IN */
+ struct sockaddr *addr, /* OUT */
+ mongoc_socklen_t *addrlen) /* INOUT */
+{
+ int ret;
+
+ ENTRY;
+
+ BSON_ASSERT (sock);
+
+ ret = getsockname (sock->sd, addr, addrlen);
+
+ _mongoc_socket_capture_errno (sock);
+
+ RETURN (ret);
+}
+
+
+char *
+mongoc_socket_getnameinfo (mongoc_socket_t *sock) /* IN */
+{
+ /* getpeername parameter types vary, we check in CheckCompiler.m4 */
+ struct sockaddr_storage addr;
+ mongoc_socklen_t len = (mongoc_socklen_t) sizeof addr;
+ char *ret;
+ char host[BSON_HOST_NAME_MAX + 1];
+
+ ENTRY;
+
+ BSON_ASSERT (sock);
+
+ if (getpeername (sock->sd, (struct sockaddr *) &addr, &len)) {
+ RETURN (NULL);
+ }
+
+ if (getnameinfo (
+ (struct sockaddr *) &addr, len, host, sizeof host, NULL, 0, 0)) {
+ RETURN (NULL);
+ }
+
+ ret = bson_strdup (host);
+ RETURN (ret);
+}
+
+
+bool
+mongoc_socket_check_closed (mongoc_socket_t *sock) /* IN */
+{
+ bool closed = false;
+ char buf[1];
+ ssize_t r;
+
+ if (_mongoc_socket_wait (sock, POLLIN, 0)) {
+ sock->errno_ = 0;
+
+ r = recv (sock->sd, buf, 1, MSG_PEEK);
+
+ if (r < 0) {
+ _mongoc_socket_capture_errno (sock);
+ }
+
+ if (r < 1) {
+ closed = true;
+ }
+ }
+
+ return closed;
+}
+
+/*
+ *
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_socket_inet_ntop --
+ *
+ * Convert the ip from addrinfo into a c string.
+ *
+ * Returns:
+ * The value is returned into 'buffer'. The memory has to be allocated
+ * by the caller
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+void
+mongoc_socket_inet_ntop (struct addrinfo *rp, /* IN */
+ char *buf, /* INOUT */
+ size_t buflen) /* IN */
+{
+ void *ptr;
+ char tmp[256];
+
+ switch (rp->ai_family) {
+ case AF_INET:
+ ptr = &((struct sockaddr_in *) rp->ai_addr)->sin_addr;
+ inet_ntop (rp->ai_family, ptr, tmp, sizeof (tmp));
+ bson_snprintf (buf, buflen, "ipv4 %s", tmp);
+ break;
+ case AF_INET6:
+ ptr = &((struct sockaddr_in6 *) rp->ai_addr)->sin6_addr;
+ inet_ntop (rp->ai_family, ptr, tmp, sizeof (tmp));
+ bson_snprintf (buf, buflen, "ipv6 %s", tmp);
+ break;
+ default:
+ bson_snprintf (buf, buflen, "unknown ip %d", rp->ai_family);
+ break;
+ }
+}
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-socket.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-socket.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-socket.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-socket.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-ssl-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-ssl-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-ssl-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-ssl-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-ssl.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-ssl.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-ssl.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-ssl.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-ssl.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-ssl.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-ssl.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-ssl.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-sspi-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-sspi-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-sspi-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-sspi-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-sspi.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-sspi.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-sspi.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-sspi.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-buffered.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-buffered.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-buffered.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-buffered.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-buffered.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-buffered.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-buffered.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-buffered.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-file.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-file.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-file.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-file.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-file.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-file.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-file.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-file.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-gridfs-download-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-gridfs-download-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-gridfs-download-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-gridfs-download-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-gridfs-download.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-gridfs-download.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-gridfs-download.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-gridfs-download.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-gridfs-upload-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-gridfs-upload-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-gridfs-upload-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-gridfs-upload-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-gridfs-upload.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-gridfs-upload.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-gridfs-upload.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-gridfs-upload.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-gridfs.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-gridfs.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-gridfs.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-gridfs.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-gridfs.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-gridfs.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-gridfs.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-gridfs.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-socket.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-socket.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-socket.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-socket.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-socket.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-socket.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-socket.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-socket.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-libressl-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-libressl-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-libressl-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-libressl-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-libressl.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-libressl.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-libressl.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-libressl.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-libressl.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-libressl.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-libressl.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-libressl.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-openssl-bio-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-openssl-bio-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-openssl-bio-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-openssl-bio-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-openssl-bio.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-openssl-bio.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-openssl-bio.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-openssl-bio.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-openssl-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-openssl-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-openssl-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-openssl-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-openssl.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-openssl.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-openssl.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-openssl.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-openssl.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-openssl.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-openssl.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-openssl.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-transport-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-transport-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-transport-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-transport-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-transport.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-transport.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-transport.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-transport.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-transport.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-transport.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-transport.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-transport.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-thread-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-thread-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-thread-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-thread-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-timeout-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-timeout-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-timeout-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-timeout-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-timeout.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-timeout.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-timeout.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-timeout.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-background-monitoring-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-background-monitoring-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-background-monitoring-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-background-monitoring-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-background-monitoring.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-background-monitoring.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-background-monitoring.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-background-monitoring.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-description-apm-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-description-apm-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-description-apm-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-description-apm-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-description-apm.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-description-apm.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-description-apm.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-description-apm.c
diff --git a/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-description-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-description-private.h
new file mode 100644
index 00000000..3a12b103
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-description-private.h
@@ -0,0 +1,197 @@
+/*
+ * Copyright 2014 MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mongoc-prelude.h"
+
+#ifndef MONGOC_TOPOLOGY_DESCRIPTION_PRIVATE_H
+#define MONGOC_TOPOLOGY_DESCRIPTION_PRIVATE_H
+
+#include "mongoc-set-private.h"
+#include "mongoc-server-description.h"
+#include "mongoc-array-private.h"
+#include "mongoc-topology-description.h"
+#include "mongoc-apm-private.h"
+
+
+typedef enum {
+ MONGOC_TOPOLOGY_UNKNOWN,
+ MONGOC_TOPOLOGY_SHARDED,
+ MONGOC_TOPOLOGY_RS_NO_PRIMARY,
+ MONGOC_TOPOLOGY_RS_WITH_PRIMARY,
+ MONGOC_TOPOLOGY_SINGLE,
+ MONGOC_TOPOLOGY_LOAD_BALANCED,
+ MONGOC_TOPOLOGY_DESCRIPTION_TYPES
+} mongoc_topology_description_type_t;
+
+struct _mongoc_topology_description_t {
+ bson_oid_t topology_id;
+ bool opened;
+ mongoc_topology_description_type_t type;
+ int64_t heartbeat_msec;
+ mongoc_set_t *_servers_;
+ char *set_name;
+ int64_t max_set_version;
+ bson_oid_t max_election_id;
+ bson_error_t compatibility_error;
+ uint32_t max_server_id;
+ int32_t max_hosts; /* srvMaxHosts */
+ bool stale;
+ unsigned int rand_seed;
+
+ /* the greatest seen cluster time, for a MongoDB 3.6+ sharded cluster.
+ * see Driver Sessions Spec. */
+ bson_t cluster_time;
+
+ /* smallest seen logicalSessionTimeoutMinutes, or -1 if any server has no
+ * logicalSessionTimeoutMinutes. see Server Discovery and Monitoring Spec */
+ int64_t session_timeout_minutes;
+
+ mongoc_apm_callbacks_t apm_callbacks;
+ void *apm_context;
+};
+
+typedef enum {
+ MONGOC_SS_READ,
+ MONGOC_SS_WRITE,
+ MONGOC_SS_AGGREGATE_WITH_WRITE
+} mongoc_ss_optype_t;
+
+void
+mongoc_topology_description_init (mongoc_topology_description_t *description,
+ int64_t heartbeat_msec);
+
+
+/**
+ * @brief Get a pointer to the set of server descriptions in the topology
+ * description.
+ */
+static BSON_INLINE mongoc_set_t *
+mc_tpld_servers (mongoc_topology_description_t *tpld)
+{
+ BSON_ASSERT_PARAM (tpld);
+ return tpld->_servers_;
+}
+
+static BSON_INLINE const mongoc_set_t *
+mc_tpld_servers_const (const mongoc_topology_description_t *tpld)
+{
+ BSON_ASSERT_PARAM (tpld);
+ return tpld->_servers_;
+}
+
+void
+_mongoc_topology_description_copy_to (const mongoc_topology_description_t *src,
+ mongoc_topology_description_t *dst);
+
+void
+mongoc_topology_description_cleanup (
+ mongoc_topology_description_t *description);
+
+void
+mongoc_topology_description_handle_hello (
+ mongoc_topology_description_t *topology,
+ uint32_t server_id,
+ const bson_t *hello_response,
+ int64_t rtt_msec,
+ const bson_error_t *error /* IN */);
+
+mongoc_server_description_t const *
+mongoc_topology_description_select (
+ const mongoc_topology_description_t *description,
+ mongoc_ss_optype_t optype,
+ const mongoc_read_prefs_t *read_pref,
+ bool *must_use_primary,
+ int64_t local_threshold_ms);
+
+mongoc_server_description_t *
+mongoc_topology_description_server_by_id (
+ mongoc_topology_description_t *description,
+ uint32_t id,
+ bson_error_t *error);
+
+const mongoc_server_description_t *
+mongoc_topology_description_server_by_id_const (
+ const mongoc_topology_description_t *description,
+ uint32_t id,
+ bson_error_t *error);
+
+int32_t
+mongoc_topology_description_lowest_max_wire_version (
+ const mongoc_topology_description_t *td);
+
+bool
+mongoc_topology_description_all_sds_have_write_date (
+ const mongoc_topology_description_t *td);
+
+bool
+_mongoc_topology_description_validate_max_staleness (
+ const mongoc_topology_description_t *td,
+ int64_t max_staleness_seconds,
+ bson_error_t *error);
+
+void
+mongoc_topology_description_suitable_servers (
+ mongoc_array_t *set, /* OUT */
+ mongoc_ss_optype_t optype,
+ const mongoc_topology_description_t *topology,
+ const mongoc_read_prefs_t *read_pref,
+ bool *must_use_primary,
+ size_t local_threshold_ms);
+
+bool
+mongoc_topology_description_has_data_node (
+ const mongoc_topology_description_t *td);
+
+void
+mongoc_topology_description_invalidate_server (
+ mongoc_topology_description_t *topology,
+ uint32_t id,
+ const bson_error_t *error /* IN */);
+
+bool
+mongoc_topology_description_add_server (mongoc_topology_description_t *topology,
+ const char *server,
+ uint32_t *id /* OUT */);
+
+void
+mongoc_topology_description_update_cluster_time (
+ mongoc_topology_description_t *td, const bson_t *reply);
+
+void
+mongoc_topology_description_reconcile (mongoc_topology_description_t *td,
+ mongoc_host_list_t *host_list);
+
+/**
+ * @brief Invalidate open connnections to a server.
+ *
+ * Pooled clients with open connections will discover the invalidation
+ * the next time they fetch a stream to the server.
+ *
+ * @param td The topology description that will be updated.
+ * @param server_id The ID of the server to invalidate.
+ * @param service_id A service ID for load-balanced deployments. Use
+ * kZeroServiceID if not applicable.
+ *
+ * @note Not applicable to single-threaded clients, which only maintain a
+ * single connection per server and therefore have no connection pool.
+ */
+void
+_mongoc_topology_description_clear_connection_pool (
+ mongoc_topology_description_t *td,
+ uint32_t server_id,
+ const bson_oid_t *service_id);
+
+#endif /* MONGOC_TOPOLOGY_DESCRIPTION_PRIVATE_H */
diff --git a/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-description.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-description.c
new file mode 100644
index 00000000..6b54bf04
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-description.c
@@ -0,0 +1,2556 @@
+/*
+ * Copyright 2014 MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mongoc-array-private.h"
+#include "mongoc-error.h"
+#include "mongoc-server-description-private.h"
+#include "mongoc-topology-description-apm-private.h"
+#include "mongoc-trace-private.h"
+#include "mongoc-util-private.h"
+#include "mongoc-read-prefs-private.h"
+#include "mongoc-set-private.h"
+#include "mongoc-client-private.h"
+#include "mongoc-thread-private.h"
+#include "mongoc-host-list-private.h"
+#include "utlist.h"
+
+
+static bool
+_is_data_node (const mongoc_server_description_t *sd)
+{
+ switch (sd->type) {
+ case MONGOC_SERVER_MONGOS:
+ case MONGOC_SERVER_STANDALONE:
+ case MONGOC_SERVER_RS_SECONDARY:
+ case MONGOC_SERVER_RS_PRIMARY:
+ case MONGOC_SERVER_LOAD_BALANCER:
+ return true;
+ case MONGOC_SERVER_RS_OTHER:
+ case MONGOC_SERVER_RS_ARBITER:
+ case MONGOC_SERVER_UNKNOWN:
+ case MONGOC_SERVER_POSSIBLE_PRIMARY:
+ case MONGOC_SERVER_RS_GHOST:
+ case MONGOC_SERVER_DESCRIPTION_TYPES:
+ default:
+ return false;
+ }
+}
+
+
+static void
+_mongoc_topology_server_dtor (void *server_, void *ctx_)
+{
+ mongoc_server_description_destroy ((mongoc_server_description_t *) server_);
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_topology_description_init --
+ *
+ * Initialize the given topology description
+ *
+ * Returns:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+void
+mongoc_topology_description_init (mongoc_topology_description_t *description,
+ int64_t heartbeat_msec)
+{
+ ENTRY;
+
+ BSON_ASSERT (description);
+
+ memset (description, 0, sizeof (*description));
+
+ bson_oid_init (&description->topology_id, NULL);
+ description->opened = false;
+ description->type = MONGOC_TOPOLOGY_UNKNOWN;
+ description->heartbeat_msec = heartbeat_msec;
+ description->_servers_ =
+ mongoc_set_new (8, _mongoc_topology_server_dtor, NULL);
+ description->set_name = NULL;
+ description->max_set_version = MONGOC_NO_SET_VERSION;
+ description->stale = true;
+ description->rand_seed = (unsigned int) bson_get_monotonic_time ();
+ bson_init (&description->cluster_time);
+ description->session_timeout_minutes = MONGOC_NO_SESSIONS;
+
+ EXIT;
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_topology_description_copy_to --
+ *
+ * Deep-copy @src to an uninitialized topology description @dst.
+ * @dst must not already point to any allocated resources. Clean
+ * up with mongoc_topology_description_cleanup.
+ *
+ * Returns:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+void
+_mongoc_topology_description_copy_to (const mongoc_topology_description_t *src,
+ mongoc_topology_description_t *dst)
+{
+ size_t nitems;
+ size_t i;
+ const mongoc_server_description_t *sd;
+ uint32_t id;
+
+ ENTRY;
+
+ BSON_ASSERT (src);
+ BSON_ASSERT (dst);
+
+ bson_oid_copy (&src->topology_id, &dst->topology_id);
+ bson_oid_copy (&src->max_election_id, &dst->max_election_id);
+ dst->opened = src->opened;
+ dst->type = src->type;
+ dst->heartbeat_msec = src->heartbeat_msec;
+ dst->rand_seed = src->rand_seed;
+
+ nitems = bson_next_power_of_two (mc_tpld_servers_const (src)->items_len);
+ dst->_servers_ = mongoc_set_new (nitems, _mongoc_topology_server_dtor, NULL);
+ for (i = 0; i < mc_tpld_servers_const (src)->items_len; i++) {
+ sd = mongoc_set_get_item_and_id_const (
+ mc_tpld_servers_const (src), (int) i, &id);
+ mongoc_set_add (
+ mc_tpld_servers (dst), id, mongoc_server_description_new_copy (sd));
+ }
+
+ dst->set_name = bson_strdup (src->set_name);
+ dst->max_set_version = src->max_set_version;
+ memcpy (&dst->compatibility_error,
+ &src->compatibility_error,
+ sizeof (bson_error_t));
+ dst->max_server_id = src->max_server_id;
+ dst->max_hosts = src->max_hosts;
+ dst->stale = src->stale;
+ memcpy (&dst->apm_callbacks,
+ &src->apm_callbacks,
+ sizeof (mongoc_apm_callbacks_t));
+
+ dst->apm_context = src->apm_context;
+
+ bson_copy_to (&src->cluster_time, &dst->cluster_time);
+
+ dst->session_timeout_minutes = src->session_timeout_minutes;
+
+ EXIT;
+}
+
+/*
+ *-------------------------------------------------------------------------
+ *
+ * mongoc_topology_description_new_copy --
+ *
+ * Allocates a new topology description and deep-copies @description to it
+ * using _mongoc_topology_description_copy_to.
+ *
+ * Returns:
+ * A copy of a topology description that you must destroy with
+ * mongoc_topology_description_destroy, or NULL if @description is NULL.
+ *
+ * Side effects:
+ * None.
+ *
+ *-------------------------------------------------------------------------
+ */
+mongoc_topology_description_t *
+mongoc_topology_description_new_copy (
+ const mongoc_topology_description_t *description)
+{
+ mongoc_topology_description_t *copy;
+
+ if (!description) {
+ return NULL;
+ }
+
+ copy = (mongoc_topology_description_t *) bson_malloc0 (sizeof (*copy));
+
+ _mongoc_topology_description_copy_to (description, copy);
+
+ return copy;
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_topology_description_cleanup --
+ *
+ * Destroy allocated resources within @description but don't free it.
+ *
+ * Returns:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+void
+mongoc_topology_description_cleanup (mongoc_topology_description_t *description)
+{
+ ENTRY;
+
+ BSON_ASSERT (description);
+
+ if (mc_tpld_servers (description)) {
+ mongoc_set_destroy (mc_tpld_servers (description));
+ }
+
+ if (description->set_name) {
+ bson_free (description->set_name);
+ }
+
+ bson_destroy (&description->cluster_time);
+
+ EXIT;
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_topology_description_destroy --
+ *
+ * Destroy allocated resources within @description and free
+ * @description.
+ *
+ * Returns:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+void
+mongoc_topology_description_destroy (mongoc_topology_description_t *description)
+{
+ ENTRY;
+
+ if (!description) {
+ EXIT;
+ }
+
+ mongoc_topology_description_cleanup (description);
+ bson_free (description);
+
+ EXIT;
+}
+
+/* find the primary, then stop iterating */
+static bool
+_mongoc_topology_description_has_primary_cb (const void *item,
+ void *ctx /* OUT */)
+{
+ const mongoc_server_description_t *server = item;
+ const mongoc_server_description_t **primary = ctx;
+
+ /* TODO should this include MONGOS? */
+ if (server->type == MONGOC_SERVER_RS_PRIMARY ||
+ server->type == MONGOC_SERVER_STANDALONE) {
+ *primary = (mongoc_server_description_t *) item;
+ return false;
+ }
+ return true;
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_topology_description_has_primary --
+ *
+ * If topology has a primary, return it.
+ *
+ * Returns:
+ * A pointer to the primary, or NULL.
+ *
+ * Side effects:
+ * None
+ *
+ *--------------------------------------------------------------------------
+ */
+static const mongoc_server_description_t *
+_mongoc_topology_description_has_primary (
+ const mongoc_topology_description_t *description)
+{
+ mongoc_server_description_t *primary = NULL;
+
+ mongoc_set_for_each_const (mc_tpld_servers_const (description),
+ _mongoc_topology_description_has_primary_cb,
+ &primary);
+
+ return primary;
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_topology_description_later_election --
+ *
+ * Check if we've seen a more recent election in the replica set
+ * than this server has.
+ *
+ * Returns:
+ * True if the topology description's max replica set version plus
+ * election id is later than the server description's.
+ *
+ * Side effects:
+ * None
+ *
+ *--------------------------------------------------------------------------
+ */
+static bool
+_mongoc_topology_description_later_election (
+ mongoc_topology_description_t *td, const mongoc_server_description_t *sd)
+{
+ /* initially max_set_version is -1 and max_election_id is zeroed */
+ return td->max_set_version > sd->set_version ||
+ (td->max_set_version == sd->set_version &&
+ bson_oid_compare (&td->max_election_id, &sd->election_id) > 0);
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_topology_description_set_max_set_version --
+ *
+ * Remember that we've seen a new replica set version. Unconditionally
+ * sets td->set_version to sd->set_version.
+ *
+ *--------------------------------------------------------------------------
+ */
+static void
+_mongoc_topology_description_set_max_set_version (
+ mongoc_topology_description_t *td, const mongoc_server_description_t *sd)
+{
+ td->max_set_version = sd->set_version;
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_topology_description_set_max_election_id --
+ *
+ * Remember that we've seen a new election id. Unconditionally sets
+ * td->max_election_id to sd->election_id.
+ *
+ *--------------------------------------------------------------------------
+ */
+static void
+_mongoc_topology_description_set_max_election_id (
+ mongoc_topology_description_t *td, const mongoc_server_description_t *sd)
+{
+ bson_oid_copy (&sd->election_id, &td->max_election_id);
+}
+
+static bool
+_mongoc_topology_description_server_is_candidate (
+ mongoc_server_description_type_t desc_type,
+ mongoc_read_mode_t read_mode,
+ mongoc_topology_description_type_t topology_type)
+{
+ switch ((int) topology_type) {
+ case MONGOC_TOPOLOGY_SINGLE:
+ switch ((int) desc_type) {
+ case MONGOC_SERVER_STANDALONE:
+ return true;
+ default:
+ return false;
+ }
+
+ case MONGOC_TOPOLOGY_RS_NO_PRIMARY:
+ case MONGOC_TOPOLOGY_RS_WITH_PRIMARY:
+ switch ((int) read_mode) {
+ case MONGOC_READ_PRIMARY:
+ switch ((int) desc_type) {
+ case MONGOC_SERVER_RS_PRIMARY:
+ return true;
+ default:
+ return false;
+ }
+ case MONGOC_READ_SECONDARY:
+ switch ((int) desc_type) {
+ case MONGOC_SERVER_RS_SECONDARY:
+ return true;
+ default:
+ return false;
+ }
+ default:
+ switch ((int) desc_type) {
+ case MONGOC_SERVER_RS_PRIMARY:
+ case MONGOC_SERVER_RS_SECONDARY:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ case MONGOC_TOPOLOGY_SHARDED:
+ switch ((int) desc_type) {
+ case MONGOC_SERVER_MONGOS:
+ return true;
+ default:
+ return false;
+ }
+
+ /* Note, there is no call path that leads to the
+ * MONGOC_TOPOLOGY_LOAD_BALANCED case. Server selection for load balanced
+ * topologies bypasses this logic. This silences compiler warnings on
+ * unhandled enum values. */
+ case MONGOC_TOPOLOGY_LOAD_BALANCED:
+ return desc_type == MONGOC_SERVER_LOAD_BALANCER;
+
+ default:
+ return false;
+ }
+}
+
+typedef struct _mongoc_suitable_data_t {
+ mongoc_read_mode_t read_mode;
+ mongoc_topology_description_type_t topology_type;
+ const mongoc_server_description_t *primary; /* OUT */
+ const mongoc_server_description_t **candidates; /* OUT */
+ size_t candidates_len; /* OUT */
+ bool has_secondary; /* OUT */
+} mongoc_suitable_data_t;
+
+static bool
+_mongoc_replica_set_read_suitable_cb (const void *item, void *ctx)
+{
+ const mongoc_server_description_t *server = item;
+ mongoc_suitable_data_t *data = (mongoc_suitable_data_t *) ctx;
+
+ /* primary's used in staleness calculation, even with mode SECONDARY */
+ if (server->type == MONGOC_SERVER_RS_PRIMARY) {
+ data->primary = server;
+ }
+
+ if (_mongoc_topology_description_server_is_candidate (
+ server->type, data->read_mode, data->topology_type)) {
+ if (server->type == MONGOC_SERVER_RS_PRIMARY) {
+ if (data->read_mode == MONGOC_READ_PRIMARY ||
+ data->read_mode == MONGOC_READ_PRIMARY_PREFERRED) {
+ /* we want a primary and we have one, done! */
+ return false;
+ }
+ }
+
+ if (server->type == MONGOC_SERVER_RS_SECONDARY) {
+ data->has_secondary = true;
+ }
+
+ /* add to our candidates */
+ data->candidates[data->candidates_len++] = server;
+ } else {
+ TRACE ("Rejected [%s] [%s] for mode [%s]",
+ mongoc_server_description_type (server),
+ server->host.host_and_port,
+ _mongoc_read_mode_as_str (data->read_mode));
+ }
+
+ return true;
+}
+
+
+/* if any mongos are candidates, add them to the candidates array */
+static void
+_mongoc_try_mode_secondary (mongoc_array_t *set, /* OUT */
+ const mongoc_topology_description_t *topology,
+ const mongoc_read_prefs_t *read_pref,
+ bool *must_use_primary,
+ size_t local_threshold_ms)
+{
+ mongoc_read_prefs_t *secondary;
+
+ secondary = mongoc_read_prefs_copy (read_pref);
+ mongoc_read_prefs_set_mode (secondary, MONGOC_READ_SECONDARY);
+
+ mongoc_topology_description_suitable_servers (set,
+ MONGOC_SS_READ,
+ topology,
+ secondary,
+ must_use_primary,
+ local_threshold_ms);
+
+ mongoc_read_prefs_destroy (secondary);
+}
+
+
+/* if any mongos are candidates, add them to the candidates array */
+static bool
+_mongoc_find_suitable_mongos_cb (const void *item, void *ctx)
+{
+ const mongoc_server_description_t *server = item;
+ mongoc_suitable_data_t *data = (mongoc_suitable_data_t *) ctx;
+
+ if (_mongoc_topology_description_server_is_candidate (
+ server->type, data->read_mode, data->topology_type)) {
+ data->candidates[data->candidates_len++] = server;
+ }
+ return true;
+}
+
+
+/*
+ *-------------------------------------------------------------------------
+ *
+ * mongoc_topology_description_lowest_max_wire_version --
+ *
+ * The topology's max wire version.
+ *
+ * Returns:
+ * The minimum of all known servers' max wire versions, or INT32_MAX
+ * if there are no known servers.
+ *
+ * Side effects:
+ * None.
+ *
+ *-------------------------------------------------------------------------
+ */
+int32_t
+mongoc_topology_description_lowest_max_wire_version (
+ const mongoc_topology_description_t *td)
+{
+ int i;
+ int32_t ret = INT32_MAX;
+ const mongoc_set_t *servers = mc_tpld_servers_const (td);
+
+ for (i = 0; (size_t) i < servers->items_len; i++) {
+ const mongoc_server_description_t *sd =
+ mongoc_set_get_item_const (servers, i);
+ if (sd->type != MONGOC_SERVER_UNKNOWN &&
+ sd->type != MONGOC_SERVER_POSSIBLE_PRIMARY &&
+ sd->max_wire_version < ret) {
+ ret = sd->max_wire_version;
+ }
+ }
+
+ return ret;
+}
+
+
+/*
+ *-------------------------------------------------------------------------
+ *
+ * mongoc_topology_description_all_sds_have_write_date --
+ *
+ * Whether the primary and all secondaries' server descriptions have
+ * last_write_date_ms.
+ *
+ * Side effects:
+ * None.
+ *
+ *-------------------------------------------------------------------------
+ */
+bool
+mongoc_topology_description_all_sds_have_write_date (
+ const mongoc_topology_description_t *td)
+{
+ int i;
+ for (i = 0; (size_t) i < mc_tpld_servers_const (td)->items_len; i++) {
+ const mongoc_server_description_t *sd =
+ mongoc_set_get_item_const (mc_tpld_servers_const (td), i);
+
+ if (sd->last_write_date_ms <= 0 &&
+ (sd->type == MONGOC_SERVER_RS_PRIMARY ||
+ sd->type == MONGOC_SERVER_RS_SECONDARY)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/*
+ *-------------------------------------------------------------------------
+ *
+ * _mongoc_topology_description_validate_max_staleness --
+ *
+ * If the provided "maxStalenessSeconds" component of the read
+ * preference is not valid for this topology, fill out @error and
+ * return false.
+ *
+ * Side effects:
+ * None.
+ *
+ *-------------------------------------------------------------------------
+ */
+bool
+_mongoc_topology_description_validate_max_staleness (
+ const mongoc_topology_description_t *td,
+ int64_t max_staleness_seconds,
+ bson_error_t *error)
+{
+ mongoc_topology_description_type_t td_type;
+
+ /* Server Selection Spec: A driver MUST raise an error if the TopologyType
+ * is ReplicaSetWithPrimary or ReplicaSetNoPrimary and either of these
+ * conditions is false:
+ *
+ * maxStalenessSeconds * 1000 >= heartbeatFrequencyMS + idleWritePeriodMS
+ * maxStalenessSeconds >= smallestMaxStalenessSeconds
+ */
+
+ td_type = td->type;
+
+ if (td_type != MONGOC_TOPOLOGY_RS_WITH_PRIMARY &&
+ td_type != MONGOC_TOPOLOGY_RS_NO_PRIMARY) {
+ return true;
+ }
+
+ if (max_staleness_seconds * 1000 <
+ td->heartbeat_msec + MONGOC_IDLE_WRITE_PERIOD_MS) {
+ bson_set_error (error,
+ MONGOC_ERROR_COMMAND,
+ MONGOC_ERROR_COMMAND_INVALID_ARG,
+ "maxStalenessSeconds is set to %" PRId64
+ ", it must be at least heartbeatFrequencyMS (%" PRId64
+ ") + server's idle write period (%d seconds)",
+ max_staleness_seconds,
+ td->heartbeat_msec,
+ MONGOC_IDLE_WRITE_PERIOD_MS / 1000);
+ return false;
+ }
+
+ if (max_staleness_seconds < MONGOC_SMALLEST_MAX_STALENESS_SECONDS) {
+ bson_set_error (error,
+ MONGOC_ERROR_COMMAND,
+ MONGOC_ERROR_COMMAND_INVALID_ARG,
+ "maxStalenessSeconds is set to %" PRId64
+ ", it must be at least %d seconds",
+ max_staleness_seconds,
+ MONGOC_SMALLEST_MAX_STALENESS_SECONDS);
+ return false;
+ }
+
+ return true;
+}
+
+static bool
+_check_any_server_less_than_wire_version_13 (const void *sd_,
+ void *any_too_old_)
+{
+ const mongoc_server_description_t *sd = sd_;
+ bool *any_too_old = any_too_old_;
+ if (sd->max_wire_version < WIRE_VERSION_5_0) {
+ *any_too_old = true;
+ return false /* Stop searching */;
+ }
+
+ return true /* Keep searching */;
+}
+
+/**
+ * @brief Calculate the read mode that we should be using, based on what was
+ * requested and what is available in the topology.
+ *
+ * Per the CRUD spec, if the requested read mode is *not* primary, and *any*
+ * server in the topology has a wire version < server v5.0, we must override the
+ * read mode preference with "primary." Server v5.0 indicates support on a
+ * secondary server for using aggregate pipelines that contain writing stages
+ * (i.e. '$out' and '$merge').
+ */
+static bool
+_must_use_primary (const mongoc_topology_description_t *td,
+ mongoc_ss_optype_t optype,
+ mongoc_read_mode_t requested_read_mode)
+{
+ if (requested_read_mode == MONGOC_READ_PRIMARY) {
+ /* We never alter from a primary read mode. This early-return is just an
+ * optimization to skip scanning for old servers, as we would end up
+ * returning MONGOC_READ_PRIMARY regardless. */
+ return requested_read_mode;
+ }
+ switch (optype) {
+ case MONGOC_SS_WRITE:
+ /* We don't deal with write operations */
+ return false;
+ case MONGOC_SS_READ:
+ /* Maintain the requested read mode if it is a regular read operation */
+ return false;
+ case MONGOC_SS_AGGREGATE_WITH_WRITE: {
+ /* Check if any of the servers are too old to support the
+ * aggregate-with-write on a secondary server */
+ bool any_too_old = false;
+ mongoc_set_for_each_const (mc_tpld_servers_const (td),
+ _check_any_server_less_than_wire_version_13,
+ &any_too_old);
+ if (any_too_old) {
+ /* Force the read preference back to reading from a primary server, as
+ * one or more servers in the system may not support the operation */
+ return true;
+ }
+ /* We're okay to send an aggr-with-write to a secondary server, so permit
+ * the caller's read mode preference */
+ return false;
+ }
+ default:
+ BSON_UNREACHABLE ("Invalid mongoc_ss_optype_t for _must_use_primary()");
+ }
+}
+
+/*
+ *-------------------------------------------------------------------------
+ *
+ * mongoc_topology_description_suitable_servers --
+ *
+ * Fill out an array of servers matching the read preference and
+ * localThresholdMS.
+ *
+ * Side effects:
+ * None.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+void
+mongoc_topology_description_suitable_servers (
+ mongoc_array_t *set, /* OUT */
+ mongoc_ss_optype_t optype,
+ const mongoc_topology_description_t *topology,
+ const mongoc_read_prefs_t *read_pref,
+ bool *must_use_primary,
+ size_t local_threshold_ms)
+{
+ mongoc_suitable_data_t data;
+
+ const mongoc_set_t *td_servers = mc_tpld_servers_const (topology);
+ int64_t nearest = -1;
+ int i;
+ const mongoc_read_mode_t given_read_mode =
+ mongoc_read_prefs_get_mode (read_pref);
+ const bool override_use_primary =
+ _must_use_primary (topology, optype, given_read_mode);
+
+ data.primary = NULL;
+ data.topology_type = topology->type;
+ data.has_secondary = false;
+ data.candidates_len = 0;
+ data.candidates = bson_malloc0 (sizeof (mongoc_server_description_t *) *
+ td_servers->items_len);
+
+ /* The "effective" read mode is the read mode that we should behave for, and
+ * depends on the user's provided read mode, the type of operation that the
+ * user wishes to perform, and the server versions that we are talking to.
+ *
+ * If the operation is a write operation, read mode is irrelevant.
+ *
+ * If the operation is a regular read, we just use the caller's read mode.
+ *
+ * If the operation is an aggregate that contains writing stages, we need to
+ * be more careful about selecting an appropriate server.
+ */
+ data.read_mode =
+ override_use_primary ? MONGOC_READ_PRIMARY : given_read_mode;
+ if (must_use_primary) {
+ /* The caller wants to know if we have overriden their read preference */
+ *must_use_primary = override_use_primary;
+ }
+
+ /* Single server --
+ * Either it is suitable or it isn't */
+ if (topology->type == MONGOC_TOPOLOGY_SINGLE) {
+ const mongoc_server_description_t *server =
+ mongoc_set_get_item_const (td_servers, 0);
+ if (_mongoc_topology_description_server_is_candidate (
+ server->type, data.read_mode, topology->type)) {
+ _mongoc_array_append_val (set, server);
+ } else {
+ TRACE (
+ "Rejected [%s] [%s] for read mode [%s] with topology type Single",
+ mongoc_server_description_type (server),
+ server->host.host_and_port,
+ _mongoc_read_mode_as_str (data.read_mode));
+ }
+ goto DONE;
+ }
+
+ /* Replica sets --
+ * Find suitable servers based on read mode */
+ if (topology->type == MONGOC_TOPOLOGY_RS_NO_PRIMARY ||
+ topology->type == MONGOC_TOPOLOGY_RS_WITH_PRIMARY) {
+ switch (optype) {
+ case MONGOC_SS_AGGREGATE_WITH_WRITE:
+ case MONGOC_SS_READ: {
+ mongoc_set_for_each_const (
+ td_servers, _mongoc_replica_set_read_suitable_cb, &data);
+
+ if (data.read_mode == MONGOC_READ_PRIMARY) {
+ if (data.primary) {
+ _mongoc_array_append_val (set, data.primary);
+ }
+
+ goto DONE;
+ }
+
+ if (data.read_mode == MONGOC_READ_PRIMARY_PREFERRED && data.primary) {
+ _mongoc_array_append_val (set, data.primary);
+ goto DONE;
+ }
+
+ if (data.read_mode == MONGOC_READ_SECONDARY_PREFERRED) {
+ /* try read_mode SECONDARY */
+ _mongoc_try_mode_secondary (
+ set, topology, read_pref, must_use_primary, local_threshold_ms);
+
+ /* otherwise fall back to primary */
+ if (!set->len && data.primary) {
+ _mongoc_array_append_val (set, data.primary);
+ }
+
+ goto DONE;
+ }
+
+ if (data.read_mode == MONGOC_READ_SECONDARY) {
+ for (i = 0; i < data.candidates_len; i++) {
+ if (data.candidates[i] &&
+ data.candidates[i]->type != MONGOC_SERVER_RS_SECONDARY) {
+ TRACE ("Rejected [%s] [%s] for mode [%s] with RS topology",
+ mongoc_server_description_type (data.candidates[i]),
+ data.candidates[i]->host.host_and_port,
+ _mongoc_read_mode_as_str (data.read_mode));
+ data.candidates[i] = NULL;
+ }
+ }
+ }
+
+ /* mode is SECONDARY or NEAREST, filter by staleness and tags */
+ mongoc_server_description_filter_stale (data.candidates,
+ data.candidates_len,
+ data.primary,
+ topology->heartbeat_msec,
+ read_pref);
+
+ mongoc_server_description_filter_tags (
+ data.candidates, data.candidates_len, read_pref);
+ } break;
+ case MONGOC_SS_WRITE: {
+ if (topology->type == MONGOC_TOPOLOGY_RS_WITH_PRIMARY) {
+ mongoc_set_for_each_const (
+ td_servers,
+ _mongoc_topology_description_has_primary_cb,
+ (void *) &data.primary);
+ if (data.primary) {
+ _mongoc_array_append_val (set, data.primary);
+ goto DONE;
+ }
+ }
+ } break;
+ default:
+ BSON_UNREACHABLE ("Invalid optype");
+ }
+ }
+
+ /* Sharded clusters --
+ * All candidates in the latency window are suitable */
+ if (topology->type == MONGOC_TOPOLOGY_SHARDED) {
+ mongoc_set_for_each_const (
+ td_servers, _mongoc_find_suitable_mongos_cb, &data);
+ }
+
+ /* Load balanced clusters --
+ * Always select the only server. */
+ if (topology->type == MONGOC_TOPOLOGY_LOAD_BALANCED) {
+ const mongoc_server_description_t *server;
+ BSON_ASSERT (td_servers->items_len == 1);
+ server = mongoc_set_get_item_const (td_servers, 0);
+ _mongoc_array_append_val (set, server);
+ goto DONE;
+ }
+
+ /* Ways to get here:
+ * - secondary read
+ * - secondary preferred read
+ * - primary_preferred and no primary read
+ * - sharded anything
+ * Find the nearest, then select within the window */
+
+ for (i = 0; i < data.candidates_len; i++) {
+ if (data.candidates[i] &&
+ (nearest == -1 ||
+ nearest > data.candidates[i]->round_trip_time_msec)) {
+ nearest = data.candidates[i]->round_trip_time_msec;
+ }
+ }
+
+ for (i = 0; i < data.candidates_len; i++) {
+ if (data.candidates[i] && (data.candidates[i]->round_trip_time_msec <=
+ nearest + local_threshold_ms)) {
+ _mongoc_array_append_val (set, data.candidates[i]);
+ }
+ }
+
+DONE:
+
+ bson_free ((mongoc_server_description_t *) data.candidates);
+
+ return;
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_topology_description_has_data_node --
+ *
+ * Internal method: are any servers not Arbiter, Ghost, or Unknown?
+ *
+ *--------------------------------------------------------------------------
+ */
+bool
+mongoc_topology_description_has_data_node (
+ const mongoc_topology_description_t *td)
+{
+ int i;
+ const mongoc_set_t *servers = mc_tpld_servers_const (td);
+
+ for (i = 0; i < (int) servers->items_len; i++) {
+ const mongoc_server_description_t *sd =
+ mongoc_set_get_item_const (servers, i);
+ if (_is_data_node (sd)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/*
+ *-------------------------------------------------------------------------
+ *
+ * mongoc_topology_description_select --
+ *
+ * Return a server description of a node that is appropriate for
+ * the given read preference and operation type.
+ *
+ * NOTE: this method simply attempts to select a server from the
+ * current topology, it does not retry or trigger topology checks.
+ *
+ * Returns:
+ * Selected server description, or NULL upon failure.
+ *
+ * Side effects:
+ * None.
+ *
+ *-------------------------------------------------------------------------
+ */
+mongoc_server_description_t const *
+mongoc_topology_description_select (
+ const mongoc_topology_description_t *topology,
+ mongoc_ss_optype_t optype,
+ const mongoc_read_prefs_t *read_pref,
+ bool *must_use_primary,
+ int64_t local_threshold_ms)
+{
+ mongoc_array_t suitable_servers;
+ mongoc_server_description_t const *sd = NULL;
+ int rand_n;
+
+ ENTRY;
+
+ if (topology->type == MONGOC_TOPOLOGY_SINGLE) {
+ sd = mongoc_set_get_item_const (mc_tpld_servers_const (topology), 0);
+
+ if (optype == MONGOC_SS_AGGREGATE_WITH_WRITE &&
+ sd->max_wire_version < WIRE_VERSION_5_0) {
+ /* The single server may be part of an unseen replica set that may not
+ * support aggr-with-write operations on secondaries. Force the read
+ * preference to use a primary. */
+ if (must_use_primary) {
+ *must_use_primary = true;
+ }
+ }
+
+ if (sd->has_hello_response) {
+ RETURN (sd);
+ } else {
+ TRACE ("Topology type single, [%s] is down", sd->host.host_and_port);
+ RETURN (NULL);
+ }
+ }
+
+ _mongoc_array_init (&suitable_servers,
+ sizeof (mongoc_server_description_t *));
+
+ mongoc_topology_description_suitable_servers (&suitable_servers,
+ optype,
+ topology,
+ read_pref,
+ must_use_primary,
+ local_threshold_ms);
+ if (suitable_servers.len != 0) {
+ rand_n = _mongoc_rand_simple ((unsigned *) &topology->rand_seed);
+ sd = _mongoc_array_index (&suitable_servers,
+ mongoc_server_description_t *,
+ rand_n % suitable_servers.len);
+ }
+
+ _mongoc_array_destroy (&suitable_servers);
+
+ if (sd) {
+ TRACE ("Topology type [%s], selected [%s] [%s]",
+ mongoc_topology_description_type (topology),
+ mongoc_server_description_type (sd),
+ sd->host.host_and_port);
+ }
+
+ RETURN (sd);
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_topology_description_server_by_id --
+ *
+ * Get the server description for @id, if that server is present
+ * in @description. Otherwise, return NULL and fill out optional
+ * @error.
+ *
+ * NOTE: In most cases, caller should create a duplicate of the
+ * returned server description.
+ *
+ * Returns:
+ * A mongoc_server_description_t *, or NULL.
+ *
+ * Side effects:
+ * Fills out optional @error if server not found.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+mongoc_server_description_t *
+mongoc_topology_description_server_by_id (
+ mongoc_topology_description_t *description, uint32_t id, bson_error_t *error)
+{
+ return (mongoc_server_description_t *)
+ mongoc_topology_description_server_by_id_const (description, id, error);
+}
+
+const mongoc_server_description_t *
+mongoc_topology_description_server_by_id_const (
+ const mongoc_topology_description_t *td, uint32_t id, bson_error_t *error)
+{
+ const mongoc_server_description_t *sd;
+
+ BSON_ASSERT_PARAM (td);
+
+ sd = mongoc_set_get_const (mc_tpld_servers_const (td), id);
+ if (!sd) {
+ bson_set_error (error,
+ MONGOC_ERROR_STREAM,
+ MONGOC_ERROR_STREAM_NOT_ESTABLISHED,
+ "Could not find description for node %u",
+ id);
+ }
+
+ return sd;
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_topology_description_remove_server --
+ *
+ * If present, remove this server from this topology description.
+ *
+ * Returns:
+ * None.
+ *
+ * Side effects:
+ * Removes the server description from topology and destroys it.
+ *
+ *--------------------------------------------------------------------------
+ */
+static void
+_mongoc_topology_description_remove_server (
+ mongoc_topology_description_t *description,
+ const mongoc_server_description_t *server)
+{
+ BSON_ASSERT (description);
+ BSON_ASSERT (server);
+
+ _mongoc_topology_description_monitor_server_closed (description, server);
+ mongoc_set_rm (mc_tpld_servers (description), server->id);
+
+ /* Check if removing server resulted in an empty set of servers */
+ if (mc_tpld_servers_const (description)->items_len == 0) {
+ MONGOC_WARNING ("Last server removed from topology");
+ }
+}
+
+typedef struct _mongoc_address_and_id_t {
+ const char *address; /* IN */
+ bool found; /* OUT */
+ uint32_t id; /* OUT */
+} mongoc_address_and_id_t;
+
+/* find the given server and stop iterating */
+static bool
+_mongoc_topology_description_has_server_cb (const void *item,
+ void *ctx /* IN - OUT */)
+{
+ const mongoc_server_description_t *server = item;
+ mongoc_address_and_id_t *data = (mongoc_address_and_id_t *) ctx;
+
+ if (strcasecmp (data->address, server->connection_address) == 0) {
+ data->found = true;
+ data->id = server->id;
+ return false;
+ }
+ return true;
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_topology_description_has_set_version --
+ *
+ * Whether @topology's max replica set version has been set.
+ *
+ * Returns:
+ * True if the max setVersion was ever set.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+static bool
+_mongoc_topology_description_has_set_version (mongoc_topology_description_t *td)
+{
+ return td->max_set_version != MONGOC_NO_SET_VERSION;
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_topology_description_topology_has_server --
+ *
+ * Return true if @server is in @topology. If so, place its id in
+ * @id if given.
+ *
+ * Returns:
+ * True if server is in topology, false otherwise.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+static bool
+_mongoc_topology_description_has_server (
+ mongoc_topology_description_t *description,
+ const char *address,
+ uint32_t *id /* OUT */)
+{
+ mongoc_address_and_id_t data;
+
+ BSON_ASSERT (description);
+ BSON_ASSERT (address);
+
+ data.address = address;
+ data.found = false;
+ mongoc_set_for_each_const (mc_tpld_servers_const (description),
+ _mongoc_topology_description_has_server_cb,
+ &data);
+
+ if (data.found && id) {
+ *id = data.id;
+ }
+
+ return data.found;
+}
+
+typedef struct _mongoc_address_and_type_t {
+ const char *address;
+ mongoc_server_description_type_t type;
+} mongoc_address_and_type_t;
+
+static bool
+_mongoc_label_unknown_member_cb (void *item, void *ctx)
+{
+ mongoc_server_description_t *server = (mongoc_server_description_t *) item;
+ mongoc_address_and_type_t *data = (mongoc_address_and_type_t *) ctx;
+
+ if (strcasecmp (server->connection_address, data->address) == 0 &&
+ server->type == MONGOC_SERVER_UNKNOWN) {
+ mongoc_server_description_set_state (server, data->type);
+ return false;
+ }
+ return true;
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_topology_description_label_unknown_member --
+ *
+ * Find the server description with the given @address and if its
+ * type is UNKNOWN, set its type to @type.
+ *
+ * Returns:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+static void
+_mongoc_topology_description_label_unknown_member (
+ mongoc_topology_description_t *description,
+ const char *address,
+ mongoc_server_description_type_t type)
+{
+ mongoc_address_and_type_t data;
+
+ BSON_ASSERT (description);
+ BSON_ASSERT (address);
+
+ data.type = type;
+ data.address = address;
+
+ mongoc_set_for_each (
+ mc_tpld_servers (description), _mongoc_label_unknown_member_cb, &data);
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_topology_description_set_state --
+ *
+ * Change the state of this cluster and unblock things waiting
+ * on a change of topology type.
+ *
+ * Returns:
+ * None.
+ *
+ * Side effects:
+ * Unblocks anything waiting on this description to change states.
+ *
+ *--------------------------------------------------------------------------
+ */
+static void
+_mongoc_topology_description_set_state (
+ mongoc_topology_description_t *description,
+ mongoc_topology_description_type_t type)
+{
+ description->type = type;
+}
+
+
+static void
+_update_rs_type (mongoc_topology_description_t *topology)
+{
+ if (_mongoc_topology_description_has_primary (topology)) {
+ _mongoc_topology_description_set_state (topology,
+ MONGOC_TOPOLOGY_RS_WITH_PRIMARY);
+ } else {
+ _mongoc_topology_description_set_state (topology,
+ MONGOC_TOPOLOGY_RS_NO_PRIMARY);
+ }
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_topology_description_check_if_has_primary --
+ *
+ * If there is a primary in topology, set topology
+ * type to RS_WITH_PRIMARY, otherwise set it to
+ * RS_NO_PRIMARY.
+ *
+ * Returns:
+ * None.
+ *
+ * Side effects:
+ * Changes the topology type.
+ *
+ *--------------------------------------------------------------------------
+ */
+static void
+_mongoc_topology_description_check_if_has_primary (
+ mongoc_topology_description_t *topology,
+ const mongoc_server_description_t *server)
+{
+ _update_rs_type (topology);
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_topology_description_invalidate_server --
+ *
+ * Invalidate a server if a network error occurred while using it in
+ * another part of the client. Server description is set to type
+ * UNKNOWN, the error is recorded, and other parameters are reset to
+ * defaults. Pass in the reason for invalidation in @error.
+ *
+ * @todo Try to remove this function when CDRIVER-3654 is complete.
+ * It is only called when an application thread needs to mark a server Unknown.
+ * But an application error is also tied to other behavior, and should also
+ * consider the connection generation. This logic is captured in
+ * _mongoc_topology_handle_app_error. This should not be called directly
+ */
+void
+mongoc_topology_description_invalidate_server (
+ mongoc_topology_description_t *td,
+ uint32_t id,
+ const bson_error_t *error /* IN */)
+{
+ BSON_ASSERT (error);
+
+ if (td->type == MONGOC_TOPOLOGY_LOAD_BALANCED) {
+ /* Load balancers must never be marked unknown. */
+ return;
+ }
+
+ /* send NULL hello reply */
+ mongoc_topology_description_handle_hello (
+ td, id, NULL, MONGOC_RTT_UNSET, error);
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_topology_description_add_server --
+ *
+ * Add the specified server to the cluster topology if it is not
+ * already a member. If @id, place its id in @id.
+ *
+ * Return:
+ * True if the server was added or already existed in the topology,
+ * false if an error occurred.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+bool
+mongoc_topology_description_add_server (mongoc_topology_description_t *topology,
+ const char *server,
+ uint32_t *id /* OUT */)
+{
+ uint32_t server_id;
+ mongoc_server_description_t *description;
+
+ BSON_ASSERT (topology);
+ BSON_ASSERT (server);
+
+ if (!_mongoc_topology_description_has_server (
+ topology, server, &server_id)) {
+ /* TODO this might not be an accurate count in all cases */
+ server_id = ++topology->max_server_id;
+
+ description =
+ (mongoc_server_description_t *) bson_malloc0 (sizeof *description);
+ mongoc_server_description_init (description, server, server_id);
+
+ mongoc_set_add (mc_tpld_servers (topology), server_id, description);
+
+ /* if we're in topology_new then no callbacks are registered and this is
+ * a no-op. later, if we discover a new RS member this sends an event. */
+ _mongoc_topology_description_monitor_server_opening (topology,
+ description);
+ }
+
+ if (id) {
+ *id = server_id;
+ }
+
+ return true;
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_topology_description_update_cluster_time --
+ *
+ * Drivers Session Spec: Drivers MUST examine responses to server commands to
+ * see if they contain a top level field named $clusterTime formatted as
+ * follows:
+ *
+ * {
+ * ...
+ * $clusterTime : {
+ * clusterTime : <BsonTimestamp>,
+ * signature : {
+ * hash : <BsonBinaryData>,
+ * keyId : <BsonInt64>
+ * }
+ * },
+ * ...
+ * }
+ *
+ * Whenever a driver receives a clusterTime from a server it MUST compare it
+ * to the current highest seen clusterTime for the cluster. If the new
+ * clusterTime is higher than the highest seen clusterTime it MUST become
+ * the new highest seen clusterTime. Two clusterTimes are compared using
+ * only the BsonTimestamp value of the clusterTime embedded field (be sure to
+ * include both the timestamp and the increment of the BsonTimestamp in the
+ * comparison). The signature field does not participate in the comparison.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+void
+mongoc_topology_description_update_cluster_time (
+ mongoc_topology_description_t *td, const bson_t *reply)
+{
+ bson_iter_t iter;
+ bson_iter_t child;
+ const uint8_t *data;
+ uint32_t size;
+ bson_t cluster_time;
+
+ if (!reply || !bson_iter_init_find (&iter, reply, "$clusterTime")) {
+ return;
+ }
+
+ if (!BSON_ITER_HOLDS_DOCUMENT (&iter) ||
+ !bson_iter_recurse (&iter, &child)) {
+ MONGOC_ERROR ("Can't parse $clusterTime");
+ return;
+ }
+
+ bson_iter_document (&iter, &size, &data);
+ BSON_ASSERT (bson_init_static (&cluster_time, data, (size_t) size));
+
+ if (bson_empty (&td->cluster_time) ||
+ _mongoc_cluster_time_greater (&cluster_time, &td->cluster_time)) {
+ bson_destroy (&td->cluster_time);
+ bson_copy_to (&cluster_time, &td->cluster_time);
+ }
+}
+
+
+static void
+_mongoc_topology_description_add_new_servers (
+ mongoc_topology_description_t *topology,
+ const mongoc_server_description_t *server)
+{
+ bson_iter_t member_iter;
+ const bson_t *rs_members[3];
+ int i;
+
+ rs_members[0] = &server->hosts;
+ rs_members[1] = &server->arbiters;
+ rs_members[2] = &server->passives;
+
+ for (i = 0; i < 3; i++) {
+ BSON_ASSERT (bson_iter_init (&member_iter, rs_members[i]));
+
+ while (bson_iter_next (&member_iter)) {
+ mongoc_topology_description_add_server (
+ topology, bson_iter_utf8 (&member_iter, NULL), NULL);
+ }
+ }
+}
+
+typedef struct _mongoc_primary_and_topology_t {
+ mongoc_topology_description_t *topology;
+ const mongoc_server_description_t *primary;
+} mongoc_primary_and_topology_t;
+
+/* invalidate old primaries */
+static bool
+_mongoc_topology_description_invalidate_primaries_cb (void *item, void *ctx)
+{
+ mongoc_server_description_t *server = (mongoc_server_description_t *) item;
+ mongoc_primary_and_topology_t *data = (mongoc_primary_and_topology_t *) ctx;
+
+ if (server->id != data->primary->id &&
+ server->type == MONGOC_SERVER_RS_PRIMARY) {
+ mongoc_server_description_set_state (server, MONGOC_SERVER_UNKNOWN);
+ mongoc_server_description_set_set_version (server, MONGOC_NO_SET_VERSION);
+ mongoc_server_description_set_election_id (server, NULL);
+ mongoc_server_description_reset (server);
+ }
+ return true;
+}
+
+
+/* Remove and destroy all replica set members not in primary's hosts lists */
+static void
+_mongoc_topology_description_remove_unreported_servers (
+ mongoc_topology_description_t *topology,
+ const mongoc_server_description_t *primary)
+{
+ mongoc_array_t to_remove;
+ int i;
+
+ _mongoc_array_init (&to_remove, sizeof (mongoc_server_description_t *));
+
+ /* Accumulate servers to be removed - do this before calling
+ * _mongoc_topology_description_remove_server, which could call
+ * mongoc_server_description_cleanup on the primary itself if it
+ * doesn't report its own connection_address in its hosts list.
+ * See hosts_differ_from_seeds.json */
+ for (i = 0; i < mc_tpld_servers_const (topology)->items_len; i++) {
+ const mongoc_server_description_t *member =
+ mongoc_set_get_item_const (mc_tpld_servers_const (topology), i);
+ const char *address = member->connection_address;
+ if (!mongoc_server_description_has_rs_member (primary, address)) {
+ _mongoc_array_append_val (&to_remove, member);
+ }
+ }
+
+ /* now it's safe to call _mongoc_topology_description_remove_server,
+ * even on the primary */
+ for (i = 0; i < to_remove.len; i++) {
+ const mongoc_server_description_t *member =
+ _mongoc_array_index (&to_remove, mongoc_server_description_t *, i);
+
+ _mongoc_topology_description_remove_server (topology, member);
+ }
+
+ _mongoc_array_destroy (&to_remove);
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_topology_description_matches_me --
+ *
+ * Server Discovery And Monitoring Spec: "Removal from the topology of
+ * seed list members where the "me" property does not match the address
+ * used to connect prevents clients from being able to select a server,
+ * only to fail to re-select that server once the primary has responded.
+ *
+ * Returns:
+ * True if "me" matches "connection_address".
+ *
+ * Side Effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+static bool
+_mongoc_topology_description_matches_me (
+ const mongoc_server_description_t *server)
+{
+ BSON_ASSERT (server->connection_address);
+
+ if (!server->me) {
+ /* "me" is unknown: consider it a match */
+ return true;
+ }
+
+ return strcasecmp (server->connection_address, server->me) == 0;
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_update_rs_from_primary --
+ *
+ * First, determine that this is really the primary:
+ * -If this node isn't in the cluster, do nothing.
+ * -If the cluster's set name is null, set it to node's set name.
+ * Otherwise if the cluster's set name is different from node's,
+ * we found a rogue primary, so remove it from the cluster and
+ * check the cluster for a primary, then return.
+ * -If any of the members of cluster reports an address different
+ * from node's, node cannot be the primary.
+ * Now that we know this is the primary:
+ * -If any hosts, passives, or arbiters in node's description aren't
+ * in the cluster, add them as UNKNOWN servers.
+ * -If the cluster has any servers that aren't in node's description,
+ * remove and destroy them.
+ * Finally, check the cluster for the new primary.
+ *
+ * Returns:
+ * None.
+ *
+ * Side effects:
+ * Changes to the cluster, possible removal of cluster nodes.
+ *
+ *--------------------------------------------------------------------------
+ */
+static void
+_mongoc_topology_description_update_rs_from_primary (
+ mongoc_topology_description_t *topology,
+ const mongoc_server_description_t *server)
+{
+ mongoc_primary_and_topology_t data;
+ bson_error_t error;
+
+ BSON_ASSERT (topology);
+ BSON_ASSERT (server);
+
+ if (!_mongoc_topology_description_has_server (
+ topology, server->connection_address, NULL))
+ return;
+
+ /* If server->set_name was null this function wouldn't be called from
+ * mongoc_server_description_handle_hello(). static code analyzers however
+ * don't know that so we check for it explicitly. */
+ if (server->set_name) {
+ /* 'Server' can only be the primary if it has the right rs name */
+
+ if (!topology->set_name) {
+ topology->set_name = bson_strdup (server->set_name);
+ } else if (strcmp (topology->set_name, server->set_name) != 0) {
+ _mongoc_topology_description_remove_server (topology, server);
+ _update_rs_type (topology);
+ return;
+ }
+ }
+
+ if (mongoc_server_description_has_set_version (server) &&
+ mongoc_server_description_has_election_id (server)) {
+ /* Server Discovery And Monitoring Spec: "The client remembers the
+ * greatest electionId reported by a primary, and distrusts primaries
+ * with lesser electionIds. This prevents the client from oscillating
+ * between the old and new primary during a split-brain period."
+ */
+ if (_mongoc_topology_description_later_election (topology, server)) {
+ bson_set_error (&error,
+ MONGOC_ERROR_STREAM,
+ MONGOC_ERROR_STREAM_CONNECT,
+ "member's setVersion or electionId is stale");
+ mongoc_topology_description_invalidate_server (
+ topology, server->id, &error);
+ _update_rs_type (topology);
+ return;
+ }
+
+ /* server's electionId >= topology's max electionId */
+ _mongoc_topology_description_set_max_election_id (topology, server);
+ }
+
+ if (mongoc_server_description_has_set_version (server) &&
+ (!_mongoc_topology_description_has_set_version (topology) ||
+ server->set_version > topology->max_set_version)) {
+ _mongoc_topology_description_set_max_set_version (topology, server);
+ }
+
+ /* 'Server' is the primary! Invalidate other primaries if found */
+ data.primary = server;
+ data.topology = topology;
+ mongoc_set_for_each (mc_tpld_servers (topology),
+ _mongoc_topology_description_invalidate_primaries_cb,
+ &data);
+
+ /* Add to topology description any new servers primary knows about */
+ _mongoc_topology_description_add_new_servers (topology, server);
+
+ /* Remove from topology description any servers primary doesn't know about */
+ _mongoc_topology_description_remove_unreported_servers (topology, server);
+
+ /* Finally, set topology type */
+ _update_rs_type (topology);
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_topology_description_update_rs_without_primary --
+ *
+ * Update cluster's information when there is no primary.
+ *
+ * Returns:
+ * None.
+ *
+ * Side Effects:
+ * Alters cluster state, may remove node from cluster.
+ *
+ *--------------------------------------------------------------------------
+ */
+static void
+_mongoc_topology_description_update_rs_without_primary (
+ mongoc_topology_description_t *topology,
+ const mongoc_server_description_t *server)
+{
+ BSON_ASSERT (topology);
+ BSON_ASSERT (server);
+
+ if (!_mongoc_topology_description_has_server (
+ topology, server->connection_address, NULL)) {
+ return;
+ }
+
+ /* make sure we're talking about the same replica set */
+ if (server->set_name) {
+ if (!topology->set_name) {
+ topology->set_name = bson_strdup (server->set_name);
+ } else if (strcmp (topology->set_name, server->set_name) != 0) {
+ _mongoc_topology_description_remove_server (topology, server);
+ return;
+ }
+ }
+
+ /* Add new servers that this replica set member knows about */
+ _mongoc_topology_description_add_new_servers (topology, server);
+
+ /* If this server thinks there is a primary, label it POSSIBLE_PRIMARY */
+ if (server->current_primary) {
+ _mongoc_topology_description_label_unknown_member (
+ topology, server->current_primary, MONGOC_SERVER_POSSIBLE_PRIMARY);
+ }
+
+ if (!_mongoc_topology_description_matches_me (server)) {
+ _mongoc_topology_description_remove_server (topology, server);
+ return;
+ }
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_topology_description_update_rs_with_primary_from_member --
+ *
+ * Update cluster's information when there is a primary, but the
+ * update is coming from another replica set member.
+ *
+ * Returns:
+ * None.
+ *
+ * Side Effects:
+ * Alters cluster state.
+ *
+ *--------------------------------------------------------------------------
+ */
+static void
+_mongoc_topology_description_update_rs_with_primary_from_member (
+ mongoc_topology_description_t *topology,
+ const mongoc_server_description_t *server)
+{
+ BSON_ASSERT (topology);
+ BSON_ASSERT (server);
+
+ if (!_mongoc_topology_description_has_server (
+ topology, server->connection_address, NULL)) {
+ return;
+ }
+
+ /* set_name should never be null here */
+ if (strcmp (topology->set_name, server->set_name) != 0) {
+ _mongoc_topology_description_remove_server (topology, server);
+ _update_rs_type (topology);
+ return;
+ }
+
+ if (!_mongoc_topology_description_matches_me (server)) {
+ _mongoc_topology_description_remove_server (topology, server);
+ return;
+ }
+
+ /* If there is no primary, label server's current_primary as the
+ * POSSIBLE_PRIMARY */
+ if (!_mongoc_topology_description_has_primary (topology) &&
+ server->current_primary) {
+ _mongoc_topology_description_set_state (topology,
+ MONGOC_TOPOLOGY_RS_NO_PRIMARY);
+ _mongoc_topology_description_label_unknown_member (
+ topology, server->current_primary, MONGOC_SERVER_POSSIBLE_PRIMARY);
+ }
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_topology_description_set_topology_type_to_sharded --
+ *
+ * Sets topology's type to SHARDED.
+ *
+ * Returns:
+ * None
+ *
+ * Side effects:
+ * Alter's topology's type
+ *
+ *--------------------------------------------------------------------------
+ */
+static void
+_mongoc_topology_description_set_topology_type_to_sharded (
+ mongoc_topology_description_t *topology,
+ const mongoc_server_description_t *server)
+{
+ _mongoc_topology_description_set_state (topology, MONGOC_TOPOLOGY_SHARDED);
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_topology_description_transition_unknown_to_rs_no_primary --
+ *
+ * Encapsulates transition from cluster state UNKNOWN to
+ * RS_NO_PRIMARY. Sets the type to RS_NO_PRIMARY,
+ * then updates the replica set accordingly.
+ *
+ * Returns:
+ * None.
+ *
+ * Side effects:
+ * Changes topology state.
+ *
+ *--------------------------------------------------------------------------
+ */
+static void
+_mongoc_topology_description_transition_unknown_to_rs_no_primary (
+ mongoc_topology_description_t *topology,
+ const mongoc_server_description_t *server)
+{
+ _mongoc_topology_description_set_state (topology,
+ MONGOC_TOPOLOGY_RS_NO_PRIMARY);
+ _mongoc_topology_description_update_rs_without_primary (topology, server);
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_topology_description_remove_and_check_primary --
+ *
+ * Remove the server and check if the topology still has a primary.
+ *
+ * Returns:
+ * None.
+ *
+ * Side effects:
+ * Removes server from topology and destroys it.
+ *
+ *--------------------------------------------------------------------------
+ */
+static void
+_mongoc_topology_description_remove_and_check_primary (
+ mongoc_topology_description_t *topology,
+ const mongoc_server_description_t *server)
+{
+ _mongoc_topology_description_remove_server (topology, server);
+ _update_rs_type (topology);
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_topology_description_update_unknown_with_standalone --
+ *
+ * If the cluster doesn't contain this server, do nothing.
+ * Otherwise, if the topology only has one seed, change its
+ * type to SINGLE. If the topology has multiple seeds, it does not
+ * include us, so remove this server and destroy it.
+ *
+ * Returns:
+ * None.
+ *
+ * Side effects:
+ * Changes the topology type, might remove server from topology.
+ *
+ *--------------------------------------------------------------------------
+ */
+static void
+_mongoc_topology_description_update_unknown_with_standalone (
+ mongoc_topology_description_t *topology,
+ const mongoc_server_description_t *server)
+{
+ BSON_ASSERT (topology);
+ BSON_ASSERT (server);
+
+ if (!_mongoc_topology_description_has_server (
+ topology, server->connection_address, NULL))
+ return;
+
+ if (mc_tpld_servers_const (topology)->items_len > 1) {
+ /* This cluster contains other servers, it cannot be a standalone. */
+ _mongoc_topology_description_remove_server (topology, server);
+ } else {
+ _mongoc_topology_description_set_state (topology, MONGOC_TOPOLOGY_SINGLE);
+ }
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * This table implements the 'ToplogyType' table outlined in the Server
+ * Discovery and Monitoring spec. Each row represents a server type,
+ * and each column represents the topology type. Given a current topology
+ * type T and a newly-observed server type S, use the function at
+ * state_transions[S][T] to transition to a new state.
+ *
+ * Rows should be read like so:
+ * { server type for this row
+ * UNKNOWN,
+ * SHARDED,
+ * RS_NO_PRIMARY,
+ * RS_WITH_PRIMARY
+ * }
+ *
+ *--------------------------------------------------------------------------
+ */
+
+typedef void (*transition_t) (mongoc_topology_description_t *topology,
+ const mongoc_server_description_t *server);
+
+transition_t gSDAMTransitionTable
+ [MONGOC_SERVER_DESCRIPTION_TYPES][MONGOC_TOPOLOGY_DESCRIPTION_TYPES] = {
+ {
+ /* UNKNOWN */
+ NULL, /* MONGOC_TOPOLOGY_UNKNOWN */
+ NULL, /* MONGOC_TOPOLOGY_SHARDED */
+ NULL, /* MONGOC_TOPOLOGY_RS_NO_PRIMARY */
+ _mongoc_topology_description_check_if_has_primary /* MONGOC_TOPOLOGY_RS_WITH_PRIMARY
+ */
+ },
+ {/* STANDALONE */
+ _mongoc_topology_description_update_unknown_with_standalone,
+ _mongoc_topology_description_remove_server,
+ _mongoc_topology_description_remove_server,
+ _mongoc_topology_description_remove_and_check_primary},
+ {/* MONGOS */
+ _mongoc_topology_description_set_topology_type_to_sharded,
+ NULL,
+ _mongoc_topology_description_remove_server,
+ _mongoc_topology_description_remove_and_check_primary},
+ {/* POSSIBLE_PRIMARY */
+ NULL,
+ NULL,
+ NULL,
+ NULL},
+ {/* PRIMARY */
+ _mongoc_topology_description_update_rs_from_primary,
+ _mongoc_topology_description_remove_server,
+ _mongoc_topology_description_update_rs_from_primary,
+ _mongoc_topology_description_update_rs_from_primary},
+ {/* SECONDARY */
+ _mongoc_topology_description_transition_unknown_to_rs_no_primary,
+ _mongoc_topology_description_remove_server,
+ _mongoc_topology_description_update_rs_without_primary,
+ _mongoc_topology_description_update_rs_with_primary_from_member},
+ {/* ARBITER */
+ _mongoc_topology_description_transition_unknown_to_rs_no_primary,
+ _mongoc_topology_description_remove_server,
+ _mongoc_topology_description_update_rs_without_primary,
+ _mongoc_topology_description_update_rs_with_primary_from_member},
+ {/* RS_OTHER */
+ _mongoc_topology_description_transition_unknown_to_rs_no_primary,
+ _mongoc_topology_description_remove_server,
+ _mongoc_topology_description_update_rs_without_primary,
+ _mongoc_topology_description_update_rs_with_primary_from_member},
+ {/* RS_GHOST */
+ NULL,
+ _mongoc_topology_description_remove_server,
+ NULL,
+ _mongoc_topology_description_check_if_has_primary}};
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _tpld_type_str --
+ *
+ * Get this topology's type, one of the types defined in the Server
+ * Discovery And Monitoring Spec.
+ *
+ * Returns:
+ * A string.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+static const char *
+_tpld_type_str (mongoc_topology_description_type_t type)
+{
+ switch (type) {
+ case MONGOC_TOPOLOGY_UNKNOWN:
+ return "Unknown";
+ case MONGOC_TOPOLOGY_SHARDED:
+ return "Sharded";
+ case MONGOC_TOPOLOGY_RS_NO_PRIMARY:
+ return "RSNoPrimary";
+ case MONGOC_TOPOLOGY_RS_WITH_PRIMARY:
+ return "RSWithPrimary";
+ case MONGOC_TOPOLOGY_SINGLE:
+ return "Single";
+ case MONGOC_TOPOLOGY_LOAD_BALANCED:
+ return "LoadBalanced";
+ case MONGOC_TOPOLOGY_DESCRIPTION_TYPES:
+ default:
+ MONGOC_ERROR ("Invalid mongoc_topology_description_type_t type");
+ return "Invalid";
+ }
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_topology_description_update_session_timeout --
+ *
+ * Fill out td.session_timeout_minutes.
+ *
+ * Server Discovery and Monitoring Spec: "set logicalSessionTimeoutMinutes
+ * to the smallest logicalSessionTimeoutMinutes value among all
+ * ServerDescriptions of known ServerType. If any ServerDescription of
+ * known ServerType has a null logicalSessionTimeoutMinutes, then
+ * logicalSessionTimeoutMinutes MUST be set to null."
+ *
+ * --------------------------------------------------------------------------
+ */
+
+static void
+_mongoc_topology_description_update_session_timeout (
+ mongoc_topology_description_t *td)
+{
+ mongoc_set_t *set;
+ size_t i;
+ mongoc_server_description_t *sd;
+
+ set = mc_tpld_servers (td);
+
+ td->session_timeout_minutes = MONGOC_NO_SESSIONS;
+
+ for (i = 0; i < set->items_len; i++) {
+ sd = (mongoc_server_description_t *) mongoc_set_get_item (set, (int) i);
+ if (!_is_data_node (sd)) {
+ continue;
+ }
+
+ if (sd->session_timeout_minutes == MONGOC_NO_SESSIONS) {
+ td->session_timeout_minutes = MONGOC_NO_SESSIONS;
+ return;
+ } else if (td->session_timeout_minutes == MONGOC_NO_SESSIONS) {
+ td->session_timeout_minutes = sd->session_timeout_minutes;
+ } else if (td->session_timeout_minutes > sd->session_timeout_minutes) {
+ td->session_timeout_minutes = sd->session_timeout_minutes;
+ }
+ }
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_topology_description_check_compatible --
+ *
+ * Fill out td.compatibility_error if any server's wire versions do
+ * not overlap with ours. Otherwise clear td.compatibility_error.
+ *
+ * If any server is incompatible, the topology as a whole is considered
+ * incompatible.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+static void
+_mongoc_topology_description_check_compatible (
+ mongoc_topology_description_t *td)
+{
+ size_t i;
+ mongoc_set_t const *const servers = mc_tpld_servers_const (td);
+
+ memset (&td->compatibility_error, 0, sizeof (bson_error_t));
+
+ for (i = 0; i < servers->items_len; i++) {
+ mongoc_server_description_t const *const sd =
+ mongoc_set_get_item_const (servers, (int) i);
+ if (sd->type == MONGOC_SERVER_UNKNOWN ||
+ sd->type == MONGOC_SERVER_POSSIBLE_PRIMARY) {
+ continue;
+ }
+
+ if (sd->min_wire_version > WIRE_VERSION_MAX) {
+ bson_set_error (
+ &td->compatibility_error,
+ MONGOC_ERROR_PROTOCOL,
+ MONGOC_ERROR_PROTOCOL_BAD_WIRE_VERSION,
+ "Server at %s requires wire version %d,"
+ " but this version of libmongoc only supports up to %d",
+ sd->host.host_and_port,
+ sd->min_wire_version,
+ WIRE_VERSION_MAX);
+ } else if (sd->max_wire_version < WIRE_VERSION_MIN) {
+ bson_set_error (
+ &td->compatibility_error,
+ MONGOC_ERROR_PROTOCOL,
+ MONGOC_ERROR_PROTOCOL_BAD_WIRE_VERSION,
+ "Server at %s reports wire version %d, but this"
+ " version of libmongoc requires at least %d (MongoDB %s)",
+ sd->host.host_and_port,
+ sd->max_wire_version,
+ WIRE_VERSION_MIN,
+ _mongoc_wire_version_to_server_version (WIRE_VERSION_MIN));
+ }
+ }
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_topology_description_handle_hello --
+ *
+ * Handle a hello. This is called by the background SDAM process,
+ * and by client when performing a handshake or invalidating servers.
+ * If there was an error calling hello, pass it in as @error.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+void
+mongoc_topology_description_handle_hello (
+ mongoc_topology_description_t *topology,
+ uint32_t server_id,
+ const bson_t *hello_response,
+ int64_t rtt_msec,
+ const bson_error_t *error /* IN */)
+{
+ mongoc_topology_description_t *prev_td = NULL;
+ mongoc_server_description_t *prev_sd = NULL;
+ mongoc_server_description_t *sd;
+ bson_iter_t iter;
+ /* sd_changed is set if the server description meaningfully changed AND
+ * callbacks are registered. */
+ bool sd_changed = false;
+
+ BSON_ASSERT (topology);
+ BSON_ASSERT (server_id != 0);
+
+ sd = mongoc_topology_description_server_by_id (topology, server_id, NULL);
+ if (!sd) {
+ return; /* server already removed from topology */
+ }
+
+ if (topology->apm_callbacks.topology_changed) {
+ prev_td = bson_malloc0 (sizeof (mongoc_topology_description_t));
+ _mongoc_topology_description_copy_to (topology, prev_td);
+ }
+
+ if (hello_response &&
+ bson_iter_init_find (&iter, hello_response, "topologyVersion") &&
+ BSON_ITER_HOLDS_DOCUMENT (&iter)) {
+ bson_t incoming_topology_version;
+ const uint8_t *bytes;
+ uint32_t len;
+
+ bson_iter_document (&iter, &len, &bytes);
+ bson_init_static (&incoming_topology_version, bytes, len);
+
+ if (mongoc_server_description_topology_version_cmp (
+ &sd->topology_version, &incoming_topology_version) == 1) {
+ TRACE ("%s", "topology version is strictly less. Skipping.");
+ if (prev_td) {
+ mongoc_topology_description_cleanup (prev_td);
+ bson_free (prev_td);
+ }
+ return;
+ }
+ }
+
+ if (topology->apm_callbacks.topology_changed ||
+ topology->apm_callbacks.server_changed) {
+ /* Only copy the previous server description if a monitoring callback is
+ * registered. */
+ prev_sd = mongoc_server_description_new_copy (sd);
+ }
+
+ DUMP_BSON (hello_response);
+ /* pass the current error in */
+
+ mongoc_server_description_handle_hello (sd, hello_response, rtt_msec, error);
+
+ /* if the user specified a set_name in the connection string
+ * and they are in topology type single, check that the set name
+ * matches. */
+ if (topology->set_name && topology->type == MONGOC_TOPOLOGY_SINGLE) {
+ bool wrong_set_name = false;
+ bson_error_t set_name_err = {0};
+
+ if (!sd->set_name) {
+ wrong_set_name = true;
+ bson_set_error (&set_name_err,
+ MONGOC_ERROR_SERVER_SELECTION,
+ MONGOC_ERROR_SERVER_SELECTION_FAILURE,
+ "no reported set name, but expected '%s'",
+ topology->set_name);
+ } else if (0 != strcmp (sd->set_name, topology->set_name)) {
+ wrong_set_name = true;
+ bson_set_error (&set_name_err,
+ MONGOC_ERROR_SERVER_SELECTION,
+ MONGOC_ERROR_SERVER_SELECTION_FAILURE,
+ "reported set name '%s' does not match '%s'",
+ sd->set_name,
+ topology->set_name);
+ }
+
+ if (wrong_set_name) {
+ /* Replace with unknown. */
+ TRACE ("%s", "wrong set name");
+ mongoc_server_description_handle_hello (
+ sd, NULL, MONGOC_RTT_UNSET, &set_name_err);
+ }
+ }
+
+ mongoc_topology_description_update_cluster_time (topology, hello_response);
+
+ if (prev_sd) {
+ sd_changed = !_mongoc_server_description_equal (prev_sd, sd);
+ }
+ if (sd_changed) {
+ _mongoc_topology_description_monitor_server_changed (
+ topology, prev_sd, sd);
+ }
+
+ if (gSDAMTransitionTable[sd->type][topology->type]) {
+ TRACE ("Topology description %s handling server description %s",
+ _tpld_type_str (topology->type),
+ mongoc_server_description_type (sd));
+ gSDAMTransitionTable[sd->type][topology->type](topology, sd);
+ } else {
+ TRACE ("Topology description %s ignoring server description %s",
+ _tpld_type_str (topology->type),
+ mongoc_server_description_type (sd));
+ }
+
+ _mongoc_topology_description_update_session_timeout (topology);
+
+ /* Don't bother checking wire version compatibility if we already errored */
+ if (hello_response && (!error || !error->code)) {
+ _mongoc_topology_description_check_compatible (topology);
+ }
+
+ /* If server description did not change, then neither did topology
+ * description */
+ if (sd_changed) {
+ _mongoc_topology_description_monitor_changed (prev_td, topology);
+ }
+
+ if (prev_td) {
+ mongoc_topology_description_cleanup (prev_td);
+ bson_free (prev_td);
+ }
+
+ mongoc_server_description_destroy (prev_sd);
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_topology_description_has_readable_server --
+ *
+ * SDAM Monitoring Spec:
+ * "Determines if the topology has a readable server available."
+ *
+ * NOTE: this method should only be called by user code in an SDAM
+ * Monitoring callback.
+ *
+ *--------------------------------------------------------------------------
+ */
+bool
+mongoc_topology_description_has_readable_server (
+ const mongoc_topology_description_t *td, const mongoc_read_prefs_t *prefs)
+{
+ bson_error_t error;
+
+ if (!mongoc_topology_compatible (td, NULL, &error)) {
+ return false;
+ }
+
+ /* local threshold argument doesn't matter */
+ return mongoc_topology_description_select (
+ td, MONGOC_SS_READ, prefs, NULL, 0) != NULL;
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_topology_description_has_writable_server --
+ *
+ * SDAM Monitoring Spec:
+ * "Determines if the topology has a writable server available."
+ *
+ * NOTE: this method should only be called by user code in an SDAM
+ * Monitoring callback.
+ *
+ *--------------------------------------------------------------------------
+ */
+bool
+mongoc_topology_description_has_writable_server (
+ const mongoc_topology_description_t *td)
+{
+ bson_error_t error;
+
+ if (!mongoc_topology_compatible (td, NULL, &error)) {
+ return false;
+ }
+
+ return mongoc_topology_description_select (
+ td, MONGOC_SS_WRITE, NULL, NULL, 0) != NULL;
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_topology_description_type --
+ *
+ * Get this topology's type, one of the types defined in the Server
+ * Discovery And Monitoring Spec.
+ *
+ * NOTE: this method should only be called by user code in an SDAM
+ * Monitoring callback.
+ *
+ * Returns:
+ * A string.
+ *
+ *--------------------------------------------------------------------------
+ */
+const char *
+mongoc_topology_description_type (const mongoc_topology_description_t *td)
+{
+ switch (td->type) {
+ case MONGOC_TOPOLOGY_UNKNOWN:
+ return "Unknown";
+ case MONGOC_TOPOLOGY_SHARDED:
+ return "Sharded";
+ case MONGOC_TOPOLOGY_RS_NO_PRIMARY:
+ return "ReplicaSetNoPrimary";
+ case MONGOC_TOPOLOGY_RS_WITH_PRIMARY:
+ return "ReplicaSetWithPrimary";
+ case MONGOC_TOPOLOGY_SINGLE:
+ return "Single";
+ case MONGOC_TOPOLOGY_LOAD_BALANCED:
+ return "LoadBalanced";
+ case MONGOC_TOPOLOGY_DESCRIPTION_TYPES:
+ default:
+ fprintf (stderr, "ERROR: Unknown topology type %d\n", td->type);
+ BSON_ASSERT (0);
+ }
+
+ return NULL;
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_topology_description_get_servers --
+ *
+ * Fetch an array of server descriptions for all known servers in the
+ * topology.
+ *
+ * Returns:
+ * An array you must free with mongoc_server_descriptions_destroy_all.
+ *
+ *--------------------------------------------------------------------------
+ */
+mongoc_server_description_t **
+mongoc_topology_description_get_servers (
+ const mongoc_topology_description_t *td, size_t *n /* OUT */)
+{
+ size_t i;
+ const mongoc_set_t *const set =
+ mc_tpld_servers_const (BSON_ASSERT_PTR_INLINE (td));
+ /* enough room for all descriptions, even if some are unknown */
+ mongoc_server_description_t **sds =
+ bson_malloc0 (sizeof (mongoc_server_description_t *) * set->items_len);
+
+ BSON_ASSERT_PARAM (n);
+
+ *n = 0;
+
+ for (i = 0; i < set->items_len; ++i) {
+ const mongoc_server_description_t *sd =
+ mongoc_set_get_item_const (set, (int) i);
+
+ if (sd->type != MONGOC_SERVER_UNKNOWN) {
+ sds[*n] = mongoc_server_description_new_copy (sd);
+ ++(*n);
+ }
+ }
+
+ return sds;
+}
+
+typedef struct {
+ mongoc_host_list_t *host_list;
+ size_t num_missing;
+} _count_num_hosts_to_remove_ctx_t;
+
+static bool
+_count_num_hosts_to_remove (void *sd_void, void *ctx_void)
+{
+ mongoc_server_description_t *sd;
+ _count_num_hosts_to_remove_ctx_t *ctx;
+ mongoc_host_list_t *host_list;
+
+ sd = sd_void;
+ ctx = ctx_void;
+ host_list = ctx->host_list;
+
+ if (!_mongoc_host_list_contains_one (host_list, &sd->host)) {
+ ++ctx->num_missing;
+ }
+
+ return true;
+}
+
+typedef struct {
+ mongoc_host_list_t *host_list;
+ mongoc_topology_description_t *td;
+} _remove_if_not_in_host_list_ctx_t;
+
+static bool
+_remove_if_not_in_host_list_cb (void *sd_void, void *ctx_void)
+{
+ _remove_if_not_in_host_list_ctx_t *ctx;
+ mongoc_topology_description_t *td;
+ mongoc_server_description_t *sd;
+ mongoc_host_list_t *host_list;
+
+ ctx = ctx_void;
+ sd = sd_void;
+ host_list = ctx->host_list;
+ td = ctx->td;
+
+ if (_mongoc_host_list_contains_one (host_list, &sd->host)) {
+ return true;
+ }
+ _mongoc_topology_description_remove_server (td, sd);
+ return true;
+}
+
+void
+mongoc_topology_description_reconcile (mongoc_topology_description_t *td,
+ mongoc_host_list_t *host_list)
+{
+ mongoc_set_t *servers;
+ size_t host_list_length;
+ size_t num_missing;
+
+ BSON_ASSERT_PARAM (td);
+
+ servers = mc_tpld_servers (td);
+ host_list_length = _mongoc_host_list_length (host_list);
+
+ /* Avoid removing all servers in topology, even temporarily, by deferring
+ * actual removal until after new hosts have been added. */
+ {
+ _count_num_hosts_to_remove_ctx_t ctx;
+
+ ctx.host_list = host_list;
+ ctx.num_missing = 0u;
+
+ mongoc_set_for_each (servers, _count_num_hosts_to_remove, &ctx);
+
+ num_missing = ctx.num_missing;
+ }
+
+ /* Polling SRV Records for mongos Discovery Spec: If srvMaxHosts is zero or
+ * greater than or equal to the number of valid hosts, each valid new host
+ * MUST be added to the topology as Unknown. */
+ if (td->max_hosts == 0 || (size_t) td->max_hosts >= host_list_length) {
+ mongoc_host_list_t *host;
+
+ LL_FOREACH (host_list, host)
+ {
+ /* "add" is really an "upsert" */
+ mongoc_topology_description_add_server (td, host->host_and_port, NULL);
+ }
+ }
+
+ /* Polling SRV Records for mongos Discovery Spec: If srvMaxHosts is greater
+ * than zero and less than the number of valid hosts, valid new hosts MUST be
+ * randomly selected and added to the topology as Unknown until the topology
+ * has srvMaxHosts hosts. */
+ else {
+ const size_t max_with_missing = td->max_hosts + num_missing;
+
+ size_t idx = 0u;
+ size_t hl_array_size = 0u;
+
+ /* Polling SRV Records for mongos Discovery Spec: Drivers MUST use the
+ * same randomization algorithm as they do for initial selection.
+ * Do not limit size of results yet (pass host_list_length) as we want to
+ * update any existing hosts in the topology, but add new hosts.
+ */
+ const mongoc_host_list_t *const *hl_array = _mongoc_apply_srv_max_hosts (
+ host_list, host_list_length, &hl_array_size);
+
+ for (idx = 0u;
+ servers->items_len < max_with_missing && idx < hl_array_size;
+ ++idx) {
+ const mongoc_host_list_t *const elem = hl_array[idx];
+
+ /* "add" is really an "upsert" */
+ mongoc_topology_description_add_server (td, elem->host_and_port, NULL);
+ }
+
+ /* There should not be a situation where all items in the valid host list
+ * were traversed without the number of hosts in the topology reaching
+ * srvMaxHosts. */
+ BSON_ASSERT (servers->items_len == max_with_missing);
+
+ bson_free ((void *) hl_array);
+ }
+
+ /* Polling SRV Records for mongos Discovery Spec: For all verified host
+ * names, as returned through the DNS SRV query, the driver MUST remove
+ * all hosts that are part of the topology, but are no longer in the
+ * returned set of valid hosts. */
+ {
+ _remove_if_not_in_host_list_ctx_t ctx;
+
+ ctx.host_list = host_list;
+ ctx.td = td;
+
+ mongoc_set_for_each (servers, _remove_if_not_in_host_list_cb, &ctx);
+ }
+
+ /* At this point, the number of hosts in the host list should not exceed
+ * srvMaxHosts. */
+ BSON_ASSERT (td->max_hosts == 0 ||
+ servers->items_len <= (size_t) td->max_hosts);
+}
+
+
+void
+_mongoc_topology_description_clear_connection_pool (
+ mongoc_topology_description_t *td,
+ uint32_t server_id,
+ const bson_oid_t *service_id)
+{
+ mongoc_server_description_t *sd;
+ bson_error_t error;
+
+ BSON_ASSERT (service_id);
+
+ sd = mongoc_topology_description_server_by_id (td, server_id, &error);
+ if (!sd) {
+ /* Server removed, ignore and ignore error. */
+ return;
+ }
+
+ TRACE ("clearing pool for server: %s", sd->host.host_and_port);
+
+ mc_tpl_sd_increment_generation (sd, service_id);
+}
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-description.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-description.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-description.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-description.h
diff --git a/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-private.h
new file mode 100644
index 00000000..d269f1ad
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-private.h
@@ -0,0 +1,611 @@
+/*
+ * Copyright 2014 MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mongoc-prelude.h"
+
+#ifndef MONGOC_TOPOLOGY_PRIVATE_H
+#define MONGOC_TOPOLOGY_PRIVATE_H
+
+#include "mongoc-config.h"
+#include "mongoc-topology-scanner-private.h"
+#include "mongoc-server-description-private.h"
+#include "mongoc-topology-description-private.h"
+#include "mongoc-thread-private.h"
+#include "mongoc-uri.h"
+#include "mongoc-client-session-private.h"
+#include "mongoc-crypt-private.h"
+#include "mongoc-ts-pool-private.h"
+#include "mongoc-shared-private.h"
+
+#define MONGOC_TOPOLOGY_MIN_HEARTBEAT_FREQUENCY_MS 500
+#define MONGOC_TOPOLOGY_SOCKET_CHECK_INTERVAL_MS 5000
+#define MONGOC_TOPOLOGY_COOLDOWN_MS 5000
+#define MONGOC_TOPOLOGY_LOCAL_THRESHOLD_MS 15
+#define MONGOC_TOPOLOGY_SERVER_SELECTION_TIMEOUT_MS 30000
+#define MONGOC_TOPOLOGY_HEARTBEAT_FREQUENCY_MS_MULTI_THREADED 10000
+#define MONGOC_TOPOLOGY_HEARTBEAT_FREQUENCY_MS_SINGLE_THREADED 60000
+#define MONGOC_TOPOLOGY_MIN_RESCAN_SRV_INTERVAL_MS 60000
+
+typedef enum {
+ MONGOC_TOPOLOGY_SCANNER_OFF,
+ MONGOC_TOPOLOGY_SCANNER_BG_RUNNING,
+ MONGOC_TOPOLOGY_SCANNER_SHUTTING_DOWN
+} mongoc_topology_scanner_state_t;
+
+typedef enum mongoc_topology_cse_state_t {
+ MONGOC_CSE_DISABLED,
+ MONGOC_CSE_STARTING,
+ MONGOC_CSE_ENABLED,
+} mongoc_topology_cse_state_t;
+
+struct _mongoc_background_monitor_t;
+struct _mongoc_client_pool_t;
+
+typedef enum { MONGOC_RR_SRV, MONGOC_RR_TXT } mongoc_rr_type_t;
+
+typedef struct _mongoc_rr_data_t {
+ /* Number of records returned by DNS. */
+ uint32_t count;
+
+ /* Set to lowest TTL found when polling SRV records. */
+ uint32_t min_ttl;
+
+ /* Set to the resulting host list when polling SRV records */
+ mongoc_host_list_t *hosts;
+
+ /* Set to the TXT record when polling for TXT */
+ char *txt_record_opts;
+} mongoc_rr_data_t;
+
+struct _mongoc_topology_t;
+
+MONGOC_DECL_SPECIAL_TS_POOL (
+ mongoc_server_session_t,
+ mongoc_server_session_pool,
+ struct _mongoc_topology_t,
+ /* ctor/dtor/prune are defined in the new_with_params call */
+ NULL,
+ NULL,
+ NULL)
+
+typedef bool (*_mongoc_rr_resolver_fn) (const char *hostname,
+ mongoc_rr_type_t rr_type,
+ mongoc_rr_data_t *rr_data,
+ size_t initial_buffer_size,
+ bson_error_t *error);
+
+/**
+ * @brief A reference-counted reference to a topology description.
+ *
+ * The referred-to topology description should be access via the `.ptr` member
+ * of this object.
+ */
+typedef union mc_shared_tpld {
+ /* Private: The reference-counted shared pointer that manages the topology
+ * description. */
+ mongoc_shared_ptr _sptr_;
+ /** The pointed-to topology description */
+ mongoc_topology_description_t const *ptr;
+} mc_shared_tpld;
+
+/** A null-pointer initializer for an `mc_shared_tpld` */
+#define MC_SHARED_TPLD_NULL ((mc_shared_tpld){._sptr_ = MONGOC_SHARED_PTR_NULL})
+
+typedef struct _mongoc_topology_t {
+ /**
+ * @brief The topology description. Do not access directly. Instead, use
+ * mc_tpld_take_ref()
+ */
+ mc_shared_tpld _shared_descr_;
+
+ /* topology->uri is initialized as a copy of the client/pool's URI.
+ * For a "mongodb+srv://" URI, topology->uri is then updated in
+ * mongoc_topology_new() after initial seedlist discovery.
+ */
+ mongoc_uri_t *uri;
+ mongoc_topology_scanner_t *scanner;
+ bool server_selection_try_once;
+
+ int64_t last_scan;
+ int64_t local_threshold_msec;
+ int64_t connect_timeout_msec;
+ int64_t server_selection_timeout_msec;
+ /* defaults to 500ms, configurable by tests */
+ int64_t min_heartbeat_frequency_msec;
+
+ /* Minimum of SRV record TTLs, but no lower than 60 seconds.
+ * May be zero for non-SRV/non-MongoS topology. */
+ int64_t srv_polling_rescan_interval_ms;
+ int64_t srv_polling_last_scan_ms;
+ /* For multi-threaded, srv polling occurs in a separate thread. */
+ bson_thread_t srv_polling_thread;
+ bson_mutex_t srv_polling_mtx;
+ mongoc_cond_t srv_polling_cond;
+
+ /**
+ * @brief Signal for background monitoring threads to signal stop/shutdown.
+ *
+ * The values stored are mongoc_topology_scanner_state_t values
+ */
+ int scanner_state;
+
+ /**
+ * @brief This lock is held in order to serialize operations that modify the
+ * topology description. It *should not* be held while performing read-only
+ * operations on the topology.
+ *
+ * This mutex is also used by server selection to synchronize with threads
+ * that may update the topology following a failed server selection. It is
+ * used in conjunction with `cond_client`. This protects _shared_descr_, as
+ * well as the server_monitors and rtt_monitors.
+ */
+ bson_mutex_t tpld_modification_mtx;
+
+ /**
+ * @brief Condition variable used to signal client threads that the topology
+ * has been updated by another thread. This CV should be used with
+ * tpld_modification_mtx, as it signals modifications to the topology.
+ *
+ * Note that mc_tpld_modify_begin/commit/drop will acquire/release
+ * tpld_modification_mtx as well.
+ */
+ mongoc_cond_t cond_client;
+
+ bool single_threaded;
+ bool stale;
+
+ mongoc_server_session_pool session_pool;
+
+ /* Is client side encryption enabled? */
+ mongoc_topology_cse_state_t cse_state;
+ bool is_srv_polling;
+
+#ifdef MONGOC_ENABLE_CLIENT_SIDE_ENCRYPTION
+ _mongoc_crypt_t *crypt;
+ struct _mongoc_client_t *mongocryptd_client; /* single threaded */
+ struct _mongoc_client_t *keyvault_client; /* single threaded */
+ struct _mongoc_client_pool_t *mongocryptd_client_pool; /* multi threaded */
+ struct _mongoc_client_pool_t *keyvault_client_pool; /* multi threaded */
+ char *keyvault_db;
+ char *keyvault_coll;
+ bool bypass_auto_encryption;
+ bool mongocryptd_bypass_spawn;
+ char *mongocryptd_spawn_path;
+ bson_t *mongocryptd_spawn_args;
+#endif
+
+ /* For background monitoring. */
+ mongoc_set_t *server_monitors;
+ mongoc_set_t *rtt_monitors;
+ bson_mutex_t apm_mutex;
+
+ /* This is overridable for SRV polling tests to mock DNS records. */
+ _mongoc_rr_resolver_fn rr_resolver;
+
+ /* valid is false when mongoc_topology_new failed to construct a valid
+ * topology. This could occur if the URI is invalid.
+ * An invalid topology does not monitor servers. */
+ bool valid;
+} mongoc_topology_t;
+
+mongoc_topology_t *
+mongoc_topology_new (const mongoc_uri_t *uri, bool single_threaded);
+
+void
+mongoc_topology_set_apm_callbacks (mongoc_topology_t *topology,
+ mongoc_topology_description_t *td,
+ mongoc_apm_callbacks_t *callbacks,
+ void *context);
+
+void
+mongoc_topology_destroy (mongoc_topology_t *topology);
+
+void
+mongoc_topology_reconcile (const mongoc_topology_t *topology,
+ mongoc_topology_description_t *td);
+
+bool
+mongoc_topology_compatible (const mongoc_topology_description_t *td,
+ const mongoc_read_prefs_t *read_prefs,
+ bson_error_t *error);
+
+/**
+ * @brief Select a server description for an operation. May scan and update the
+ * topology.
+ *
+ * A server description might be returned that matches the given `optype` and
+ * `read_prefs`. If the topology is out-of-date or due for a scan, then this
+ * function will perform a scan and update the topology accordingly. If no
+ * matching server is found, returns a NULL pointer.
+ *
+ * @param topology The topology to inspect and/or update.
+ * @param optype The operation that is intended to be performed.
+ * @param read_prefs The read preferences for the command.
+ * @param must_use_primary An optional output parameter. Server selection might
+ * need to override the caller's read preferences' read mode to 'primary'.
+ * Whether or not that takes place will be set through this pointer.
+ * @param error An output parameter for any error information.
+ * @return mongoc_server_description_t* A copy of the topology's server
+ * description that matches the request, or NULL if there is no such server.
+ *
+ * @note The returned object is a COPY, and should be released with
+ * `mongoc_server_description_destroy()`
+ *
+ * @note This function may update the topology description.
+ */
+mongoc_server_description_t *
+mongoc_topology_select (mongoc_topology_t *topology,
+ mongoc_ss_optype_t optype,
+ const mongoc_read_prefs_t *read_prefs,
+ bool *must_use_primary,
+ bson_error_t *error);
+
+/**
+ * @brief Obtain the integral ID of a server description matching the requested
+ * ops.
+ *
+ * Refer to @see mongoc_topology_select() for more information
+ *
+ * @param topology The topology to inspect and/or update.
+ * @param optype The operation that is intended to be performed.
+ * @param read_prefs The read preferences for the command.
+ * @param must_use_primary An optional output parameter. Server selection might
+ * need to override the caller's read preferences' read mode to 'primary'.
+ * Whether or not that takes place will be set through this pointer.
+ * @param error An output parameter for any error information.
+ * @return uint32_t A non-zero integer ID of the server description. In case of
+ * error, sets `error` and returns zero.
+ *
+ * @note This function may update the topology description.
+ */
+uint32_t
+mongoc_topology_select_server_id (mongoc_topology_t *topology,
+ mongoc_ss_optype_t optype,
+ const mongoc_read_prefs_t *read_prefs,
+ bool *must_use_primary,
+ bson_error_t *error);
+
+/**
+ * @brief Return a new mongoc_host_list_t for the given server matching the
+ * given ID.
+ *
+ * @param topology The topology description to inspect
+ * @param id The ID of a server in the topology
+ * @param error Output error information
+ * @return mongoc_host_list_t* A new host list, or NULL on error
+ *
+ * @note The returned list should be freed with
+ * `_mongoc_host_list_destroy_all()`
+ */
+mongoc_host_list_t *
+_mongoc_topology_host_by_id (const mongoc_topology_description_t *topology,
+ uint32_t id,
+ bson_error_t *error);
+
+/**
+ * @brief Update the topology from the response to a handshake on a new
+ * application connection.
+ *
+ * @note Only applicable to a client pool (single-threaded clients reuse
+ * monitoring connections).
+ *
+ * @param topology The topology that will be updated.
+ * @param sd The server description that contains the hello response.
+ * @return true If the server is valid in the topology.
+ * @return false If the server was already removed from the topology.
+ */
+bool
+_mongoc_topology_update_from_handshake (mongoc_topology_t *topology,
+ const mongoc_server_description_t *sd);
+
+void
+_mongoc_topology_update_last_used (mongoc_topology_t *topology,
+ uint32_t server_id);
+
+int64_t
+mongoc_topology_server_timestamp (mongoc_topology_t *topology, uint32_t id);
+
+/**
+ * @brief Get the current type of the topology
+ */
+mongoc_topology_description_type_t
+_mongoc_topology_get_type (const mongoc_topology_t *topology);
+
+bool
+_mongoc_topology_set_appname (mongoc_topology_t *topology, const char *appname);
+
+void
+_mongoc_topology_update_cluster_time (mongoc_topology_t *topology,
+ const bson_t *reply);
+
+mongoc_server_session_t *
+_mongoc_topology_pop_server_session (mongoc_topology_t *topology,
+ bson_error_t *error);
+
+void
+_mongoc_topology_push_server_session (mongoc_topology_t *topology,
+ mongoc_server_session_t *server_session);
+
+bool
+_mongoc_topology_end_sessions_cmd (mongoc_topology_t *topology, bson_t *cmd);
+
+void
+_mongoc_topology_do_blocking_scan (mongoc_topology_t *topology,
+ bson_error_t *error);
+
+/**
+ * @brief Duplicate the handshake command of the topology scanner.
+ *
+ * @param topology The topology to inspect.
+ * @param copy_into The destination of the copy. Should be uninitialized storage
+ * for a bson_t.
+ *
+ * @note This API will lazily construct the handshake command for the scanner.
+ *
+ * @note This is called at the start of the scan in
+ * _mongoc_topology_run_background, when a node is added in
+ * _mongoc_topology_reconcile_add_nodes, or when running a hello directly on a
+ * node in _mongoc_stream_run_hello.
+ */
+void
+_mongoc_topology_dup_handshake_cmd (const mongoc_topology_t *topology,
+ bson_t *copy_into);
+void
+_mongoc_topology_request_scan (mongoc_topology_t *topology);
+
+void
+_mongoc_topology_bypass_cooldown (mongoc_topology_t *topology);
+
+typedef enum {
+ MONGOC_SDAM_APP_ERROR_COMMAND,
+ MONGOC_SDAM_APP_ERROR_NETWORK,
+ MONGOC_SDAM_APP_ERROR_TIMEOUT
+} _mongoc_sdam_app_error_type_t;
+
+/**
+ * @brief Handle an error from an app connection
+ *
+ * Processes network errors, timeouts, and command replies.
+ *
+ * @param topology The topology that will be updated
+ * @param server_id The ID of the server on which the error occurred.
+ * @param handshake_complete Whether the handshake was complete for this server
+ * @param type The type of error to process
+ * @param reply If checking for a command error, the server reply. Otherwise
+ * NULL
+ * @param why An error that will be attached to the server description
+ * @param max_wire_version
+ * @param generation The generation of the server description the caller was
+ * using.
+ * @param service_id A service ID for a load-balanced deployment. If not
+ * applicable, pass kZeroServiceID.
+ * @return true If the topology was updated and the pool was cleared.
+ * @return false If no modifications were made and the error was ignored.
+ *
+ * @note May update the topology description.
+ */
+bool
+_mongoc_topology_handle_app_error (mongoc_topology_t *topology,
+ uint32_t server_id,
+ bool handshake_complete,
+ _mongoc_sdam_app_error_type_t type,
+ const bson_t *reply,
+ const bson_error_t *why,
+ uint32_t max_wire_version,
+ uint32_t generation,
+ const bson_oid_t *service_id);
+
+void
+mongoc_topology_rescan_srv (mongoc_topology_t *topology);
+
+bool
+mongoc_topology_should_rescan_srv (mongoc_topology_t *topology);
+
+/* _mongoc_topology_set_rr_resolver is called by tests to mock DNS responses for
+ * SRV polling.
+ * This is necessarily called after initial seedlist discovery completes in
+ * mongoc_topology_new.
+ * Callers should call this before monitoring starts.
+ */
+void
+_mongoc_topology_set_rr_resolver (mongoc_topology_t *topology,
+ _mongoc_rr_resolver_fn rr_resolver);
+
+/* _mongoc_topology_set_srv_polling_rescan_interval_ms is called by tests to
+ * shorten the rescan interval.
+ * Callers should call this before monitoring starts.
+ */
+void
+_mongoc_topology_set_srv_polling_rescan_interval_ms (
+ mongoc_topology_t *topology, int64_t val);
+
+/**
+ * @brief Return the latest connection generation for the server_id and/or
+ * service_id.
+ *
+ * Use this generation for newly established connections.
+ *
+ * @param td The topology that contains the server
+ * @param server_id The ID of the server to inspect
+ * @param service_id The service ID of the connection if applicable, or
+ * kZeroServiceID.
+ * @returns uint32_t A generation counter for the given server, or zero if the
+ * server does not exist in the topology.
+ */
+uint32_t
+_mongoc_topology_get_connection_pool_generation (
+ const mongoc_topology_description_t *td,
+ uint32_t server_id,
+ const bson_oid_t *service_id);
+
+/**
+ * @brief Obtain a reference to the current topology description for the given
+ * topology.
+ *
+ * Returns a ref-counted reference to the topology description. The returned
+ * reference must later be released with mc_tpld_drop_ref(). The contents of the
+ * topology description are immutable.
+ */
+static BSON_INLINE mc_shared_tpld
+mc_tpld_take_ref (const mongoc_topology_t *tpl)
+{
+ return (mc_shared_tpld){
+ ._sptr_ = mongoc_atomic_shared_ptr_load (&tpl->_shared_descr_._sptr_)};
+}
+
+/**
+ * @brief Release a reference to a topology description obtained via
+ * mc_tpld_take_ref().
+ *
+ * The pointed-to shared reference will be reset to NULL.
+ */
+static BSON_INLINE void
+mc_tpld_drop_ref (mc_shared_tpld *p)
+{
+ mongoc_shared_ptr_reset_null (&p->_sptr_);
+}
+
+/**
+ * @brief Refresh a reference to a topology description for the given topology.
+ *
+ * @param td Pointer-to-shared-pointer of the topology description
+ * @param tpl The topology to query.
+ *
+ * The pointed-to shared pointer will be modified to refer to the topology
+ * description of the topology.
+ *
+ * Equivalent to a call to `mc_tpld_drop_ref()` followed by a call to
+ * `mc_tpld_take_ref()`.
+ */
+static BSON_INLINE void
+mc_tpld_renew_ref (mc_shared_tpld *td, mongoc_topology_t *tpl)
+{
+ mc_tpld_drop_ref (td);
+ *td = mc_tpld_take_ref (tpl);
+}
+
+/**
+ * @brief A pending topology description modification.
+ *
+ * Create an instance using `mc_tpld_modify_begin()`.
+ */
+typedef struct mc_tpld_modification {
+ /** The new topology. Modifications should be applied to this topology
+ * description. Those modifications will be published by
+ * `mc_tpld_modify_commit()`. */
+ mongoc_topology_description_t *new_td;
+ /** The topology that owns the topology description */
+ mongoc_topology_t *topology;
+} mc_tpld_modification;
+
+/**
+ * @brief Begin a new modification transaction of the topology description owned
+ * by `tpl`
+ *
+ * @return mc_tpld_modification A pending modification.
+ *
+ * @note MUST be followed by a call to `mc_tpld_modify_commit` OR
+ * `mc_tpld_modify_drop`
+ *
+ * @note THIS FUNCTION MAY BLOCK: This call takes a lock, which will only be
+ * released by mc_tpld_modify_commit() or mc_tpld_modify_drop(). Do not call
+ * this API while the current thread is already performing a modification!
+ */
+mc_tpld_modification
+mc_tpld_modify_begin (mongoc_topology_t *tpl);
+
+/**
+ * @brief Commit a topology description modification to the owning topology.
+ *
+ * All later calls to mc_tpld_take_ref() will see the new topology.
+ */
+void mc_tpld_modify_commit (mc_tpld_modification);
+
+/**
+ * @brief Drop a pending modification to a topology description. No changes will
+ * be made to the topology.
+ */
+void mc_tpld_modify_drop (mc_tpld_modification);
+
+/**
+ * @brief Obtain a pointer-to-mutable mongoc_topology_description_t for the
+ * given topology.
+ *
+ * This call is "unsafe" as the returned pointer may be invalidated by
+ * concurrent modifications done using mc_tpld_modify_begin() and
+ * mc_tpld_modify_commit().
+ *
+ * To obtain a safe pointer to the topology description, use mc_tpld_take_ref().
+ */
+static BSON_INLINE mongoc_topology_description_t *
+mc_tpld_unsafe_get_mutable (mongoc_topology_t *tpl)
+{
+ return tpl->_shared_descr_._sptr_.ptr;
+}
+
+/**
+ * @brief Obtain a pointer-to-const mongoc_topology_description_t for the
+ * given topology.
+ *
+ * This call is "unsafe" as the returned pointer may be invalidated by
+ * concurrent modifications done using mc_tpld_modify_begin() and
+ * mc_tpld_modify_commit().
+ *
+ * To obtain a safe pointer to the topology description, use mc_tpld_take_ref().
+ *
+ * @return const mongoc_topology_description_t* Pointer to the topology
+ * description for the given topology.
+ */
+static BSON_INLINE const mongoc_topology_description_t *
+mc_tpld_unsafe_get_const (const mongoc_topology_t *tpl)
+{
+ return tpl->_shared_descr_._sptr_.ptr;
+}
+
+/**
+ * @brief Directly invalidate a server in the topology by its ID.
+ *
+ * This is intended for testing purposes, as it provides thread-safe
+ * direct topology modification.
+ *
+ * @param td The topology to modify.
+ * @param server_id The ID of a server in the topology.
+ */
+static BSON_INLINE void
+_mongoc_topology_invalidate_server (mongoc_topology_t *td, uint32_t server_id)
+{
+ bson_error_t error;
+ mc_tpld_modification tdmod = mc_tpld_modify_begin (td);
+ bson_set_error (
+ &error, MONGOC_ERROR_STREAM, MONGOC_ERROR_STREAM_CONNECT, "invalidated");
+ mongoc_topology_description_invalidate_server (
+ tdmod.new_td, server_id, &error);
+ mc_tpld_modify_commit (tdmod);
+}
+
+/* Return an array view to `max_hosts` or fewer elements of `hl`, or NULL if
+ * `hl` is empty. The size of the returned array is written to `hl_array_size`
+ * even if `hl` is empty.
+ *
+ * The returned array must be freed with `bson_free()`. The elements of the
+ * array must not be freed, as they are still owned by `hl`.
+ */
+const mongoc_host_list_t **
+_mongoc_apply_srv_max_hosts (const mongoc_host_list_t *hl,
+ int32_t max_hosts,
+ size_t *hl_array_size);
+
+#endif
diff --git a/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-scanner-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-scanner-private.h
new file mode 100644
index 00000000..5344da08
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-scanner-private.h
@@ -0,0 +1,285 @@
+/*
+ * Copyright 2014 MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mongoc-prelude.h"
+
+#ifndef MONGOC_TOPOLOGY_SCANNER_PRIVATE_H
+#define MONGOC_TOPOLOGY_SCANNER_PRIVATE_H
+
+/* TODO: rename to TOPOLOGY scanner */
+
+#include <bson/bson.h>
+#include "mongoc-async-private.h"
+#include "mongoc-async-cmd-private.h"
+#include "mongoc-handshake-private.h"
+#include "mongoc-host-list.h"
+#include "mongoc-apm-private.h"
+#include "mongoc-scram-private.h"
+#include "mongoc-ssl.h"
+#include "mongoc-crypto-private.h"
+#include "mongoc-server-description-private.h"
+#include "common-thread-private.h"
+
+BSON_BEGIN_DECLS
+
+typedef void (*mongoc_topology_scanner_setup_err_cb_t) (
+ uint32_t id, void *data, const bson_error_t *error /* IN */);
+
+typedef void (*mongoc_topology_scanner_cb_t) (
+ uint32_t id,
+ const bson_t *bson,
+ int64_t rtt,
+ void *data,
+ const bson_error_t *error /* IN */);
+
+struct mongoc_topology_scanner;
+struct mongoc_topology_scanner_node;
+
+typedef struct mongoc_topology_scanner_node {
+ uint32_t id;
+ /* after scanning, this is set to the successful stream if one exists. */
+ mongoc_stream_t *stream;
+
+ int64_t last_used;
+ /* last_failed is set upon a network error trying to check a server.
+ * last_failed is used to enforce cooldownMS.
+ * last_failed is not set upon a network error during an application operation on @stream. */
+ int64_t last_failed;
+ bool has_auth;
+ bool hello_ok;
+ mongoc_host_list_t host;
+ struct mongoc_topology_scanner *ts;
+
+ struct mongoc_topology_scanner_node *next;
+ struct mongoc_topology_scanner_node *prev;
+
+ bool retired;
+ bson_error_t last_error;
+
+ /* the hostname for a node may resolve to multiple DNS results.
+ * dns_results has the full list of DNS results, ordered by host preference.
+ * successful_dns_result is the most recent successful DNS result.
+ */
+ struct addrinfo *dns_results;
+ struct addrinfo *successful_dns_result;
+ int64_t last_dns_cache;
+
+ /* used by single-threaded clients to store negotiated sasl mechanisms on a
+ * node. */
+ mongoc_handshake_sasl_supported_mechs_t sasl_supported_mechs;
+ bool negotiated_sasl_supported_mechs;
+ bson_t speculative_auth_response;
+ mongoc_scram_t scram;
+
+ /* handshake_sd is a server description constructed from the response of the
+ * initial handshake. It is bound to the lifetime of stream. */
+ mongoc_server_description_t *handshake_sd;
+} mongoc_topology_scanner_node_t;
+
+typedef enum handshake_state_t {
+ /**
+ * The handshake command has no value. The handshake_cmd pointer will be
+ * NULL.
+ */
+ HANDSHAKE_CMD_UNINITIALIZED,
+ /**
+ * The handshake command could not be constructed because it would be too
+ * large. The handshake_cmd pointer will be NULL.
+ */
+ HANDSHAKE_CMD_TOO_BIG,
+ /**
+ * The handshake command is valid and ready to be copied-from.
+ */
+ HANDSHAKE_CMD_OKAY,
+} handshake_state_t;
+
+typedef struct mongoc_topology_scanner {
+ mongoc_async_t *async;
+ int64_t connect_timeout_msec;
+ mongoc_topology_scanner_node_t *nodes;
+ bson_t hello_cmd;
+ bson_t legacy_hello_cmd;
+ bson_mutex_t handshake_cmd_mtx;
+ bson_t *handshake_cmd;
+ handshake_state_t handshake_state;
+ bson_t cluster_time;
+ const char *appname;
+
+ mongoc_topology_scanner_setup_err_cb_t setup_err_cb;
+ mongoc_topology_scanner_cb_t cb;
+ void *cb_data;
+ const mongoc_uri_t *uri;
+ mongoc_async_cmd_setup_t setup;
+ mongoc_stream_initiator_t initiator;
+ void *initiator_context;
+ bson_error_t error;
+
+#ifdef MONGOC_ENABLE_SSL
+ mongoc_ssl_opt_t *ssl_opts;
+#endif
+
+ mongoc_apm_callbacks_t apm_callbacks;
+ void *apm_context;
+ int64_t dns_cache_timeout_ms;
+ /* only used by single-threaded clients to negotiate auth mechanisms. */
+ bool negotiate_sasl_supported_mechs;
+ bool bypass_cooldown;
+ bool speculative_authentication;
+
+ mongoc_server_api_t *api;
+ bool loadbalanced;
+} mongoc_topology_scanner_t;
+
+mongoc_topology_scanner_t *
+mongoc_topology_scanner_new (
+ const mongoc_uri_t *uri,
+ mongoc_topology_scanner_setup_err_cb_t setup_err_cb,
+ mongoc_topology_scanner_cb_t cb,
+ void *data,
+ int64_t connect_timeout_msec);
+
+void
+mongoc_topology_scanner_destroy (mongoc_topology_scanner_t *ts);
+
+bool
+mongoc_topology_scanner_valid (mongoc_topology_scanner_t *ts);
+
+void
+mongoc_topology_scanner_add (mongoc_topology_scanner_t *ts,
+ const mongoc_host_list_t *host,
+ uint32_t id,
+ bool hello_ok);
+
+void
+mongoc_topology_scanner_scan (mongoc_topology_scanner_t *ts, uint32_t id);
+
+void
+mongoc_topology_scanner_disconnect (mongoc_topology_scanner_t *scanner);
+
+void
+mongoc_topology_scanner_node_retire (mongoc_topology_scanner_node_t *node);
+
+void
+mongoc_topology_scanner_node_disconnect (mongoc_topology_scanner_node_t *node,
+ bool failed);
+
+void
+mongoc_topology_scanner_node_destroy (mongoc_topology_scanner_node_t *node,
+ bool failed);
+
+bool
+mongoc_topology_scanner_in_cooldown (mongoc_topology_scanner_t *ts,
+ int64_t when);
+
+void
+mongoc_topology_scanner_start (mongoc_topology_scanner_t *ts,
+ bool obey_cooldown);
+
+void
+mongoc_topology_scanner_work (mongoc_topology_scanner_t *ts);
+
+void
+_mongoc_topology_scanner_finish (mongoc_topology_scanner_t *ts);
+
+void
+mongoc_topology_scanner_get_error (mongoc_topology_scanner_t *ts,
+ bson_error_t *error);
+
+void
+mongoc_topology_scanner_reset (mongoc_topology_scanner_t *ts);
+
+void
+mongoc_topology_scanner_node_setup (mongoc_topology_scanner_node_t *node,
+ bson_error_t *error);
+
+mongoc_topology_scanner_node_t *
+mongoc_topology_scanner_get_node (mongoc_topology_scanner_t *ts, uint32_t id);
+
+void
+_mongoc_topology_scanner_add_speculative_authentication (
+ bson_t *cmd,
+ const mongoc_uri_t *uri,
+ const mongoc_ssl_opt_t *ssl_opts,
+ mongoc_scram_cache_t *scram_cache,
+ mongoc_scram_t *scram /* OUT */);
+
+void
+_mongoc_topology_scanner_parse_speculative_authentication (
+ const bson_t *hello, bson_t *speculative_authenticate);
+
+const char *
+_mongoc_topology_scanner_get_speculative_auth_mechanism (
+ const mongoc_uri_t *uri);
+
+const bson_t *
+_mongoc_topology_scanner_get_monitoring_cmd (mongoc_topology_scanner_t *ts,
+ bool hello_ok);
+
+/**
+ * @brief Get the scanner's associated handshake command BSON document.
+ *
+ * @param ts The scanner to inspect
+ * @param copy_into A pointer to an initialized bson_t. The handshake command
+ * will be copied into the pointee.
+ */
+void
+_mongoc_topology_scanner_dup_handshake_cmd (mongoc_topology_scanner_t *ts,
+ bson_t *copy_into);
+
+bool
+mongoc_topology_scanner_has_node_for_host (mongoc_topology_scanner_t *ts,
+ mongoc_host_list_t *host);
+
+void
+mongoc_topology_scanner_set_stream_initiator (mongoc_topology_scanner_t *ts,
+ mongoc_stream_initiator_t si,
+ void *ctx);
+bool
+_mongoc_topology_scanner_set_appname (mongoc_topology_scanner_t *ts,
+ const char *name);
+void
+_mongoc_topology_scanner_set_cluster_time (mongoc_topology_scanner_t *ts,
+ const bson_t *cluster_time);
+
+void
+_mongoc_topology_scanner_set_dns_cache_timeout (mongoc_topology_scanner_t *ts,
+ int64_t timeout_ms);
+
+#ifdef MONGOC_ENABLE_SSL
+void
+mongoc_topology_scanner_set_ssl_opts (mongoc_topology_scanner_t *ts,
+ mongoc_ssl_opt_t *opts);
+#endif
+
+bool
+mongoc_topology_scanner_node_in_cooldown (mongoc_topology_scanner_node_t *node,
+ int64_t when);
+
+void
+_mongoc_topology_scanner_set_server_api (mongoc_topology_scanner_t *ts,
+ const mongoc_server_api_t *api);
+
+void
+_mongoc_topology_scanner_set_loadbalanced (mongoc_topology_scanner_t *ts,
+ bool val);
+
+/* for testing. */
+mongoc_stream_t *
+_mongoc_topology_scanner_tcp_initiate (mongoc_async_cmd_t *acmd);
+
+BSON_END_DECLS
+
+#endif /* MONGOC_TOPOLOGY_SCANNER_PRIVATE_H */
diff --git a/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-scanner.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-scanner.c
new file mode 100644
index 00000000..553468e2
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-scanner.c
@@ -0,0 +1,1488 @@
+/*
+ * Copyright 2014 MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <bson/bson.h>
+
+#include "mongoc-config.h"
+#include "mongoc-error.h"
+#include "mongoc-trace-private.h"
+#include "mongoc-topology-scanner-private.h"
+#include "mongoc-stream-private.h"
+#include "mongoc-stream-socket.h"
+
+#include "mongoc-handshake.h"
+#include "mongoc-handshake-private.h"
+
+#ifdef MONGOC_ENABLE_SSL
+#include "mongoc-stream-tls.h"
+#endif
+
+#include "mongoc-counters-private.h"
+#include "utlist.h"
+#include "mongoc-topology-private.h"
+#include "mongoc-host-list-private.h"
+#include "mongoc-uri-private.h"
+#include "mongoc-cluster-private.h"
+#include "mongoc-client-private.h"
+#include "mongoc-util-private.h"
+
+#undef MONGOC_LOG_DOMAIN
+#define MONGOC_LOG_DOMAIN "topology_scanner"
+
+#define DNS_CACHE_TIMEOUT_MS 10 * 60 * 1000
+#define HAPPY_EYEBALLS_DELAY_MS 250
+
+/* forward declarations */
+static void
+_async_connected (mongoc_async_cmd_t *acmd);
+
+static void
+_async_success (mongoc_async_cmd_t *acmd,
+ const bson_t *hello_response,
+ int64_t duration_usec);
+
+static void
+_async_error_or_timeout (mongoc_async_cmd_t *acmd,
+ int64_t duration_usec,
+ const char *default_err_msg);
+
+static void
+_async_handler (mongoc_async_cmd_t *acmd,
+ mongoc_async_cmd_result_t async_status,
+ const bson_t *hello_response,
+ int64_t duration_usec);
+
+static void
+_mongoc_topology_scanner_monitor_heartbeat_started (
+ const mongoc_topology_scanner_t *ts, const mongoc_host_list_t *host);
+
+static void
+_mongoc_topology_scanner_monitor_heartbeat_succeeded (
+ const mongoc_topology_scanner_t *ts,
+ const mongoc_host_list_t *host,
+ const bson_t *reply,
+ int64_t duration_usec);
+
+static void
+_mongoc_topology_scanner_monitor_heartbeat_failed (
+ const mongoc_topology_scanner_t *ts,
+ const mongoc_host_list_t *host,
+ const bson_error_t *error,
+ int64_t duration_usec);
+
+
+/* reset "retired" nodes that failed or were removed in the previous scan */
+static void
+_delete_retired_nodes (mongoc_topology_scanner_t *ts);
+
+/* cancel any pending async commands for a specific node excluding acmd.
+ * If acmd is NULL, cancel all async commands on the node. */
+static void
+_cancel_commands_excluding (mongoc_topology_scanner_node_t *node,
+ mongoc_async_cmd_t *acmd);
+
+/* return the number of pending async commands for a node. */
+static int
+_count_acmds (mongoc_topology_scanner_node_t *node);
+
+/* if acmd fails, schedule the sibling commands sooner. */
+static void
+_jumpstart_other_acmds (mongoc_topology_scanner_node_t *node,
+ mongoc_async_cmd_t *acmd);
+
+static void
+_add_hello (mongoc_topology_scanner_t *ts)
+{
+ mongoc_server_api_t *api = ts->api;
+
+ BSON_APPEND_INT32 (&ts->hello_cmd, "hello", 1);
+ BSON_APPEND_BOOL (&ts->hello_cmd, "helloOk", true);
+
+ BSON_APPEND_INT32 (&ts->legacy_hello_cmd, HANDSHAKE_CMD_LEGACY_HELLO, 1);
+ BSON_APPEND_BOOL (&ts->legacy_hello_cmd, "helloOk", true);
+
+ if (api) {
+ _mongoc_cmd_append_server_api (&ts->hello_cmd, api);
+ }
+}
+
+static void
+_init_hello (mongoc_topology_scanner_t *ts)
+{
+ bson_init (&ts->hello_cmd);
+ bson_init (&ts->legacy_hello_cmd);
+ bson_init (&ts->cluster_time);
+ ts->handshake_cmd = NULL;
+
+ _add_hello (ts);
+}
+
+static void
+_reset_hello (mongoc_topology_scanner_t *ts)
+{
+ bson_t *prev_cmd;
+ bson_reinit (&ts->hello_cmd);
+ bson_reinit (&ts->legacy_hello_cmd);
+
+ bson_mutex_lock (&ts->handshake_cmd_mtx);
+ prev_cmd = ts->handshake_cmd;
+ ts->handshake_cmd = NULL;
+ ts->handshake_state = HANDSHAKE_CMD_UNINITIALIZED;
+ bson_mutex_unlock (&ts->handshake_cmd_mtx);
+ bson_destroy (prev_cmd);
+
+ _add_hello (ts);
+}
+
+const char *
+_mongoc_topology_scanner_get_speculative_auth_mechanism (
+ const mongoc_uri_t *uri)
+{
+ const char *mechanism = mongoc_uri_get_auth_mechanism (uri);
+ bool requires_auth = mechanism || mongoc_uri_get_username (uri);
+
+ if (!requires_auth) {
+ return NULL;
+ }
+
+ if (!mechanism) {
+ return "SCRAM-SHA-256";
+ }
+
+ return mechanism;
+}
+
+void
+_mongoc_topology_scanner_add_speculative_authentication (
+ bson_t *cmd,
+ const mongoc_uri_t *uri,
+ const mongoc_ssl_opt_t *ssl_opts,
+ mongoc_scram_cache_t *scram_cache,
+ mongoc_scram_t *scram /* OUT */)
+{
+ bson_t auth_cmd;
+ bson_error_t error;
+ bool has_auth = false;
+ const char *mechanism =
+ _mongoc_topology_scanner_get_speculative_auth_mechanism (uri);
+
+ if (!mechanism) {
+ return;
+ }
+
+ if (strcasecmp (mechanism, "MONGODB-X509") == 0) {
+ /* Ignore errors while building authentication document: we proceed with
+ * the handshake as usual and let the subsequent authenticate command
+ * fail. */
+ if (_mongoc_cluster_get_auth_cmd_x509 (
+ uri, ssl_opts, &auth_cmd, &error)) {
+ has_auth = true;
+ BSON_APPEND_UTF8 (&auth_cmd, "db", "$external");
+ }
+ }
+
+#ifdef MONGOC_ENABLE_CRYPTO
+ if (strcasecmp (mechanism, "SCRAM-SHA-1") == 0 ||
+ strcasecmp (mechanism, "SCRAM-SHA-256") == 0) {
+ mongoc_crypto_hash_algorithm_t algo =
+ strcasecmp (mechanism, "SCRAM-SHA-1") == 0
+ ? MONGOC_CRYPTO_ALGORITHM_SHA_1
+ : MONGOC_CRYPTO_ALGORITHM_SHA_256;
+
+ _mongoc_uri_init_scram (uri, scram, algo);
+
+ if (scram_cache) {
+ _mongoc_scram_set_cache (scram, scram_cache);
+ }
+
+ if (_mongoc_cluster_get_auth_cmd_scram (algo, scram, &auth_cmd, &error)) {
+ const char *auth_source;
+
+ if (!(auth_source = mongoc_uri_get_auth_source (uri)) ||
+ (*auth_source == '\0')) {
+ auth_source = "admin";
+ }
+
+ has_auth = true;
+ BSON_APPEND_UTF8 (&auth_cmd, "db", auth_source);
+ }
+ }
+#endif
+
+ if (has_auth) {
+ BSON_APPEND_DOCUMENT (cmd, "speculativeAuthenticate", &auth_cmd);
+ bson_destroy (&auth_cmd);
+ }
+}
+
+void
+_mongoc_topology_scanner_parse_speculative_authentication (
+ const bson_t *hello, bson_t *speculative_authenticate)
+{
+ bson_iter_t iter;
+ uint32_t data_len;
+ const uint8_t *data;
+ bson_t auth_response;
+
+ BSON_ASSERT (hello);
+ BSON_ASSERT (speculative_authenticate);
+
+ if (!bson_iter_init_find (&iter, hello, "speculativeAuthenticate")) {
+ return;
+ }
+
+ bson_iter_document (&iter, &data_len, &data);
+ BSON_ASSERT (bson_init_static (&auth_response, data, data_len));
+
+ bson_destroy (speculative_authenticate);
+ bson_copy_to (&auth_response, speculative_authenticate);
+}
+
+static bson_t *
+_build_handshake_cmd (const bson_t *basis_cmd,
+ const char *appname,
+ const mongoc_uri_t *uri,
+ bool is_loadbalanced)
+{
+ bson_t *doc = bson_copy (basis_cmd);
+ bson_t subdoc;
+ bson_iter_t iter;
+ const char *key;
+ int keylen;
+ const bson_t *compressors;
+ int count = 0;
+ char buf[16];
+ bool subdoc_okay;
+
+ BSON_APPEND_DOCUMENT_BEGIN (doc, HANDSHAKE_FIELD, &subdoc);
+ subdoc_okay =
+ _mongoc_handshake_build_doc_with_application (&subdoc, appname);
+ bson_append_document_end (doc, &subdoc);
+
+ if (!subdoc_okay) {
+ bson_destroy (doc);
+ return NULL;
+ }
+
+ BSON_APPEND_ARRAY_BEGIN (doc, "compression", &subdoc);
+ if (uri) {
+ compressors = mongoc_uri_get_compressors (uri);
+
+ if (bson_iter_init (&iter, compressors)) {
+ while (bson_iter_next (&iter)) {
+ keylen = bson_uint32_to_string (count++, &key, buf, sizeof buf);
+ bson_append_utf8 (
+ &subdoc, key, (int) keylen, bson_iter_key (&iter), -1);
+ }
+ }
+ }
+ bson_append_array_end (doc, &subdoc);
+
+ if (is_loadbalanced) {
+ BSON_APPEND_BOOL (doc, "loadBalanced", true);
+ }
+
+ /* Return whether the handshake doc fit the size limit */
+ return doc;
+}
+
+const bson_t *
+_mongoc_topology_scanner_get_monitoring_cmd (mongoc_topology_scanner_t *ts,
+ bool hello_ok)
+{
+ return hello_ok || ts->api ? &ts->hello_cmd : &ts->legacy_hello_cmd;
+}
+
+void
+_mongoc_topology_scanner_dup_handshake_cmd (mongoc_topology_scanner_t *ts,
+ bson_t *copy_into)
+{
+ bson_t *new_cmd;
+ const char *appname;
+ BSON_ASSERT_PARAM (ts);
+ BSON_ASSERT_PARAM (copy_into);
+
+ /* appname will only be changed from NULL, so a non-null pointer will never
+ * be invalidated after this fetch. */
+ appname =
+ bson_atomic_ptr_fetch ((void *) &ts->appname, bson_memory_order_relaxed);
+
+ bson_mutex_lock (&ts->handshake_cmd_mtx);
+ /* If this is the first time using the node or if it's the first time
+ * using it after a failure, build handshake doc */
+ if (ts->handshake_state != HANDSHAKE_CMD_UNINITIALIZED) {
+ /* We're good to just return the handshake now */
+ goto after_init;
+ }
+
+ /* There is not yet a handshake command associated with this scanner.
+ * Initialize one and set it now. */
+ /* Note: Don't hold the mutex while we build our command */
+ /* Construct a new handshake command to be sent */
+ BSON_ASSERT (ts->handshake_cmd == NULL);
+ bson_mutex_unlock (&ts->handshake_cmd_mtx);
+ new_cmd =
+ _build_handshake_cmd (ts->api ? &ts->hello_cmd : &ts->legacy_hello_cmd,
+ appname,
+ ts->uri,
+ ts->loadbalanced);
+ bson_mutex_lock (&ts->handshake_cmd_mtx);
+ if (ts->handshake_state != HANDSHAKE_CMD_UNINITIALIZED) {
+ /* Someone else updated the handshake_cmd while we were building ours.
+ * Defer to their copy and just destroy the one we created. */
+ bson_destroy (new_cmd);
+ goto after_init;
+ }
+ BSON_ASSERT (ts->handshake_cmd == NULL);
+ /* We're still the one updating the command */
+ ts->handshake_cmd = new_cmd;
+ /* The "_build" may have failed. */
+ /* Even if new_cmd is NULL, this is still what we want */
+ ts->handshake_state =
+ new_cmd == NULL ? HANDSHAKE_CMD_TOO_BIG : HANDSHAKE_CMD_OKAY;
+ if (ts->handshake_state == HANDSHAKE_CMD_TOO_BIG) {
+ MONGOC_WARNING ("Handshake doc too big, not including in hello");
+ }
+
+after_init:
+ /* If the doc turned out to be too big */
+ if (ts->handshake_state == HANDSHAKE_CMD_TOO_BIG) {
+ bson_t *ret = ts->api ? &ts->hello_cmd : &ts->legacy_hello_cmd;
+ bson_copy_to (ret, copy_into);
+ } else {
+ BSON_ASSERT (ts->handshake_cmd != NULL);
+ bson_copy_to (ts->handshake_cmd, copy_into);
+ }
+ bson_mutex_unlock (&ts->handshake_cmd_mtx);
+}
+
+static void
+_begin_hello_cmd (mongoc_topology_scanner_node_t *node,
+ mongoc_stream_t *stream,
+ bool is_setup_done,
+ struct addrinfo *dns_result,
+ int64_t initiate_delay_ms,
+ bool use_handshake)
+{
+ mongoc_topology_scanner_t *ts = node->ts;
+ bson_t cmd;
+
+ if (node->last_used != -1 && node->last_failed == -1 && !use_handshake) {
+ /* The node's been used before and not failed recently */
+ bson_copy_to (
+ _mongoc_topology_scanner_get_monitoring_cmd (ts, node->hello_ok),
+ &cmd);
+ } else {
+ _mongoc_topology_scanner_dup_handshake_cmd (ts, &cmd);
+ }
+
+ if (node->ts->negotiate_sasl_supported_mechs &&
+ !node->negotiated_sasl_supported_mechs) {
+ _mongoc_handshake_append_sasl_supported_mechs (ts->uri, &cmd);
+ }
+
+ if (node->ts->speculative_authentication && !node->has_auth &&
+ bson_empty (&node->speculative_auth_response) && node->scram.step == 0) {
+ mongoc_ssl_opt_t *ssl_opts = NULL;
+
+#ifdef MONGOC_ENABLE_SSL
+ ssl_opts = ts->ssl_opts;
+#endif
+
+ _mongoc_topology_scanner_add_speculative_authentication (
+ &cmd, ts->uri, ssl_opts, NULL, &node->scram);
+ }
+
+ if (!bson_empty (&ts->cluster_time)) {
+ bson_append_document (&cmd, "$clusterTime", 12, &ts->cluster_time);
+ }
+
+ /* if the node should connect with a TCP socket, stream will be null, and
+ * dns_result will be set. The async loop is responsible for calling the
+ * _tcp_initiator to construct TCP sockets. */
+ mongoc_async_cmd_new (ts->async,
+ stream,
+ is_setup_done,
+ dns_result,
+ _mongoc_topology_scanner_tcp_initiate,
+ initiate_delay_ms,
+ ts->setup,
+ node->host.host,
+ "admin",
+ &cmd,
+ &_async_handler,
+ node,
+ ts->connect_timeout_msec);
+
+ bson_destroy (&cmd);
+}
+
+
+mongoc_topology_scanner_t *
+mongoc_topology_scanner_new (
+ const mongoc_uri_t *uri,
+ mongoc_topology_scanner_setup_err_cb_t setup_err_cb,
+ mongoc_topology_scanner_cb_t cb,
+ void *data,
+ int64_t connect_timeout_msec)
+{
+ mongoc_topology_scanner_t *ts =
+ (mongoc_topology_scanner_t *) bson_malloc0 (sizeof (*ts));
+
+ ts->async = mongoc_async_new ();
+
+ ts->setup_err_cb = setup_err_cb;
+ ts->cb = cb;
+ ts->cb_data = data;
+ ts->uri = uri;
+ ts->appname = NULL;
+ ts->api = NULL;
+ ts->handshake_state = HANDSHAKE_CMD_UNINITIALIZED;
+ ts->connect_timeout_msec = connect_timeout_msec;
+ /* may be overridden for testing. */
+ ts->dns_cache_timeout_ms = DNS_CACHE_TIMEOUT_MS;
+ bson_mutex_init (&ts->handshake_cmd_mtx);
+
+ _init_hello (ts);
+
+ return ts;
+}
+
+#ifdef MONGOC_ENABLE_SSL
+void
+mongoc_topology_scanner_set_ssl_opts (mongoc_topology_scanner_t *ts,
+ mongoc_ssl_opt_t *opts)
+{
+ ts->ssl_opts = opts;
+ ts->setup = mongoc_async_cmd_tls_setup;
+}
+#endif
+
+void
+mongoc_topology_scanner_set_stream_initiator (mongoc_topology_scanner_t *ts,
+ mongoc_stream_initiator_t si,
+ void *ctx)
+{
+ ts->initiator = si;
+ ts->initiator_context = ctx;
+ ts->setup = NULL;
+}
+
+void
+mongoc_topology_scanner_destroy (mongoc_topology_scanner_t *ts)
+{
+ mongoc_topology_scanner_node_t *ele, *tmp;
+
+ DL_FOREACH_SAFE (ts->nodes, ele, tmp)
+ {
+ mongoc_topology_scanner_node_destroy (ele, false);
+ }
+
+ mongoc_async_destroy (ts->async);
+ bson_destroy (&ts->hello_cmd);
+ bson_destroy (&ts->legacy_hello_cmd);
+ bson_destroy (ts->handshake_cmd);
+ bson_destroy (&ts->cluster_time);
+ mongoc_server_api_destroy (ts->api);
+ bson_mutex_destroy (&ts->handshake_cmd_mtx);
+
+ /* This field can be set by a mongoc_client */
+ bson_free ((char *) ts->appname);
+
+ bson_free (ts);
+}
+
+/* whether the scanner was successfully initialized - false if a mongodb+srv
+ * URI failed to resolve to any hosts */
+bool
+mongoc_topology_scanner_valid (mongoc_topology_scanner_t *ts)
+{
+ return ts->nodes != NULL;
+}
+
+void
+mongoc_topology_scanner_add (mongoc_topology_scanner_t *ts,
+ const mongoc_host_list_t *host,
+ uint32_t id,
+ bool hello_ok)
+{
+ mongoc_topology_scanner_node_t *node;
+
+ node = (mongoc_topology_scanner_node_t *) bson_malloc0 (sizeof (*node));
+
+ memcpy (&node->host, host, sizeof (*host));
+
+ node->id = id;
+ node->ts = ts;
+ node->last_failed = -1;
+ node->last_used = -1;
+ node->hello_ok = hello_ok;
+ bson_init (&node->speculative_auth_response);
+
+ DL_APPEND (ts->nodes, node);
+}
+
+void
+mongoc_topology_scanner_scan (mongoc_topology_scanner_t *ts, uint32_t id)
+{
+ mongoc_topology_scanner_node_t *node;
+
+ node = mongoc_topology_scanner_get_node (ts, id);
+
+ /* begin non-blocking connection, don't wait for success */
+ if (node) {
+ mongoc_topology_scanner_node_setup (node, &node->last_error);
+ }
+
+ /* if setup fails the node stays in the scanner. destroyed after the scan. */
+}
+
+void
+mongoc_topology_scanner_disconnect (mongoc_topology_scanner_t *scanner)
+{
+ mongoc_topology_scanner_node_t *node;
+
+ BSON_ASSERT (scanner);
+ node = scanner->nodes;
+
+ while (node) {
+ mongoc_topology_scanner_node_disconnect (node, false);
+ node = node->next;
+ }
+}
+
+void
+mongoc_topology_scanner_node_retire (mongoc_topology_scanner_node_t *node)
+{
+ /* cancel any pending commands. */
+ _cancel_commands_excluding (node, NULL);
+
+ node->retired = true;
+}
+
+void
+mongoc_topology_scanner_node_disconnect (mongoc_topology_scanner_node_t *node,
+ bool failed)
+{
+ /* the node may or may not have succeeded in finding a working stream. */
+ if (node->stream) {
+ if (failed) {
+ mongoc_stream_failed (node->stream);
+ } else {
+ mongoc_stream_destroy (node->stream);
+ }
+
+ node->stream = NULL;
+ memset (
+ &node->sasl_supported_mechs, 0, sizeof (node->sasl_supported_mechs));
+ node->negotiated_sasl_supported_mechs = false;
+ bson_reinit (&node->speculative_auth_response);
+ }
+ mongoc_server_description_destroy (node->handshake_sd);
+ node->handshake_sd = NULL;
+}
+
+void
+mongoc_topology_scanner_node_destroy (mongoc_topology_scanner_node_t *node,
+ bool failed)
+{
+ DL_DELETE (node->ts->nodes, node);
+ mongoc_topology_scanner_node_disconnect (node, failed);
+ if (node->dns_results) {
+ freeaddrinfo (node->dns_results);
+ }
+
+ bson_destroy (&node->speculative_auth_response);
+
+#ifdef MONGOC_ENABLE_CRYPTO
+ _mongoc_scram_destroy (&node->scram);
+#endif
+
+ bson_free (node);
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_topology_scanner_get_node --
+ *
+ * Return the scanner node with the given id.
+ *
+ *--------------------------------------------------------------------------
+ */
+mongoc_topology_scanner_node_t *
+mongoc_topology_scanner_get_node (mongoc_topology_scanner_t *ts, uint32_t id)
+{
+ mongoc_topology_scanner_node_t *ele, *tmp;
+
+ DL_FOREACH_SAFE (ts->nodes, ele, tmp)
+ {
+ if (ele->id == id) {
+ return ele;
+ }
+
+ if (ele->id > id) {
+ break;
+ }
+ }
+
+ return NULL;
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_topology_scanner_has_node_for_host --
+ *
+ * Whether the scanner has a node for the given host and port.
+ *
+ *--------------------------------------------------------------------------
+ */
+bool
+mongoc_topology_scanner_has_node_for_host (mongoc_topology_scanner_t *ts,
+ mongoc_host_list_t *host)
+{
+ mongoc_topology_scanner_node_t *ele, *tmp;
+
+ DL_FOREACH_SAFE (ts->nodes, ele, tmp)
+ {
+ if (_mongoc_host_list_compare_one (&ele->host, host)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static void
+_async_connected (mongoc_async_cmd_t *acmd)
+{
+ mongoc_topology_scanner_node_t *node =
+ (mongoc_topology_scanner_node_t *) acmd->data;
+ /* this cmd connected successfully, cancel other cmds on this node. */
+ _cancel_commands_excluding (node, acmd);
+ node->successful_dns_result = acmd->dns_result;
+}
+
+static void
+_async_success (mongoc_async_cmd_t *acmd,
+ const bson_t *hello_response,
+ int64_t duration_usec)
+{
+ void *data = acmd->data;
+ mongoc_topology_scanner_node_t *node =
+ (mongoc_topology_scanner_node_t *) data;
+ mongoc_stream_t *stream = acmd->stream;
+ mongoc_topology_scanner_t *ts = node->ts;
+
+ if (node->retired) {
+ if (stream) {
+ mongoc_stream_failed (stream);
+ }
+ return;
+ }
+
+ node->last_used = bson_get_monotonic_time ();
+ node->last_failed = -1;
+
+ _mongoc_topology_scanner_monitor_heartbeat_succeeded (
+ ts, &node->host, hello_response, duration_usec);
+
+ /* set our successful stream. */
+ BSON_ASSERT (!node->stream);
+ node->stream = stream;
+
+ if (!node->handshake_sd) {
+ mongoc_server_description_t sd;
+
+ /* Store a server description associated with the handshake. */
+ mongoc_server_description_init (&sd, node->host.host_and_port, node->id);
+ mongoc_server_description_handle_hello (
+ &sd, hello_response, duration_usec / 1000, &acmd->error);
+ node->handshake_sd = mongoc_server_description_new_copy (&sd);
+ mongoc_server_description_cleanup (&sd);
+ }
+
+ if (ts->negotiate_sasl_supported_mechs &&
+ !node->negotiated_sasl_supported_mechs) {
+ _mongoc_handshake_parse_sasl_supported_mechs (
+ hello_response, &node->sasl_supported_mechs);
+ }
+
+ if (ts->speculative_authentication) {
+ _mongoc_topology_scanner_parse_speculative_authentication (
+ hello_response, &node->speculative_auth_response);
+ }
+
+ /* mongoc_topology_scanner_cb_t takes rtt_msec, not usec */
+ ts->cb (node->id,
+ hello_response,
+ duration_usec / 1000,
+ ts->cb_data,
+ &acmd->error);
+}
+
+static void
+_async_error_or_timeout (mongoc_async_cmd_t *acmd,
+ int64_t duration_usec,
+ const char *default_err_msg)
+{
+ void *data = acmd->data;
+ mongoc_topology_scanner_node_t *node =
+ (mongoc_topology_scanner_node_t *) data;
+ mongoc_stream_t *stream = acmd->stream;
+ mongoc_topology_scanner_t *ts = node->ts;
+ bson_error_t *error = &acmd->error;
+ int64_t now = bson_get_monotonic_time ();
+ const char *message;
+
+ /* the stream may have failed on initiation. */
+ if (stream) {
+ mongoc_stream_failed (stream);
+ }
+
+ if (node->retired) {
+ return;
+ }
+
+ node->last_used = now;
+
+ if (!node->stream && _count_acmds (node) == 1) {
+ /* there are no remaining streams, connecting has failed. */
+ node->last_failed = now;
+ if (error->code) {
+ message = error->message;
+ } else {
+ message = default_err_msg;
+ }
+
+ /* invalidate any cached DNS results. */
+ if (node->dns_results) {
+ freeaddrinfo (node->dns_results);
+ node->dns_results = NULL;
+ node->successful_dns_result = NULL;
+ }
+
+ bson_set_error (&node->last_error,
+ MONGOC_ERROR_CLIENT,
+ MONGOC_ERROR_STREAM_CONNECT,
+ "%s calling hello on \'%s\'",
+ message,
+ node->host.host_and_port);
+
+ _mongoc_topology_scanner_monitor_heartbeat_failed (
+ ts, &node->host, &node->last_error, duration_usec);
+
+ /* call the topology scanner callback. cannot connect to this node.
+ * callback takes rtt_msec, not usec. */
+ ts->cb (node->id, NULL, duration_usec / 1000, ts->cb_data, error);
+
+ mongoc_server_description_destroy (node->handshake_sd);
+ node->handshake_sd = NULL;
+ } else {
+ /* there are still more commands left for this node or it succeeded
+ * with another stream. skip the topology scanner callback. */
+ _jumpstart_other_acmds (node, acmd);
+ }
+}
+
+/*
+ *-----------------------------------------------------------------------
+ *
+ * This is the callback passed to async_cmd when we're running
+ * hellos from within the topology monitor.
+ *
+ *-----------------------------------------------------------------------
+ */
+
+static void
+_async_handler (mongoc_async_cmd_t *acmd,
+ mongoc_async_cmd_result_t async_status,
+ const bson_t *hello_response,
+ int64_t duration_usec)
+{
+ BSON_ASSERT (acmd->data);
+
+ switch (async_status) {
+ case MONGOC_ASYNC_CMD_CONNECTED:
+ _async_connected (acmd);
+ return;
+ case MONGOC_ASYNC_CMD_SUCCESS:
+ _async_success (acmd, hello_response, duration_usec);
+ return;
+ case MONGOC_ASYNC_CMD_TIMEOUT:
+ _async_error_or_timeout (acmd, duration_usec, "connection timeout");
+ return;
+ case MONGOC_ASYNC_CMD_ERROR:
+ _async_error_or_timeout (acmd, duration_usec, "connection error");
+ return;
+ case MONGOC_ASYNC_CMD_IN_PROGRESS:
+ default:
+ fprintf (stderr, "unexpected async status: %d\n", async_status);
+ BSON_ASSERT (false);
+ return;
+ }
+}
+
+mongoc_stream_t *
+_mongoc_topology_scanner_node_setup_stream_for_tls (
+ mongoc_topology_scanner_node_t *node, mongoc_stream_t *stream)
+{
+#ifdef MONGOC_ENABLE_SSL
+ mongoc_stream_t *tls_stream;
+#endif
+ if (!stream) {
+ return NULL;
+ }
+#ifdef MONGOC_ENABLE_SSL
+ if (node->ts->ssl_opts) {
+ tls_stream = mongoc_stream_tls_new_with_hostname (
+ stream, node->host.host, node->ts->ssl_opts, 1);
+ if (!tls_stream) {
+ mongoc_stream_destroy (stream);
+ return NULL;
+ } else {
+ return tls_stream;
+ }
+ }
+#endif
+ return stream;
+}
+
+/* attempt to create a new socket stream using this dns result. */
+mongoc_stream_t *
+_mongoc_topology_scanner_tcp_initiate (mongoc_async_cmd_t *acmd)
+{
+ mongoc_topology_scanner_node_t *node =
+ (mongoc_topology_scanner_node_t *) acmd->data;
+ struct addrinfo *res = acmd->dns_result;
+ mongoc_socket_t *sock = NULL;
+
+ BSON_ASSERT (acmd->dns_result);
+ /* create a new non-blocking socket. */
+ if (!(sock = mongoc_socket_new (
+ res->ai_family, res->ai_socktype, res->ai_protocol))) {
+ return NULL;
+ }
+
+ (void) mongoc_socket_connect (
+ sock, res->ai_addr, (mongoc_socklen_t) res->ai_addrlen, 0);
+
+ return _mongoc_topology_scanner_node_setup_stream_for_tls (
+ node, mongoc_stream_socket_new (sock));
+}
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_topology_scanner_node_setup_tcp --
+ *
+ * Create an async command for each DNS record found for this node.
+ *
+ * Returns:
+ * A bool. On failure error is set.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+bool
+mongoc_topology_scanner_node_setup_tcp (mongoc_topology_scanner_node_t *node,
+ bson_error_t *error)
+{
+ struct addrinfo hints;
+ struct addrinfo *iter;
+ char portstr[8];
+ mongoc_host_list_t *host;
+ int s;
+ int64_t delay = 0;
+ int64_t now = bson_get_monotonic_time ();
+
+ ENTRY;
+
+ host = &node->host;
+
+ /* if cached dns results are expired, flush. */
+ if (node->dns_results &&
+ (now - node->last_dns_cache) > node->ts->dns_cache_timeout_ms * 1000) {
+ freeaddrinfo (node->dns_results);
+ node->dns_results = NULL;
+ node->successful_dns_result = NULL;
+ }
+
+ if (!node->dns_results) {
+ bson_snprintf (portstr, sizeof portstr, "%hu", host->port);
+
+ memset (&hints, 0, sizeof hints);
+ hints.ai_family = host->family;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = 0;
+ hints.ai_protocol = 0;
+
+ s = getaddrinfo (host->host, portstr, &hints, &node->dns_results);
+
+ if (s != 0) {
+ mongoc_counter_dns_failure_inc ();
+ bson_set_error (error,
+ MONGOC_ERROR_STREAM,
+ MONGOC_ERROR_STREAM_NAME_RESOLUTION,
+ "Failed to resolve '%s'",
+ host->host);
+ RETURN (false);
+ }
+
+ mongoc_counter_dns_success_inc ();
+ node->last_dns_cache = now;
+ }
+
+ if (node->successful_dns_result) {
+ _begin_hello_cmd (node,
+ NULL /* stream */,
+ false /* is_setup_done */,
+ node->successful_dns_result,
+ 0 /* initiate_delay_ms */,
+ true /* use_handshake */);
+ } else {
+ LL_FOREACH2 (node->dns_results, iter, ai_next)
+ {
+ _begin_hello_cmd (node,
+ NULL /* stream */,
+ false /* is_setup_done */,
+ iter,
+ delay,
+ true /* use_handshake */);
+ /* each subsequent DNS result will have an additional 250ms delay. */
+ delay += HAPPY_EYEBALLS_DELAY_MS;
+ }
+ }
+
+ RETURN (true);
+}
+
+bool
+mongoc_topology_scanner_node_connect_unix (mongoc_topology_scanner_node_t *node,
+ bson_error_t *error)
+{
+#ifdef _WIN32
+ ENTRY;
+ bson_set_error (error,
+ MONGOC_ERROR_STREAM,
+ MONGOC_ERROR_STREAM_CONNECT,
+ "UNIX domain sockets not supported on win32.");
+ RETURN (false);
+#else
+ struct sockaddr_un saddr;
+ mongoc_socket_t *sock;
+ mongoc_stream_t *stream;
+ mongoc_host_list_t *host;
+
+ ENTRY;
+
+ host = &node->host;
+
+ memset (&saddr, 0, sizeof saddr);
+ saddr.sun_family = AF_UNIX;
+ bson_snprintf (saddr.sun_path, sizeof saddr.sun_path - 1, "%s", host->host);
+
+ sock = mongoc_socket_new (AF_UNIX, SOCK_STREAM, 0);
+
+ if (sock == NULL) {
+ bson_set_error (error,
+ MONGOC_ERROR_STREAM,
+ MONGOC_ERROR_STREAM_SOCKET,
+ "Failed to create socket.");
+ RETURN (false);
+ }
+
+ if (-1 == mongoc_socket_connect (
+ sock, (struct sockaddr *) &saddr, sizeof saddr, -1)) {
+ char buf[128];
+ char *errstr;
+
+ errstr = bson_strerror_r (mongoc_socket_errno (sock), buf, sizeof (buf));
+
+ bson_set_error (error,
+ MONGOC_ERROR_STREAM,
+ MONGOC_ERROR_STREAM_CONNECT,
+ "Failed to connect to UNIX domain socket: %s",
+ errstr);
+ mongoc_socket_destroy (sock);
+ RETURN (false);
+ }
+
+ stream = _mongoc_topology_scanner_node_setup_stream_for_tls (
+ node, mongoc_stream_socket_new (sock));
+ if (stream) {
+ _begin_hello_cmd (node,
+ stream,
+ false /* is_setup_done */,
+ NULL /* dns result */,
+ 0 /* delay */,
+ true /* use_handshake */);
+ RETURN (true);
+ }
+ bson_set_error (error,
+ MONGOC_ERROR_STREAM,
+ MONGOC_ERROR_STREAM_CONNECT,
+ "Failed to create TLS stream");
+ RETURN (false);
+#endif
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_topology_scanner_node_setup --
+ *
+ * Create a stream and begin a non-blocking connect.
+ *
+ * Returns:
+ * true on success, or false and error is set.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+void
+mongoc_topology_scanner_node_setup (mongoc_topology_scanner_node_t *node,
+ bson_error_t *error)
+{
+ bool success = false;
+ mongoc_stream_t *stream;
+ int64_t start;
+
+ _mongoc_topology_scanner_monitor_heartbeat_started (node->ts, &node->host);
+ start = bson_get_monotonic_time ();
+
+ /* if there is already a working stream, push it back to be re-scanned. */
+ if (node->stream) {
+ _begin_hello_cmd (node,
+ node->stream,
+ true /* is_setup_done */,
+ NULL /* dns_result */,
+ 0 /* initiate_delay_ms */,
+ false /* use_handshake */);
+ node->stream = NULL;
+ return;
+ }
+
+ BSON_ASSERT (!node->retired);
+
+ if (node->ts->initiator) {
+ stream = node->ts->initiator (
+ node->ts->uri, &node->host, node->ts->initiator_context, error);
+ if (stream) {
+ success = true;
+ _begin_hello_cmd (node,
+ stream,
+ false /* is_setup_done */,
+ NULL /* dns_result */,
+ 0 /* initiate_delay_ms */,
+ true /* use_handshake */);
+ }
+ } else {
+ if (node->host.family == AF_UNIX) {
+ success = mongoc_topology_scanner_node_connect_unix (node, error);
+ } else {
+ success = mongoc_topology_scanner_node_setup_tcp (node, error);
+ }
+ }
+
+ if (!success) {
+ _mongoc_topology_scanner_monitor_heartbeat_failed (
+ node->ts,
+ &node->host,
+ error,
+ (bson_get_monotonic_time () - start) / 1000);
+
+ node->ts->setup_err_cb (node->id, node->ts->cb_data, error);
+ return;
+ }
+
+ node->has_auth = false;
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_topology_scanner_node_in_cooldown --
+ *
+ * Return true if @node has experienced a network error attempting
+ * to call "hello" less than 5 seconds before @when, a timestamp in
+ * microseconds.
+ *
+ * Server Discovery and Monitoring Spec: "After a single-threaded client
+ * gets a network error trying to check a server, the client skips
+ * re-checking the server until cooldownMS has passed. This avoids
+ * spending connectTimeoutMS on each unavailable server during each scan.
+ * This value MUST be 5000 ms, and it MUST NOT be configurable."
+ *
+ *--------------------------------------------------------------------------
+ */
+bool
+mongoc_topology_scanner_node_in_cooldown (mongoc_topology_scanner_node_t *node,
+ int64_t when)
+{
+ if (node->last_failed == -1 || node->ts->bypass_cooldown) {
+ return false; /* node is new, or connected */
+ }
+
+ return node->last_failed + 1000 * MONGOC_TOPOLOGY_COOLDOWN_MS >= when;
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_topology_scanner_in_cooldown --
+ *
+ * Return true if all nodes will be in cooldown at time @when, a
+ * timestamp in microseconds.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+bool
+mongoc_topology_scanner_in_cooldown (mongoc_topology_scanner_t *ts,
+ int64_t when)
+{
+ mongoc_topology_scanner_node_t *node;
+
+ if (ts->bypass_cooldown) {
+ return false;
+ }
+ DL_FOREACH (ts->nodes, node)
+ {
+ if (!mongoc_topology_scanner_node_in_cooldown (node, when)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_topology_scanner_start --
+ *
+ * Initializes the scanner and begins a full topology check. This
+ * should be called once before calling mongoc_topology_scanner_work()
+ * to complete the scan.
+ *
+ * If "obey_cooldown" is true, this is a single-threaded blocking scan
+ * that must obey the Server Discovery And Monitoring Spec's cooldownMS:
+ *
+ * "After a single-threaded client gets a network error trying to check
+ * a server, the client skips re-checking the server until cooldownMS has
+ * passed.
+ *
+ * "This avoids spending connectTimeoutMS on each unavailable server
+ * during each scan.
+ *
+ * "This value MUST be 5000 ms, and it MUST NOT be configurable."
+ *
+ *--------------------------------------------------------------------------
+ */
+
+void
+mongoc_topology_scanner_start (mongoc_topology_scanner_t *ts,
+ bool obey_cooldown)
+{
+ mongoc_topology_scanner_node_t *node, *tmp;
+ bool skip;
+ int64_t now;
+
+ BSON_ASSERT (ts);
+
+ _delete_retired_nodes (ts);
+
+ now = bson_get_monotonic_time ();
+
+ DL_FOREACH_SAFE (ts->nodes, node, tmp)
+ {
+ skip =
+ obey_cooldown && mongoc_topology_scanner_node_in_cooldown (node, now);
+
+ if (!skip) {
+ mongoc_topology_scanner_node_setup (node, &node->last_error);
+ }
+ }
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_topology_scanner_finish_scan --
+ *
+ * Summarizes all scanner node errors into one error message,
+ * deletes retired nodes.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+void
+_mongoc_topology_scanner_finish (mongoc_topology_scanner_t *ts)
+{
+ mongoc_topology_scanner_node_t *node, *tmp;
+ bson_error_t *error = &ts->error;
+ bson_string_t *msg;
+
+ memset (&ts->error, 0, sizeof (bson_error_t));
+
+ msg = bson_string_new (NULL);
+
+ DL_FOREACH_SAFE (ts->nodes, node, tmp)
+ {
+ if (node->last_error.code) {
+ if (msg->len) {
+ bson_string_append_c (msg, ' ');
+ }
+
+ bson_string_append_printf (msg, "[%s]", node->last_error.message);
+
+ /* last error domain and code win */
+ error->domain = node->last_error.domain;
+ error->code = node->last_error.code;
+ }
+ }
+
+ bson_strncpy ((char *) &error->message, msg->str, sizeof (error->message));
+ bson_string_free (msg, true);
+
+ _delete_retired_nodes (ts);
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_topology_scanner_work --
+ *
+ * Crank the knob on the topology scanner state machine. This should
+ * be called only after mongoc_topology_scanner_start() has been used
+ * to begin the scan.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+void
+mongoc_topology_scanner_work (mongoc_topology_scanner_t *ts)
+{
+ mongoc_async_run (ts->async);
+ BSON_ASSERT (ts->async->ncmds == 0);
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_topology_scanner_get_error --
+ *
+ * Copy the scanner's current error; which may no-error (code 0).
+ *
+ *--------------------------------------------------------------------------
+ */
+
+void
+mongoc_topology_scanner_get_error (mongoc_topology_scanner_t *ts,
+ bson_error_t *error)
+{
+ BSON_ASSERT (ts);
+ BSON_ASSERT (error);
+
+ memcpy (error, &ts->error, sizeof (bson_error_t));
+}
+
+/*
+ * Set a field in the topology scanner.
+ */
+bool
+_mongoc_topology_scanner_set_appname (mongoc_topology_scanner_t *ts,
+ const char *appname)
+{
+ char *s;
+ const char *prev;
+ if (!_mongoc_handshake_appname_is_valid (appname)) {
+ MONGOC_ERROR ("Cannot set appname: %s is invalid", appname);
+ return false;
+ }
+
+ s = bson_strdup (appname);
+ prev = bson_atomic_ptr_compare_exchange_strong (
+ (void *) &ts->appname, NULL, s, bson_memory_order_relaxed);
+ if (prev == NULL) {
+ return true;
+ }
+
+ MONGOC_ERROR ("Cannot set appname more than once");
+ bson_free (s);
+ return false;
+}
+
+/*
+ * Set the scanner's clusterTime unconditionally: don't compare with prior
+ * @cluster_time is like {clusterTime: <timestamp>}
+ */
+void
+_mongoc_topology_scanner_set_cluster_time (mongoc_topology_scanner_t *ts,
+ const bson_t *cluster_time)
+{
+ bson_destroy (&ts->cluster_time);
+ bson_copy_to (cluster_time, &ts->cluster_time);
+}
+
+/* SDAM Monitoring Spec: send HeartbeatStartedEvent */
+static void
+_mongoc_topology_scanner_monitor_heartbeat_started (
+ const mongoc_topology_scanner_t *ts, const mongoc_host_list_t *host)
+{
+ if (ts->apm_callbacks.server_heartbeat_started) {
+ mongoc_apm_server_heartbeat_started_t event;
+ event.host = host;
+ event.context = ts->apm_context;
+ event.awaited = false;
+ ts->apm_callbacks.server_heartbeat_started (&event);
+ }
+}
+
+/* SDAM Monitoring Spec: send HeartbeatSucceededEvent */
+static void
+_mongoc_topology_scanner_monitor_heartbeat_succeeded (
+ const mongoc_topology_scanner_t *ts,
+ const mongoc_host_list_t *host,
+ const bson_t *reply,
+ int64_t duration_usec)
+{
+ if (ts->apm_callbacks.server_heartbeat_succeeded) {
+ mongoc_apm_server_heartbeat_succeeded_t event;
+ bson_t hello_redacted;
+
+ bson_init (&hello_redacted);
+ bson_copy_to_excluding_noinit (
+ reply, &hello_redacted, "speculativeAuthenticate", NULL);
+
+ event.host = host;
+ event.context = ts->apm_context;
+ event.reply = reply;
+ event.duration_usec = duration_usec;
+ event.awaited = false;
+ ts->apm_callbacks.server_heartbeat_succeeded (&event);
+
+ bson_destroy (&hello_redacted);
+ }
+}
+
+/* SDAM Monitoring Spec: send HeartbeatFailedEvent */
+static void
+_mongoc_topology_scanner_monitor_heartbeat_failed (
+ const mongoc_topology_scanner_t *ts,
+ const mongoc_host_list_t *host,
+ const bson_error_t *error,
+ int64_t duration_usec)
+{
+ if (ts->apm_callbacks.server_heartbeat_failed) {
+ mongoc_apm_server_heartbeat_failed_t event;
+ event.host = host;
+ event.context = ts->apm_context;
+ event.error = error;
+ event.duration_usec = duration_usec;
+ event.awaited = false;
+ ts->apm_callbacks.server_heartbeat_failed (&event);
+ }
+}
+
+/* this is for testing the dns cache timeout. */
+void
+_mongoc_topology_scanner_set_dns_cache_timeout (mongoc_topology_scanner_t *ts,
+ int64_t timeout_ms)
+{
+ ts->dns_cache_timeout_ms = timeout_ms;
+}
+
+/* reset "retired" nodes that failed or were removed in the previous scan */
+static void
+_delete_retired_nodes (mongoc_topology_scanner_t *ts)
+{
+ mongoc_topology_scanner_node_t *node, *tmp;
+
+ DL_FOREACH_SAFE (ts->nodes, node, tmp)
+ {
+ if (node->retired) {
+ mongoc_topology_scanner_node_destroy (node, true);
+ }
+ }
+}
+
+static void
+_cancel_commands_excluding (mongoc_topology_scanner_node_t *node,
+ mongoc_async_cmd_t *acmd)
+{
+ mongoc_async_cmd_t *iter;
+ DL_FOREACH (node->ts->async->cmds, iter)
+ {
+ if ((mongoc_topology_scanner_node_t *) iter->data == node &&
+ iter != acmd) {
+ iter->state = MONGOC_ASYNC_CMD_CANCELED_STATE;
+ }
+ }
+}
+
+static int
+_count_acmds (mongoc_topology_scanner_node_t *node)
+{
+ mongoc_async_cmd_t *iter;
+ int count = 0;
+ DL_FOREACH (node->ts->async->cmds, iter)
+ {
+ if ((mongoc_topology_scanner_node_t *) iter->data == node) {
+ ++count;
+ }
+ }
+ return count;
+}
+
+static void
+_jumpstart_other_acmds (mongoc_topology_scanner_node_t *node,
+ mongoc_async_cmd_t *acmd)
+{
+ mongoc_async_cmd_t *iter;
+ DL_FOREACH (node->ts->async->cmds, iter)
+ {
+ if ((mongoc_topology_scanner_node_t *) iter->data == node &&
+ iter != acmd && acmd->initiate_delay_ms < iter->initiate_delay_ms) {
+ iter->initiate_delay_ms =
+ BSON_MAX (iter->initiate_delay_ms - HAPPY_EYEBALLS_DELAY_MS, 0);
+ }
+ }
+}
+
+void
+_mongoc_topology_scanner_set_server_api (mongoc_topology_scanner_t *ts,
+ const mongoc_server_api_t *api)
+{
+ BSON_ASSERT (ts);
+ BSON_ASSERT (api);
+
+ mongoc_server_api_destroy (ts->api);
+ ts->api = mongoc_server_api_copy (api);
+ _reset_hello (ts);
+}
+
+/* This must be called before the handshake command is constructed. */
+void
+_mongoc_topology_scanner_set_loadbalanced (mongoc_topology_scanner_t *ts,
+ bool val)
+{
+ BSON_ASSERT (ts->handshake_cmd == NULL);
+ ts->loadbalanced = true;
+}
diff --git a/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology.c
new file mode 100644
index 00000000..a9bca4f1
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology.c
@@ -0,0 +1,2033 @@
+/*
+ * Copyright 2014 MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mongoc-config.h"
+
+#include "mongoc-handshake.h"
+#include "mongoc-handshake-private.h"
+
+#include "mongoc-error.h"
+#include "mongoc-host-list-private.h"
+#include "mongoc-log.h"
+#include "mongoc-topology-private.h"
+#include "mongoc-topology-description-apm-private.h"
+#include "mongoc-client-private.h"
+#include "mongoc-cmd-private.h"
+#include "mongoc-uri-private.h"
+#include "mongoc-util-private.h"
+#include "mongoc-trace-private.h"
+#include "mongoc-error-private.h"
+#include "mongoc-topology-background-monitoring-private.h"
+#include "mongoc-read-prefs-private.h"
+
+#include "utlist.h"
+
+#include <stdint.h>
+
+static void
+_topology_collect_errors (const mongoc_topology_description_t *topology,
+ bson_error_t *error_out);
+
+static bool
+_mongoc_topology_reconcile_add_nodes (mongoc_server_description_t *sd,
+ mongoc_topology_scanner_t *scanner)
+{
+ mongoc_topology_scanner_node_t *node;
+
+ /* Search by ID and update hello_ok */
+ node = mongoc_topology_scanner_get_node (scanner, sd->id);
+ if (node) {
+ node->hello_ok = sd->hello_ok;
+ } else if (!mongoc_topology_scanner_has_node_for_host (scanner, &sd->host)) {
+ /* A node for this host was retired in this scan. */
+ mongoc_topology_scanner_add (scanner, &sd->host, sd->id, sd->hello_ok);
+ mongoc_topology_scanner_scan (scanner, sd->id);
+ }
+
+ return true;
+}
+
+/* Called from:
+ * - the topology scanner callback (when a hello was just received)
+ * - at the start of a single-threaded scan (mongoc_topology_scan_once)
+ * Not called for multi threaded monitoring.
+ */
+void
+mongoc_topology_reconcile (const mongoc_topology_t *topology,
+ mongoc_topology_description_t *td)
+{
+ mongoc_set_t *servers;
+ mongoc_server_description_t *sd;
+ int i;
+ mongoc_topology_scanner_node_t *ele, *tmp;
+
+ servers = mc_tpld_servers (td);
+ /* Add newly discovered nodes */
+ for (i = 0; i < (int) servers->items_len; i++) {
+ sd = mongoc_set_get_item (servers, i);
+ _mongoc_topology_reconcile_add_nodes (sd, topology->scanner);
+ }
+
+ /* Remove removed nodes */
+ DL_FOREACH_SAFE (topology->scanner->nodes, ele, tmp)
+ {
+ if (!mongoc_topology_description_server_by_id (td, ele->id, NULL)) {
+ mongoc_topology_scanner_node_retire (ele);
+ }
+ }
+}
+
+
+/* call this while already holding the lock */
+static bool
+_mongoc_topology_update_no_lock (uint32_t id,
+ const bson_t *hello_response,
+ int64_t rtt_msec,
+ mongoc_topology_description_t *td,
+ const bson_error_t *error /* IN */)
+{
+ mongoc_topology_description_handle_hello (
+ td, id, hello_response, rtt_msec, error);
+
+ /* return false if server removed from topology */
+ return mongoc_topology_description_server_by_id (td, id, NULL) != NULL;
+}
+
+
+/*
+ *-------------------------------------------------------------------------
+ *
+ * _mongoc_topology_scanner_setup_err_cb --
+ *
+ * Callback method to handle errors during topology scanner node
+ * setup, typically DNS or SSL errors.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+void
+_mongoc_topology_scanner_setup_err_cb (uint32_t id,
+ void *data,
+ const bson_error_t *error /* IN */)
+{
+ mongoc_topology_t *topology = BSON_ASSERT_PTR_INLINE (data);
+
+ if (_mongoc_topology_get_type (topology) == MONGOC_TOPOLOGY_LOAD_BALANCED) {
+ /* In load balanced mode, scanning is only for connection establishment.
+ * It must not modify the topology description. */
+ } else {
+ /* We need to update the topology description */
+ mc_tpld_modification mod = mc_tpld_modify_begin (topology);
+ mongoc_topology_description_handle_hello (
+ mod.new_td, id, NULL /* hello reply */, -1 /* rtt_msec */, error);
+ mc_tpld_modify_commit (mod);
+ }
+}
+
+
+/*
+ *-------------------------------------------------------------------------
+ *
+ * _mongoc_topology_scanner_cb --
+ *
+ * Callback method to handle hello responses received by async
+ * command objects.
+ *
+ * Only called for single-threaded monitoring.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+void
+_mongoc_topology_scanner_cb (uint32_t id,
+ const bson_t *hello_response,
+ int64_t rtt_msec,
+ void *data,
+ const bson_error_t *error /* IN */)
+{
+ mongoc_topology_t *const topology = BSON_ASSERT_PTR_INLINE (data);
+ mongoc_server_description_t *sd;
+ mc_tpld_modification tdmod;
+
+ if (_mongoc_topology_get_type (topology) == MONGOC_TOPOLOGY_LOAD_BALANCED) {
+ /* In load balanced mode, scanning is only for connection establishment.
+ * It must not modify the topology description. */
+ return;
+ }
+
+ tdmod = mc_tpld_modify_begin (topology);
+
+ sd = mongoc_topology_description_server_by_id (tdmod.new_td, id, NULL);
+
+ if (!hello_response) {
+ /* Server monitoring: When a server check fails due to a network error
+ * (including a network timeout), the client MUST clear its connection
+ * pool for the server */
+ _mongoc_topology_description_clear_connection_pool (
+ tdmod.new_td, id, &kZeroServiceId);
+ }
+
+ /* Server Discovery and Monitoring Spec: "Once a server is connected, the
+ * client MUST change its type to Unknown only after it has retried the
+ * server once." */
+ if (!hello_response && sd && sd->type != MONGOC_SERVER_UNKNOWN) {
+ _mongoc_topology_update_no_lock (
+ id, hello_response, rtt_msec, tdmod.new_td, error);
+
+ /* add another hello call to the current scan - the scan continues
+ * until all commands are done */
+ mongoc_topology_scanner_scan (topology->scanner, sd->id);
+ } else {
+ _mongoc_topology_update_no_lock (
+ id, hello_response, rtt_msec, tdmod.new_td, error);
+
+ /* The processing of the hello results above may have added, changed, or
+ * removed server descriptions. We need to reconcile that with our
+ * monitoring agents
+ */
+ mongoc_topology_reconcile (topology, tdmod.new_td);
+
+ mongoc_cond_broadcast (&topology->cond_client);
+ }
+
+
+ mc_tpld_modify_commit (tdmod);
+}
+
+static void
+_server_session_init (mongoc_server_session_t *session,
+ mongoc_topology_t *unused,
+ bson_error_t *error)
+{
+ _mongoc_server_session_init (session, error);
+}
+
+static void
+_server_session_destroy (mongoc_server_session_t *session,
+ mongoc_topology_t *unused)
+{
+ _mongoc_server_session_destroy (session);
+}
+
+static int
+_server_session_should_prune (mongoc_server_session_t *session,
+ mongoc_topology_t *topo)
+{
+ bool is_loadbalanced;
+ int timeout;
+ mc_shared_tpld td;
+
+ BSON_ASSERT_PARAM (session);
+ BSON_ASSERT_PARAM (topo);
+
+ /** If "dirty" (i.e. contains a network error), it should be dropped */
+ if (session->dirty) {
+ return true;
+ }
+
+ /** If the session has never been used, it should be dropped */
+ if (session->last_used_usec == SESSION_NEVER_USED) {
+ return true;
+ }
+
+ /* Check for a timeout */
+ td = mc_tpld_take_ref (topo);
+ timeout = td.ptr->session_timeout_minutes;
+ is_loadbalanced = td.ptr->type == MONGOC_TOPOLOGY_LOAD_BALANCED;
+ mc_tpld_drop_ref (&td);
+
+ /** Load balanced topology sessions never expire */
+ if (is_loadbalanced) {
+ return false;
+ }
+
+ /* Prune the session if it has hit a timeout */
+ return _mongoc_server_session_timed_out (session, timeout);
+}
+
+static void
+_tpld_destroy_and_free (void *tpl_descr)
+{
+ mongoc_topology_description_t *td = tpl_descr;
+ mongoc_topology_description_destroy (td);
+}
+
+const mongoc_host_list_t **
+_mongoc_apply_srv_max_hosts (const mongoc_host_list_t *hl,
+ const int32_t max_hosts,
+ size_t *const hl_array_size)
+{
+ size_t hl_size;
+ size_t idx;
+ const mongoc_host_list_t **hl_array;
+
+ BSON_ASSERT (max_hosts >= 0);
+ BSON_ASSERT_PARAM (hl_array_size);
+
+ hl_size = (size_t) _mongoc_host_list_length (hl);
+
+ if (hl_size == 0) {
+ *hl_array_size = 0;
+ return NULL;
+ }
+
+ hl_array = bson_malloc (hl_size * sizeof (mongoc_host_list_t *));
+
+ for (idx = 0u; hl; hl = hl->next) {
+ hl_array[idx++] = hl;
+ }
+
+ if (max_hosts == 0 || /* Unlimited. */
+ hl_size == 1u || /* Trivial case. */
+ hl_size <= (size_t) max_hosts /* Already satisfies limit. */
+ ) {
+ /* No random shuffle or selection required. */
+ *hl_array_size = hl_size;
+ return hl_array;
+ }
+
+ /* Initial DNS Seedlist Discovery Spec: If `srvMaxHosts` is greater than zero
+ * and less than the number of hosts in the DNS result, the driver MUST
+ * randomly select that many hosts and use them to populate the seedlist.
+ * Drivers SHOULD use the `Fisher-Yates shuffle` for randomization. */
+ for (idx = hl_size - 1u; idx > 0u; --idx) {
+ /* 0 <= swap_pos <= idx */
+ const size_t swap_pos =
+ _mongoc_rand_size_t (0u, idx, _mongoc_simple_rand_size_t);
+
+ const mongoc_host_list_t *tmp = hl_array[swap_pos];
+ hl_array[swap_pos] = hl_array[idx];
+ hl_array[idx] = tmp;
+ }
+
+ *hl_array_size = max_hosts;
+
+ return hl_array;
+}
+
+/*
+ *-------------------------------------------------------------------------
+ *
+ * mongoc_topology_new --
+ *
+ * Creates and returns a new topology object.
+ *
+ * Returns:
+ * A new topology object.
+ *
+ * Side effects:
+ * None.
+ *
+ *-------------------------------------------------------------------------
+ */
+mongoc_topology_t *
+mongoc_topology_new (const mongoc_uri_t *uri, bool single_threaded)
+{
+ int64_t heartbeat_default;
+ int64_t heartbeat;
+ mongoc_topology_t *topology;
+ mongoc_topology_description_type_t init_type;
+ mongoc_topology_description_t *td;
+ const char *srv_hostname;
+ const mongoc_host_list_t *hl;
+ mongoc_rr_data_t rr_data;
+ bool has_directconnection;
+ bool directconnection;
+
+ BSON_ASSERT (uri);
+
+#ifndef MONGOC_ENABLE_CRYPTO
+ if (mongoc_uri_get_option_as_bool (
+ uri, MONGOC_URI_RETRYWRITES, MONGOC_DEFAULT_RETRYWRITES)) {
+ /* retryWrites requires sessions, which require crypto - just warn */
+ MONGOC_WARNING (
+ "retryWrites not supported without an SSL crypto library");
+ }
+#endif
+
+ topology = (mongoc_topology_t *) bson_malloc0 (sizeof *topology);
+ topology->session_pool =
+ mongoc_server_session_pool_new_with_params (_server_session_init,
+ _server_session_destroy,
+ _server_session_should_prune,
+ topology);
+
+ topology->valid = false;
+ heartbeat_default =
+ single_threaded ? MONGOC_TOPOLOGY_HEARTBEAT_FREQUENCY_MS_SINGLE_THREADED
+ : MONGOC_TOPOLOGY_HEARTBEAT_FREQUENCY_MS_MULTI_THREADED;
+
+ heartbeat = mongoc_uri_get_option_as_int32 (
+ uri, MONGOC_URI_HEARTBEATFREQUENCYMS, heartbeat_default);
+
+ topology->_shared_descr_._sptr_ = mongoc_shared_ptr_create (
+ bson_malloc0 (sizeof (mongoc_topology_description_t)),
+ _tpld_destroy_and_free);
+ td = mc_tpld_unsafe_get_mutable (topology);
+ mongoc_topology_description_init (td, heartbeat);
+
+ td->set_name = bson_strdup (mongoc_uri_get_replica_set (uri));
+
+ topology->uri = mongoc_uri_copy (uri);
+ topology->cse_state = MONGOC_CSE_DISABLED;
+ topology->single_threaded = single_threaded;
+ if (single_threaded) {
+ /* Server Selection Spec:
+ *
+ * "Single-threaded drivers MUST provide a "serverSelectionTryOnce"
+ * mode, in which the driver scans the topology exactly once after
+ * server selection fails, then either selects a server or raises an
+ * error.
+ *
+ * "The serverSelectionTryOnce option MUST be true by default."
+ */
+ topology->server_selection_try_once = mongoc_uri_get_option_as_bool (
+ uri, MONGOC_URI_SERVERSELECTIONTRYONCE, true);
+ } else {
+ topology->server_selection_try_once = false;
+ }
+
+ topology->server_selection_timeout_msec = mongoc_uri_get_option_as_int32 (
+ topology->uri,
+ MONGOC_URI_SERVERSELECTIONTIMEOUTMS,
+ MONGOC_TOPOLOGY_SERVER_SELECTION_TIMEOUT_MS);
+
+ /* tests can override this */
+ topology->min_heartbeat_frequency_msec =
+ MONGOC_TOPOLOGY_MIN_HEARTBEAT_FREQUENCY_MS;
+
+ topology->local_threshold_msec =
+ mongoc_uri_get_local_threshold_option (topology->uri);
+
+ /* Total time allowed to check a server is connectTimeoutMS.
+ * Server Discovery And Monitoring Spec:
+ *
+ * "The socket used to check a server MUST use the same connectTimeoutMS as
+ * regular sockets. Multi-threaded clients SHOULD set monitoring sockets'
+ * socketTimeoutMS to the connectTimeoutMS."
+ */
+ topology->connect_timeout_msec =
+ mongoc_uri_get_option_as_int32 (topology->uri,
+ MONGOC_URI_CONNECTTIMEOUTMS,
+ MONGOC_DEFAULT_CONNECTTIMEOUTMS);
+
+ topology->scanner_state = MONGOC_TOPOLOGY_SCANNER_OFF;
+ topology->scanner =
+ mongoc_topology_scanner_new (topology->uri,
+ _mongoc_topology_scanner_setup_err_cb,
+ _mongoc_topology_scanner_cb,
+ topology,
+ topology->connect_timeout_msec);
+
+ bson_mutex_init (&topology->tpld_modification_mtx);
+ mongoc_cond_init (&topology->cond_client);
+
+ if (single_threaded) {
+ /* single threaded drivers attempt speculative authentication during a
+ * topology scan */
+ topology->scanner->speculative_authentication = true;
+
+ /* single threaded clients negotiate sasl supported mechanisms during
+ * a topology scan. */
+ if (_mongoc_uri_requires_auth_negotiation (uri)) {
+ topology->scanner->negotiate_sasl_supported_mechs = true;
+ }
+ }
+
+ srv_hostname = mongoc_uri_get_srv_hostname (uri);
+ if (srv_hostname) {
+ char *prefixed_hostname;
+
+ memset (&rr_data, 0, sizeof (mongoc_rr_data_t));
+ /* Set the default resource record resolver */
+ topology->rr_resolver = _mongoc_client_get_rr;
+
+ /* Initialize the last scan time and interval. Even if the initial DNS
+ * lookup fails, SRV polling will still start when background monitoring
+ * starts. */
+ topology->srv_polling_last_scan_ms = bson_get_monotonic_time () / 1000;
+ topology->srv_polling_rescan_interval_ms =
+ MONGOC_TOPOLOGY_MIN_RESCAN_SRV_INTERVAL_MS;
+
+ /* a mongodb+srv URI. try SRV lookup, if no error then also try TXT */
+ prefixed_hostname = bson_strdup_printf (
+ "_%s._tcp.%s", mongoc_uri_get_srv_service_name (uri), srv_hostname);
+ if (!topology->rr_resolver (prefixed_hostname,
+ MONGOC_RR_SRV,
+ &rr_data,
+ MONGOC_RR_DEFAULT_BUFFER_SIZE,
+ &topology->scanner->error)) {
+ GOTO (srv_fail);
+ }
+
+ /* Failure to find TXT records will not return an error (since it is only
+ * for options). But _mongoc_client_get_rr may return an error if
+ * there is more than one TXT record returned. */
+ if (!topology->rr_resolver (srv_hostname,
+ MONGOC_RR_TXT,
+ &rr_data,
+ MONGOC_RR_DEFAULT_BUFFER_SIZE,
+ &topology->scanner->error)) {
+ GOTO (srv_fail);
+ }
+
+ /* Use rr_data to update the topology's URI. */
+ if (rr_data.txt_record_opts &&
+ !mongoc_uri_parse_options (topology->uri,
+ rr_data.txt_record_opts,
+ true /* from_dns */,
+ &topology->scanner->error)) {
+ GOTO (srv_fail);
+ }
+
+ if (!mongoc_uri_init_with_srv_host_list (
+ topology->uri, rr_data.hosts, &topology->scanner->error)) {
+ GOTO (srv_fail);
+ }
+
+ topology->srv_polling_last_scan_ms = bson_get_monotonic_time () / 1000;
+ /* TODO (CDRIVER-4047) use BSON_MIN */
+ topology->srv_polling_rescan_interval_ms = BSON_MAX (
+ rr_data.min_ttl * 1000, MONGOC_TOPOLOGY_MIN_RESCAN_SRV_INTERVAL_MS);
+
+ topology->valid = true;
+ srv_fail:
+ bson_free (rr_data.txt_record_opts);
+ bson_free (prefixed_hostname);
+ _mongoc_host_list_destroy_all (rr_data.hosts);
+ } else {
+ topology->valid = true;
+ }
+
+ if (!mongoc_uri_finalize (topology->uri, &topology->scanner->error)) {
+ topology->valid = false;
+ }
+
+ td->max_hosts =
+ mongoc_uri_get_option_as_int32 (uri, MONGOC_URI_SRVMAXHOSTS, 0);
+
+ /*
+ * Set topology type from URI:
+ * + if directConnection=true
+ * - whether or not we have a replicaSet name, initialize to SINGLE
+ * (directConnect with SRV or multiple hosts triggers a URI parse error)
+ * + if directConnection=false
+ * - if we've got a replicaSet name, initialize to RS_NO_PRIMARY
+ * - otherwise, initialize to UNKNOWN
+ * + if directConnection was not specified in the URI (old behavior)
+ * - if we've got a replicaSet name, initialize to RS_NO_PRIMARY
+ * - otherwise, if the seed list has a single host, initialize to SINGLE
+ * - everything else gets initialized to UNKNOWN
+ */
+ has_directconnection =
+ mongoc_uri_has_option (uri, MONGOC_URI_DIRECTCONNECTION);
+ directconnection =
+ has_directconnection &&
+ mongoc_uri_get_option_as_bool (uri, MONGOC_URI_DIRECTCONNECTION, false);
+ hl = mongoc_uri_get_hosts (topology->uri);
+ /* If loadBalanced is enabled, directConnection is disabled. This was
+ * validated in mongoc_uri_finalize_loadbalanced, which is called by
+ * mongoc_uri_finalize. */
+ if (mongoc_uri_get_option_as_bool (
+ topology->uri, MONGOC_URI_LOADBALANCED, false)) {
+ init_type = MONGOC_TOPOLOGY_LOAD_BALANCED;
+ if (topology->single_threaded) {
+ /* Cooldown only applies to server monitoring for single-threaded
+ * clients. In load balanced mode, the topology scanner is used to
+ * create connections. The cooldown period does not apply. A network
+ * error to a load balanced connection does not imply subsequent
+ * connection attempts will be to the same server and that a delay
+ * should occur. */
+ _mongoc_topology_bypass_cooldown (topology);
+ }
+ _mongoc_topology_scanner_set_loadbalanced (topology->scanner, true);
+ } else if (srv_hostname && !has_directconnection) {
+ init_type = MONGOC_TOPOLOGY_UNKNOWN;
+ } else if (has_directconnection) {
+ if (directconnection) {
+ init_type = MONGOC_TOPOLOGY_SINGLE;
+ } else {
+ if (mongoc_uri_get_replica_set (topology->uri)) {
+ init_type = MONGOC_TOPOLOGY_RS_NO_PRIMARY;
+ } else {
+ init_type = MONGOC_TOPOLOGY_UNKNOWN;
+ }
+ }
+ } else if (mongoc_uri_get_replica_set (topology->uri)) {
+ init_type = MONGOC_TOPOLOGY_RS_NO_PRIMARY;
+ } else {
+ if (hl && hl->next) {
+ init_type = MONGOC_TOPOLOGY_UNKNOWN;
+ } else {
+ init_type = MONGOC_TOPOLOGY_SINGLE;
+ }
+ }
+
+ td->type = init_type;
+
+ if (!topology->single_threaded) {
+ topology->server_monitors = mongoc_set_new (1, NULL, NULL);
+ topology->rtt_monitors = mongoc_set_new (1, NULL, NULL);
+ bson_mutex_init (&topology->apm_mutex);
+ bson_mutex_init (&topology->srv_polling_mtx);
+ mongoc_cond_init (&topology->srv_polling_cond);
+ }
+
+ if (!topology->valid) {
+ TRACE ("%s", "topology invalid");
+ /* add no nodes */
+ return topology;
+ }
+
+ {
+ size_t idx = 0u;
+ size_t hl_array_size = 0u;
+ uint32_t id = 0u;
+
+ const mongoc_host_list_t *const *hl_array =
+ _mongoc_apply_srv_max_hosts (hl, td->max_hosts, &hl_array_size);
+
+ for (idx = 0u; idx < hl_array_size; ++idx) {
+ const mongoc_host_list_t *const elem = hl_array[idx];
+
+ mongoc_topology_description_add_server (td, elem->host_and_port, &id);
+ mongoc_topology_scanner_add (topology->scanner, elem, id, false);
+ }
+
+ bson_free ((void *) hl_array);
+ }
+
+ return topology;
+}
+
+/*
+ *-------------------------------------------------------------------------
+ *
+ * mongoc_topology_set_apm_callbacks --
+ *
+ * Set Application Performance Monitoring callbacks.
+ *
+ *-------------------------------------------------------------------------
+ */
+void
+mongoc_topology_set_apm_callbacks (mongoc_topology_t *topology,
+ mongoc_topology_description_t *td,
+ mongoc_apm_callbacks_t *callbacks,
+ void *context)
+{
+ if (callbacks) {
+ memcpy (&td->apm_callbacks, callbacks, sizeof (mongoc_apm_callbacks_t));
+ memcpy (&topology->scanner->apm_callbacks,
+ callbacks,
+ sizeof (mongoc_apm_callbacks_t));
+ } else {
+ memset (&td->apm_callbacks, 0, sizeof (mongoc_apm_callbacks_t));
+ memset (
+ &topology->scanner->apm_callbacks, 0, sizeof (mongoc_apm_callbacks_t));
+ }
+
+ td->apm_context = context;
+ topology->scanner->apm_context = context;
+}
+
+/*
+ *-------------------------------------------------------------------------
+ *
+ * mongoc_topology_destroy --
+ *
+ * Free the memory associated with this topology object.
+ *
+ * Returns:
+ * None.
+ *
+ * Side effects:
+ * @topology will be cleaned up.
+ *
+ *-------------------------------------------------------------------------
+ */
+void
+mongoc_topology_destroy (mongoc_topology_t *topology)
+{
+ if (!topology) {
+ return;
+ }
+
+#ifdef MONGOC_ENABLE_CLIENT_SIDE_ENCRYPTION
+ bson_free (topology->keyvault_db);
+ bson_free (topology->keyvault_coll);
+ mongoc_client_destroy (topology->mongocryptd_client);
+ mongoc_client_pool_destroy (topology->mongocryptd_client_pool);
+ _mongoc_crypt_destroy (topology->crypt);
+ bson_destroy (topology->mongocryptd_spawn_args);
+ bson_free (topology->mongocryptd_spawn_path);
+#endif
+
+ if (!topology->single_threaded) {
+ _mongoc_topology_background_monitoring_stop (topology);
+ BSON_ASSERT (topology->scanner_state == MONGOC_TOPOLOGY_SCANNER_OFF);
+ mongoc_set_destroy (topology->server_monitors);
+ mongoc_set_destroy (topology->rtt_monitors);
+ bson_mutex_destroy (&topology->apm_mutex);
+ bson_mutex_destroy (&topology->srv_polling_mtx);
+ mongoc_cond_destroy (&topology->srv_polling_cond);
+ }
+
+ if (topology->valid) {
+ /* Do not emit a topology_closed event. A topology opening event was not
+ * emitted. */
+ _mongoc_topology_description_monitor_closed (
+ mc_tpld_unsafe_get_const (topology));
+ }
+
+ mongoc_uri_destroy (topology->uri);
+ mongoc_shared_ptr_reset_null (&topology->_shared_descr_._sptr_);
+ mongoc_topology_scanner_destroy (topology->scanner);
+ mongoc_server_session_pool_free (topology->session_pool);
+
+ mongoc_cond_destroy (&topology->cond_client);
+ bson_mutex_destroy (&topology->tpld_modification_mtx);
+
+ bson_free (topology);
+}
+
+/* Returns false if none of the hosts were valid. */
+bool
+mongoc_topology_apply_scanned_srv_hosts (mongoc_uri_t *uri,
+ mongoc_topology_description_t *td,
+ mongoc_host_list_t *hosts,
+ bson_error_t *error)
+{
+ mongoc_host_list_t *host;
+ mongoc_host_list_t *valid_hosts = NULL;
+ bool had_valid_hosts = false;
+
+ /* Validate that the hosts have a matching domain.
+ * If validation fails, log it.
+ * If no valid hosts remain, do not update the topology description.
+ */
+ LL_FOREACH (hosts, host)
+ {
+ if (mongoc_uri_validate_srv_result (uri, host->host, error)) {
+ _mongoc_host_list_upsert (&valid_hosts, host);
+ } else {
+ MONGOC_ERROR ("Invalid host returned by SRV: %s", host->host_and_port);
+ /* Continue on, there may still be valid hosts returned. */
+ }
+ }
+
+ if (valid_hosts) {
+ /* Reconcile with the topology description. Newly found servers will start
+ * getting monitored and are eligible to be used by clients. */
+ mongoc_topology_description_reconcile (td, valid_hosts);
+ had_valid_hosts = true;
+ } else {
+ bson_set_error (error,
+ MONGOC_ERROR_STREAM,
+ MONGOC_ERROR_STREAM_NAME_RESOLUTION,
+ "SRV response did not contain any valid hosts");
+ }
+
+ _mongoc_host_list_destroy_all (valid_hosts);
+ return had_valid_hosts;
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_topology_should_rescan_srv --
+ *
+ * Checks whether it is valid to rescan SRV records on the topology.
+ * Namely, that the topology type is Sharded or Unknown, and that
+ * the topology URI was configured with SRV.
+ *
+ * If this returns false, caller can stop scanning SRV records
+ * and does not need to try again in the future.
+ *
+ * --------------------------------------------------------------------------
+ */
+bool
+mongoc_topology_should_rescan_srv (mongoc_topology_t *topology)
+{
+ const char *srv_hostname = mongoc_uri_get_srv_hostname (topology->uri);
+ mongoc_topology_description_type_t type;
+
+ if (!srv_hostname) {
+ /* Only rescan if we have a mongodb+srv:// URI. */
+ return false;
+ }
+
+ type = _mongoc_topology_get_type (topology);
+
+ /* Only perform rescan for sharded topology. */
+ return type == MONGOC_TOPOLOGY_SHARDED || type == MONGOC_TOPOLOGY_UNKNOWN;
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_topology_rescan_srv --
+ *
+ * Queries SRV records for new hosts in a mongos cluster.
+ * Caller must call mongoc_topology_should_rescan_srv before calling
+ * to ensure preconditions are met.
+ *
+ * NOTE: This method may update the topology description.
+ *
+ * --------------------------------------------------------------------------
+ */
+void
+mongoc_topology_rescan_srv (mongoc_topology_t *topology)
+{
+ mongoc_rr_data_t rr_data = {0};
+ const char *srv_hostname;
+ char *prefixed_hostname = NULL;
+ int64_t scan_time_ms;
+ bool ret;
+ mc_shared_tpld td;
+ mc_tpld_modification tdmod;
+
+ BSON_ASSERT (mongoc_topology_should_rescan_srv (topology));
+
+ srv_hostname = mongoc_uri_get_srv_hostname (topology->uri);
+ scan_time_ms = topology->srv_polling_last_scan_ms +
+ topology->srv_polling_rescan_interval_ms;
+ if (bson_get_monotonic_time () / 1000 < scan_time_ms) {
+ /* Query SRV no more frequently than srv_polling_rescan_interval_ms. */
+ return;
+ }
+
+ TRACE ("%s", "Polling for SRV records");
+
+ /* Go forth and query... */
+ prefixed_hostname =
+ bson_strdup_printf ("_%s._tcp.%s",
+ mongoc_uri_get_srv_service_name (topology->uri),
+ srv_hostname);
+
+ ret = topology->rr_resolver (prefixed_hostname,
+ MONGOC_RR_SRV,
+ &rr_data,
+ MONGOC_RR_DEFAULT_BUFFER_SIZE,
+ &topology->scanner->error);
+
+ td = mc_tpld_take_ref (topology);
+ topology->srv_polling_last_scan_ms = bson_get_monotonic_time () / 1000;
+ if (!ret) {
+ /* Failed querying, soldier on and try again next time. */
+ topology->srv_polling_rescan_interval_ms = td.ptr->heartbeat_msec;
+ MONGOC_ERROR ("SRV polling error: %s", topology->scanner->error.message);
+ GOTO (done);
+ }
+
+ /* TODO (CDRIVER-4047) use BSON_MIN */
+ topology->srv_polling_rescan_interval_ms = BSON_MAX (
+ rr_data.min_ttl * 1000, MONGOC_TOPOLOGY_MIN_RESCAN_SRV_INTERVAL_MS);
+
+ tdmod = mc_tpld_modify_begin (topology);
+ if (!mongoc_topology_apply_scanned_srv_hosts (topology->uri,
+ tdmod.new_td,
+ rr_data.hosts,
+ &topology->scanner->error)) {
+ MONGOC_ERROR ("%s", topology->scanner->error.message);
+ /* Special case when DNS returns zero records successfully or no valid
+ * hosts exist.
+ * Leave the toplogy alone and perform another scan at the next interval
+ * rather than removing all records and having nothing to connect to.
+ * For no verified hosts drivers "MUST temporarily set
+ * srv_polling_rescan_interval_ms
+ * to heartbeatFrequencyMS until at least one verified SRV record is
+ * obtained."
+ */
+ topology->srv_polling_rescan_interval_ms = td.ptr->heartbeat_msec;
+ }
+ mc_tpld_modify_commit (tdmod);
+
+done:
+ mc_tpld_drop_ref (&td);
+ bson_free (prefixed_hostname);
+ _mongoc_host_list_destroy_all (rr_data.hosts);
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_topology_scan_once --
+ *
+ * Runs a single complete scan.
+ *
+ * NOTE: This method updates the topology description.
+ *
+ * Only runs for single threaded monitoring. (obey_cooldown is always
+ * true).
+ *
+ *--------------------------------------------------------------------------
+ */
+static void
+mongoc_topology_scan_once (mongoc_topology_t *topology, bool obey_cooldown)
+{
+ mc_tpld_modification tdmod;
+ if (mongoc_topology_should_rescan_srv (topology)) {
+ /* Prior to scanning hosts, update the list of SRV hosts, if applicable.
+ */
+ mongoc_topology_rescan_srv (topology);
+ }
+
+ /* since the last scan, members may be added or removed from the topology
+ * description based on hello responses in connection handshakes, see
+ * _mongoc_topology_update_from_handshake. retire scanner nodes for removed
+ * members and create scanner nodes for new ones. */
+ tdmod = mc_tpld_modify_begin (topology);
+ mongoc_topology_reconcile (topology, tdmod.new_td);
+ mc_tpld_modify_commit (tdmod);
+
+ mongoc_topology_scanner_start (topology->scanner, obey_cooldown);
+ mongoc_topology_scanner_work (topology->scanner);
+
+ _mongoc_topology_scanner_finish (topology->scanner);
+
+ topology->last_scan = bson_get_monotonic_time ();
+ topology->stale = false;
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_topology_do_blocking_scan --
+ *
+ * Monitoring entry for single-threaded use case. Assumes the caller
+ * has checked that it's the right time to scan.
+ *
+ *--------------------------------------------------------------------------
+ */
+void
+_mongoc_topology_do_blocking_scan (mongoc_topology_t *topology,
+ bson_error_t *error)
+{
+ _mongoc_handshake_freeze ();
+
+ mongoc_topology_scan_once (topology, true /* obey cooldown */);
+ mongoc_topology_scanner_get_error (topology->scanner, error);
+}
+
+
+bool
+mongoc_topology_compatible (const mongoc_topology_description_t *td,
+ const mongoc_read_prefs_t *read_prefs,
+ bson_error_t *error)
+{
+ int64_t max_staleness_seconds;
+ int32_t max_wire_version;
+
+ if (td->compatibility_error.code) {
+ if (error) {
+ memcpy (error, &td->compatibility_error, sizeof (bson_error_t));
+ }
+ return false;
+ }
+
+ if (!read_prefs) {
+ /* NULL means read preference Primary */
+ return true;
+ }
+
+ max_staleness_seconds =
+ mongoc_read_prefs_get_max_staleness_seconds (read_prefs);
+
+ if (max_staleness_seconds != MONGOC_NO_MAX_STALENESS) {
+ max_wire_version =
+ mongoc_topology_description_lowest_max_wire_version (td);
+
+ if (max_wire_version < WIRE_VERSION_MAX_STALENESS) {
+ bson_set_error (error,
+ MONGOC_ERROR_COMMAND,
+ MONGOC_ERROR_PROTOCOL_BAD_WIRE_VERSION,
+ "Not all servers support maxStalenessSeconds");
+ return false;
+ }
+
+ /* shouldn't happen if we've properly enforced wire version */
+ if (!mongoc_topology_description_all_sds_have_write_date (td)) {
+ bson_set_error (error,
+ MONGOC_ERROR_COMMAND,
+ MONGOC_ERROR_PROTOCOL_BAD_WIRE_VERSION,
+ "Not all servers have lastWriteDate");
+ return false;
+ }
+
+ if (!_mongoc_topology_description_validate_max_staleness (
+ td, max_staleness_seconds, error)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+static void
+_mongoc_server_selection_error (const char *msg,
+ const bson_error_t *scanner_error,
+ bson_error_t *error)
+{
+ if (scanner_error && scanner_error->code) {
+ bson_set_error (error,
+ MONGOC_ERROR_SERVER_SELECTION,
+ MONGOC_ERROR_SERVER_SELECTION_FAILURE,
+ "%s: %s",
+ msg,
+ scanner_error->message);
+ } else {
+ bson_set_error (error,
+ MONGOC_ERROR_SERVER_SELECTION,
+ MONGOC_ERROR_SERVER_SELECTION_FAILURE,
+ "%s",
+ msg);
+ }
+}
+
+
+mongoc_server_description_t *
+mongoc_topology_select (mongoc_topology_t *topology,
+ mongoc_ss_optype_t optype,
+ const mongoc_read_prefs_t *read_prefs,
+ bool *must_use_primary,
+ bson_error_t *error)
+{
+ uint32_t server_id = mongoc_topology_select_server_id (
+ topology, optype, read_prefs, must_use_primary, error);
+
+ if (server_id) {
+ /* new copy of the server description */
+ mongoc_server_description_t *ret;
+ mc_shared_tpld td = mc_tpld_take_ref (topology);
+ mongoc_server_description_t const *sd =
+ mongoc_topology_description_server_by_id_const (
+ td.ptr, server_id, error);
+ ret = mongoc_server_description_new_copy (sd);
+ mc_tpld_drop_ref (&td);
+ return ret;
+ } else {
+ return NULL;
+ }
+}
+
+/* Bypasses normal server selection behavior for a load balanced topology.
+ * Returns the id of the one load balancer server. Returns 0 on failure.
+ * Successful post-condition: On a single threaded client, a connection will
+ * have been established. */
+static uint32_t
+_mongoc_topology_select_server_id_loadbalanced (mongoc_topology_t *topology,
+ bson_error_t *error)
+{
+ mongoc_server_description_t const *selected_server;
+ int32_t selected_server_id;
+ mongoc_topology_scanner_node_t *node;
+ bson_error_t scanner_error = {0};
+ mc_shared_tpld td = mc_tpld_take_ref (topology);
+
+ BSON_ASSERT (td.ptr->type == MONGOC_TOPOLOGY_LOAD_BALANCED);
+
+ /* Emit the opening SDAM events if they have not emitted already. */
+ if (!td.ptr->opened) {
+ mc_tpld_modification tdmod = mc_tpld_modify_begin (topology);
+ _mongoc_topology_description_monitor_opening (tdmod.new_td);
+ mc_tpld_modify_commit (tdmod);
+ mc_tpld_renew_ref (&td, topology);
+ }
+ selected_server =
+ mongoc_topology_description_select (td.ptr,
+ MONGOC_SS_WRITE,
+ NULL /* read prefs */,
+ NULL /* chosen read mode */,
+ 0 /* local threshold */);
+
+ if (!selected_server) {
+ _mongoc_server_selection_error (
+ "No suitable server found in load balanced deployment", NULL, error);
+ selected_server_id = 0;
+ goto done;
+ }
+
+ selected_server_id = selected_server->id;
+
+ if (!topology->single_threaded) {
+ goto done;
+ }
+
+ /* If this is a single threaded topology, we must ensure that a connection is
+ * available to this server. Wrapping drivers make the assumption that
+ * successful server selection implies a connection is available. */
+ node =
+ mongoc_topology_scanner_get_node (topology->scanner, selected_server_id);
+ if (!node) {
+ _mongoc_server_selection_error (
+ "Topology scanner in invalid state; cannot find load balancer",
+ NULL,
+ error);
+ selected_server_id = 0;
+ goto done;
+ }
+
+ if (!node->stream) {
+ TRACE ("%s",
+ "Server selection performing scan since no connection has "
+ "been established");
+ _mongoc_topology_do_blocking_scan (topology, &scanner_error);
+ }
+
+ if (!node->stream) {
+ /* Use the same error domain / code that is returned in mongoc-cluster.c
+ * when fetching a stream fails. */
+ if (scanner_error.code) {
+ bson_set_error (error,
+ MONGOC_ERROR_STREAM,
+ MONGOC_ERROR_STREAM_NOT_ESTABLISHED,
+ "Could not establish stream for node %s: %s",
+ node->host.host_and_port,
+ scanner_error.message);
+ } else {
+ bson_set_error (error,
+ MONGOC_ERROR_STREAM,
+ MONGOC_ERROR_STREAM_NOT_ESTABLISHED,
+ "Could not establish stream for node %s",
+ node->host.host_and_port);
+ }
+ selected_server_id = 0;
+ goto done;
+ }
+
+done:
+ mc_tpld_drop_ref (&td);
+ return selected_server_id;
+}
+
+
+uint32_t
+mongoc_topology_select_server_id (mongoc_topology_t *topology,
+ mongoc_ss_optype_t optype,
+ const mongoc_read_prefs_t *read_prefs,
+ bool *must_use_primary,
+ bson_error_t *error)
+{
+ static const char *timeout_msg =
+ "No suitable servers found: `serverSelectionTimeoutMS` expired";
+
+ mongoc_topology_scanner_t *ts;
+ int r;
+ int64_t local_threshold_ms;
+ const mongoc_server_description_t *selected_server = NULL;
+ bool try_once;
+ int64_t sleep_usec;
+ bool tried_once;
+ bson_error_t scanner_error = {0};
+ int64_t heartbeat_msec;
+ uint32_t server_id;
+ mc_shared_tpld td = mc_tpld_take_ref (topology);
+
+ /* These names come from the Server Selection Spec pseudocode */
+ int64_t loop_start; /* when we entered this function */
+ int64_t loop_end; /* when we last completed a loop (single-threaded) */
+ int64_t scan_ready; /* the soonest we can do a blocking scan */
+ int64_t next_update; /* the latest we must do a blocking scan */
+ int64_t expire_at; /* when server selection timeout expires */
+
+ BSON_ASSERT (topology);
+ ts = topology->scanner;
+
+ if (!mongoc_topology_scanner_valid (ts)) {
+ if (error) {
+ mongoc_topology_scanner_get_error (ts, error);
+ error->domain = MONGOC_ERROR_SERVER_SELECTION;
+ error->code = MONGOC_ERROR_SERVER_SELECTION_FAILURE;
+ }
+ server_id = 0;
+ goto done;
+ }
+
+ if (td.ptr->type == MONGOC_TOPOLOGY_LOAD_BALANCED) {
+ server_id =
+ _mongoc_topology_select_server_id_loadbalanced (topology, error);
+ goto done;
+ }
+
+ heartbeat_msec = td.ptr->heartbeat_msec;
+ local_threshold_ms = topology->local_threshold_msec;
+ try_once = topology->server_selection_try_once;
+ loop_start = loop_end = bson_get_monotonic_time ();
+ expire_at =
+ loop_start + ((int64_t) topology->server_selection_timeout_msec * 1000);
+
+ if (topology->single_threaded) {
+ if (!td.ptr->opened) {
+ mc_tpld_modification tdmod = mc_tpld_modify_begin (topology);
+ _mongoc_topology_description_monitor_opening (tdmod.new_td);
+ mc_tpld_modify_commit (tdmod);
+ mc_tpld_renew_ref (&td, topology);
+ }
+
+ tried_once = false;
+ next_update = topology->last_scan + heartbeat_msec * 1000;
+ if (next_update < loop_start) {
+ /* we must scan now */
+ topology->stale = true;
+ }
+
+ /* until we find a server or time out */
+ for (;;) {
+ if (topology->stale) {
+ /* how soon are we allowed to scan? */
+ scan_ready = topology->last_scan +
+ topology->min_heartbeat_frequency_msec * 1000;
+
+ if (scan_ready > expire_at && !try_once) {
+ /* selection timeout will expire before min heartbeat passes */
+ _mongoc_server_selection_error (
+ "No suitable servers found: "
+ "`serverselectiontimeoutms` timed out",
+ &scanner_error,
+ error);
+
+ server_id = 0;
+ goto done;
+ }
+
+ sleep_usec = scan_ready - loop_end;
+ if (sleep_usec > 0) {
+ if (try_once &&
+ mongoc_topology_scanner_in_cooldown (ts, scan_ready)) {
+ _mongoc_server_selection_error (
+ "No servers yet eligible for rescan",
+ &scanner_error,
+ error);
+
+ server_id = 0;
+ goto done;
+ }
+
+ _mongoc_usleep (sleep_usec);
+ }
+
+ /* takes up to connectTimeoutMS. sets "last_scan", clears "stale" */
+ _mongoc_topology_do_blocking_scan (topology, &scanner_error);
+ loop_end = topology->last_scan;
+ tried_once = true;
+ }
+
+ /* Topology may have just been updated by a scan. */
+ mc_tpld_renew_ref (&td, topology);
+
+ if (!mongoc_topology_compatible (td.ptr, read_prefs, error)) {
+ server_id = 0;
+ goto done;
+ }
+
+ selected_server = mongoc_topology_description_select (
+ td.ptr, optype, read_prefs, must_use_primary, local_threshold_ms);
+
+ if (selected_server) {
+ server_id = selected_server->id;
+ goto done;
+ }
+
+ topology->stale = true;
+
+ if (try_once) {
+ if (tried_once) {
+ _mongoc_server_selection_error (
+ "No suitable servers found (`serverSelectionTryOnce` set)",
+ &scanner_error,
+ error);
+
+ server_id = 0;
+ goto done;
+ }
+ } else {
+ loop_end = bson_get_monotonic_time ();
+
+ if (loop_end > expire_at) {
+ /* no time left in server_selection_timeout_msec */
+ _mongoc_server_selection_error (
+ timeout_msg, &scanner_error, error);
+
+ server_id = 0;
+ goto done;
+ }
+ }
+ }
+ }
+
+ /* With background thread */
+ /* we break out when we've found a server or timed out */
+ for (;;) {
+ /* Topology may have been updated on a previous loop iteration */
+ mc_tpld_renew_ref (&td, topology);
+
+ if (!mongoc_topology_compatible (td.ptr, read_prefs, error)) {
+ server_id = 0;
+ goto done;
+ }
+
+ selected_server = mongoc_topology_description_select (
+ td.ptr, optype, read_prefs, must_use_primary, local_threshold_ms);
+
+ if (selected_server) {
+ server_id = selected_server->id;
+ goto done;
+ }
+
+ /* tlpd_modification_mtx is used to synchronize updates to the topology.
+ * Take that lock to do a wait on the topology to become up-to-date and
+ * synchronize with a condition variable that will be signalled upon
+ * topology changes. */
+ bson_mutex_lock (&topology->tpld_modification_mtx);
+ /* Now that we have the lock, check again, since a scan may have
+ * occurred while we were waiting on the lock. */
+ mc_tpld_renew_ref (&td, topology);
+ selected_server = mongoc_topology_description_select (
+ td.ptr, optype, read_prefs, must_use_primary, local_threshold_ms);
+ if (selected_server) {
+ server_id = selected_server->id;
+ bson_mutex_unlock (&topology->tpld_modification_mtx);
+ goto done;
+ }
+
+ /* Still nothing. Request that the scanner do a scan now. */
+ TRACE (
+ "server selection requesting an immediate scan, want %s",
+ _mongoc_read_mode_as_str (mongoc_read_prefs_get_mode (read_prefs)));
+ _mongoc_topology_request_scan (topology);
+
+ TRACE ("server selection about to wait for %" PRId64 "ms",
+ (expire_at - loop_start) / 1000);
+ r = mongoc_cond_timedwait (&topology->cond_client,
+ &topology->tpld_modification_mtx,
+ (expire_at - loop_start) / 1000);
+ TRACE ("%s", "server selection awake");
+ /* Refresh our topology handle */
+ mc_tpld_renew_ref (&td, topology);
+ _topology_collect_errors (td.ptr, &scanner_error);
+
+ bson_mutex_unlock (&topology->tpld_modification_mtx);
+
+#ifdef _WIN32
+ if (r == WSAETIMEDOUT) {
+#else
+ if (r == ETIMEDOUT) {
+#endif
+ /* handle timeouts */
+ _mongoc_server_selection_error (timeout_msg, &scanner_error, error);
+
+ server_id = 0;
+ goto done;
+ } else if (r) {
+ bson_set_error (error,
+ MONGOC_ERROR_SERVER_SELECTION,
+ MONGOC_ERROR_SERVER_SELECTION_FAILURE,
+ "Unknown error '%d' received while waiting on "
+ "thread condition",
+ r);
+ server_id = 0;
+ goto done;
+ }
+
+ loop_start = bson_get_monotonic_time ();
+
+ if (loop_start > expire_at) {
+ _mongoc_server_selection_error (timeout_msg, &scanner_error, error);
+
+ server_id = 0;
+ goto done;
+ }
+ }
+
+done:
+ mc_tpld_drop_ref (&td);
+ return server_id;
+}
+
+
+mongoc_host_list_t *
+_mongoc_topology_host_by_id (const mongoc_topology_description_t *td,
+ uint32_t id,
+ bson_error_t *error)
+{
+ mongoc_server_description_t const *sd;
+ mongoc_host_list_t *host = NULL;
+
+ /* not a copy - direct pointer into topology description data */
+ sd = mongoc_topology_description_server_by_id_const (td, id, error);
+
+ if (sd) {
+ host = bson_malloc0 (sizeof (mongoc_host_list_t));
+ memcpy (host, &sd->host, sizeof (mongoc_host_list_t));
+ }
+
+ return host;
+}
+
+
+void
+_mongoc_topology_request_scan (mongoc_topology_t *topology)
+{
+ _mongoc_topology_background_monitoring_request_scan (topology);
+}
+
+bool
+_mongoc_topology_update_from_handshake (mongoc_topology_t *topology,
+ const mongoc_server_description_t *sd)
+{
+ bool has_server;
+ mc_tpld_modification tdmod;
+
+ BSON_ASSERT (topology);
+ BSON_ASSERT (sd);
+ BSON_ASSERT (!topology->single_threaded);
+
+ if (_mongoc_topology_get_type (topology) == MONGOC_TOPOLOGY_LOAD_BALANCED) {
+ /* In load balanced mode, scanning is only for connection establishment.
+ * It must not modify the topology description. */
+ return true;
+ }
+
+ tdmod = mc_tpld_modify_begin (topology);
+
+ /* return false if server was removed from topology */
+ has_server = _mongoc_topology_update_no_lock (sd->id,
+ &sd->last_hello_response,
+ sd->round_trip_time_msec,
+ tdmod.new_td,
+ NULL);
+
+ /* if pooled, wake threads waiting in mongoc_topology_server_by_id */
+ mongoc_cond_broadcast (&topology->cond_client);
+ /* Update background monitoring. */
+ _mongoc_topology_background_monitoring_reconcile (topology, tdmod.new_td);
+ mc_tpld_modify_commit (tdmod);
+
+ return has_server;
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_topology_update_last_used --
+ *
+ * Internal function. In single-threaded mode only, track when the socket
+ * to a particular server was last used. This is required for
+ * mongoc_cluster_check_interval to know when a socket has been idle.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+void
+_mongoc_topology_update_last_used (mongoc_topology_t *topology,
+ uint32_t server_id)
+{
+ mongoc_topology_scanner_node_t *node;
+
+ if (!topology->single_threaded) {
+ return;
+ }
+
+ node = mongoc_topology_scanner_get_node (topology->scanner, server_id);
+ if (node) {
+ node->last_used = bson_get_monotonic_time ();
+ }
+}
+
+
+mongoc_topology_description_type_t
+_mongoc_topology_get_type (const mongoc_topology_t *topology)
+{
+ mc_shared_tpld td = mc_tpld_take_ref (topology);
+ mongoc_topology_description_type_t td_type = td.ptr->type;
+ mc_tpld_drop_ref (&td);
+ return td_type;
+}
+
+bool
+_mongoc_topology_set_appname (mongoc_topology_t *topology, const char *appname)
+{
+ bool ret = false;
+
+ if (topology->scanner_state == MONGOC_TOPOLOGY_SCANNER_OFF) {
+ ret = _mongoc_topology_scanner_set_appname (topology->scanner, appname);
+ } else {
+ MONGOC_ERROR ("Cannot set appname after handshake initiated");
+ }
+ return ret;
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_topology_update_cluster_time --
+ *
+ * Internal function. If the server reply has a later $clusterTime than
+ * any seen before, update the topology's clusterTime. See the Driver
+ * Sessions Spec.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+void
+_mongoc_topology_update_cluster_time (mongoc_topology_t *topology,
+ const bson_t *reply)
+{
+ bson_iter_t iter;
+ bson_iter_t child;
+ const uint8_t *data;
+ uint32_t size;
+ bson_t cluster_time;
+ mc_shared_tpld td;
+
+ if (!reply || !bson_iter_init_find (&iter, reply, "$clusterTime")) {
+ return;
+ }
+
+ if (!BSON_ITER_HOLDS_DOCUMENT (&iter) ||
+ !bson_iter_recurse (&iter, &child)) {
+ MONGOC_ERROR ("Can't parse $clusterTime");
+ return;
+ }
+
+ bson_iter_document (&iter, &size, &data);
+ BSON_ASSERT (bson_init_static (&cluster_time, data, (size_t) size));
+
+ td = mc_tpld_take_ref (topology);
+
+ /* This func is called frequently and repeatedly, but the cluster time itself
+ * is infrequently updated. mc_tpld_modify_begin() is very expensive, so we
+ * only want to actually call it if we anticipate performing an update to the
+ * cluster time.
+ *
+ * Check that the cluster time has actually changed from what we have on
+ * record before opening a topology modification to update it. */
+ if (bson_empty (&td.ptr->cluster_time) ||
+ _mongoc_cluster_time_greater (&cluster_time, &td.ptr->cluster_time)) {
+ mc_tpld_modification tdmod = mc_tpld_modify_begin (topology);
+ /* Check again if we need to update the cluster time, since it may have
+ * been updated behind our back. */
+ if (bson_empty (&tdmod.new_td->cluster_time) ||
+ _mongoc_cluster_time_greater (&cluster_time,
+ &tdmod.new_td->cluster_time)) {
+ bson_destroy (&tdmod.new_td->cluster_time);
+ bson_copy_to (&cluster_time, &tdmod.new_td->cluster_time);
+ _mongoc_topology_scanner_set_cluster_time (
+ topology->scanner, &tdmod.new_td->cluster_time);
+ mc_tpld_modify_commit (tdmod);
+ } else {
+ mc_tpld_modify_drop (tdmod);
+ }
+ }
+ mc_tpld_drop_ref (&td);
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_topology_pop_server_session --
+ *
+ * Internal function. Get a server session from the pool or create
+ * one. On error, return NULL and fill out @error.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+mongoc_server_session_t *
+_mongoc_topology_pop_server_session (mongoc_topology_t *topology,
+ bson_error_t *error)
+{
+ int64_t timeout;
+ mongoc_server_session_t *ss = NULL;
+ bool loadbalanced;
+ mc_shared_tpld td = mc_tpld_take_ref (topology);
+
+ ENTRY;
+
+ timeout = td.ptr->session_timeout_minutes;
+ loadbalanced = td.ptr->type == MONGOC_TOPOLOGY_LOAD_BALANCED;
+
+ /* When the topology type is LoadBalanced, sessions are always supported. */
+ if (!loadbalanced && timeout == MONGOC_NO_SESSIONS) {
+ /* if needed, connect and check for session timeout again */
+ if (!mongoc_topology_description_has_data_node (td.ptr)) {
+ if (!mongoc_topology_select_server_id (topology,
+ MONGOC_SS_READ,
+ NULL /* read prefs */,
+ NULL /* chosen read mode */,
+ error)) {
+ ss = NULL;
+ goto done;
+ }
+
+ /* Topology may have been updated by a scan */
+ mc_tpld_renew_ref (&td, topology);
+
+ timeout = td.ptr->session_timeout_minutes;
+ }
+
+ if (timeout == MONGOC_NO_SESSIONS) {
+ bson_set_error (error,
+ MONGOC_ERROR_CLIENT,
+ MONGOC_ERROR_CLIENT_SESSION_FAILURE,
+ "Server does not support sessions");
+ ss = NULL;
+ goto done;
+ }
+ }
+
+ ss = mongoc_server_session_pool_get (topology->session_pool, error);
+
+done:
+ mc_tpld_drop_ref (&td);
+ RETURN (ss);
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_topology_push_server_session --
+ *
+ * Internal function. Return a server session to the pool.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+void
+_mongoc_topology_push_server_session (mongoc_topology_t *topology,
+ mongoc_server_session_t *server_session)
+{
+ ENTRY;
+
+ /**
+ * ! note:
+ * At time of writing, this diverges from the spec:
+ * https://github.com/mongodb/specifications/blob/df6be82f865e9b72444488fd62ae1eb5fca18569/source/sessions/driver-sessions.rst#algorithm-to-return-a-serversession-instance-to-the-server-session-pool
+ *
+ * The spec notes that before returning a session, we should first inspect
+ * the back of the pool for expired items and delete them. In this case, we
+ * simply return the item to the top of the pool and leave the remainder
+ * unchanged.
+ *
+ * The next pop operation that encounters an expired session will clear the
+ * entire session pool, thus preventing unbounded growth of the pool.
+ */
+ mongoc_server_session_pool_return (server_session);
+
+ EXIT;
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_topology_end_sessions_cmd --
+ *
+ * Internal function. End up to 10,000 server sessions. @cmd is an
+ * uninitialized document. Sessions are destroyed as their ids are
+ * appended to @cmd.
+ *
+ * Driver Sessions Spec: "If the number of sessions is very large the
+ * endSessions command SHOULD be run multiple times to end 10,000
+ * sessions at a time (in order to avoid creating excessively large
+ * commands)."
+ *
+ * Returns:
+ * true if any session ids were appended to @cmd.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+bool
+_mongoc_topology_end_sessions_cmd (mongoc_topology_t *topology, bson_t *cmd)
+{
+ bson_t ar;
+ /* Only end up to 10'000 sessions */
+ const int ENDED_SESSION_PRUNING_LIMIT = 10000;
+ int i = 0;
+ mongoc_server_session_t *ss =
+ mongoc_server_session_pool_get_existing (topology->session_pool);
+
+ bson_init (cmd);
+ BSON_APPEND_ARRAY_BEGIN (cmd, "endSessions", &ar);
+
+ for (; i < ENDED_SESSION_PRUNING_LIMIT && ss != NULL;
+ ++i,
+ ss = mongoc_server_session_pool_get_existing (topology->session_pool)) {
+ char buf[16];
+ const char *key;
+ bson_uint32_to_string (i, &key, buf, sizeof buf);
+ BSON_APPEND_DOCUMENT (&ar, key, &ss->lsid);
+ mongoc_server_session_pool_drop (ss);
+ }
+
+ if (ss) {
+ /* We deleted at least 10'000 sessions, so we will need to return the
+ * final session that we didn't drop */
+ mongoc_server_session_pool_return (ss);
+ }
+
+ bson_append_array_end (cmd, &ar);
+
+ return i > 0;
+}
+
+void
+_mongoc_topology_dup_handshake_cmd (const mongoc_topology_t *topology,
+ bson_t *copy_into)
+{
+ _mongoc_topology_scanner_dup_handshake_cmd (topology->scanner, copy_into);
+}
+
+void
+_mongoc_topology_bypass_cooldown (mongoc_topology_t *topology)
+{
+ BSON_ASSERT (topology->single_threaded);
+ topology->scanner->bypass_cooldown = true;
+}
+
+static void
+_find_topology_version (const bson_t *reply, bson_t *topology_version)
+{
+ bson_iter_t iter;
+ const uint8_t *bytes;
+ uint32_t len;
+
+ if (!bson_iter_init_find (&iter, reply, "topologyVersion") ||
+ !BSON_ITER_HOLDS_DOCUMENT (&iter)) {
+ bson_init (topology_version);
+ return;
+ }
+ bson_iter_document (&iter, &len, &bytes);
+ bson_init_static (topology_version, bytes, len);
+}
+
+
+static bool
+_handle_sdam_app_error_command (mongoc_topology_t *topology,
+ const mongoc_topology_description_t *td,
+ uint32_t server_id,
+ uint32_t generation,
+ const bson_oid_t *service_id,
+ const mongoc_server_description_t *sd,
+ uint32_t max_wire_version,
+ const bson_t *reply)
+{
+ bson_error_t cmd_error;
+ bson_t incoming_topology_version;
+ bool pool_cleared = false;
+ bool should_clear_pool = false;
+ mc_tpld_modification tdmod;
+ mongoc_server_description_t *mut_sd;
+
+ if (_mongoc_cmd_check_ok_no_wce (
+ reply, MONGOC_ERROR_API_VERSION_2, &cmd_error)) {
+ /* No error. */
+ return false;
+ }
+
+ if (!_mongoc_error_is_state_change (&cmd_error)) {
+ /* Not a "not primary" or "node is recovering" error. */
+ return false;
+ }
+
+ /* Check if the error is "stale", i.e. the topologyVersion refers to an
+ * older
+ * version of the server than we have stored in the topology description.
+ */
+ _find_topology_version (reply, &incoming_topology_version);
+ if (mongoc_server_description_topology_version_cmp (
+ &sd->topology_version, &incoming_topology_version) >= 0) {
+ /* The server description is greater or equal, ignore the error. */
+ bson_destroy (&incoming_topology_version);
+ return false;
+ }
+
+ should_clear_pool = (max_wire_version <= WIRE_VERSION_4_0 ||
+ _mongoc_error_is_shutdown (&cmd_error));
+
+ tdmod = mc_tpld_modify_begin (topology);
+
+ /* Get the server handle again, which might have been removed. */
+ mut_sd =
+ mongoc_topology_description_server_by_id (tdmod.new_td, server_id, NULL);
+
+ if (!mut_sd) {
+ /* Server was already removed/invalidated */
+ mc_tpld_modify_drop (tdmod);
+ bson_destroy (&incoming_topology_version);
+ return false;
+ }
+
+ /* Check the topology version a second time, now that we have an exclusive
+ * lock on the latest topology description. */
+ if (mongoc_server_description_topology_version_cmp (
+ &mut_sd->topology_version, &incoming_topology_version) >= 0) {
+ /* The server description is greater or equal, ignore the error. */
+ mc_tpld_modify_drop (tdmod);
+ bson_destroy (&incoming_topology_version);
+ return false;
+ }
+
+ if (generation < mc_tpl_sd_get_generation (mut_sd, service_id)) {
+ /* Our view of the server description is stale. Ignore it. */
+ mc_tpld_modify_drop (tdmod);
+ bson_destroy (&incoming_topology_version);
+ return false;
+ }
+
+ /* Overwrite the topology version. */
+ mongoc_server_description_set_topology_version (mut_sd,
+ &incoming_topology_version);
+
+ /* SDAM: When handling a "not primary" or "node is recovering" error, the
+ * client MUST clear the server's connection pool if and only if the error
+ * is "node is shutting down" or the error originated from server version
+ * < 4.2.
+ */
+ if (should_clear_pool) {
+ _mongoc_topology_description_clear_connection_pool (
+ tdmod.new_td, server_id, service_id);
+ pool_cleared = true;
+ }
+
+ /*
+ * SDAM: When the client sees a "not primary" or "node is recovering"
+ * error and the error's topologyVersion is strictly greater than the
+ * current ServerDescription's topologyVersion it MUST replace the
+ * server's description with a ServerDescription of type Unknown.
+ */
+ mongoc_topology_description_invalidate_server (
+ tdmod.new_td, server_id, &cmd_error);
+
+ if (topology->single_threaded) {
+ /* SDAM: For single-threaded clients, in the case of a "not primary" or
+ * "node is shutting down" error, the client MUST mark the topology as
+ * "stale"
+ */
+ if (_mongoc_error_is_not_primary (&cmd_error)) {
+ topology->stale = true;
+ }
+ } else {
+ /* SDAM Spec: "Multi-threaded and asynchronous clients MUST request an
+ * immediate check of the server."
+ * Instead of requesting a check of the one server, request a scan
+ * to all servers (to find the new primary).
+ */
+ _mongoc_topology_request_scan (topology);
+ }
+
+ mc_tpld_modify_commit (tdmod);
+ bson_destroy (&incoming_topology_version);
+
+ return pool_cleared;
+}
+
+
+bool
+_mongoc_topology_handle_app_error (mongoc_topology_t *topology,
+ uint32_t server_id,
+ bool handshake_complete,
+ _mongoc_sdam_app_error_type_t type,
+ const bson_t *reply,
+ const bson_error_t *why,
+ uint32_t max_wire_version,
+ uint32_t generation,
+ const bson_oid_t *service_id)
+{
+ bson_error_t server_selection_error;
+ const mongoc_server_description_t *sd;
+ bool cleared_pool = false;
+ mc_shared_tpld td = mc_tpld_take_ref (topology);
+
+ /* Start by checking every condition in which we should ignore the error */
+ sd = mongoc_topology_description_server_by_id_const (
+ td.ptr, server_id, &server_selection_error);
+
+ if (!sd) {
+ /* The server was already removed from the topology. Ignore error. */
+ goto ignore_error;
+ }
+
+ /* When establishing a new connection in load balanced mode, drivers MUST NOT
+ * perform SDAM error handling for any errors that occur before the MongoDB
+ * Handshake. */
+ if (td.ptr->type == MONGOC_TOPOLOGY_LOAD_BALANCED && !handshake_complete) {
+ goto ignore_error;
+ }
+
+ if (generation < mc_tpl_sd_get_generation (sd, service_id)) {
+ /* This is a stale connection. Ignore. */
+ goto ignore_error;
+ }
+
+ if (type == MONGOC_SDAM_APP_ERROR_TIMEOUT && handshake_complete) {
+ /* Timeout errors after handshake are ok, do nothing. */
+ goto ignore_error;
+ }
+
+ /* Do something with the error */
+ if (type == MONGOC_SDAM_APP_ERROR_COMMAND) {
+ cleared_pool = _handle_sdam_app_error_command (topology,
+ td.ptr,
+ server_id,
+ generation,
+ service_id,
+ sd,
+ max_wire_version,
+ reply);
+ } else {
+ /* Invalidate the server that saw the error. */
+ mc_tpld_modification tdmod = mc_tpld_modify_begin (topology);
+ sd = mongoc_topology_description_server_by_id_const (
+ tdmod.new_td, server_id, NULL);
+ /* Check if the server has already been invalidated */
+ if (!sd || generation < mc_tpl_sd_get_generation (sd, service_id)) {
+ mc_tpld_modify_drop (tdmod);
+ goto ignore_error;
+ }
+ /* Mark server as unknown. */
+ mongoc_topology_description_invalidate_server (
+ tdmod.new_td, server_id, why);
+ /* Clear the connection pool */
+ _mongoc_topology_description_clear_connection_pool (
+ tdmod.new_td, server_id, service_id);
+ cleared_pool = true;
+ if (!topology->single_threaded) {
+ _mongoc_topology_background_monitoring_cancel_check (topology,
+ server_id);
+ }
+ mc_tpld_modify_commit (tdmod);
+ }
+
+ignore_error: /* <- Jump taken if we should ignore the error */
+
+ mc_tpld_drop_ref (&td);
+ return cleared_pool;
+}
+
+/* Called from application threads
+ * Caller must hold topology lock.
+ * For single-threaded monitoring, the topology scanner may include errors for
+ * servers that were removed from the topology.
+ */
+static void
+_topology_collect_errors (const mongoc_topology_description_t *td,
+ bson_error_t *error_out)
+{
+ const mongoc_server_description_t *server_description;
+ bson_string_t *error_message;
+ int i;
+
+ memset (error_out, 0, sizeof (bson_error_t));
+ error_message = bson_string_new ("");
+
+ for (i = 0; i < mc_tpld_servers_const (td)->items_len; i++) {
+ const bson_error_t *error;
+
+ server_description = mc_tpld_servers_const (td)->items[i].item;
+ error = &server_description->error;
+ if (error->code) {
+ if (error_message->len > 0) {
+ bson_string_append_c (error_message, ' ');
+ }
+ bson_string_append_printf (
+ error_message, "[%s]", server_description->error.message);
+ /* The last error's code and domain wins. */
+ error_out->code = error->code;
+ error_out->domain = error->domain;
+ }
+ }
+
+ bson_strncpy ((char *) &error_out->message,
+ error_message->str,
+ sizeof (error_out->message));
+ bson_string_free (error_message, true);
+}
+
+void
+_mongoc_topology_set_rr_resolver (mongoc_topology_t *topology,
+ _mongoc_rr_resolver_fn rr_resolver)
+{
+ topology->rr_resolver = rr_resolver;
+}
+
+void
+_mongoc_topology_set_srv_polling_rescan_interval_ms (
+ mongoc_topology_t *topology, int64_t val)
+{
+ topology->srv_polling_rescan_interval_ms = val;
+}
+
+uint32_t
+_mongoc_topology_get_connection_pool_generation (
+ const mongoc_topology_description_t *td,
+ uint32_t server_id,
+ const bson_oid_t *service_id)
+{
+ const mongoc_server_description_t *sd;
+ bson_error_t error;
+
+ BSON_ASSERT (service_id);
+
+ sd = mongoc_topology_description_server_by_id_const (td, server_id, &error);
+ if (!sd) {
+ /* Server removed, ignore and ignore error. */
+ return 0;
+ }
+
+ return mc_tpl_sd_get_generation (sd, service_id);
+}
+
+mc_tpld_modification
+mc_tpld_modify_begin (mongoc_topology_t *tpl)
+{
+ mc_shared_tpld prev_td;
+ mongoc_topology_description_t *new_td;
+ bson_mutex_lock (&tpl->tpld_modification_mtx);
+ prev_td = mc_tpld_take_ref (tpl);
+ new_td = mongoc_topology_description_new_copy (prev_td.ptr),
+ mc_tpld_drop_ref (&prev_td);
+ return (mc_tpld_modification){
+ .new_td = new_td,
+ .topology = tpl,
+ };
+}
+
+void
+mc_tpld_modify_commit (mc_tpld_modification mod)
+{
+ mongoc_shared_ptr old_sptr =
+ mongoc_shared_ptr_copy (mod.topology->_shared_descr_._sptr_);
+ mongoc_shared_ptr new_sptr =
+ mongoc_shared_ptr_create (mod.new_td, _tpld_destroy_and_free);
+ mongoc_atomic_shared_ptr_store (&mod.topology->_shared_descr_._sptr_,
+ new_sptr);
+ bson_mutex_unlock (&mod.topology->tpld_modification_mtx);
+ mongoc_shared_ptr_reset_null (&new_sptr);
+ mongoc_shared_ptr_reset_null (&old_sptr);
+}
+
+void
+mc_tpld_modify_drop (mc_tpld_modification mod)
+{
+ bson_mutex_unlock (&mod.topology->tpld_modification_mtx);
+ mongoc_topology_description_destroy (mod.new_td);
+}
diff --git a/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-trace-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-trace-private.h
new file mode 100644
index 00000000..604b2762
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-trace-private.h
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2013 MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mongoc-prelude.h"
+
+
+#ifndef MONGOC_TRACE_PRIVATE_H
+#define MONGOC_TRACE_PRIVATE_H
+
+
+#include <bson/bson.h>
+#include <ctype.h>
+
+#include "mongoc-log.h"
+#include "mongoc-log-private.h"
+#include "mongoc-config.h"
+
+
+BSON_BEGIN_DECLS
+
+#define TRACE(msg, ...) \
+ do { \
+ if (MONGOC_TRACE_ENABLED) { \
+ mongoc_log (MONGOC_LOG_LEVEL_TRACE, \
+ MONGOC_LOG_DOMAIN, \
+ "TRACE: %s():%d " msg, \
+ BSON_FUNC, \
+ __LINE__, \
+ __VA_ARGS__); \
+ } \
+ } while (0)
+#define ENTRY \
+ do { \
+ if (MONGOC_TRACE_ENABLED) { \
+ mongoc_log (MONGOC_LOG_LEVEL_TRACE, \
+ MONGOC_LOG_DOMAIN, \
+ "ENTRY: %s():%d", \
+ BSON_FUNC, \
+ __LINE__); \
+ } \
+ } while (0)
+#define EXIT \
+ do { \
+ if (MONGOC_TRACE_ENABLED) { \
+ mongoc_log (MONGOC_LOG_LEVEL_TRACE, \
+ MONGOC_LOG_DOMAIN, \
+ " EXIT: %s():%d", \
+ BSON_FUNC, \
+ __LINE__); \
+ } \
+ return; \
+ } while (0)
+#define RETURN(ret) \
+ do { \
+ if (MONGOC_TRACE_ENABLED) { \
+ mongoc_log (MONGOC_LOG_LEVEL_TRACE, \
+ MONGOC_LOG_DOMAIN, \
+ " EXIT: %s():%d", \
+ BSON_FUNC, \
+ __LINE__); \
+ } \
+ return ret; \
+ } while (0)
+#define GOTO(label) \
+ do { \
+ if (MONGOC_TRACE_ENABLED) { \
+ mongoc_log (MONGOC_LOG_LEVEL_TRACE, \
+ MONGOC_LOG_DOMAIN, \
+ " GOTO: %s():%d %s", \
+ BSON_FUNC, \
+ __LINE__, \
+ #label); \
+ } \
+ goto label; \
+ } while (0)
+#define DUMP_BYTES(_n, _b, _l) \
+ do { \
+ if (MONGOC_TRACE_ENABLED) { \
+ mongoc_log (MONGOC_LOG_LEVEL_TRACE, \
+ MONGOC_LOG_DOMAIN, \
+ "TRACE: %s():%d %s = %p [%d]", \
+ BSON_FUNC, \
+ __LINE__, \
+ #_n, \
+ _b, \
+ (int) _l); \
+ mongoc_log_trace_bytes (MONGOC_LOG_DOMAIN, _b, _l); \
+ } \
+ } while (0)
+#define DUMP_BSON(_bson) \
+ do { \
+ if (MONGOC_TRACE_ENABLED) { \
+ char *_bson_str; \
+ if (_bson) { \
+ _bson_str = bson_as_canonical_extended_json (_bson, NULL); \
+ } else { \
+ _bson_str = bson_strdup ("<NULL>"); \
+ } \
+ mongoc_log (MONGOC_LOG_LEVEL_TRACE, \
+ MONGOC_LOG_DOMAIN, \
+ "TRACE: %s():%d %s = %s", \
+ BSON_FUNC, \
+ __LINE__, \
+ #_bson, \
+ _bson_str); \
+ bson_free (_bson_str); \
+ } \
+ } while (0)
+#define DUMP_IOVEC(_n, _iov, _iovcnt) \
+ do { \
+ if (MONGOC_TRACE_ENABLED) { \
+ mongoc_log (MONGOC_LOG_LEVEL_TRACE, \
+ MONGOC_LOG_DOMAIN, \
+ "TRACE: %s():%d %s = %p [%d]", \
+ BSON_FUNC, \
+ __LINE__, \
+ #_n, \
+ (void *) _iov, \
+ (int) _iovcnt); \
+ mongoc_log_trace_iovec (MONGOC_LOG_DOMAIN, _iov, _iovcnt); \
+ } \
+ } while (0)
+
+
+BSON_END_DECLS
+
+
+#endif /* MONGOC_TRACE_PRIVATE_H */
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-ts-pool-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-ts-pool-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-ts-pool-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-ts-pool-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-ts-pool.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-ts-pool.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-ts-pool.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-ts-pool.c
diff --git a/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-uri-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-uri-private.h
new file mode 100644
index 00000000..37182bf0
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-uri-private.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2015 MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mongoc-prelude.h"
+
+#ifndef MONGOC_URI_PRIVATE_H
+#define MONGOC_URI_PRIVATE_H
+
+#include "mongoc-uri.h"
+#include "mongoc-scram-private.h"
+#include "mongoc-crypto-private.h"
+
+
+BSON_BEGIN_DECLS
+
+
+bool
+mongoc_uri_upsert_host_and_port (mongoc_uri_t *uri,
+ const char *host_and_port,
+ bson_error_t *error);
+bool
+mongoc_uri_upsert_host (mongoc_uri_t *uri,
+ const char *host,
+ uint16_t port,
+ bson_error_t *error);
+void
+mongoc_uri_remove_host (mongoc_uri_t *uri, const char *host, uint16_t port);
+
+bool
+mongoc_uri_parse_host (mongoc_uri_t *uri, const char *str);
+bool
+mongoc_uri_parse_options (mongoc_uri_t *uri,
+ const char *str,
+ bool from_dns,
+ bson_error_t *error);
+int32_t
+mongoc_uri_get_local_threshold_option (const mongoc_uri_t *uri);
+
+bool
+_mongoc_uri_requires_auth_negotiation (const mongoc_uri_t *uri);
+
+const char *
+mongoc_uri_canonicalize_option (const char *key);
+
+mongoc_uri_t *
+_mongoc_uri_copy_and_replace_host_list (const mongoc_uri_t *original,
+ const char *host);
+
+bool
+mongoc_uri_init_with_srv_host_list (mongoc_uri_t *uri,
+ mongoc_host_list_t *hosts,
+ bson_error_t *error);
+
+bool
+mongoc_uri_validate_srv_result (const mongoc_uri_t *uri,
+ const char *host,
+ bson_error_t *error);
+
+#ifdef MONGOC_ENABLE_CRYPTO
+void
+_mongoc_uri_init_scram (const mongoc_uri_t *uri,
+ mongoc_scram_t *scram,
+ mongoc_crypto_hash_algorithm_t algo);
+#endif
+
+bool
+mongoc_uri_finalize (mongoc_uri_t *uri, bson_error_t *error);
+
+BSON_END_DECLS
+
+
+#endif /* MONGOC_URI_PRIVATE_H */
diff --git a/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-uri.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-uri.c
new file mode 100644
index 00000000..51230470
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-uri.c
@@ -0,0 +1,3333 @@
+/*
+ * Copyright 2013 MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <math.h>
+
+/* strcasecmp on windows */
+#include "mongoc-util-private.h"
+
+#include "mongoc-config.h"
+#include "mongoc-host-list.h"
+#include "mongoc-host-list-private.h"
+#include "mongoc-log.h"
+#include "mongoc-handshake-private.h"
+#include "mongoc-socket.h"
+#include "mongoc-topology-private.h"
+#include "mongoc-uri-private.h"
+#include "mongoc-read-concern-private.h"
+#include "mongoc-write-concern-private.h"
+#include "mongoc-compression-private.h"
+#include "utlist.h"
+
+struct _mongoc_uri_t {
+ char *str;
+ bool is_srv;
+ char srv[BSON_HOST_NAME_MAX + 1];
+ mongoc_host_list_t *hosts;
+ char *username;
+ char *password;
+ char *database;
+ bson_t raw; /* Unparsed options, see mongoc_uri_parse_options */
+ bson_t options; /* Type-coerced and canonicalized options */
+ bson_t credentials;
+ bson_t compressors;
+ mongoc_read_prefs_t *read_prefs;
+ mongoc_read_concern_t *read_concern;
+ mongoc_write_concern_t *write_concern;
+};
+
+#define MONGOC_URI_ERROR(error, format, ...) \
+ bson_set_error (error, \
+ MONGOC_ERROR_COMMAND, \
+ MONGOC_ERROR_COMMAND_INVALID_ARG, \
+ format, \
+ __VA_ARGS__);
+
+
+static const char *escape_instructions = "Percent-encode username and password"
+ " according to RFC 3986";
+
+static bool
+_mongoc_uri_set_option_as_int32 (mongoc_uri_t *uri,
+ const char *option,
+ int32_t value);
+
+static bool
+_mongoc_uri_set_option_as_int32_with_error (mongoc_uri_t *uri,
+ const char *option,
+ int32_t value,
+ bson_error_t *error);
+
+static bool
+_mongoc_uri_set_option_as_int64_with_error (mongoc_uri_t *uri,
+ const char *option,
+ int64_t value,
+ bson_error_t *error);
+
+static bool
+ends_with (const char *str, const char *suffix);
+
+static void
+mongoc_uri_do_unescape (char **str)
+{
+ char *tmp;
+
+ if ((tmp = *str)) {
+ *str = mongoc_uri_unescape (tmp);
+ bson_free (tmp);
+ }
+}
+
+
+#define VALIDATE_SRV_ERR() \
+ do { \
+ bson_set_error (error, \
+ MONGOC_ERROR_STREAM, \
+ MONGOC_ERROR_STREAM_NAME_RESOLUTION, \
+ "Invalid host \"%s\" returned for service \"%s\": " \
+ "host must be subdomain of service name", \
+ host, \
+ srv_hostname); \
+ return false; \
+ } while (0)
+
+
+static int
+count_dots (const char *s)
+{
+ int n = 0;
+ const char *dot = s;
+
+ while ((dot = strchr (dot + 1, '.'))) {
+ n++;
+ }
+
+ return n;
+}
+
+static char *
+lowercase_str_new (const char *key)
+{
+ char *ret = bson_strdup (key);
+ mongoc_lowercase (key, ret);
+ return ret;
+}
+
+/* at least one character, and does not start with dot */
+static bool
+valid_hostname (const char *s)
+{
+ size_t len = strlen (s);
+
+ return len > 1 && s[0] != '.';
+}
+
+
+bool
+mongoc_uri_validate_srv_result (const mongoc_uri_t *uri,
+ const char *host,
+ bson_error_t *error)
+{
+ const char *srv_hostname;
+ const char *srv_host;
+
+ srv_hostname = mongoc_uri_get_srv_hostname (uri);
+ BSON_ASSERT (srv_hostname);
+
+ if (!valid_hostname (host)) {
+ VALIDATE_SRV_ERR ();
+ }
+
+ srv_host = strchr (srv_hostname, '.');
+ BSON_ASSERT (srv_host);
+
+ /* host must be descendent of service root: if service is
+ * "a.foo.co" host can be like "a.foo.co", "b.foo.co", "a.b.foo.co", etc.
+ */
+ if (strlen (host) < strlen (srv_host)) {
+ VALIDATE_SRV_ERR ();
+ }
+
+ if (!ends_with (host, srv_host)) {
+ VALIDATE_SRV_ERR ();
+ }
+
+ return true;
+}
+
+/* copy and upsert @host into @uri's host list. */
+static bool
+_upsert_into_host_list (mongoc_uri_t *uri,
+ mongoc_host_list_t *host,
+ bson_error_t *error)
+{
+ if (uri->is_srv &&
+ !mongoc_uri_validate_srv_result (uri, host->host, error)) {
+ return false;
+ }
+
+ _mongoc_host_list_upsert (&uri->hosts, host);
+
+ return true;
+}
+
+bool
+mongoc_uri_upsert_host_and_port (mongoc_uri_t *uri,
+ const char *host_and_port,
+ bson_error_t *error)
+{
+ mongoc_host_list_t temp;
+
+ memset (&temp, 0, sizeof (mongoc_host_list_t));
+ if (!_mongoc_host_list_from_string_with_err (&temp, host_and_port, error)) {
+ return false;
+ }
+
+ return _upsert_into_host_list (uri, &temp, error);
+}
+
+bool
+mongoc_uri_upsert_host (mongoc_uri_t *uri,
+ const char *host,
+ uint16_t port,
+ bson_error_t *error)
+{
+ mongoc_host_list_t temp;
+
+ memset (&temp, 0, sizeof (mongoc_host_list_t));
+ if (!_mongoc_host_list_from_hostport_with_err (&temp, host, port, error)) {
+ return false;
+ }
+
+ return _upsert_into_host_list (uri, &temp, error);
+}
+
+void
+mongoc_uri_remove_host (mongoc_uri_t *uri, const char *host, uint16_t port)
+{
+ _mongoc_host_list_remove_host (&(uri->hosts), host, port);
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * scan_to_unichar --
+ *
+ * Scans 'str' until either a character matching 'match' is found,
+ * until one of the characters in 'terminators' is encountered, or
+ * until we reach the end of 'str'.
+ *
+ * NOTE: 'terminators' may not include multibyte UTF-8 characters.
+ *
+ * Returns:
+ * If 'match' is found, returns a copy of the section of 'str' before
+ * that character. Otherwise, returns NULL.
+ *
+ * Side Effects:
+ * If 'match' is found, sets 'end' to begin at the matching character
+ * in 'str'.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+static char *
+scan_to_unichar (const char *str,
+ bson_unichar_t match,
+ const char *terminators,
+ const char **end)
+{
+ bson_unichar_t c;
+ const char *iter;
+
+ for (iter = str; iter && *iter && (c = bson_utf8_get_char (iter));
+ iter = bson_utf8_next_char (iter)) {
+ if (c == match) {
+ *end = iter;
+ return bson_strndup (str, iter - str);
+ } else if (c == '\\') {
+ iter = bson_utf8_next_char (iter);
+ if (!bson_utf8_get_char (iter)) {
+ break;
+ }
+ } else {
+ const char *term_iter;
+ for (term_iter = terminators; *term_iter; term_iter++) {
+ if (c == *term_iter) {
+ return NULL;
+ }
+ }
+ }
+ }
+
+ return NULL;
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * ends_with --
+ *
+ * Return true if str ends with suffix.
+ *
+ *--------------------------------------------------------------------------
+ */
+static bool
+ends_with (const char *str, const char *suffix)
+{
+ size_t str_len = strlen (str);
+ size_t suffix_len = strlen (suffix);
+ const char *s1, *s2;
+
+ if (str_len < suffix_len) {
+ return false;
+ }
+
+ /* start at the ends of both strings */
+ s1 = str + str_len;
+ s2 = suffix + suffix_len;
+
+ /* until either pointer reaches start of its string, compare the pointers */
+ for (; s1 >= str && s2 >= suffix; s1--, s2--) {
+ if (*s1 != *s2) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+static bool
+mongoc_uri_parse_scheme (mongoc_uri_t *uri, const char *str, const char **end)
+{
+ if (!strncmp (str, "mongodb+srv://", 14)) {
+ uri->is_srv = true;
+ *end = str + 14;
+ return true;
+ }
+
+ if (!strncmp (str, "mongodb://", 10)) {
+ uri->is_srv = false;
+ *end = str + 10;
+ return true;
+ }
+
+ return false;
+}
+
+
+static bool
+mongoc_uri_has_unescaped_chars (const char *str, const char *chars)
+{
+ const char *c;
+ const char *tmp;
+ char *s;
+
+ for (c = chars; *c; c++) {
+ s = scan_to_unichar (str, (bson_unichar_t) *c, "", &tmp);
+ if (s) {
+ bson_free (s);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+/* "str" is non-NULL, the part of URI between "mongodb://" and first "@" */
+static bool
+mongoc_uri_parse_userpass (mongoc_uri_t *uri,
+ const char *str,
+ bson_error_t *error)
+{
+ const char *prohibited = "@:/";
+ const char *end_user;
+
+ BSON_ASSERT (str);
+ BSON_ASSERT (uri);
+
+ if ((uri->username = scan_to_unichar (str, ':', "", &end_user))) {
+ uri->password = bson_strdup (end_user + 1);
+ } else {
+ uri->username = bson_strdup (str);
+ uri->password = NULL;
+ }
+
+ if (mongoc_uri_has_unescaped_chars (uri->username, prohibited)) {
+ MONGOC_URI_ERROR (error,
+ "Username \"%s\" must not have unescaped chars. %s",
+ uri->username,
+ escape_instructions);
+ return false;
+ }
+
+ mongoc_uri_do_unescape (&uri->username);
+ if (!uri->username) {
+ MONGOC_URI_ERROR (
+ error, "Incorrect URI escapes in username. %s", escape_instructions);
+ return false;
+ }
+
+ /* Providing password at all is optional */
+ if (uri->password) {
+ if (mongoc_uri_has_unescaped_chars (uri->password, prohibited)) {
+ MONGOC_URI_ERROR (error,
+ "Password \"%s\" must not have unescaped chars. %s",
+ uri->password,
+ escape_instructions);
+ return false;
+ }
+
+ mongoc_uri_do_unescape (&uri->password);
+ if (!uri->password) {
+ MONGOC_URI_ERROR (error, "%s", "Incorrect URI escapes in password");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool
+mongoc_uri_parse_host (mongoc_uri_t *uri, const char *host_and_port_in)
+{
+ char *host_and_port = bson_strdup (host_and_port_in);
+ bson_error_t err = {0};
+ bool r;
+
+ /* unescape host. It doesn't hurt including port. */
+ if (mongoc_uri_has_unescaped_chars (host_and_port, "/")) {
+ MONGOC_WARNING ("Unix Domain Sockets must be escaped (e.g. / = %%2F)");
+ bson_free (host_and_port);
+ return false;
+ }
+
+ mongoc_uri_do_unescape (&host_and_port);
+ if (!host_and_port) {
+ /* invalid */
+ bson_free (host_and_port);
+ return false;
+ }
+
+ r = mongoc_uri_upsert_host_and_port (uri, host_and_port, &err);
+
+ if (!r) {
+ MONGOC_ERROR ("%s", err.message);
+ bson_free (host_and_port);
+ return false;
+ }
+
+ bson_free (host_and_port);
+ return true;
+}
+
+
+bool
+mongoc_uri_parse_srv (mongoc_uri_t *uri, const char *str)
+{
+ char *service;
+
+ if (*str == '\0') {
+ return false;
+ }
+
+ service = bson_strdup (str);
+ mongoc_uri_do_unescape (&service);
+ if (!service) {
+ /* invalid */
+ return false;
+ }
+
+ if (!valid_hostname (service) || count_dots (service) < 2) {
+ bson_free (service);
+ return false;
+ }
+
+ bson_strncpy (uri->srv, service, sizeof uri->srv);
+ bson_free (service);
+
+ if (strchr (uri->srv, ',') || strchr (uri->srv, ':')) {
+ /* prohibit port number or multiple service names */
+ return false;
+ }
+
+ return true;
+}
+
+
+/* "hosts" is non-NULL, the part between "mongodb://" or "@" and last "/" */
+static bool
+mongoc_uri_parse_hosts (mongoc_uri_t *uri, const char *hosts)
+{
+ const char *next;
+ const char *end_hostport;
+ char *s;
+ BSON_ASSERT (hosts);
+ /*
+ * Parsing the series of hosts is a lot more complicated than you might
+ * imagine. This is due to some characters being both separators as well as
+ * valid characters within the "hostname". In particularly, we can have file
+ * paths to specify paths to UNIX domain sockets. We impose the restriction
+ * that they must be suffixed with ".sock" to simplify the parsing.
+ *
+ * You can separate hosts and file system paths to UNIX domain sockets with
+ * ",".
+ */
+ s = scan_to_unichar (hosts, '?', "", &end_hostport);
+ if (s) {
+ MONGOC_WARNING (
+ "%s", "A '/' is required between the host list and any options.");
+ goto error;
+ }
+ next = hosts;
+ do {
+ /* makes a copy of the section of the string */
+ s = scan_to_unichar (next, ',', "", &end_hostport);
+ if (s) {
+ next = (char *) end_hostport + 1;
+ } else {
+ s = bson_strdup (next);
+ next = NULL;
+ }
+ if (!mongoc_uri_parse_host (uri, s)) {
+ goto error;
+ }
+ bson_free (s);
+ } while (next);
+ return true;
+error:
+ bson_free (s);
+ return false;
+}
+
+/* -----------------------------------------------------------------------------
+ *
+ * mongoc_uri_parse_database --
+ *
+ * Parse the database after @str. @str is expected to point after the
+ * host list to the character immediately after the / in the uri string.
+ * If no database is specified in the uri, e.g. the uri has a form like:
+ * mongodb://localhost/?option=X then uri->database remains NULL after
+ * parsing.
+ *
+ * Return:
+ * True if the parsed database is valid. An empty database is considered
+ * valid.
+ * -----------------------------------------------------------------------------
+ */
+static bool
+mongoc_uri_parse_database (mongoc_uri_t *uri, const char *str, const char **end)
+{
+ const char *end_database;
+ const char *c;
+ char *invalid_c;
+ const char *tmp;
+
+ if ((uri->database = scan_to_unichar (str, '?', "", &end_database))) {
+ if (strcmp (uri->database, "") == 0) {
+ /* no database is found, don't store the empty string. */
+ bson_free (uri->database);
+ uri->database = NULL;
+ /* but it is valid to have an empty database. */
+ return true;
+ }
+ *end = end_database;
+ } else if (*str) {
+ uri->database = bson_strdup (str);
+ *end = str + strlen (str);
+ }
+
+ mongoc_uri_do_unescape (&uri->database);
+ if (!uri->database) {
+ /* invalid */
+ return false;
+ }
+
+ /* invalid characters in database name */
+ for (c = "/\\. \"$"; *c; c++) {
+ invalid_c =
+ scan_to_unichar (uri->database, (bson_unichar_t) *c, "", &tmp);
+ if (invalid_c) {
+ bson_free (invalid_c);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+static bool
+mongoc_uri_parse_auth_mechanism_properties (mongoc_uri_t *uri, const char *str)
+{
+ char *field;
+ char *value;
+ const char *end_scan;
+ bson_t properties;
+
+ bson_init (&properties);
+
+ /* build up the properties document */
+ while ((field = scan_to_unichar (str, ':', "&", &end_scan))) {
+ str = end_scan + 1;
+ if (!(value = scan_to_unichar (str, ',', ":&", &end_scan))) {
+ value = bson_strdup (str);
+ str = "";
+ } else {
+ str = end_scan + 1;
+ }
+ bson_append_utf8 (&properties, field, -1, value, -1);
+ bson_free (field);
+ bson_free (value);
+ }
+
+ /* append our auth properties to our credentials */
+ if (!mongoc_uri_set_mechanism_properties (uri, &properties)) {
+ bson_destroy (&properties);
+ return false;
+ }
+ bson_destroy (&properties);
+ return true;
+}
+
+
+static bool
+mongoc_uri_check_srv_service_name (mongoc_uri_t *uri, const char *str)
+{
+ /* 63 character DNS query limit, excluding prepended underscore. */
+ const size_t mongoc_srv_service_name_max = 62u;
+
+ size_t length = 0u;
+ size_t num_alpha = 0u;
+ size_t i = 0u;
+ char prev = '\0';
+
+ BSON_ASSERT_PARAM (uri);
+ BSON_ASSERT_PARAM (str);
+
+ length = strlen (str);
+
+ /* Initial DNS Seedlist Discovery Spec: This option specifies a valid SRV
+ * service name according to RFC 6335, with the exception that it may exceed
+ * 15 characters as long as the 63rd (62nd with prepended underscore)
+ * character DNS query limit is not surpassed. */
+ if (length > mongoc_srv_service_name_max) {
+ return false;
+ }
+
+ /* RFC 6335: MUST be at least 1 character. */
+ if (length == 0u) {
+ return false;
+ }
+
+ for (i = 0u; i < length; ++i) {
+ const char c = str[i];
+
+ /* RFC 6335: MUST contain only US-ASCII letters 'A' - 'Z' and 'a' - 'z',
+ * digits '0' - '9', and hyphens ('-', ASCII 0x2D or decimal 45). */
+ if (!isalpha (c) && !isdigit (c) && c != '-') {
+ return false;
+ }
+
+ /* RFC 6335: hyphens MUST NOT be adjacent to other hyphens. */
+ if (c == '-' && prev == '-') {
+ return false;
+ }
+
+ num_alpha += isalpha (c) ? 1u : 0u;
+ prev = c;
+ }
+
+ /* RFC 6335: MUST contain at least one letter ('A' - 'Z' or 'a' - 'z') */
+ if (num_alpha == 0u) {
+ return false;
+ }
+
+ /* RFC 6335: MUST NOT begin or end with a hyphen. */
+ if (str[0] == '-' || str[length - 1u] == '-') {
+ return false;
+ }
+
+ return true;
+}
+
+static bool
+mongoc_uri_parse_tags (mongoc_uri_t *uri, /* IN */
+ const char *str) /* IN */
+{
+ const char *end_keyval;
+ const char *end_key;
+ bson_t b;
+ char *keyval;
+ char *key;
+
+ bson_init (&b);
+
+again:
+ if ((keyval = scan_to_unichar (str, ',', "", &end_keyval))) {
+ if (!(key = scan_to_unichar (keyval, ':', "", &end_key))) {
+ bson_free (keyval);
+ goto fail;
+ }
+
+ bson_append_utf8 (&b, key, -1, end_key + 1, -1);
+ bson_free (key);
+ bson_free (keyval);
+ str = end_keyval + 1;
+ goto again;
+ } else if ((key = scan_to_unichar (str, ':', "", &end_key))) {
+ bson_append_utf8 (&b, key, -1, end_key + 1, -1);
+ bson_free (key);
+ } else if (strlen (str)) {
+ /* we're not finished but we couldn't parse the string */
+ goto fail;
+ }
+
+ mongoc_read_prefs_add_tag (uri->read_prefs, &b);
+ bson_destroy (&b);
+
+ return true;
+
+fail:
+ MONGOC_WARNING ("Unsupported value for \"" MONGOC_URI_READPREFERENCETAGS
+ "\": \"%s\"",
+ str);
+ bson_destroy (&b);
+ return false;
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_uri_bson_append_or_replace_key --
+ *
+ *
+ * Appends 'option' to the end of 'options' if not already set.
+ *
+ * Since we cannot grow utf8 strings inline, we have to allocate a
+ * temporary bson variable and splice in the new value if the key
+ * is already set.
+ *
+ * NOTE: This function keeps the order of the BSON keys.
+ *
+ * NOTE: 'option' is case*in*sensitive.
+ *
+ *
+ *--------------------------------------------------------------------------
+ */
+
+static void
+mongoc_uri_bson_append_or_replace_key (bson_t *options,
+ const char *option,
+ const char *value)
+{
+ bson_iter_t iter;
+ bool found = false;
+
+ if (bson_iter_init (&iter, options)) {
+ bson_t tmp = BSON_INITIALIZER;
+
+ while (bson_iter_next (&iter)) {
+ const bson_value_t *bvalue;
+
+ if (!strcasecmp (bson_iter_key (&iter), option)) {
+ bson_append_utf8 (&tmp, option, -1, value, -1);
+ found = true;
+ continue;
+ }
+
+ bvalue = bson_iter_value (&iter);
+ BSON_APPEND_VALUE (&tmp, bson_iter_key (&iter), bvalue);
+ }
+
+ if (!found) {
+ bson_append_utf8 (&tmp, option, -1, value, -1);
+ }
+
+ bson_destroy (options);
+ bson_copy_to (&tmp, options);
+ bson_destroy (&tmp);
+ }
+}
+
+
+bool
+mongoc_uri_has_option (const mongoc_uri_t *uri, const char *key)
+{
+ bson_iter_t iter;
+
+ return bson_iter_init_find_case (&iter, &uri->options, key);
+}
+
+bool
+mongoc_uri_option_is_int32 (const char *key)
+{
+ return mongoc_uri_option_is_int64 (key) ||
+ !strcasecmp (key, MONGOC_URI_CONNECTTIMEOUTMS) ||
+ !strcasecmp (key, MONGOC_URI_HEARTBEATFREQUENCYMS) ||
+ !strcasecmp (key, MONGOC_URI_SERVERSELECTIONTIMEOUTMS) ||
+ !strcasecmp (key, MONGOC_URI_SOCKETCHECKINTERVALMS) ||
+ !strcasecmp (key, MONGOC_URI_SOCKETTIMEOUTMS) ||
+ !strcasecmp (key, MONGOC_URI_LOCALTHRESHOLDMS) ||
+ !strcasecmp (key, MONGOC_URI_MAXPOOLSIZE) ||
+ !strcasecmp (key, MONGOC_URI_MAXSTALENESSSECONDS) ||
+ !strcasecmp (key, MONGOC_URI_MINPOOLSIZE) ||
+ !strcasecmp (key, MONGOC_URI_MAXIDLETIMEMS) ||
+ !strcasecmp (key, MONGOC_URI_WAITQUEUEMULTIPLE) ||
+ !strcasecmp (key, MONGOC_URI_WAITQUEUETIMEOUTMS) ||
+ !strcasecmp (key, MONGOC_URI_ZLIBCOMPRESSIONLEVEL) ||
+ !strcasecmp (key, MONGOC_URI_SRVMAXHOSTS);
+}
+
+bool
+mongoc_uri_option_is_int64 (const char *key)
+{
+ return !strcasecmp (key, MONGOC_URI_WTIMEOUTMS);
+}
+
+bool
+mongoc_uri_option_is_bool (const char *key)
+{
+ return !strcasecmp (key, MONGOC_URI_CANONICALIZEHOSTNAME) ||
+ !strcasecmp (key, MONGOC_URI_DIRECTCONNECTION) ||
+ !strcasecmp (key, MONGOC_URI_JOURNAL) ||
+ !strcasecmp (key, MONGOC_URI_RETRYREADS) ||
+ !strcasecmp (key, MONGOC_URI_RETRYWRITES) ||
+ !strcasecmp (key, MONGOC_URI_SAFE) ||
+ !strcasecmp (key, MONGOC_URI_SERVERSELECTIONTRYONCE) ||
+ !strcasecmp (key, MONGOC_URI_TLS) ||
+ !strcasecmp (key, MONGOC_URI_TLSINSECURE) ||
+ !strcasecmp (key, MONGOC_URI_TLSALLOWINVALIDCERTIFICATES) ||
+ !strcasecmp (key, MONGOC_URI_TLSALLOWINVALIDHOSTNAMES) ||
+ !strcasecmp (key, MONGOC_URI_TLSDISABLECERTIFICATEREVOCATIONCHECK) ||
+ !strcasecmp (key, MONGOC_URI_TLSDISABLEOCSPENDPOINTCHECK) ||
+ !strcasecmp (key, MONGOC_URI_LOADBALANCED) ||
+ /* deprecated options */
+ !strcasecmp (key, MONGOC_URI_SSL) ||
+ !strcasecmp (key, MONGOC_URI_SSLALLOWINVALIDCERTIFICATES) ||
+ !strcasecmp (key, MONGOC_URI_SSLALLOWINVALIDHOSTNAMES);
+}
+
+bool
+mongoc_uri_option_is_utf8 (const char *key)
+{
+ return !strcasecmp (key, MONGOC_URI_APPNAME) ||
+ !strcasecmp (key, MONGOC_URI_REPLICASET) ||
+ !strcasecmp (key, MONGOC_URI_READPREFERENCE) ||
+ !strcasecmp (key, MONGOC_URI_SRVSERVICENAME) ||
+ !strcasecmp (key, MONGOC_URI_TLSCERTIFICATEKEYFILE) ||
+ !strcasecmp (key, MONGOC_URI_TLSCERTIFICATEKEYFILEPASSWORD) ||
+ !strcasecmp (key, MONGOC_URI_TLSCAFILE) ||
+ /* deprecated options */
+ !strcasecmp (key, MONGOC_URI_SSLCLIENTCERTIFICATEKEYFILE) ||
+ !strcasecmp (key, MONGOC_URI_SSLCLIENTCERTIFICATEKEYPASSWORD) ||
+ !strcasecmp (key, MONGOC_URI_SSLCERTIFICATEAUTHORITYFILE);
+}
+
+const char *
+mongoc_uri_canonicalize_option (const char *key)
+{
+ if (!strcasecmp (key, MONGOC_URI_SSL)) {
+ return MONGOC_URI_TLS;
+ } else if (!strcasecmp (key, MONGOC_URI_SSLCLIENTCERTIFICATEKEYFILE)) {
+ return MONGOC_URI_TLSCERTIFICATEKEYFILE;
+ } else if (!strcasecmp (key, MONGOC_URI_SSLCLIENTCERTIFICATEKEYPASSWORD)) {
+ return MONGOC_URI_TLSCERTIFICATEKEYFILEPASSWORD;
+ } else if (!strcasecmp (key, MONGOC_URI_SSLCERTIFICATEAUTHORITYFILE)) {
+ return MONGOC_URI_TLSCAFILE;
+ } else if (!strcasecmp (key, MONGOC_URI_SSLALLOWINVALIDCERTIFICATES)) {
+ return MONGOC_URI_TLSALLOWINVALIDCERTIFICATES;
+ } else if (!strcasecmp (key, MONGOC_URI_SSLALLOWINVALIDHOSTNAMES)) {
+ return MONGOC_URI_TLSALLOWINVALIDHOSTNAMES;
+ } else {
+ return key;
+ }
+}
+
+static bool
+_mongoc_uri_parse_int64 (const char *key, const char *value, int64_t *result)
+{
+ char *endptr;
+ int64_t i;
+
+ errno = 0;
+ i = bson_ascii_strtoll (value, &endptr, 10);
+ if (errno || endptr < value + strlen (value)) {
+ MONGOC_WARNING ("Invalid %s: cannot parse integer\n", key);
+ return false;
+ }
+
+ *result = i;
+ return true;
+}
+
+
+static bool
+mongoc_uri_parse_int32 (const char *key, const char *value, int32_t *result)
+{
+ int64_t i;
+
+ if (!_mongoc_uri_parse_int64 (key, value, &i)) {
+ /* _mongoc_uri_parse_int64 emits a warning if it could not parse the
+ * given value, so we don't have to add one here.
+ */
+ return false;
+ }
+
+ if (i > INT32_MAX || i < INT32_MIN) {
+ MONGOC_WARNING ("Invalid %s: cannot fit in int32\n", key);
+ return false;
+ }
+
+ *result = (int32_t) i;
+ return true;
+}
+
+
+static bool
+dns_option_allowed (const char *lkey)
+{
+ /* Initial DNS Seedlist Discovery Spec: "A Client MUST only support the
+ * authSource, replicaSet, and loadBalanced options through a TXT record, and
+ * MUST raise an error if any other option is encountered."
+ */
+ return !strcmp (lkey, MONGOC_URI_AUTHSOURCE) ||
+ !strcmp (lkey, MONGOC_URI_REPLICASET) ||
+ !strcmp (lkey, MONGOC_URI_LOADBALANCED);
+}
+
+
+/* Decompose a key=val pair and place them into a document.
+ * Includes case-folding for key portion.
+ */
+static bool
+mongoc_uri_split_option (mongoc_uri_t *uri,
+ bson_t *options,
+ const char *str,
+ bool from_dns,
+ bson_error_t *error)
+{
+ bson_iter_t iter;
+ const char *end_key;
+ char *key = NULL;
+ char *lkey = NULL;
+ char *value = NULL;
+ const char *opt;
+ char *opt_end;
+ size_t opt_len;
+ bool ret = false;
+
+ if (!(key = scan_to_unichar (str, '=', "", &end_key))) {
+ MONGOC_URI_ERROR (error, "URI option \"%s\" contains no \"=\" sign", str);
+ goto CLEANUP;
+ }
+
+ value = bson_strdup (end_key + 1);
+ mongoc_uri_do_unescape (&value);
+ if (!value) {
+ /* do_unescape detected invalid UTF-8 and freed value */
+ MONGOC_URI_ERROR (
+ error, "Value for URI option \"%s\" contains invalid UTF-8", key);
+ goto CLEANUP;
+ }
+
+ lkey = bson_strdup (key);
+ mongoc_lowercase (key, lkey);
+
+ /* Initial DNS Seedlist Discovery Spec: "A Client MUST only support the
+ * authSource, replicaSet, and loadBalanced options through a TXT record, and
+ * MUST raise an error if any other option is encountered."*/
+ if (from_dns && !dns_option_allowed (lkey)) {
+ MONGOC_URI_ERROR (
+ error, "URI option \"%s\" prohibited in TXT record", key);
+ goto CLEANUP;
+ }
+
+ /* Special case: READPREFERENCETAGS is a composing option.
+ * Multiple instances should append, not overwrite.
+ * Encode them directly to the options field,
+ * bypassing canonicalization and duplicate checks.
+ */
+ if (!strcmp (lkey, MONGOC_URI_READPREFERENCETAGS)) {
+ if (!mongoc_uri_parse_tags (uri, value)) {
+ MONGOC_URI_ERROR (
+ error, "Unsupported value for \"%s\": \"%s\"", key, value);
+ goto CLEANUP;
+ }
+ } else if (bson_iter_init_find (&iter, &uri->raw, lkey) ||
+ bson_iter_init_find (&iter, options, lkey)) {
+ /* Special case, MONGOC_URI_W == "any non-int" is not overridden
+ * by later values.
+ */
+ if (!strcmp (lkey, MONGOC_URI_W) &&
+ (opt = bson_iter_utf8_unsafe (&iter, &opt_len))) {
+ strtol (opt, &opt_end, 10);
+ if (*opt_end != '\0') {
+ ret = true;
+ goto CLEANUP;
+ }
+ }
+
+ /* Initial DNS Seedlist Discovery Spec: "Client MUST use options
+ * specified in the Connection String to override options provided
+ * through TXT records." So, do NOT override existing options with TXT
+ * options. */
+ if (from_dns) {
+ MONGOC_WARNING (
+ "Cannot override URI option \"%s\" from TXT record \"%s\"",
+ key,
+ str);
+ ret = true;
+ goto CLEANUP;
+ }
+ MONGOC_WARNING ("Overwriting previously provided value for '%s'", key);
+ }
+
+ if (!(strcmp (lkey, MONGOC_URI_REPLICASET)) && *value == '\0') {
+ MONGOC_URI_ERROR (
+ error, "Value for URI option \"%s\" cannot be empty string", lkey);
+ goto CLEANUP;
+ }
+
+ mongoc_uri_bson_append_or_replace_key (options, lkey, value);
+ ret = true;
+
+CLEANUP:
+ bson_free (key);
+ bson_free (lkey);
+ bson_free (value);
+
+ return ret;
+}
+
+
+/* Check for canonical/deprecated conflicts
+ * between the option list a, and b.
+ * If both names exist either way with differing values, error.
+ */
+static bool
+mongoc_uri_options_validate_names (const bson_t *a,
+ const bson_t *b,
+ bson_error_t *error)
+{
+ bson_iter_t key_iter, canon_iter;
+ const char *key = NULL;
+ const char *canon = NULL;
+ const char *value = NULL;
+ const char *cval = NULL;
+ size_t value_len = 0;
+ size_t cval_len = 0;
+
+ /* Scan `a` looking for deprecated names
+ * where the canonical name was also used in `a`,
+ * or was used in `b`. */
+ bson_iter_init (&key_iter, a);
+ while (bson_iter_next (&key_iter)) {
+ key = bson_iter_key (&key_iter);
+ value = bson_iter_utf8_unsafe (&key_iter, &value_len);
+ canon = mongoc_uri_canonicalize_option (key);
+
+ if (key == canon) {
+ /* Canonical form, no point checking `b`. */
+ continue;
+ }
+
+ /* Check for a conflict in `a`. */
+ if (bson_iter_init_find (&canon_iter, a, canon)) {
+ cval = bson_iter_utf8_unsafe (&canon_iter, &cval_len);
+ if ((value_len != cval_len) || strcmp (value, cval)) {
+ goto HANDLE_CONFLICT;
+ }
+ }
+
+ /* Check for a conflict in `b`. */
+ if (bson_iter_init_find (&canon_iter, b, canon)) {
+ cval = bson_iter_utf8_unsafe (&canon_iter, &cval_len);
+ if ((value_len != cval_len) || strcmp (value, cval)) {
+ goto HANDLE_CONFLICT;
+ }
+ }
+ }
+
+ return true;
+
+HANDLE_CONFLICT:
+ MONGOC_URI_ERROR (error,
+ "Deprecated option '%s=%s' conflicts with "
+ "canonical name '%s=%s'",
+ key,
+ value,
+ canon,
+ cval);
+
+ return false;
+}
+
+
+#define HANDLE_DUPE() \
+ if (from_dns) { \
+ MONGOC_WARNING ("Cannot override URI option \"%s\" from TXT record", \
+ key); \
+ continue; \
+ } else { \
+ MONGOC_WARNING ("Overwriting previously provided value for '%s'", key); \
+ }
+
+static bool
+mongoc_uri_apply_options (mongoc_uri_t *uri,
+ const bson_t *options,
+ bool from_dns,
+ bson_error_t *error)
+{
+ bson_iter_t iter;
+ int32_t v_int;
+ int64_t v_int64;
+ const char *key = NULL;
+ const char *canon = NULL;
+ const char *value = NULL;
+ size_t value_len;
+ bool bval;
+
+ bson_iter_init (&iter, options);
+ while (bson_iter_next (&iter)) {
+ key = bson_iter_key (&iter);
+ canon = mongoc_uri_canonicalize_option (key);
+ value = bson_iter_utf8_unsafe (&iter, &value_len);
+
+ /* Keep a record of how the option was originally presented. */
+ mongoc_uri_bson_append_or_replace_key (&uri->raw, key, value);
+
+ /* This check precedes mongoc_uri_option_is_int32 as all 64-bit values are
+ * also recognised as 32-bit ints.
+ */
+ if (mongoc_uri_option_is_int64 (key)) {
+ if (0 < strlen (value)) {
+ if (!_mongoc_uri_parse_int64 (key, value, &v_int64)) {
+ goto UNSUPPORTED_VALUE;
+ }
+
+ if (!_mongoc_uri_set_option_as_int64_with_error (
+ uri, canon, v_int64, error)) {
+ return false;
+ }
+ } else {
+ MONGOC_WARNING ("Empty value provided for \"%s\"", key);
+ }
+ } else if (mongoc_uri_option_is_int32 (key)) {
+ if (0 < strlen (value)) {
+ if (!mongoc_uri_parse_int32 (key, value, &v_int)) {
+ goto UNSUPPORTED_VALUE;
+ }
+
+ if (!_mongoc_uri_set_option_as_int32_with_error (
+ uri, canon, v_int, error)) {
+ return false;
+ }
+ } else {
+ MONGOC_WARNING ("Empty value provided for \"%s\"", key);
+ }
+ } else if (!strcmp (key, MONGOC_URI_W)) {
+ if (*value == '-' || isdigit (*value)) {
+ v_int = (int) strtol (value, NULL, 10);
+ _mongoc_uri_set_option_as_int32 (uri, MONGOC_URI_W, v_int);
+ } else if (0 == strcasecmp (value, "majority")) {
+ mongoc_uri_bson_append_or_replace_key (
+ &uri->options, MONGOC_URI_W, "majority");
+ } else if (*value) {
+ mongoc_uri_bson_append_or_replace_key (
+ &uri->options, MONGOC_URI_W, value);
+ }
+
+ } else if (mongoc_uri_option_is_bool (key)) {
+ if (0 < strlen (value)) {
+ if (0 == strcasecmp (value, "true")) {
+ bval = true;
+ } else if (0 == strcasecmp (value, "false")) {
+ bval = false;
+ } else if ((0 == strcmp (value, "1")) ||
+ (0 == strcasecmp (value, "yes")) ||
+ (0 == strcasecmp (value, "y")) ||
+ (0 == strcasecmp (value, "t"))) {
+ MONGOC_WARNING ("Deprecated boolean value for \"%s\": \"%s\", "
+ "please update to \"%s=true\"",
+ key,
+ value,
+ key);
+ bval = true;
+ } else if ((0 == strcasecmp (value, "0")) ||
+ (0 == strcasecmp (value, "-1")) ||
+ (0 == strcmp (value, "no")) ||
+ (0 == strcmp (value, "n")) ||
+ (0 == strcmp (value, "f"))) {
+ MONGOC_WARNING ("Deprecated boolean value for \"%s\": \"%s\", "
+ "please update to \"%s=false\"",
+ key,
+ value,
+ key);
+ bval = false;
+ } else {
+ goto UNSUPPORTED_VALUE;
+ }
+
+ if (!mongoc_uri_set_option_as_bool (uri, canon, bval)) {
+ bson_set_error (error,
+ MONGOC_ERROR_COMMAND,
+ MONGOC_ERROR_COMMAND_INVALID_ARG,
+ "Failed to set %s to %d",
+ canon,
+ bval);
+ return false;
+ }
+ } else {
+ MONGOC_WARNING ("Empty value provided for \"%s\"", key);
+ }
+
+ } else if (!strcmp (key, MONGOC_URI_READPREFERENCETAGS)) {
+ /* Skip this option here.
+ * It was marshalled during mongoc_uri_split_option()
+ * as a special case composing option.
+ */
+
+ } else if (!strcmp (key, MONGOC_URI_AUTHMECHANISM) ||
+ !strcmp (key, MONGOC_URI_AUTHSOURCE)) {
+ if (bson_has_field (&uri->credentials, key)) {
+ HANDLE_DUPE ();
+ }
+ mongoc_uri_bson_append_or_replace_key (
+ &uri->credentials, canon, value);
+
+ } else if (!strcmp (key, MONGOC_URI_READCONCERNLEVEL)) {
+ if (!mongoc_read_concern_is_default (uri->read_concern)) {
+ HANDLE_DUPE ();
+ }
+ mongoc_read_concern_set_level (uri->read_concern, value);
+
+ } else if (!strcmp (key, MONGOC_URI_GSSAPISERVICENAME)) {
+ char *tmp = bson_strdup_printf ("SERVICE_NAME:%s", value);
+ if (bson_has_field (&uri->credentials,
+ MONGOC_URI_AUTHMECHANISMPROPERTIES)) {
+ MONGOC_WARNING ("authMechanismProperties SERVICE_NAME already set, "
+ "ignoring '%s'",
+ key);
+ } else if (!mongoc_uri_parse_auth_mechanism_properties (uri, tmp)) {
+ bson_free (tmp);
+ goto UNSUPPORTED_VALUE;
+ }
+ bson_free (tmp);
+
+ } else if (!strcmp (key, MONGOC_URI_SRVSERVICENAME)) {
+ if (!mongoc_uri_check_srv_service_name (uri, value)) {
+ goto UNSUPPORTED_VALUE;
+ }
+ mongoc_uri_bson_append_or_replace_key (&uri->options, canon, value);
+
+ } else if (!strcmp (key, MONGOC_URI_AUTHMECHANISMPROPERTIES)) {
+ if (bson_has_field (&uri->credentials, key)) {
+ HANDLE_DUPE ();
+ }
+ if (!mongoc_uri_parse_auth_mechanism_properties (uri, value)) {
+ goto UNSUPPORTED_VALUE;
+ }
+
+ } else if (!strcmp (key, MONGOC_URI_APPNAME)) {
+ /* Part of uri->options */
+ if (!mongoc_uri_set_appname (uri, value)) {
+ goto UNSUPPORTED_VALUE;
+ }
+
+ } else if (!strcmp (key, MONGOC_URI_COMPRESSORS)) {
+ if (!bson_empty (mongoc_uri_get_compressors (uri))) {
+ HANDLE_DUPE ();
+ }
+ if (!mongoc_uri_set_compressors (uri, value)) {
+ goto UNSUPPORTED_VALUE;
+ }
+
+ } else if (mongoc_uri_option_is_utf8 (key)) {
+ mongoc_uri_bson_append_or_replace_key (&uri->options, canon, value);
+
+ } else {
+ /*
+ * Keys that aren't supported by a driver MUST be ignored.
+ *
+ * A WARN level logging message MUST be issued
+ * https://github.com/mongodb/specifications/blob/master/source/connection-string/connection-string-spec.rst#keys
+ */
+ MONGOC_WARNING ("Unsupported URI option \"%s\"", key);
+ }
+ }
+
+ return true;
+
+UNSUPPORTED_VALUE:
+ MONGOC_URI_ERROR (error, "Unsupported value for \"%s\": \"%s\"", key, value);
+
+ return false;
+}
+
+
+/* Processes a query string formatted set of driver options
+ * (i.e. tls=true&connectTimeoutMS=250 ) into a BSON dict of values.
+ * uri->raw is initially populated with the raw split of key/value pairs,
+ * then the keys are canonicalized and the values coerced
+ * to their appropriate type and stored in uri->options.
+ */
+bool
+mongoc_uri_parse_options (mongoc_uri_t *uri,
+ const char *str,
+ bool from_dns,
+ bson_error_t *error)
+{
+ bson_t options;
+ const char *end_option;
+ char *option;
+
+ bson_init (&options);
+ while ((option = scan_to_unichar (str, '&', "", &end_option))) {
+ if (!mongoc_uri_split_option (uri, &options, option, from_dns, error)) {
+ bson_free (option);
+ bson_destroy (&options);
+ return false;
+ }
+ bson_free (option);
+ str = end_option + 1;
+ }
+
+ if (*str && !mongoc_uri_split_option (uri, &options, str, from_dns, error)) {
+ bson_destroy (&options);
+ return false;
+ }
+
+ /* Walk both sides of this map to handle each ordering:
+ * deprecated first canonical later, and vice-versa.
+ * Then finalize parse by writing final values to uri->options.
+ */
+ if (!mongoc_uri_options_validate_names (&uri->options, &options, error) ||
+ !mongoc_uri_options_validate_names (&options, &uri->options, error) ||
+ !mongoc_uri_apply_options (uri, &options, from_dns, error)) {
+ bson_destroy (&options);
+ return false;
+ }
+
+ bson_destroy (&options);
+ return true;
+}
+
+
+static bool
+mongoc_uri_finalize_tls (mongoc_uri_t *uri, bson_error_t *error)
+{
+ /* Initial DNS Seedlist Discovery Spec: "If mongodb+srv is used, a driver
+ * MUST implicitly also enable TLS." */
+ if (uri->is_srv && !bson_has_field (&uri->options, MONGOC_URI_TLS)) {
+ mongoc_uri_set_option_as_bool (uri, MONGOC_URI_TLS, true);
+ }
+
+ /* tlsInsecure implies tlsAllowInvalidCertificates, tlsAllowInvalidHostnames,
+ * tlsDisableOCSPEndpointCheck, and tlsDisableCertificateRevocationCheck, so
+ * consider it an error to have both. The user might have the wrong idea. */
+ if (bson_has_field (&uri->options, MONGOC_URI_TLSINSECURE) &&
+ (bson_has_field (&uri->options,
+ MONGOC_URI_TLSALLOWINVALIDCERTIFICATES) ||
+ bson_has_field (&uri->options, MONGOC_URI_TLSALLOWINVALIDHOSTNAMES) ||
+ bson_has_field (&uri->options,
+ MONGOC_URI_TLSDISABLEOCSPENDPOINTCHECK) ||
+ bson_has_field (&uri->options,
+ MONGOC_URI_TLSDISABLECERTIFICATEREVOCATIONCHECK))) {
+ MONGOC_URI_ERROR (error,
+ "%s may not be specified with %s, %s, %s, or %s",
+ MONGOC_URI_TLSINSECURE,
+ MONGOC_URI_TLSALLOWINVALIDCERTIFICATES,
+ MONGOC_URI_TLSALLOWINVALIDHOSTNAMES,
+ MONGOC_URI_TLSDISABLEOCSPENDPOINTCHECK,
+ MONGOC_URI_TLSDISABLECERTIFICATEREVOCATIONCHECK);
+ return false;
+ }
+
+ /* tlsAllowInvalidCertificates implies tlsDisableOCSPEndpointCheck and
+ * tlsDisableCertificateRevocationCheck, so consider it an error to have
+ * both. The user might have the wrong idea. */
+ if (bson_has_field (&uri->options, MONGOC_URI_TLSALLOWINVALIDCERTIFICATES) &&
+ (bson_has_field (&uri->options,
+ MONGOC_URI_TLSDISABLECERTIFICATEREVOCATIONCHECK) ||
+ bson_has_field (&uri->options,
+ MONGOC_URI_TLSDISABLEOCSPENDPOINTCHECK))) {
+ MONGOC_URI_ERROR (error,
+ "%s may not be specified with %s or %s",
+ MONGOC_URI_TLSALLOWINVALIDCERTIFICATES,
+ MONGOC_URI_TLSDISABLEOCSPENDPOINTCHECK,
+ MONGOC_URI_TLSDISABLECERTIFICATEREVOCATIONCHECK);
+ return false;
+ }
+
+ /* tlsDisableCertificateRevocationCheck implies tlsDisableOCSPEndpointCheck,
+ * so consider it an error to have both. The user might have the wrong idea.
+ */
+ if (bson_has_field (&uri->options,
+ MONGOC_URI_TLSDISABLECERTIFICATEREVOCATIONCHECK) &&
+ bson_has_field (&uri->options, MONGOC_URI_TLSDISABLEOCSPENDPOINTCHECK)) {
+ MONGOC_URI_ERROR (error,
+ "%s may not be specified with %s",
+ MONGOC_URI_TLSDISABLECERTIFICATEREVOCATIONCHECK,
+ MONGOC_URI_TLSDISABLEOCSPENDPOINTCHECK);
+ return false;
+ }
+
+ return true;
+}
+
+
+static bool
+mongoc_uri_finalize_auth (mongoc_uri_t *uri, bson_error_t *error)
+{
+ bson_iter_t iter;
+ const char *source = NULL;
+ const bool require_auth = uri->username != NULL;
+
+ if (bson_iter_init_find_case (
+ &iter, &uri->credentials, MONGOC_URI_AUTHSOURCE)) {
+ source = bson_iter_utf8 (&iter, NULL);
+ }
+
+ if (mongoc_uri_get_auth_mechanism (uri)) {
+ /* authSource with GSSAPI or X509 should always be external */
+ if (!strcasecmp (mongoc_uri_get_auth_mechanism (uri), "GSSAPI") ||
+ !strcasecmp (mongoc_uri_get_auth_mechanism (uri), "MONGODB-X509")) {
+ if (source) {
+ if (strcasecmp (source, "$external")) {
+ MONGOC_URI_ERROR (
+ error,
+ "%s",
+ "GSSAPI and X509 require \"$external\" authSource");
+ return false;
+ }
+ } else {
+ bson_append_utf8 (
+ &uri->credentials, MONGOC_URI_AUTHSOURCE, -1, "$external", -1);
+ }
+ }
+ /* MONGODB-X509 and MONGODB-AWS are the only mechanisms that don't require
+ * username */
+ if (!(strcasecmp (mongoc_uri_get_auth_mechanism (uri), "MONGODB-X509") ==
+ 0 ||
+ strcasecmp (mongoc_uri_get_auth_mechanism (uri), "MONGODB-AWS") ==
+ 0)) {
+ if (!mongoc_uri_get_username (uri) ||
+ strcmp (mongoc_uri_get_username (uri), "") == 0) {
+ MONGOC_URI_ERROR (error,
+ "'%s' authentication mechanism requires username",
+ mongoc_uri_get_auth_mechanism (uri));
+ return false;
+ }
+ }
+ /* MONGODB-X509 errors if a password is supplied. */
+ if (strcasecmp (mongoc_uri_get_auth_mechanism (uri), "MONGODB-X509") ==
+ 0) {
+ if (mongoc_uri_get_password (uri)) {
+ MONGOC_URI_ERROR (
+ error,
+ "'%s' authentication mechanism does not accept a password",
+ mongoc_uri_get_auth_mechanism (uri));
+ return false;
+ }
+ }
+ /* GSSAPI uses 'mongodb' as the default service name */
+ if (strcasecmp (mongoc_uri_get_auth_mechanism (uri), "GSSAPI") == 0 &&
+ !(bson_iter_init_find (
+ &iter, &uri->credentials, MONGOC_URI_AUTHMECHANISMPROPERTIES) &&
+ BSON_ITER_HOLDS_DOCUMENT (&iter) &&
+ bson_iter_recurse (&iter, &iter) &&
+ bson_iter_find_case (&iter, "SERVICE_NAME"))) {
+ bson_t tmp;
+ bson_t *props = NULL;
+
+ props = mongoc_uri_get_mechanism_properties (uri, &tmp)
+ ? bson_copy (&tmp)
+ : bson_new ();
+
+ BSON_APPEND_UTF8 (props, "SERVICE_NAME", "mongodb");
+ mongoc_uri_set_mechanism_properties (uri, props);
+
+ bson_destroy (props);
+ }
+
+ } else if (require_auth) /* Default auth mechanism is used */ {
+ if (!mongoc_uri_get_username (uri) ||
+ strcmp (mongoc_uri_get_username (uri), "") == 0) {
+ MONGOC_URI_ERROR (
+ error, "%s", "Default authentication mechanism requires username");
+ return false;
+ }
+ }
+ return true;
+}
+
+static bool
+mongoc_uri_finalize_directconnection (mongoc_uri_t *uri, bson_error_t *error)
+{
+ bool directconnection = false;
+
+ directconnection =
+ mongoc_uri_get_option_as_bool (uri, MONGOC_URI_DIRECTCONNECTION, false);
+ if (!directconnection) {
+ return true;
+ }
+
+ /* URI options spec: "The driver MUST report an error if the
+ * directConnection=true URI option is specified with an SRV URI, because
+ * the URI may resolve to multiple hosts. The driver MUST allow specifying
+ * directConnection=false URI option with an SRV URI." */
+ if (uri->is_srv) {
+ MONGOC_URI_ERROR (
+ error, "%s", "SRV URI not allowed with directConnection option");
+ return false;
+ }
+
+ /* URI options spec: "The driver MUST report an error if the
+ * directConnection=true URI option is specified with multiple seeds." */
+ if (uri->hosts && uri->hosts->next) {
+ MONGOC_URI_ERROR (
+ error,
+ "%s",
+ "Multiple seeds not allowed with directConnection option");
+ return false;
+ }
+
+ return true;
+}
+
+static bool
+mongoc_uri_parse_before_slash (mongoc_uri_t *uri,
+ const char *before_slash,
+ bson_error_t *error)
+{
+ char *userpass;
+ const char *hosts;
+
+ userpass = scan_to_unichar (before_slash, '@', "", &hosts);
+ if (userpass) {
+ if (!mongoc_uri_parse_userpass (uri, userpass, error)) {
+ goto error;
+ }
+
+ hosts++; /* advance past "@" */
+ if (*hosts == '@') {
+ /* special case: "mongodb://alice@@localhost" */
+ MONGOC_URI_ERROR (
+ error, "Invalid username or password. %s", escape_instructions);
+ goto error;
+ }
+ } else {
+ hosts = before_slash;
+ }
+
+ if (uri->is_srv) {
+ if (!mongoc_uri_parse_srv (uri, hosts)) {
+ MONGOC_URI_ERROR (error, "%s", "Invalid service name in URI");
+ goto error;
+ }
+ } else {
+ if (!mongoc_uri_parse_hosts (uri, hosts)) {
+ MONGOC_URI_ERROR (error, "%s", "Invalid host string in URI");
+ goto error;
+ }
+ }
+
+ bson_free (userpass);
+ return true;
+
+error:
+ bson_free (userpass);
+ return false;
+}
+
+
+static bool
+mongoc_uri_parse (mongoc_uri_t *uri, const char *str, bson_error_t *error)
+{
+ char *before_slash = NULL;
+ const char *tmp;
+
+ if (!bson_utf8_validate (str, strlen (str), false /* allow_null */)) {
+ MONGOC_URI_ERROR (error, "%s", "Invalid UTF-8 in URI");
+ goto error;
+ }
+
+ if (!mongoc_uri_parse_scheme (uri, str, &str)) {
+ MONGOC_URI_ERROR (
+ error,
+ "%s",
+ "Invalid URI Schema, expecting 'mongodb://' or 'mongodb+srv://'");
+ goto error;
+ }
+
+ before_slash = scan_to_unichar (str, '/', "", &tmp);
+ if (!before_slash) {
+ before_slash = bson_strdup (str);
+ str += strlen (before_slash);
+ } else {
+ str = tmp;
+ }
+
+ if (!mongoc_uri_parse_before_slash (uri, before_slash, error)) {
+ goto error;
+ }
+
+ if (*str) {
+ if (*str == '/') {
+ str++;
+ if (*str) {
+ if (!mongoc_uri_parse_database (uri, str, &str)) {
+ MONGOC_URI_ERROR (error, "%s", "Invalid database name in URI");
+ goto error;
+ }
+ }
+
+ if (*str == '?') {
+ str++;
+ if (*str) {
+ if (!mongoc_uri_parse_options (
+ uri, str, false /* from DNS */, error)) {
+ goto error;
+ }
+ }
+ }
+ } else {
+ MONGOC_URI_ERROR (error, "%s", "Expected end of hostname delimiter");
+ goto error;
+ }
+ }
+
+ if (!mongoc_uri_finalize (uri, error)) {
+ goto error;
+ }
+
+ bson_free (before_slash);
+ return true;
+
+error:
+ bson_free (before_slash);
+ return false;
+}
+
+
+const mongoc_host_list_t *
+mongoc_uri_get_hosts (const mongoc_uri_t *uri)
+{
+ BSON_ASSERT (uri);
+ return uri->hosts;
+}
+
+
+const char *
+mongoc_uri_get_replica_set (const mongoc_uri_t *uri)
+{
+ bson_iter_t iter;
+
+ BSON_ASSERT (uri);
+
+ if (bson_iter_init_find_case (&iter, &uri->options, MONGOC_URI_REPLICASET) &&
+ BSON_ITER_HOLDS_UTF8 (&iter)) {
+ return bson_iter_utf8 (&iter, NULL);
+ }
+
+ return NULL;
+}
+
+
+const bson_t *
+mongoc_uri_get_credentials (const mongoc_uri_t *uri)
+{
+ BSON_ASSERT (uri);
+ return &uri->credentials;
+}
+
+
+const char *
+mongoc_uri_get_auth_mechanism (const mongoc_uri_t *uri)
+{
+ bson_iter_t iter;
+
+ BSON_ASSERT (uri);
+
+ if (bson_iter_init_find_case (
+ &iter, &uri->credentials, MONGOC_URI_AUTHMECHANISM) &&
+ BSON_ITER_HOLDS_UTF8 (&iter)) {
+ return bson_iter_utf8 (&iter, NULL);
+ }
+
+ return NULL;
+}
+
+
+bool
+mongoc_uri_set_auth_mechanism (mongoc_uri_t *uri, const char *value)
+{
+ size_t len;
+
+ BSON_ASSERT (value);
+
+ len = strlen (value);
+
+ if (!bson_utf8_validate (value, len, false)) {
+ return false;
+ }
+
+ mongoc_uri_bson_append_or_replace_key (
+ &uri->credentials, MONGOC_URI_AUTHMECHANISM, value);
+
+ return true;
+}
+
+
+bool
+mongoc_uri_get_mechanism_properties (const mongoc_uri_t *uri,
+ bson_t *properties /* OUT */)
+{
+ bson_iter_t iter;
+
+ BSON_ASSERT (uri);
+ BSON_ASSERT (properties);
+
+ if (bson_iter_init_find_case (
+ &iter, &uri->credentials, MONGOC_URI_AUTHMECHANISMPROPERTIES) &&
+ BSON_ITER_HOLDS_DOCUMENT (&iter)) {
+ uint32_t len = 0;
+ const uint8_t *data = NULL;
+
+ bson_iter_document (&iter, &len, &data);
+ BSON_ASSERT (bson_init_static (properties, data, len));
+
+ return true;
+ }
+
+ return false;
+}
+
+
+bool
+mongoc_uri_set_mechanism_properties (mongoc_uri_t *uri,
+ const bson_t *properties)
+{
+ bson_iter_t iter;
+ bson_t tmp = BSON_INITIALIZER;
+ bool r;
+
+ BSON_ASSERT (uri);
+ BSON_ASSERT (properties);
+
+ if (bson_iter_init_find (
+ &iter, &uri->credentials, MONGOC_URI_AUTHMECHANISMPROPERTIES)) {
+ /* copy all elements to tmp besides authMechanismProperties */
+ bson_copy_to_excluding_noinit (&uri->credentials,
+ &tmp,
+ MONGOC_URI_AUTHMECHANISMPROPERTIES,
+ (char *) NULL);
+
+ r = BSON_APPEND_DOCUMENT (
+ &tmp, MONGOC_URI_AUTHMECHANISMPROPERTIES, properties);
+ if (!r) {
+ bson_destroy (&tmp);
+ return false;
+ }
+
+ bson_destroy (&uri->credentials);
+ bson_copy_to (&tmp, &uri->credentials);
+ bson_destroy (&tmp);
+
+ return true;
+ } else {
+ bson_destroy (&tmp);
+ return BSON_APPEND_DOCUMENT (
+ &uri->credentials, MONGOC_URI_AUTHMECHANISMPROPERTIES, properties);
+ }
+}
+
+
+static bool
+_mongoc_uri_assign_read_prefs_mode (mongoc_uri_t *uri, bson_error_t *error)
+{
+ const char *str;
+ bson_iter_t iter;
+
+ BSON_ASSERT (uri);
+
+ if (bson_iter_init_find_case (
+ &iter, &uri->options, MONGOC_URI_READPREFERENCE) &&
+ BSON_ITER_HOLDS_UTF8 (&iter)) {
+ str = bson_iter_utf8 (&iter, NULL);
+
+ if (0 == strcasecmp ("primary", str)) {
+ mongoc_read_prefs_set_mode (uri->read_prefs, MONGOC_READ_PRIMARY);
+ } else if (0 == strcasecmp ("primarypreferred", str)) {
+ mongoc_read_prefs_set_mode (uri->read_prefs,
+ MONGOC_READ_PRIMARY_PREFERRED);
+ } else if (0 == strcasecmp ("secondary", str)) {
+ mongoc_read_prefs_set_mode (uri->read_prefs, MONGOC_READ_SECONDARY);
+ } else if (0 == strcasecmp ("secondarypreferred", str)) {
+ mongoc_read_prefs_set_mode (uri->read_prefs,
+ MONGOC_READ_SECONDARY_PREFERRED);
+ } else if (0 == strcasecmp ("nearest", str)) {
+ mongoc_read_prefs_set_mode (uri->read_prefs, MONGOC_READ_NEAREST);
+ } else {
+ MONGOC_URI_ERROR (
+ error, "Unsupported readPreference value [readPreference=%s]", str);
+ return false;
+ }
+ }
+ return true;
+}
+
+
+static bool
+_mongoc_uri_build_write_concern (mongoc_uri_t *uri, bson_error_t *error)
+{
+ mongoc_write_concern_t *write_concern;
+ const char *str;
+ bson_iter_t iter;
+ int64_t wtimeoutms;
+ int value;
+
+ BSON_ASSERT (uri);
+
+ write_concern = mongoc_write_concern_new ();
+ uri->write_concern = write_concern;
+
+ if (bson_iter_init_find_case (&iter, &uri->options, MONGOC_URI_SAFE) &&
+ BSON_ITER_HOLDS_BOOL (&iter)) {
+ mongoc_write_concern_set_w (
+ write_concern,
+ bson_iter_bool (&iter) ? 1 : MONGOC_WRITE_CONCERN_W_UNACKNOWLEDGED);
+ }
+
+ wtimeoutms = mongoc_uri_get_option_as_int64 (uri, MONGOC_URI_WTIMEOUTMS, 0);
+ if (wtimeoutms < 0) {
+ MONGOC_URI_ERROR (
+ error, "Unsupported wtimeoutMS value [w=%" PRId64 "]", wtimeoutms);
+ return false;
+ } else if (wtimeoutms > 0) {
+ mongoc_write_concern_set_wtimeout_int64 (write_concern, wtimeoutms);
+ }
+
+ if (bson_iter_init_find_case (&iter, &uri->options, MONGOC_URI_JOURNAL) &&
+ BSON_ITER_HOLDS_BOOL (&iter)) {
+ mongoc_write_concern_set_journal (write_concern, bson_iter_bool (&iter));
+ }
+
+ if (bson_iter_init_find_case (&iter, &uri->options, MONGOC_URI_W)) {
+ if (BSON_ITER_HOLDS_INT32 (&iter)) {
+ value = bson_iter_int32 (&iter);
+
+ switch (value) {
+ case MONGOC_WRITE_CONCERN_W_ERRORS_IGNORED:
+ case MONGOC_WRITE_CONCERN_W_UNACKNOWLEDGED:
+ if (mongoc_write_concern_get_journal (write_concern)) {
+ MONGOC_URI_ERROR (
+ error, "Journal conflicts with w value [w=%d]", value);
+ return false;
+ }
+ mongoc_write_concern_set_w (write_concern, value);
+ break;
+ default:
+ if (value > 0) {
+ mongoc_write_concern_set_w (write_concern, value);
+ break;
+ }
+ MONGOC_URI_ERROR (error, "Unsupported w value [w=%d]", value);
+ return false;
+ }
+ } else if (BSON_ITER_HOLDS_UTF8 (&iter)) {
+ str = bson_iter_utf8 (&iter, NULL);
+
+ if (0 == strcasecmp ("majority", str)) {
+ mongoc_write_concern_set_w (write_concern,
+ MONGOC_WRITE_CONCERN_W_MAJORITY);
+ } else {
+ mongoc_write_concern_set_wtag (write_concern, str);
+ }
+ } else {
+ BSON_ASSERT (false);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/* can't use mongoc_uri_get_option_as_int32, it treats 0 specially */
+static int32_t
+_mongoc_uri_get_max_staleness_option (const mongoc_uri_t *uri)
+{
+ const bson_t *options;
+ bson_iter_t iter;
+ int32_t retval = MONGOC_NO_MAX_STALENESS;
+
+ if ((options = mongoc_uri_get_options (uri)) &&
+ bson_iter_init_find_case (
+ &iter, options, MONGOC_URI_MAXSTALENESSSECONDS) &&
+ BSON_ITER_HOLDS_INT32 (&iter)) {
+ retval = bson_iter_int32 (&iter);
+ if (retval == 0) {
+ MONGOC_WARNING (
+ "Unsupported value for \"" MONGOC_URI_MAXSTALENESSSECONDS
+ "\": \"%d\"",
+ retval);
+ retval = -1;
+ } else if (retval < 0 && retval != -1) {
+ MONGOC_WARNING (
+ "Unsupported value for \"" MONGOC_URI_MAXSTALENESSSECONDS
+ "\": \"%d\"",
+ retval);
+ retval = MONGOC_NO_MAX_STALENESS;
+ }
+ }
+
+ return retval;
+}
+
+mongoc_uri_t *
+mongoc_uri_new_with_error (const char *uri_string, bson_error_t *error)
+{
+ mongoc_uri_t *uri;
+ int32_t max_staleness_seconds;
+
+ uri = (mongoc_uri_t *) bson_malloc0 (sizeof *uri);
+ bson_init (&uri->raw);
+ bson_init (&uri->options);
+ bson_init (&uri->credentials);
+ bson_init (&uri->compressors);
+
+ /* Initialize read_prefs, since parsing may add to it */
+ uri->read_prefs = mongoc_read_prefs_new (MONGOC_READ_PRIMARY);
+
+ /* Initialize empty read_concern */
+ uri->read_concern = mongoc_read_concern_new ();
+
+ if (!uri_string) {
+ uri_string = "mongodb://127.0.0.1/";
+ }
+
+ if (!mongoc_uri_parse (uri, uri_string, error)) {
+ mongoc_uri_destroy (uri);
+ return NULL;
+ }
+
+ uri->str = bson_strdup (uri_string);
+
+ if (!_mongoc_uri_assign_read_prefs_mode (uri, error)) {
+ mongoc_uri_destroy (uri);
+ return NULL;
+ }
+ max_staleness_seconds = _mongoc_uri_get_max_staleness_option (uri);
+ mongoc_read_prefs_set_max_staleness_seconds (uri->read_prefs,
+ max_staleness_seconds);
+
+ if (!mongoc_read_prefs_is_valid (uri->read_prefs)) {
+ mongoc_uri_destroy (uri);
+ MONGOC_URI_ERROR (error, "%s", "Invalid readPreferences");
+ return NULL;
+ }
+
+ if (!_mongoc_uri_build_write_concern (uri, error)) {
+ mongoc_uri_destroy (uri);
+ return NULL;
+ }
+
+ if (!mongoc_write_concern_is_valid (uri->write_concern)) {
+ mongoc_uri_destroy (uri);
+ MONGOC_URI_ERROR (error, "%s", "Invalid writeConcern");
+ return NULL;
+ }
+
+ return uri;
+}
+
+mongoc_uri_t *
+mongoc_uri_new (const char *uri_string)
+{
+ bson_error_t error = {0};
+ mongoc_uri_t *uri;
+
+ uri = mongoc_uri_new_with_error (uri_string, &error);
+ if (error.domain) {
+ MONGOC_WARNING ("Error parsing URI: '%s'", error.message);
+ }
+
+ return uri;
+}
+
+
+mongoc_uri_t *
+mongoc_uri_new_for_host_port (const char *hostname, uint16_t port)
+{
+ mongoc_uri_t *uri;
+ char *str;
+
+ BSON_ASSERT (hostname);
+ BSON_ASSERT (port);
+
+ str = bson_strdup_printf ("mongodb://%s:%hu/", hostname, port);
+ uri = mongoc_uri_new (str);
+ bson_free (str);
+
+ return uri;
+}
+
+
+const char *
+mongoc_uri_get_username (const mongoc_uri_t *uri)
+{
+ BSON_ASSERT (uri);
+
+ return uri->username;
+}
+
+bool
+mongoc_uri_set_username (mongoc_uri_t *uri, const char *username)
+{
+ size_t len;
+
+ BSON_ASSERT (username);
+
+ len = strlen (username);
+
+ if (!bson_utf8_validate (username, len, false)) {
+ return false;
+ }
+
+ if (uri->username) {
+ bson_free (uri->username);
+ }
+
+ uri->username = bson_strdup (username);
+ return true;
+}
+
+
+const char *
+mongoc_uri_get_password (const mongoc_uri_t *uri)
+{
+ BSON_ASSERT (uri);
+
+ return uri->password;
+}
+
+bool
+mongoc_uri_set_password (mongoc_uri_t *uri, const char *password)
+{
+ size_t len;
+
+ BSON_ASSERT (password);
+
+ len = strlen (password);
+
+ if (!bson_utf8_validate (password, len, false)) {
+ return false;
+ }
+
+ if (uri->password) {
+ bson_free (uri->password);
+ }
+
+ uri->password = bson_strdup (password);
+ return true;
+}
+
+
+const char *
+mongoc_uri_get_database (const mongoc_uri_t *uri)
+{
+ BSON_ASSERT (uri);
+ return uri->database;
+}
+
+bool
+mongoc_uri_set_database (mongoc_uri_t *uri, const char *database)
+{
+ size_t len;
+
+ BSON_ASSERT (database);
+
+ len = strlen (database);
+
+ if (!bson_utf8_validate (database, len, false)) {
+ return false;
+ }
+
+ if (uri->database) {
+ bson_free (uri->database);
+ }
+
+ uri->database = bson_strdup (database);
+ return true;
+}
+
+
+const char *
+mongoc_uri_get_auth_source (const mongoc_uri_t *uri)
+{
+ bson_iter_t iter;
+ const char *mechanism;
+
+ BSON_ASSERT (uri);
+
+ if (bson_iter_init_find_case (
+ &iter, &uri->credentials, MONGOC_URI_AUTHSOURCE)) {
+ return bson_iter_utf8 (&iter, NULL);
+ }
+
+ /* Auth spec:
+ * "For GSSAPI and MONGODB-X509 authMechanisms the authSource defaults to
+ * $external. For PLAIN the authSource defaults to the database name if
+ * supplied on the connection string or $external. For MONGODB-CR,
+ * SCRAM-SHA-1 and SCRAM-SHA-256 authMechanisms, the authSource defaults to
+ * the database name if supplied on the connection string or admin."
+ */
+ mechanism = mongoc_uri_get_auth_mechanism (uri);
+ if (mechanism) {
+ if (!strcasecmp (mechanism, "GSSAPI") ||
+ !strcasecmp (mechanism, "MONGODB-X509")) {
+ return "$external";
+ }
+ if (!strcasecmp (mechanism, "PLAIN")) {
+ return uri->database ? uri->database : "$external";
+ }
+ }
+
+ return uri->database ? uri->database : "admin";
+}
+
+
+bool
+mongoc_uri_set_auth_source (mongoc_uri_t *uri, const char *value)
+{
+ size_t len;
+
+ BSON_ASSERT (value);
+
+ len = strlen (value);
+
+ if (!bson_utf8_validate (value, len, false)) {
+ return false;
+ }
+
+ mongoc_uri_bson_append_or_replace_key (
+ &uri->credentials, MONGOC_URI_AUTHSOURCE, value);
+
+ return true;
+}
+
+
+const char *
+mongoc_uri_get_appname (const mongoc_uri_t *uri)
+{
+ BSON_ASSERT (uri);
+
+ return mongoc_uri_get_option_as_utf8 (uri, MONGOC_URI_APPNAME, NULL);
+}
+
+
+bool
+mongoc_uri_set_appname (mongoc_uri_t *uri, const char *value)
+{
+ BSON_ASSERT (value);
+
+ if (!bson_utf8_validate (value, strlen (value), false)) {
+ return false;
+ }
+
+ if (!_mongoc_handshake_appname_is_valid (value)) {
+ return false;
+ }
+
+ mongoc_uri_bson_append_or_replace_key (
+ &uri->options, MONGOC_URI_APPNAME, value);
+
+ return true;
+}
+
+bool
+mongoc_uri_set_compressors (mongoc_uri_t *uri, const char *value)
+{
+ const char *end_compressor;
+ char *entry;
+
+ bson_destroy (&uri->compressors);
+ bson_init (&uri->compressors);
+
+ if (value && !bson_utf8_validate (value, strlen (value), false)) {
+ return false;
+ }
+ while ((entry = scan_to_unichar (value, ',', "", &end_compressor))) {
+ if (mongoc_compressor_supported (entry)) {
+ mongoc_uri_bson_append_or_replace_key (
+ &uri->compressors, entry, "yes");
+ } else {
+ MONGOC_WARNING ("Unsupported compressor: '%s'", entry);
+ }
+ value = end_compressor + 1;
+ bson_free (entry);
+ }
+ if (value) {
+ if (mongoc_compressor_supported (value)) {
+ mongoc_uri_bson_append_or_replace_key (
+ &uri->compressors, value, "yes");
+ } else {
+ MONGOC_WARNING ("Unsupported compressor: '%s'", value);
+ }
+ }
+
+ return true;
+}
+
+const bson_t *
+mongoc_uri_get_compressors (const mongoc_uri_t *uri)
+{
+ BSON_ASSERT (uri);
+ return &uri->compressors;
+}
+
+
+/* can't use mongoc_uri_get_option_as_int32, it treats 0 specially */
+int32_t
+mongoc_uri_get_local_threshold_option (const mongoc_uri_t *uri)
+{
+ const bson_t *options;
+ bson_iter_t iter;
+ int32_t retval = MONGOC_TOPOLOGY_LOCAL_THRESHOLD_MS;
+
+ if ((options = mongoc_uri_get_options (uri)) &&
+ bson_iter_init_find_case (&iter, options, "localthresholdms") &&
+ BSON_ITER_HOLDS_INT32 (&iter)) {
+ retval = bson_iter_int32 (&iter);
+
+ if (retval < 0) {
+ MONGOC_WARNING ("Invalid localThresholdMS: %d", retval);
+ retval = MONGOC_TOPOLOGY_LOCAL_THRESHOLD_MS;
+ }
+ }
+
+ return retval;
+}
+
+
+const char *
+mongoc_uri_get_srv_hostname (const mongoc_uri_t *uri)
+{
+ if (uri->is_srv) {
+ return uri->srv;
+ }
+
+ return NULL;
+}
+
+
+const char *
+mongoc_uri_get_service (const mongoc_uri_t *uri)
+{
+ return mongoc_uri_get_srv_hostname (uri);
+}
+
+
+/* Initial DNS Seedlist Discovery Spec: `srvServiceName` requires a string value
+ * and defaults to "mongodb". */
+static const char *const mongoc_default_srv_service_name = "mongodb";
+
+
+const char *
+mongoc_uri_get_srv_service_name (const mongoc_uri_t *uri)
+{
+ bson_iter_t iter;
+
+ BSON_ASSERT_PARAM (uri);
+
+ if (bson_iter_init_find_case (
+ &iter, &uri->options, MONGOC_URI_SRVSERVICENAME)) {
+ BSON_ASSERT (BSON_ITER_HOLDS_UTF8 (&iter));
+ return bson_iter_utf8 (&iter, NULL);
+ }
+
+ return mongoc_default_srv_service_name;
+}
+
+
+const bson_t *
+mongoc_uri_get_options (const mongoc_uri_t *uri)
+{
+ BSON_ASSERT (uri);
+ return &uri->options;
+}
+
+
+void
+mongoc_uri_destroy (mongoc_uri_t *uri)
+{
+ if (uri) {
+ _mongoc_host_list_destroy_all (uri->hosts);
+ bson_free (uri->str);
+ bson_free (uri->database);
+ bson_free (uri->username);
+ bson_destroy (&uri->raw);
+ bson_destroy (&uri->options);
+ bson_destroy (&uri->credentials);
+ bson_destroy (&uri->compressors);
+ mongoc_read_prefs_destroy (uri->read_prefs);
+ mongoc_read_concern_destroy (uri->read_concern);
+ mongoc_write_concern_destroy (uri->write_concern);
+
+ if (uri->password) {
+ bson_zero_free (uri->password, strlen (uri->password));
+ }
+
+ bson_free (uri);
+ }
+}
+
+
+mongoc_uri_t *
+mongoc_uri_copy (const mongoc_uri_t *uri)
+{
+ mongoc_uri_t *copy;
+ mongoc_host_list_t *iter;
+ bson_error_t error;
+
+ BSON_ASSERT (uri);
+
+ copy = (mongoc_uri_t *) bson_malloc0 (sizeof (*copy));
+
+ copy->str = bson_strdup (uri->str);
+ copy->is_srv = uri->is_srv;
+ bson_strncpy (copy->srv, uri->srv, sizeof uri->srv);
+ copy->username = bson_strdup (uri->username);
+ copy->password = bson_strdup (uri->password);
+ copy->database = bson_strdup (uri->database);
+
+ copy->read_prefs = mongoc_read_prefs_copy (uri->read_prefs);
+ copy->read_concern = mongoc_read_concern_copy (uri->read_concern);
+ copy->write_concern = mongoc_write_concern_copy (uri->write_concern);
+
+ LL_FOREACH (uri->hosts, iter)
+ {
+ if (!mongoc_uri_upsert_host (copy, iter->host, iter->port, &error)) {
+ MONGOC_ERROR ("%s", error.message);
+ mongoc_uri_destroy (copy);
+ return NULL;
+ }
+ }
+
+ bson_copy_to (&uri->raw, &copy->raw);
+ bson_copy_to (&uri->options, &copy->options);
+ bson_copy_to (&uri->credentials, &copy->credentials);
+ bson_copy_to (&uri->compressors, &copy->compressors);
+
+ return copy;
+}
+
+
+const char *
+mongoc_uri_get_string (const mongoc_uri_t *uri)
+{
+ BSON_ASSERT (uri);
+ return uri->str;
+}
+
+
+const bson_t *
+mongoc_uri_get_read_prefs (const mongoc_uri_t *uri)
+{
+ BSON_ASSERT (uri);
+ return mongoc_read_prefs_get_tags (uri->read_prefs);
+}
+
+char *
+mongoc_uri_unescape (const char *escaped_string)
+{
+ bson_unichar_t c;
+ bson_string_t *str;
+ unsigned int hex = 0;
+ const char *ptr;
+ const char *end;
+ size_t len;
+ bool unescape_occurred = false;
+
+ BSON_ASSERT (escaped_string);
+
+ len = strlen (escaped_string);
+
+ /*
+ * Double check that this is a UTF-8 valid string. Bail out if necessary.
+ */
+ if (!bson_utf8_validate (escaped_string, len, false)) {
+ MONGOC_WARNING ("%s(): escaped_string contains invalid UTF-8", BSON_FUNC);
+ return NULL;
+ }
+
+ ptr = escaped_string;
+ end = ptr + len;
+ str = bson_string_new (NULL);
+
+ for (; *ptr; ptr = bson_utf8_next_char (ptr)) {
+ c = bson_utf8_get_char (ptr);
+ switch (c) {
+ case '%':
+ if (((end - ptr) < 2) || !isxdigit (ptr[1]) || !isxdigit (ptr[2]) ||
+#ifdef _MSC_VER
+ (1 != sscanf_s (&ptr[1], "%02x", &hex))
+#else
+ (1 != sscanf (&ptr[1], "%02x", &hex))
+#endif
+ || 0 == hex) {
+ bson_string_free (str, true);
+ MONGOC_WARNING ("Invalid %% escape sequence");
+ return NULL;
+ }
+ bson_string_append_c (str, hex);
+ ptr += 2;
+ unescape_occurred = true;
+ break;
+ default:
+ bson_string_append_unichar (str, c);
+ break;
+ }
+ }
+
+ /* Check that after unescaping, it is still valid UTF-8 */
+ if (unescape_occurred && !bson_utf8_validate (str->str, str->len, false)) {
+ MONGOC_WARNING (
+ "Invalid %% escape sequence: unescaped string contains invalid UTF-8");
+ bson_string_free (str, true);
+ return NULL;
+ }
+
+ return bson_string_free (str, false);
+}
+
+
+const mongoc_read_prefs_t *
+mongoc_uri_get_read_prefs_t (const mongoc_uri_t *uri) /* IN */
+{
+ BSON_ASSERT (uri);
+
+ return uri->read_prefs;
+}
+
+
+void
+mongoc_uri_set_read_prefs_t (mongoc_uri_t *uri,
+ const mongoc_read_prefs_t *prefs)
+{
+ BSON_ASSERT (uri);
+ BSON_ASSERT (prefs);
+
+ mongoc_read_prefs_destroy (uri->read_prefs);
+ uri->read_prefs = mongoc_read_prefs_copy (prefs);
+}
+
+
+const mongoc_read_concern_t *
+mongoc_uri_get_read_concern (const mongoc_uri_t *uri) /* IN */
+{
+ BSON_ASSERT (uri);
+
+ return uri->read_concern;
+}
+
+
+void
+mongoc_uri_set_read_concern (mongoc_uri_t *uri, const mongoc_read_concern_t *rc)
+{
+ BSON_ASSERT (uri);
+ BSON_ASSERT (rc);
+
+ mongoc_read_concern_destroy (uri->read_concern);
+ uri->read_concern = mongoc_read_concern_copy (rc);
+}
+
+
+const mongoc_write_concern_t *
+mongoc_uri_get_write_concern (const mongoc_uri_t *uri) /* IN */
+{
+ BSON_ASSERT (uri);
+
+ return uri->write_concern;
+}
+
+
+void
+mongoc_uri_set_write_concern (mongoc_uri_t *uri,
+ const mongoc_write_concern_t *wc)
+{
+ BSON_ASSERT (uri);
+ BSON_ASSERT (wc);
+
+ mongoc_write_concern_destroy (uri->write_concern);
+ uri->write_concern = mongoc_write_concern_copy (wc);
+}
+
+
+bool
+mongoc_uri_get_tls (const mongoc_uri_t *uri) /* IN */
+{
+ bson_iter_t iter;
+
+ BSON_ASSERT (uri);
+
+ if (bson_iter_init_find_case (&iter, &uri->options, MONGOC_URI_TLS) &&
+ BSON_ITER_HOLDS_BOOL (&iter)) {
+ return bson_iter_bool (&iter);
+ }
+
+ if (bson_iter_init_find_case (
+ &iter, &uri->options, MONGOC_URI_TLSCERTIFICATEKEYFILE) ||
+ bson_iter_init_find_case (&iter, &uri->options, MONGOC_URI_TLSCAFILE) ||
+ bson_iter_init_find_case (
+ &iter, &uri->options, MONGOC_URI_TLSALLOWINVALIDCERTIFICATES) ||
+ bson_iter_init_find_case (
+ &iter, &uri->options, MONGOC_URI_TLSALLOWINVALIDHOSTNAMES) ||
+ bson_iter_init_find_case (
+ &iter, &uri->options, MONGOC_URI_TLSINSECURE) ||
+ bson_iter_init_find_case (
+ &iter, &uri->options, MONGOC_URI_TLSCERTIFICATEKEYFILEPASSWORD) ||
+ bson_iter_init_find_case (
+ &iter, &uri->options, MONGOC_URI_TLSDISABLEOCSPENDPOINTCHECK) ||
+ bson_iter_init_find_case (
+ &iter,
+ &uri->options,
+ MONGOC_URI_TLSDISABLECERTIFICATEREVOCATIONCHECK)) {
+ return true;
+ }
+
+ return false;
+}
+
+bool
+mongoc_uri_get_ssl (const mongoc_uri_t *uri) /* IN */
+{
+ return mongoc_uri_get_tls (uri);
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_uri_get_option_as_int32 --
+ *
+ * Checks if the URI 'option' is set and of correct type (int32).
+ * The special value '0' is considered as "unset".
+ * This is so users can provide
+ * sprintf("mongodb://localhost/?option=%d", myvalue) style connection
+ * strings, and still apply default values.
+ *
+ * If not set, or set to invalid type, 'fallback' is returned.
+ *
+ * NOTE: 'option' is case*in*sensitive.
+ *
+ * Returns:
+ * The value of 'option' if available as int32 (and not 0), or
+ * 'fallback'.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+int32_t
+mongoc_uri_get_option_as_int32 (const mongoc_uri_t *uri,
+ const char *option_orig,
+ int32_t fallback)
+{
+ const char *option;
+ const bson_t *options;
+ bson_iter_t iter;
+ int64_t retval = 0;
+
+ option = mongoc_uri_canonicalize_option (option_orig);
+
+ /* BC layer to allow retrieving 32-bit values stored in 64-bit options */
+ if (mongoc_uri_option_is_int64 (option_orig)) {
+ retval = mongoc_uri_get_option_as_int64 (uri, option_orig, 0);
+
+ if (retval > INT32_MAX || retval < INT32_MIN) {
+ MONGOC_WARNING ("Cannot read 64-bit value for \"%s\": %" PRId64,
+ option_orig,
+ retval);
+
+ retval = 0;
+ }
+ } else if ((options = mongoc_uri_get_options (uri)) &&
+ bson_iter_init_find_case (&iter, options, option) &&
+ BSON_ITER_HOLDS_INT32 (&iter)) {
+ retval = bson_iter_int32 (&iter);
+ }
+
+ if (!retval) {
+ retval = fallback;
+ }
+
+ return (int32_t) retval;
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_uri_set_option_as_int32 --
+ *
+ * Sets a URI option 'after the fact'. Allows users to set individual
+ * URI options without passing them as a connection string.
+ *
+ * Only allows a set of known options to be set.
+ * @see mongoc_uri_option_is_int32 ().
+ *
+ * Does in-place-update of the option BSON if 'option' is already set.
+ * Appends the option to the end otherwise.
+ *
+ * NOTE: If 'option' is already set, and is of invalid type, this
+ * function will return false.
+ *
+ * NOTE: 'option' is case*in*sensitive.
+ *
+ * Returns:
+ * true on successfully setting the option, false on failure.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+bool
+mongoc_uri_set_option_as_int32 (mongoc_uri_t *uri,
+ const char *option_orig,
+ int32_t value)
+{
+ const char *option;
+ bson_error_t error;
+ bool r;
+
+ if (mongoc_uri_option_is_int64 (option_orig)) {
+ return mongoc_uri_set_option_as_int64 (uri, option_orig, value);
+ }
+
+ option = mongoc_uri_canonicalize_option (option_orig);
+
+ if (!mongoc_uri_option_is_int32 (option)) {
+ MONGOC_WARNING (
+ "Unsupported value for \"%s\": %d, \"%s\" is not an int32 option",
+ option_orig,
+ value,
+ option);
+ return false;
+ }
+
+ r = _mongoc_uri_set_option_as_int32_with_error (uri, option, value, &error);
+ if (!r) {
+ MONGOC_WARNING ("%s", error.message);
+ }
+
+ return r;
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_uri_set_option_as_int32_with_error --
+ *
+ * Same as mongoc_uri_set_option_as_int32, with error reporting.
+ *
+ * Precondition:
+ * mongoc_uri_option_is_int32(option) must be true.
+ *
+ * Returns:
+ * true on successfully setting the option, false on failure.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+static bool
+_mongoc_uri_set_option_as_int32_with_error (mongoc_uri_t *uri,
+ const char *option_orig,
+ int32_t value,
+ bson_error_t *error)
+{
+ const char *option;
+ const bson_t *options;
+ bson_iter_t iter;
+ char *option_lowercase = NULL;
+
+ option = mongoc_uri_canonicalize_option (option_orig);
+ /* Server Discovery and Monitoring Spec: "the driver MUST NOT permit users
+ * to configure it less than minHeartbeatFrequencyMS (500ms)." */
+ if (!bson_strcasecmp (option, MONGOC_URI_HEARTBEATFREQUENCYMS) &&
+ value < MONGOC_TOPOLOGY_MIN_HEARTBEAT_FREQUENCY_MS) {
+ MONGOC_URI_ERROR (error,
+ "Invalid \"%s\" of %d: must be at least %d",
+ option_orig,
+ value,
+ MONGOC_TOPOLOGY_MIN_HEARTBEAT_FREQUENCY_MS);
+ return false;
+ }
+
+ /* zlib levels are from -1 (default) through 9 (best compression) */
+ if (!bson_strcasecmp (option, MONGOC_URI_ZLIBCOMPRESSIONLEVEL) &&
+ (value < -1 || value > 9)) {
+ MONGOC_URI_ERROR (error,
+ "Invalid \"%s\" of %d: must be between -1 and 9",
+ option_orig,
+ value);
+ return false;
+ }
+
+ if ((options = mongoc_uri_get_options (uri)) &&
+ bson_iter_init_find_case (&iter, options, option)) {
+ if (BSON_ITER_HOLDS_INT32 (&iter)) {
+ bson_iter_overwrite_int32 (&iter, value);
+ return true;
+ } else {
+ MONGOC_URI_ERROR (error,
+ "Cannot set URI option \"%s\" to %d, it already has "
+ "a non-32-bit integer value",
+ option,
+ value);
+ return false;
+ }
+ }
+ option_lowercase = lowercase_str_new (option);
+ if (!bson_append_int32 (&uri->options, option_lowercase, -1, value)) {
+ bson_free (option_lowercase);
+ MONGOC_URI_ERROR (
+ error, "Failed to set URI option \"%s\" to %d", option_orig, value);
+
+ return false;
+ }
+
+ bson_free (option_lowercase);
+ return true;
+}
+
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_uri_set_option_as_int32 --
+ *
+ * Same as mongoc_uri_set_option_as_int32, except the option is not
+ * validated against valid int32 options
+ *
+ * Returns:
+ * true on successfully setting the option, false on failure.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+static bool
+_mongoc_uri_set_option_as_int32 (mongoc_uri_t *uri,
+ const char *option_orig,
+ int32_t value)
+{
+ const char *option;
+ const bson_t *options;
+ bson_iter_t iter;
+ char *option_lowercase = NULL;
+
+ option = mongoc_uri_canonicalize_option (option_orig);
+ if ((options = mongoc_uri_get_options (uri)) &&
+ bson_iter_init_find_case (&iter, options, option)) {
+ if (BSON_ITER_HOLDS_INT32 (&iter)) {
+ bson_iter_overwrite_int32 (&iter, value);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ option_lowercase = lowercase_str_new (option);
+ bson_append_int32 (&uri->options, option_lowercase, -1, value);
+ bson_free (option_lowercase);
+ return true;
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_uri_get_option_as_int64 --
+ *
+ * Checks if the URI 'option' is set and of correct type (int32 or
+ * int64).
+ * The special value '0' is considered as "unset".
+ * This is so users can provide
+ * sprintf("mongodb://localhost/?option=%" PRId64, myvalue) style
+ * connection strings, and still apply default values.
+ *
+ * If not set, or set to invalid type, 'fallback' is returned.
+ *
+ * NOTE: 'option' is case*in*sensitive.
+ *
+ * Returns:
+ * The value of 'option' if available as int64 or int32 (and not 0), or
+ * 'fallback'.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+int64_t
+mongoc_uri_get_option_as_int64 (const mongoc_uri_t *uri,
+ const char *option_orig,
+ int64_t fallback)
+{
+ const char *option;
+ const bson_t *options;
+ bson_iter_t iter;
+ int64_t retval = fallback;
+
+ option = mongoc_uri_canonicalize_option (option_orig);
+ if ((options = mongoc_uri_get_options (uri)) &&
+ bson_iter_init_find_case (&iter, options, option)) {
+ if (BSON_ITER_HOLDS_INT (&iter)) {
+ if (!(retval = bson_iter_as_int64 (&iter))) {
+ retval = fallback;
+ }
+ }
+ }
+
+ return retval;
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_uri_set_option_as_int64 --
+ *
+ * Sets a URI option 'after the fact'. Allows users to set individual
+ * URI options without passing them as a connection string.
+ *
+ * Only allows a set of known options to be set.
+ * @see mongoc_uri_option_is_int64 ().
+ *
+ * Does in-place-update of the option BSON if 'option' is already set.
+ * Appends the option to the end otherwise.
+ *
+ * NOTE: If 'option' is already set, and is of invalid type, this
+ * function will return false.
+ *
+ * NOTE: 'option' is case*in*sensitive.
+ *
+ * Returns:
+ * true on successfully setting the option, false on failure.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+bool
+mongoc_uri_set_option_as_int64 (mongoc_uri_t *uri,
+ const char *option_orig,
+ int64_t value)
+{
+ const char *option;
+ bson_error_t error;
+ bool r;
+
+ option = mongoc_uri_canonicalize_option (option_orig);
+ if (!mongoc_uri_option_is_int64 (option)) {
+ if (mongoc_uri_option_is_int32 (option_orig)) {
+ if (value >= INT32_MIN && value <= INT32_MAX) {
+ MONGOC_WARNING (
+ "Setting value for 32-bit option \"%s\" through 64-bit method",
+ option_orig);
+
+ return mongoc_uri_set_option_as_int32 (
+ uri, option_orig, (int32_t) value);
+ }
+
+ MONGOC_WARNING ("Unsupported value for \"%s\": %" PRId64
+ ", \"%s\" is not an int64 option",
+ option_orig,
+ value,
+ option);
+ return false;
+ }
+ }
+
+ r = _mongoc_uri_set_option_as_int64_with_error (uri, option, value, &error);
+ if (!r) {
+ MONGOC_WARNING ("%s", error.message);
+ }
+
+ return r;
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_uri_set_option_as_int64_with_error --
+ *
+ * Same as mongoc_uri_set_option_as_int64, with error reporting.
+ *
+ * Precondition:
+ * mongoc_uri_option_is_int64(option) must be true.
+ *
+ * Returns:
+ * true on successfully setting the option, false on failure.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+static bool
+_mongoc_uri_set_option_as_int64_with_error (mongoc_uri_t *uri,
+ const char *option_orig,
+ int64_t value,
+ bson_error_t *error)
+{
+ const char *option;
+ const bson_t *options;
+ bson_iter_t iter;
+ char *option_lowercase = NULL;
+
+ option = mongoc_uri_canonicalize_option (option_orig);
+
+ if ((options = mongoc_uri_get_options (uri)) &&
+ bson_iter_init_find_case (&iter, options, option)) {
+ if (BSON_ITER_HOLDS_INT64 (&iter)) {
+ bson_iter_overwrite_int64 (&iter, value);
+ return true;
+ } else {
+ MONGOC_URI_ERROR (error,
+ "Cannot set URI option \"%s\" to %" PRId64
+ ", it already has "
+ "a non-64-bit integer value",
+ option,
+ value);
+ return false;
+ }
+ }
+
+ option_lowercase = lowercase_str_new (option);
+ if (!bson_append_int64 (&uri->options, option_lowercase, -1, value)) {
+ bson_free (option_lowercase);
+ MONGOC_URI_ERROR (error,
+ "Failed to set URI option \"%s\" to %" PRId64,
+ option_orig,
+ value);
+
+ return false;
+ }
+ bson_free (option_lowercase);
+ return true;
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_uri_get_option_as_bool --
+ *
+ * Checks if the URI 'option' is set and of correct type (bool).
+ *
+ * If not set, or set to invalid type, 'fallback' is returned.
+ *
+ * NOTE: 'option' is case*in*sensitive.
+ *
+ * Returns:
+ * The value of 'option' if available as bool, or 'fallback'.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+bool
+mongoc_uri_get_option_as_bool (const mongoc_uri_t *uri,
+ const char *option_orig,
+ bool fallback)
+{
+ const char *option;
+ const bson_t *options;
+ bson_iter_t iter;
+
+ option = mongoc_uri_canonicalize_option (option_orig);
+ if ((options = mongoc_uri_get_options (uri)) &&
+ bson_iter_init_find_case (&iter, options, option) &&
+ BSON_ITER_HOLDS_BOOL (&iter)) {
+ return bson_iter_bool (&iter);
+ }
+
+ return fallback;
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_uri_set_option_as_bool --
+ *
+ * Sets a URI option 'after the fact'. Allows users to set individual
+ * URI options without passing them as a connection string.
+ *
+ * Only allows a set of known options to be set.
+ * @see mongoc_uri_option_is_bool ().
+ *
+ * Does in-place-update of the option BSON if 'option' is already set.
+ * Appends the option to the end otherwise.
+ *
+ * NOTE: If 'option' is already set, and is of invalid type, this
+ * function will return false.
+ *
+ * NOTE: 'option' is case*in*sensitive.
+ *
+ * Returns:
+ * true on successfully setting the option, false on failure.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+bool
+mongoc_uri_set_option_as_bool (mongoc_uri_t *uri,
+ const char *option_orig,
+ bool value)
+{
+ const char *option;
+ char *option_lowercase;
+ const bson_t *options;
+ bson_iter_t iter;
+
+ option = mongoc_uri_canonicalize_option (option_orig);
+ BSON_ASSERT (option);
+
+ if (!mongoc_uri_option_is_bool (option)) {
+ return false;
+ }
+
+ if ((options = mongoc_uri_get_options (uri)) &&
+ bson_iter_init_find_case (&iter, options, option)) {
+ if (BSON_ITER_HOLDS_BOOL (&iter)) {
+ bson_iter_overwrite_bool (&iter, value);
+ return true;
+ } else {
+ return false;
+ }
+ }
+ option_lowercase = lowercase_str_new (option);
+ bson_append_bool (&uri->options, option_lowercase, -1, value);
+ bson_free (option_lowercase);
+ return true;
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_uri_get_option_as_utf8 --
+ *
+ * Checks if the URI 'option' is set and of correct type (utf8).
+ *
+ * If not set, or set to invalid type, 'fallback' is returned.
+ *
+ * NOTE: 'option' is case*in*sensitive.
+ *
+ * Returns:
+ * The value of 'option' if available as utf8, or 'fallback'.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+const char *
+mongoc_uri_get_option_as_utf8 (const mongoc_uri_t *uri,
+ const char *option_orig,
+ const char *fallback)
+{
+ const char *option;
+ const bson_t *options;
+ bson_iter_t iter;
+
+ option = mongoc_uri_canonicalize_option (option_orig);
+ if ((options = mongoc_uri_get_options (uri)) &&
+ bson_iter_init_find_case (&iter, options, option) &&
+ BSON_ITER_HOLDS_UTF8 (&iter)) {
+ return bson_iter_utf8 (&iter, NULL);
+ }
+
+ return fallback;
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * mongoc_uri_set_option_as_utf8 --
+ *
+ * Sets a URI option 'after the fact'. Allows users to set individual
+ * URI options without passing them as a connection string.
+ *
+ * Only allows a set of known options to be set.
+ * @see mongoc_uri_option_is_utf8 ().
+ *
+ * If the option is not already set, this function will append it to
+ *the end of the options bson. NOTE: If the option is already set the entire
+ *options bson will be overwritten, containing the new option=value
+ *(at the same position).
+ *
+ * NOTE: If 'option' is already set, and is of invalid type, this
+ * function will return false.
+ *
+ * NOTE: 'option' must be valid utf8.
+ *
+ * NOTE: 'option' is case*in*sensitive.
+ *
+ * Returns:
+ * true on successfully setting the option, false on failure.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+bool
+mongoc_uri_set_option_as_utf8 (mongoc_uri_t *uri,
+ const char *option_orig,
+ const char *value)
+{
+ const char *option;
+ size_t len;
+ char *option_lowercase = NULL;
+
+ option = mongoc_uri_canonicalize_option (option_orig);
+ BSON_ASSERT (option);
+
+ len = strlen (value);
+
+ if (!bson_utf8_validate (value, len, false)) {
+ return false;
+ }
+
+ if (!mongoc_uri_option_is_utf8 (option)) {
+ return false;
+ }
+ if (!bson_strcasecmp (option, MONGOC_URI_APPNAME)) {
+ return mongoc_uri_set_appname (uri, value);
+ } else {
+ option_lowercase = lowercase_str_new (option);
+ mongoc_uri_bson_append_or_replace_key (
+ &uri->options, option_lowercase, value);
+ bson_free (option_lowercase);
+ }
+
+ return true;
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_uri_requires_auth_negotiation --
+ *
+ * Returns true if auth mechanism is necessary for this uri. According
+ * to the auth spec: "If an application provides a username but does
+ * not provide an authentication mechanism, drivers MUST negotiate a
+ * mechanism".
+ *
+ * Returns:
+ * true if the driver should negotiate the auth mechanism for the uri
+ *
+ *--------------------------------------------------------------------------
+ */
+bool
+_mongoc_uri_requires_auth_negotiation (const mongoc_uri_t *uri)
+{
+ return mongoc_uri_get_username (uri) && !mongoc_uri_get_auth_mechanism (uri);
+}
+
+
+/* A bit of a hack. Needed for multi mongos tests to create a URI with the same
+ * auth, SSL, and compressors settings but with only one specific host. */
+mongoc_uri_t *
+_mongoc_uri_copy_and_replace_host_list (const mongoc_uri_t *original,
+ const char *host)
+{
+ mongoc_uri_t *uri = mongoc_uri_copy (original);
+ _mongoc_host_list_destroy_all (uri->hosts);
+ uri->hosts = bson_malloc0 (sizeof (mongoc_host_list_t));
+ _mongoc_host_list_from_string (uri->hosts, host);
+ return uri;
+}
+
+bool
+mongoc_uri_init_with_srv_host_list (mongoc_uri_t *uri,
+ mongoc_host_list_t *host_list,
+ bson_error_t *error)
+{
+ mongoc_host_list_t *host;
+
+ BSON_ASSERT (uri->is_srv);
+ BSON_ASSERT (!uri->hosts);
+
+ LL_FOREACH (host_list, host)
+ {
+ if (!mongoc_uri_upsert_host_and_port (uri, host->host_and_port, error)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+#ifdef MONGOC_ENABLE_CRYPTO
+void
+_mongoc_uri_init_scram (const mongoc_uri_t *uri,
+ mongoc_scram_t *scram,
+ mongoc_crypto_hash_algorithm_t algo)
+{
+ BSON_ASSERT (uri);
+ BSON_ASSERT (scram);
+
+ _mongoc_scram_init (scram, algo);
+
+ _mongoc_scram_set_pass (scram, mongoc_uri_get_password (uri));
+ _mongoc_scram_set_user (scram, mongoc_uri_get_username (uri));
+}
+#endif
+
+static bool
+mongoc_uri_finalize_loadbalanced (const mongoc_uri_t *uri, bson_error_t *error)
+{
+ if (!mongoc_uri_get_option_as_bool (uri, MONGOC_URI_LOADBALANCED, false)) {
+ return true;
+ }
+
+ /* Load Balancer Spec: When `loadBalanced=true` is provided in the connection
+ * string, the driver MUST throw an exception if the connection string
+ * contains more than one host/port. */
+ if (uri->hosts && uri->hosts->next) {
+ MONGOC_URI_ERROR (
+ error,
+ "URI with \"%s\" enabled must not contain more than one host",
+ MONGOC_URI_LOADBALANCED);
+ return false;
+ }
+
+ if (mongoc_uri_has_option (uri, MONGOC_URI_REPLICASET)) {
+ MONGOC_URI_ERROR (
+ error,
+ "URI with \"%s\" enabled must not contain option \"%s\"",
+ MONGOC_URI_LOADBALANCED,
+ MONGOC_URI_REPLICASET);
+ return false;
+ }
+
+ if (mongoc_uri_has_option (uri, MONGOC_URI_DIRECTCONNECTION) &&
+ mongoc_uri_get_option_as_bool (
+ uri, MONGOC_URI_DIRECTCONNECTION, false)) {
+ MONGOC_URI_ERROR (
+ error,
+ "URI with \"%s\" enabled must not contain option \"%s\" enabled",
+ MONGOC_URI_LOADBALANCED,
+ MONGOC_URI_DIRECTCONNECTION);
+ return false;
+ }
+
+ return true;
+}
+
+static bool
+mongoc_uri_finalize_srv (const mongoc_uri_t *uri, bson_error_t *error)
+{
+ /* Initial DNS Seedlist Discovery Spec: The driver MUST report an error if
+ * either the `srvServiceName` or `srvMaxHosts` URI options are specified
+ * with a non-SRV URI. */
+ if (!uri->is_srv) {
+ const char *option = NULL;
+
+ if (mongoc_uri_has_option (uri, MONGOC_URI_SRVSERVICENAME)) {
+ option = MONGOC_URI_SRVSERVICENAME;
+ } else if (mongoc_uri_has_option (uri, MONGOC_URI_SRVMAXHOSTS)) {
+ option = MONGOC_URI_SRVMAXHOSTS;
+ }
+
+ if (option) {
+ MONGOC_URI_ERROR (
+ error, "%s must not be specified with a non-SRV URI", option);
+ return false;
+ }
+ }
+
+ if (uri->is_srv) {
+ const int32_t max_hosts =
+ mongoc_uri_get_option_as_int32 (uri, MONGOC_URI_SRVMAXHOSTS, 0);
+
+ /* Initial DNS Seedless Discovery Spec: This option requires a
+ * non-negative integer and defaults to zero (i.e. no limit). */
+ if (max_hosts < 0) {
+ MONGOC_URI_ERROR (error,
+ "%s is required to be a non-negative integer, but "
+ "has value %" PRId32,
+ MONGOC_URI_SRVMAXHOSTS,
+ max_hosts);
+ return false;
+ }
+
+ if (max_hosts > 0) {
+ /* Initial DNS Seedless Discovery spec: If srvMaxHosts is a positive
+ * integer, the driver MUST throw an error if the connection string
+ * contains a `replicaSet` option. */
+ if (mongoc_uri_has_option (uri, MONGOC_URI_REPLICASET)) {
+ MONGOC_URI_ERROR (error,
+ "%s must not be specified with %s",
+ MONGOC_URI_SRVMAXHOSTS,
+ MONGOC_URI_REPLICASET);
+ return false;
+ }
+
+ /* Initial DNS Seedless Discovery Spec: If srvMaxHosts is a positive
+ * integer, the driver MUST throw an error if the connection string
+ * contains a `loadBalanced` option with a value of `true`.
+ */
+ if (mongoc_uri_get_option_as_bool (
+ uri, MONGOC_URI_LOADBALANCED, false)) {
+ MONGOC_URI_ERROR (error,
+ "%s must not be specified with %s=true",
+ MONGOC_URI_SRVMAXHOSTS,
+ MONGOC_URI_LOADBALANCED);
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+/* This should be called whenever URI options change (e.g. parsing a new URI
+ * string, after setting one or more options explicitly, applying TXT records).
+ * While the primary purpose of this function is to validate the URI, it may
+ * also alter the URI (e.g. implicitly enable TLS when SRV is used). Returns
+ * true on success; otherwise, returns false and sets @error. */
+bool
+mongoc_uri_finalize (mongoc_uri_t *uri, bson_error_t *error)
+{
+ BSON_ASSERT_PARAM (uri);
+
+ if (!mongoc_uri_finalize_tls (uri, error)) {
+ return false;
+ }
+
+ if (!mongoc_uri_finalize_auth (uri, error)) {
+ return false;
+ }
+
+ if (!mongoc_uri_finalize_directconnection (uri, error)) {
+ return false;
+ }
+
+ if (!mongoc_uri_finalize_loadbalanced (uri, error)) {
+ return false;
+ }
+
+ if (!mongoc_uri_finalize_srv (uri, error)) {
+ return false;
+ }
+
+ return true;
+}
diff --git a/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-uri.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-uri.h
new file mode 100644
index 00000000..183c42d5
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-uri.h
@@ -0,0 +1,232 @@
+/*
+ * Copyright 2013 MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mongoc-prelude.h"
+
+#ifndef MONGOC_URI_H
+#define MONGOC_URI_H
+
+#include <bson/bson.h>
+
+#include "mongoc-macros.h"
+#include "mongoc-host-list.h"
+#include "mongoc-read-prefs.h"
+#include "mongoc-read-concern.h"
+#include "mongoc-write-concern.h"
+#include "mongoc-config.h"
+
+
+#ifndef MONGOC_DEFAULT_PORT
+#define MONGOC_DEFAULT_PORT 27017
+#endif
+
+#define MONGOC_URI_APPNAME "appname"
+#define MONGOC_URI_AUTHMECHANISM "authmechanism"
+#define MONGOC_URI_AUTHMECHANISMPROPERTIES "authmechanismproperties"
+#define MONGOC_URI_AUTHSOURCE "authsource"
+#define MONGOC_URI_CANONICALIZEHOSTNAME "canonicalizehostname"
+#define MONGOC_URI_CONNECTTIMEOUTMS "connecttimeoutms"
+#define MONGOC_URI_COMPRESSORS "compressors"
+#define MONGOC_URI_DIRECTCONNECTION "directconnection"
+#define MONGOC_URI_GSSAPISERVICENAME "gssapiservicename"
+#define MONGOC_URI_HEARTBEATFREQUENCYMS "heartbeatfrequencyms"
+#define MONGOC_URI_JOURNAL "journal"
+#define MONGOC_URI_LOADBALANCED "loadbalanced"
+#define MONGOC_URI_LOCALTHRESHOLDMS "localthresholdms"
+#define MONGOC_URI_MAXIDLETIMEMS "maxidletimems"
+#define MONGOC_URI_MAXPOOLSIZE "maxpoolsize"
+#define MONGOC_URI_MAXSTALENESSSECONDS "maxstalenessseconds"
+#define MONGOC_URI_MINPOOLSIZE "minpoolsize"
+#define MONGOC_URI_READCONCERNLEVEL "readconcernlevel"
+#define MONGOC_URI_READPREFERENCE "readpreference"
+#define MONGOC_URI_READPREFERENCETAGS "readpreferencetags"
+#define MONGOC_URI_REPLICASET "replicaset"
+#define MONGOC_URI_RETRYREADS "retryreads"
+#define MONGOC_URI_RETRYWRITES "retrywrites"
+#define MONGOC_URI_SAFE "safe"
+#define MONGOC_URI_SERVERSELECTIONTIMEOUTMS "serverselectiontimeoutms"
+#define MONGOC_URI_SERVERSELECTIONTRYONCE "serverselectiontryonce"
+#define MONGOC_URI_SLAVEOK "slaveok"
+#define MONGOC_URI_SOCKETCHECKINTERVALMS "socketcheckintervalms"
+#define MONGOC_URI_SOCKETTIMEOUTMS "sockettimeoutms"
+#define MONGOC_URI_SRVSERVICENAME "srvservicename"
+#define MONGOC_URI_SRVMAXHOSTS "srvmaxhosts"
+#define MONGOC_URI_TLS "tls"
+#define MONGOC_URI_TLSCERTIFICATEKEYFILE "tlscertificatekeyfile"
+#define MONGOC_URI_TLSCERTIFICATEKEYFILEPASSWORD "tlscertificatekeyfilepassword"
+#define MONGOC_URI_TLSCAFILE "tlscafile"
+#define MONGOC_URI_TLSALLOWINVALIDCERTIFICATES "tlsallowinvalidcertificates"
+#define MONGOC_URI_TLSALLOWINVALIDHOSTNAMES "tlsallowinvalidhostnames"
+#define MONGOC_URI_TLSINSECURE "tlsinsecure"
+#define MONGOC_URI_TLSDISABLECERTIFICATEREVOCATIONCHECK \
+ "tlsdisablecertificaterevocationcheck"
+#define MONGOC_URI_TLSDISABLEOCSPENDPOINTCHECK "tlsdisableocspendpointcheck"
+#define MONGOC_URI_W "w"
+#define MONGOC_URI_WAITQUEUEMULTIPLE "waitqueuemultiple"
+#define MONGOC_URI_WAITQUEUETIMEOUTMS "waitqueuetimeoutms"
+#define MONGOC_URI_WTIMEOUTMS "wtimeoutms"
+#define MONGOC_URI_ZLIBCOMPRESSIONLEVEL "zlibcompressionlevel"
+
+/* Deprecated in MongoDB 4.2, use "tls" variants instead. */
+#define MONGOC_URI_SSL "ssl"
+#define MONGOC_URI_SSLCLIENTCERTIFICATEKEYFILE "sslclientcertificatekeyfile"
+#define MONGOC_URI_SSLCLIENTCERTIFICATEKEYPASSWORD \
+ "sslclientcertificatekeypassword"
+#define MONGOC_URI_SSLCERTIFICATEAUTHORITYFILE "sslcertificateauthorityfile"
+#define MONGOC_URI_SSLALLOWINVALIDCERTIFICATES "sslallowinvalidcertificates"
+#define MONGOC_URI_SSLALLOWINVALIDHOSTNAMES "sslallowinvalidhostnames"
+
+BSON_BEGIN_DECLS
+
+
+typedef struct _mongoc_uri_t mongoc_uri_t;
+
+
+MONGOC_EXPORT (mongoc_uri_t *)
+mongoc_uri_copy (const mongoc_uri_t *uri) BSON_GNUC_WARN_UNUSED_RESULT;
+MONGOC_EXPORT (void)
+mongoc_uri_destroy (mongoc_uri_t *uri);
+MONGOC_EXPORT (mongoc_uri_t *)
+mongoc_uri_new (const char *uri_string) BSON_GNUC_WARN_UNUSED_RESULT;
+MONGOC_EXPORT (mongoc_uri_t *)
+mongoc_uri_new_with_error (const char *uri_string,
+ bson_error_t *error) BSON_GNUC_WARN_UNUSED_RESULT;
+MONGOC_EXPORT (mongoc_uri_t *)
+mongoc_uri_new_for_host_port (const char *hostname,
+ uint16_t port) BSON_GNUC_WARN_UNUSED_RESULT;
+MONGOC_EXPORT (const mongoc_host_list_t *)
+mongoc_uri_get_hosts (const mongoc_uri_t *uri);
+MONGOC_EXPORT (const char *)
+mongoc_uri_get_service (const mongoc_uri_t *uri)
+ BSON_GNUC_DEPRECATED_FOR (mongoc_uri_get_srv_hostname);
+MONGOC_EXPORT (const char *)
+mongoc_uri_get_srv_hostname (const mongoc_uri_t *uri);
+MONGOC_EXPORT (const char *)
+mongoc_uri_get_srv_service_name (const mongoc_uri_t *uri);
+MONGOC_EXPORT (const char *)
+mongoc_uri_get_database (const mongoc_uri_t *uri);
+MONGOC_EXPORT (bool)
+mongoc_uri_set_database (mongoc_uri_t *uri, const char *database);
+MONGOC_EXPORT (const bson_t *)
+mongoc_uri_get_compressors (const mongoc_uri_t *uri);
+MONGOC_EXPORT (const bson_t *)
+mongoc_uri_get_options (const mongoc_uri_t *uri);
+MONGOC_EXPORT (const char *)
+mongoc_uri_get_password (const mongoc_uri_t *uri);
+MONGOC_EXPORT (bool)
+mongoc_uri_set_password (mongoc_uri_t *uri, const char *password);
+MONGOC_EXPORT (bool)
+mongoc_uri_has_option (const mongoc_uri_t *uri, const char *key);
+MONGOC_EXPORT (bool)
+mongoc_uri_option_is_int32 (const char *key);
+MONGOC_EXPORT (bool)
+mongoc_uri_option_is_int64 (const char *key);
+MONGOC_EXPORT (bool)
+mongoc_uri_option_is_bool (const char *key);
+MONGOC_EXPORT (bool)
+mongoc_uri_option_is_utf8 (const char *key);
+MONGOC_EXPORT (int32_t)
+mongoc_uri_get_option_as_int32 (const mongoc_uri_t *uri,
+ const char *option,
+ int32_t fallback);
+MONGOC_EXPORT (int64_t)
+mongoc_uri_get_option_as_int64 (const mongoc_uri_t *uri,
+ const char *option,
+ int64_t fallback);
+MONGOC_EXPORT (bool)
+mongoc_uri_get_option_as_bool (const mongoc_uri_t *uri,
+ const char *option,
+ bool fallback);
+MONGOC_EXPORT (const char *)
+mongoc_uri_get_option_as_utf8 (const mongoc_uri_t *uri,
+ const char *option,
+ const char *fallback);
+MONGOC_EXPORT (bool)
+mongoc_uri_set_option_as_int32 (mongoc_uri_t *uri,
+ const char *option,
+ int32_t value);
+MONGOC_EXPORT (bool)
+mongoc_uri_set_option_as_int64 (mongoc_uri_t *uri,
+ const char *option,
+ int64_t value);
+MONGOC_EXPORT (bool)
+mongoc_uri_set_option_as_bool (mongoc_uri_t *uri,
+ const char *option,
+ bool value);
+MONGOC_EXPORT (bool)
+mongoc_uri_set_option_as_utf8 (mongoc_uri_t *uri,
+ const char *option,
+ const char *value);
+MONGOC_EXPORT (const bson_t *)
+mongoc_uri_get_read_prefs (const mongoc_uri_t *uri)
+ BSON_GNUC_DEPRECATED_FOR (mongoc_uri_get_read_prefs_t);
+MONGOC_EXPORT (const char *)
+mongoc_uri_get_replica_set (const mongoc_uri_t *uri);
+MONGOC_EXPORT (const char *)
+mongoc_uri_get_string (const mongoc_uri_t *uri);
+MONGOC_EXPORT (const char *)
+mongoc_uri_get_username (const mongoc_uri_t *uri);
+MONGOC_EXPORT (bool)
+mongoc_uri_set_username (mongoc_uri_t *uri, const char *username);
+MONGOC_EXPORT (const bson_t *)
+mongoc_uri_get_credentials (const mongoc_uri_t *uri);
+MONGOC_EXPORT (const char *)
+mongoc_uri_get_auth_source (const mongoc_uri_t *uri);
+MONGOC_EXPORT (bool)
+mongoc_uri_set_auth_source (mongoc_uri_t *uri, const char *value);
+MONGOC_EXPORT (const char *)
+mongoc_uri_get_appname (const mongoc_uri_t *uri);
+MONGOC_EXPORT (bool)
+mongoc_uri_set_appname (mongoc_uri_t *uri, const char *value);
+MONGOC_EXPORT (bool)
+mongoc_uri_set_compressors (mongoc_uri_t *uri, const char *value);
+MONGOC_EXPORT (const char *)
+mongoc_uri_get_auth_mechanism (const mongoc_uri_t *uri);
+MONGOC_EXPORT (bool)
+mongoc_uri_set_auth_mechanism (mongoc_uri_t *uri, const char *value);
+MONGOC_EXPORT (bool)
+mongoc_uri_get_mechanism_properties (const mongoc_uri_t *uri,
+ bson_t *properties);
+MONGOC_EXPORT (bool)
+mongoc_uri_set_mechanism_properties (mongoc_uri_t *uri,
+ const bson_t *properties);
+MONGOC_EXPORT (bool)
+mongoc_uri_get_ssl (const mongoc_uri_t *uri)
+ BSON_GNUC_DEPRECATED_FOR (mongoc_uri_get_tls);
+MONGOC_EXPORT (bool)
+mongoc_uri_get_tls (const mongoc_uri_t *uri);
+MONGOC_EXPORT (char *)
+mongoc_uri_unescape (const char *escaped_string) BSON_GNUC_WARN_UNUSED_RESULT;
+MONGOC_EXPORT (const mongoc_read_prefs_t *)
+mongoc_uri_get_read_prefs_t (const mongoc_uri_t *uri);
+MONGOC_EXPORT (void)
+mongoc_uri_set_read_prefs_t (mongoc_uri_t *uri,
+ const mongoc_read_prefs_t *prefs);
+MONGOC_EXPORT (const mongoc_write_concern_t *)
+mongoc_uri_get_write_concern (const mongoc_uri_t *uri);
+MONGOC_EXPORT (void)
+mongoc_uri_set_write_concern (mongoc_uri_t *uri,
+ const mongoc_write_concern_t *wc);
+MONGOC_EXPORT (const mongoc_read_concern_t *)
+mongoc_uri_get_read_concern (const mongoc_uri_t *uri);
+MONGOC_EXPORT (void)
+mongoc_uri_set_read_concern (mongoc_uri_t *uri,
+ const mongoc_read_concern_t *rc);
+
+BSON_END_DECLS
+
+
+#endif /* MONGOC_URI_H */
diff --git a/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-util-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-util-private.h
new file mode 100644
index 00000000..98d2257a
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-util-private.h
@@ -0,0 +1,239 @@
+/*
+ * Copyright 2013 MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mongoc-prelude.h"
+
+#ifndef MONGOC_UTIL_PRIVATE_H
+#define MONGOC_UTIL_PRIVATE_H
+
+#include <bson/bson.h>
+#include "mongoc.h"
+
+#ifdef BSON_HAVE_STRINGS_H
+#include <strings.h>
+#endif
+
+#include <stdint.h>
+
+/* string comparison functions for Windows */
+#ifdef _WIN32
+#define strcasecmp _stricmp
+#define strncasecmp _strnicmp
+#endif
+
+#if BSON_GNUC_CHECK_VERSION(4, 6)
+#define BEGIN_IGNORE_DEPRECATIONS \
+ _Pragma ("GCC diagnostic push") \
+ _Pragma ("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
+#define END_IGNORE_DEPRECATIONS _Pragma ("GCC diagnostic pop")
+#elif defined(__clang__)
+#define BEGIN_IGNORE_DEPRECATIONS \
+ _Pragma ("clang diagnostic push") \
+ _Pragma ("clang diagnostic ignored \"-Wdeprecated-declarations\"")
+#define END_IGNORE_DEPRECATIONS _Pragma ("clang diagnostic pop")
+#else
+#define BEGIN_IGNORE_DEPRECATIONS
+#define END_IGNORE_DEPRECATIONS
+#endif
+
+#ifndef _WIN32
+#define MONGOC_PRINTF_FORMAT(a, b) __attribute__ ((format (__printf__, a, b)))
+#else
+#define MONGOC_PRINTF_FORMAT(a, b) /* no-op */
+#endif
+
+#define COALESCE(x, y) ((x == 0) ? (y) : (x))
+
+
+/* Helper macros for stringifying things */
+#define MONGOC_STR(s) #s
+#define MONGOC_EVALUATE_STR(s) MONGOC_STR (s)
+
+BSON_BEGIN_DECLS
+
+extern const bson_validate_flags_t _mongoc_default_insert_vflags;
+extern const bson_validate_flags_t _mongoc_default_replace_vflags;
+extern const bson_validate_flags_t _mongoc_default_update_vflags;
+
+int
+_mongoc_rand_simple (unsigned int *seed);
+
+char *
+_mongoc_hex_md5 (const char *input);
+
+void
+_mongoc_usleep (int64_t usec);
+
+/* Get the current time as a number of milliseconds since the Unix Epoch. */
+int64_t
+_mongoc_get_real_time_ms (void);
+
+const char *
+_mongoc_get_command_name (const bson_t *command);
+
+const char *
+_mongoc_get_documents_field_name (const char *command_name);
+
+bool
+_mongoc_lookup_bool (const bson_t *bson, const char *key, bool default_value);
+
+/* Returns a database name that the caller must free. */
+char *
+_mongoc_get_db_name (const char *ns);
+
+void
+_mongoc_bson_init_if_set (bson_t *bson);
+
+const char *
+_mongoc_bson_type_to_str (bson_type_t t);
+
+const char *
+_mongoc_wire_version_to_server_version (int32_t version);
+
+bool
+_mongoc_get_server_id_from_opts (const bson_t *opts,
+ mongoc_error_domain_t domain,
+ mongoc_error_code_t code,
+ uint32_t *server_id,
+ bson_error_t *error);
+
+bool
+_mongoc_validate_new_document (const bson_t *insert,
+ bson_validate_flags_t vflags,
+ bson_error_t *error);
+
+bool
+_mongoc_validate_replace (const bson_t *insert,
+ bson_validate_flags_t vflags,
+ bson_error_t *error);
+
+bool
+_mongoc_validate_update (const bson_t *update,
+ bson_validate_flags_t vflags,
+ bson_error_t *error);
+
+void
+mongoc_lowercase (const char *src, char *buf /* OUT */);
+
+bool
+mongoc_parse_port (uint16_t *port, const char *str);
+
+void
+_mongoc_bson_array_add_label (bson_t *bson, const char *label);
+
+void
+_mongoc_bson_array_copy_labels_to (const bson_t *reply, bson_t *dst);
+
+void
+_mongoc_bson_init_with_transient_txn_error (const mongoc_client_session_t *cs,
+ bson_t *reply);
+
+bool
+_mongoc_document_is_pipeline (const bson_t *document);
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * _mongoc_getenv --
+ *
+ * Get the value of an environment variable.
+ *
+ * Returns:
+ * A string you must bson_free, or NULL if the variable is not set.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+char *
+_mongoc_getenv (const char *name);
+
+/* Returns a uniformly-distributed uint32_t generated using
+ * `_mongoc_rand_bytes()` if a source of cryptographic randomness is available
+ * (defined only if `MONGOC_ENABLE_CRYPTO` is defined).
+ */
+uint32_t
+_mongoc_crypto_rand_uint32_t (void);
+
+/* Returns a uniformly-distributed uint64_t generated using
+ * `_mongoc_rand_bytes()` if a source of cryptographic randomness is available
+ * (defined only if `MONGOC_ENABLE_CRYPTO` is defined).
+ */
+uint64_t
+_mongoc_crypto_rand_uint64_t (void);
+
+/* Returns a uniformly-distributed size_t generated using
+ * `_mongoc_rand_bytes()` if a source of cryptographic randomness is available
+ * (defined only if `MONGOC_ENABLE_CRYPTO` is defined).
+ */
+size_t
+_mongoc_crypto_rand_size_t (void);
+
+/* Returns a uniformly-distributed random uint32_t generated using `rand()`.
+ * Note: may invoke `srand()`, which may not be thread-safe. Concurrent calls to
+ * `_mongoc_simple_rand_*()` functions, however, is thread-safe. */
+uint32_t
+_mongoc_simple_rand_uint32_t (void);
+
+/* Returns a uniformly-distributed random uint64_t generated using `rand()`.
+ * Note: may invoke `srand()`, which may not be thread-safe. Concurrent calls to
+ * `_mongoc_simple_rand_*()` functions, however, is thread-safe. */
+uint64_t
+_mongoc_simple_rand_uint64_t (void);
+
+/* Returns a uniformly-distributed random size_t generated using `rand()`.
+ * Note: may invoke `srand()`, which may not be thread-safe. Concurrent calls to
+ * `_mongoc_simple_rand_*()` functions, however, is thread-safe. */
+size_t
+_mongoc_simple_rand_size_t (void);
+
+/* Returns a uniformly-distributed random integer in the range [min, max].
+ *
+ * The size of the range [min, max] must not equal the size of the representable
+ * range of uint32_t (`min == 0 && max == UINT32_MAX` must not be true).
+ *
+ * The generator `rand` must return a random integer uniformly distributed in
+ * the full range of representable values of uint32_t.
+ */
+uint32_t
+_mongoc_rand_uint32_t (uint32_t min, uint32_t max, uint32_t (*rand) (void));
+
+/* Returns a uniformly-distributed random integer in the range [min, max].
+ *
+ * The size of the range [min, max] must not equal the size of the representable
+ * range of uint64_t (`min == 0 && max == UINT64_MAX` must not be true).
+ *
+ * The generator `rand` must return a random integer uniformly distributed in
+ * the full range of representable values of uint64_t.
+ */
+uint64_t
+_mongoc_rand_uint64_t (uint64_t min, uint64_t max, uint64_t (*rand) (void));
+
+/* Returns a uniformly-distributed random integer in the range [min, max].
+ *
+ * The size of the range [min, max] must not equal the size of the representable
+ * range of size_t (`min == 0 && max == SIZE_MAX` must not be true).
+ *
+ * The generator `rand` must return a random integer uniformly distributed in
+ * the full range of representable values of size_t.
+ */
+size_t
+_mongoc_rand_size_t (size_t min, size_t max, size_t (*rand) (void));
+
+BSON_END_DECLS
+
+#endif /* MONGOC_UTIL_PRIVATE_H */
diff --git a/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-util.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-util.c
new file mode 100644
index 00000000..e68678df
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-util.c
@@ -0,0 +1,865 @@
+/*
+ * Copyright 2013 MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifdef _WIN32
+#define _CRT_RAND_S
+#endif
+
+#include <string.h>
+
+#include "bson/bson.h"
+
+#include "common-md5-private.h"
+#include "common-thread-private.h"
+#include "mongoc-rand-private.h"
+#include "mongoc-util-private.h"
+#include "mongoc-client.h"
+#include "mongoc-client-session-private.h"
+#include "mongoc-trace-private.h"
+
+const bson_validate_flags_t _mongoc_default_insert_vflags =
+ BSON_VALIDATE_UTF8 | BSON_VALIDATE_UTF8_ALLOW_NULL |
+ BSON_VALIDATE_EMPTY_KEYS;
+
+const bson_validate_flags_t _mongoc_default_replace_vflags =
+ BSON_VALIDATE_UTF8 | BSON_VALIDATE_UTF8_ALLOW_NULL |
+ BSON_VALIDATE_EMPTY_KEYS;
+
+const bson_validate_flags_t _mongoc_default_update_vflags =
+ BSON_VALIDATE_UTF8 | BSON_VALIDATE_UTF8_ALLOW_NULL |
+ BSON_VALIDATE_EMPTY_KEYS;
+
+int
+_mongoc_rand_simple (unsigned int *seed)
+{
+#ifdef _WIN32
+ /* ignore the seed */
+ unsigned int ret = 0;
+ errno_t err;
+
+ err = rand_s (&ret);
+ if (0 != err) {
+ MONGOC_ERROR ("rand_s failed: %s", strerror (err));
+ }
+
+ return (int) ret;
+#else
+ return rand_r (seed);
+#endif
+}
+
+
+char *
+_mongoc_hex_md5 (const char *input)
+{
+ uint8_t digest[16];
+ bson_md5_t md5;
+ char digest_str[33];
+ int i;
+
+ COMMON_PREFIX (_bson_md5_init (&md5));
+ COMMON_PREFIX (_bson_md5_append (
+ &md5, (const uint8_t *) input, (uint32_t) strlen (input)));
+ COMMON_PREFIX (_bson_md5_finish (&md5, digest));
+
+ for (i = 0; i < sizeof digest; i++) {
+ bson_snprintf (&digest_str[i * 2], 3, "%02x", digest[i]);
+ }
+ digest_str[sizeof digest_str - 1] = '\0';
+
+ return bson_strdup (digest_str);
+}
+
+
+void
+_mongoc_usleep (int64_t usec)
+{
+#ifdef _WIN32
+ LARGE_INTEGER ft;
+ HANDLE timer;
+
+ BSON_ASSERT (usec >= 0);
+
+ ft.QuadPart = -(10 * usec);
+ timer = CreateWaitableTimer (NULL, true, NULL);
+ SetWaitableTimer (timer, &ft, 0, NULL, NULL, 0);
+ WaitForSingleObject (timer, INFINITE);
+ CloseHandle (timer);
+#else
+ BSON_ASSERT (usec >= 0);
+ usleep ((useconds_t) usec);
+#endif
+}
+
+int64_t
+_mongoc_get_real_time_ms (void)
+{
+ struct timeval tv;
+ const bool rc = bson_gettimeofday (&tv);
+ if (rc != 0) {
+ return -1;
+ }
+ return tv.tv_sec * (int64_t) 1000 + tv.tv_usec / (int64_t) 1000;
+}
+
+
+const char *
+_mongoc_get_command_name (const bson_t *command)
+{
+ bson_iter_t iter;
+ const char *name;
+ bson_iter_t child;
+ const char *wrapper_name = NULL;
+
+ BSON_ASSERT (command);
+
+ if (!bson_iter_init (&iter, command) || !bson_iter_next (&iter)) {
+ return NULL;
+ }
+
+ name = bson_iter_key (&iter);
+
+ /* wrapped in "$query" or "query"?
+ *
+ * {$query: {count: "collection"}, $readPreference: {...}}
+ */
+ if (name[0] == '$') {
+ wrapper_name = "$query";
+ } else if (!strcmp (name, "query")) {
+ wrapper_name = "query";
+ }
+
+ if (wrapper_name && bson_iter_init_find (&iter, command, wrapper_name) &&
+ BSON_ITER_HOLDS_DOCUMENT (&iter) && bson_iter_recurse (&iter, &child) &&
+ bson_iter_next (&child)) {
+ name = bson_iter_key (&child);
+ }
+
+ return name;
+}
+
+
+const char *
+_mongoc_get_documents_field_name (const char *command_name)
+{
+ if (!strcmp (command_name, "insert")) {
+ return "documents";
+ }
+
+ if (!strcmp (command_name, "update")) {
+ return "updates";
+ }
+
+ if (!strcmp (command_name, "delete")) {
+ return "deletes";
+ }
+
+ return NULL;
+}
+
+bool
+_mongoc_lookup_bool (const bson_t *bson, const char *key, bool default_value)
+{
+ bson_iter_t iter;
+ bson_iter_t child;
+
+ if (!bson) {
+ return default_value;
+ }
+
+ BSON_ASSERT (bson_iter_init (&iter, bson));
+ if (!bson_iter_find_descendant (&iter, key, &child)) {
+ return default_value;
+ }
+
+ return bson_iter_as_bool (&child);
+}
+
+char *
+_mongoc_get_db_name (const char *ns)
+{
+ size_t dblen;
+ const char *dot;
+
+ BSON_ASSERT (ns);
+
+ dot = strstr (ns, ".");
+
+ if (dot) {
+ dblen = dot - ns;
+ return bson_strndup (ns, dblen);
+ } else {
+ return bson_strdup (ns);
+ }
+}
+
+void
+_mongoc_bson_init_if_set (bson_t *bson)
+{
+ if (bson) {
+ bson_init (bson);
+ }
+}
+
+const char *
+_mongoc_bson_type_to_str (bson_type_t t)
+{
+ switch (t) {
+ case BSON_TYPE_EOD:
+ return "EOD";
+ case BSON_TYPE_DOUBLE:
+ return "DOUBLE";
+ case BSON_TYPE_UTF8:
+ return "UTF8";
+ case BSON_TYPE_DOCUMENT:
+ return "DOCUMENT";
+ case BSON_TYPE_ARRAY:
+ return "ARRAY";
+ case BSON_TYPE_BINARY:
+ return "BINARY";
+ case BSON_TYPE_UNDEFINED:
+ return "UNDEFINED";
+ case BSON_TYPE_OID:
+ return "OID";
+ case BSON_TYPE_BOOL:
+ return "BOOL";
+ case BSON_TYPE_DATE_TIME:
+ return "DATE_TIME";
+ case BSON_TYPE_NULL:
+ return "NULL";
+ case BSON_TYPE_REGEX:
+ return "REGEX";
+ case BSON_TYPE_DBPOINTER:
+ return "DBPOINTER";
+ case BSON_TYPE_CODE:
+ return "CODE";
+ case BSON_TYPE_SYMBOL:
+ return "SYMBOL";
+ case BSON_TYPE_CODEWSCOPE:
+ return "CODEWSCOPE";
+ case BSON_TYPE_INT32:
+ return "INT32";
+ case BSON_TYPE_TIMESTAMP:
+ return "TIMESTAMP";
+ case BSON_TYPE_INT64:
+ return "INT64";
+ case BSON_TYPE_MAXKEY:
+ return "MAXKEY";
+ case BSON_TYPE_MINKEY:
+ return "MINKEY";
+ case BSON_TYPE_DECIMAL128:
+ return "DECIMAL128";
+ default:
+ return "Unknown";
+ }
+}
+
+
+/* Refer to:
+ * https://github.com/mongodb/specifications/blob/master/source/wireversion-featurelist.rst
+ * and:
+ * https://github.com/mongodb/mongo/blob/master/src/mongo/db/wire_version.h#L57
+ */
+const char *
+_mongoc_wire_version_to_server_version (int32_t version)
+{
+ switch (version) {
+ case 1:
+ case 2:
+ return "2.6";
+ case 3:
+ return "3.0";
+ case 4:
+ return "3.2";
+ case 5:
+ return "3.4";
+ case 6:
+ return "3.6";
+ case 7:
+ return "4.0";
+ case 8:
+ return "4.2";
+ case 9:
+ return "4.4";
+ case 10:
+ return "4.7";
+ case 11:
+ return "4.8";
+ case 12:
+ return "4.9";
+ case 13:
+ return "5.0";
+ case 14:
+ return "5.1";
+ case 15:
+ return "5.2";
+ default:
+ return "Unknown";
+ }
+}
+
+
+/* Get "serverId" from opts. Sets *server_id to the serverId from "opts" or 0
+ * if absent. On error, fills out *error with domain and code and return false.
+ */
+bool
+_mongoc_get_server_id_from_opts (const bson_t *opts,
+ mongoc_error_domain_t domain,
+ mongoc_error_code_t code,
+ uint32_t *server_id,
+ bson_error_t *error)
+{
+ bson_iter_t iter;
+
+ ENTRY;
+
+ BSON_ASSERT (server_id);
+
+ *server_id = 0;
+
+ if (!opts || !bson_iter_init_find (&iter, opts, "serverId")) {
+ RETURN (true);
+ }
+
+ if (!BSON_ITER_HOLDS_INT (&iter)) {
+ bson_set_error (
+ error, domain, code, "The serverId option must be an integer");
+ RETURN (false);
+ }
+
+ if (bson_iter_as_int64 (&iter) <= 0) {
+ bson_set_error (error, domain, code, "The serverId option must be >= 1");
+ RETURN (false);
+ }
+
+ *server_id = (uint32_t) bson_iter_as_int64 (&iter);
+
+ RETURN (true);
+}
+
+
+bool
+_mongoc_validate_new_document (const bson_t *doc,
+ bson_validate_flags_t vflags,
+ bson_error_t *error)
+{
+ bson_error_t validate_err;
+
+ if (vflags == BSON_VALIDATE_NONE) {
+ return true;
+ }
+
+ if (!bson_validate_with_error (doc, vflags, &validate_err)) {
+ bson_set_error (error,
+ MONGOC_ERROR_COMMAND,
+ MONGOC_ERROR_COMMAND_INVALID_ARG,
+ "invalid document for insert: %s",
+ validate_err.message);
+ return false;
+ }
+
+ return true;
+}
+
+
+bool
+_mongoc_validate_replace (const bson_t *doc,
+ bson_validate_flags_t vflags,
+ bson_error_t *error)
+{
+ bson_error_t validate_err;
+ bson_iter_t iter;
+ const char *key;
+
+ if (vflags == BSON_VALIDATE_NONE) {
+ return true;
+ }
+
+ if (!bson_validate_with_error (doc, vflags, &validate_err)) {
+ bson_set_error (error,
+ MONGOC_ERROR_COMMAND,
+ MONGOC_ERROR_COMMAND_INVALID_ARG,
+ "invalid argument for replace: %s",
+ validate_err.message);
+ return false;
+ }
+
+ if (!bson_iter_init (&iter, doc)) {
+ bson_set_error (error,
+ MONGOC_ERROR_BSON,
+ MONGOC_ERROR_BSON_INVALID,
+ "replace document is corrupt");
+ return false;
+ }
+
+ while (bson_iter_next (&iter)) {
+ key = bson_iter_key (&iter);
+ if (key[0] == '$') {
+ bson_set_error (error,
+ MONGOC_ERROR_COMMAND,
+ MONGOC_ERROR_COMMAND_INVALID_ARG,
+ "Invalid key '%s': replace prohibits $ operators",
+ key);
+
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+bool
+_mongoc_validate_update (const bson_t *update,
+ bson_validate_flags_t vflags,
+ bson_error_t *error)
+{
+ bson_error_t validate_err;
+ bson_iter_t iter;
+ const char *key;
+
+ if (vflags == BSON_VALIDATE_NONE) {
+ return true;
+ }
+
+ if (!bson_validate_with_error (update, vflags, &validate_err)) {
+ bson_set_error (error,
+ MONGOC_ERROR_COMMAND,
+ MONGOC_ERROR_COMMAND_INVALID_ARG,
+ "invalid argument for update: %s",
+ validate_err.message);
+ return false;
+ }
+
+ if (_mongoc_document_is_pipeline (update)) {
+ return true;
+ }
+
+ if (!bson_iter_init (&iter, update)) {
+ bson_set_error (error,
+ MONGOC_ERROR_BSON,
+ MONGOC_ERROR_BSON_INVALID,
+ "update document is corrupt");
+ return false;
+ }
+
+ while (bson_iter_next (&iter)) {
+ key = bson_iter_key (&iter);
+ if (key[0] != '$') {
+ bson_set_error (error,
+ MONGOC_ERROR_COMMAND,
+ MONGOC_ERROR_COMMAND_INVALID_ARG,
+ "Invalid key '%s': update only works with $ operators"
+ " and pipelines",
+ key);
+
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void
+mongoc_lowercase (const char *src, char *buf /* OUT */)
+{
+ for (; *src; ++src, ++buf) {
+ /* UTF8 non-ascii characters have a 1 at the leftmost bit. If this is the
+ * case, just copy */
+ if ((*src & (0x1 << 7)) == 0) {
+ *buf = (char) tolower (*src);
+ } else {
+ *buf = *src;
+ }
+ }
+}
+
+bool
+mongoc_parse_port (uint16_t *port, const char *str)
+{
+ unsigned long ul_port;
+
+ ul_port = strtoul (str, NULL, 10);
+
+ if (ul_port == 0 || ul_port > UINT16_MAX) {
+ /* Parse error or port number out of range. mongod prohibits port 0. */
+ return false;
+ }
+
+ *port = (uint16_t) ul_port;
+ return true;
+}
+
+
+/*--------------------------------------------------------------------------
+ *
+ * _mongoc_bson_array_add_label --
+ *
+ * Append an error label like "TransientTransactionError" to a BSON
+ * array iff the array does not already contain it.
+ *
+ * Side effects:
+ * Aborts if the array is invalid or contains non-string elements.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+void
+_mongoc_bson_array_add_label (bson_t *bson, const char *label)
+{
+ bson_iter_t iter;
+ char buf[16];
+ uint32_t i = 0;
+ const char *key;
+
+ BSON_ASSERT (bson_iter_init (&iter, bson));
+ while (bson_iter_next (&iter)) {
+ if (!strcmp (bson_iter_utf8 (&iter, NULL), label)) {
+ /* already included once */
+ return;
+ }
+
+ i++;
+ }
+
+ bson_uint32_to_string (i, &key, buf, sizeof buf);
+ BSON_APPEND_UTF8 (bson, key, label);
+}
+
+
+/*--------------------------------------------------------------------------
+ *
+ * _mongoc_bson_array_copy_labels_to --
+ *
+ * Copy error labels like "TransientTransactionError" from a server
+ * reply to a BSON array iff the array does not already contain it.
+ *
+ * Side effects:
+ * Aborts if @dst is invalid or contains non-string elements.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+void
+_mongoc_bson_array_copy_labels_to (const bson_t *reply, bson_t *dst)
+{
+ bson_iter_t iter;
+ bson_iter_t label;
+
+ if (bson_iter_init_find (&iter, reply, "errorLabels")) {
+ BSON_ASSERT (bson_iter_recurse (&iter, &label));
+ while (bson_iter_next (&label)) {
+ if (BSON_ITER_HOLDS_UTF8 (&label)) {
+ _mongoc_bson_array_add_label (dst, bson_iter_utf8 (&label, NULL));
+ }
+ }
+ }
+}
+
+
+/*--------------------------------------------------------------------------
+ *
+ * _mongoc_bson_init_with_transient_txn_error --
+ *
+ * If @reply is not NULL, initialize it. If @cs is not NULL and in a
+ * transaction, add errorLabels: ["TransientTransactionError"] to @cs.
+ *
+ * Transactions Spec: TransientTransactionError includes "server
+ * selection error encountered running any command besides
+ * commitTransaction in a transaction. ...in the case of network errors
+ * or server selection errors where the client receives no server reply,
+ * the client adds the label."
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+void
+_mongoc_bson_init_with_transient_txn_error (const mongoc_client_session_t *cs,
+ bson_t *reply)
+{
+ bson_t labels;
+
+ if (!reply) {
+ return;
+ }
+
+ bson_init (reply);
+
+ if (_mongoc_client_session_in_txn (cs)) {
+ BSON_APPEND_ARRAY_BEGIN (reply, "errorLabels", &labels);
+ BSON_APPEND_UTF8 (&labels, "0", TRANSIENT_TXN_ERR);
+ bson_append_array_end (reply, &labels);
+ }
+}
+
+bool
+_mongoc_document_is_pipeline (const bson_t *document)
+{
+ bson_iter_t iter;
+ bson_iter_t child;
+ const char *key;
+ int i = 0;
+ char *i_str;
+
+ if (!bson_iter_init (&iter, document)) {
+ return false;
+ }
+
+ while (bson_iter_next (&iter)) {
+ key = bson_iter_key (&iter);
+ i_str = bson_strdup_printf ("%d", i++);
+
+ if (strcmp (key, i_str)) {
+ bson_free (i_str);
+ return false;
+ }
+
+ bson_free (i_str);
+
+ if (BSON_ITER_HOLDS_DOCUMENT (&iter)) {
+ if (!bson_iter_recurse (&iter, &child)) {
+ return false;
+ }
+ if (!bson_iter_next (&child)) {
+ return false;
+ }
+ key = bson_iter_key (&child);
+ if (key[0] != '$') {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+
+ /* should return false when the document is empty */
+ return i != 0;
+}
+
+char *
+_mongoc_getenv (const char *name)
+{
+#ifdef _MSC_VER
+ char buf[2048];
+ size_t buflen;
+
+ if ((0 == getenv_s (&buflen, buf, sizeof buf, name)) && buflen) {
+ return bson_strdup (buf);
+ } else {
+ return NULL;
+ }
+#else
+
+ if (getenv (name) && strlen (getenv (name))) {
+ return bson_strdup (getenv (name));
+ } else {
+ return NULL;
+ }
+
+#endif
+}
+
+/* Nearly Divisionless (Algorithm 5): https://arxiv.org/abs/1805.10941 */
+static uint32_t
+_mongoc_rand_nduid32 (uint32_t s, uint32_t (*rand32) (void))
+{
+ const uint64_t limit = UINT32_MAX; /* 2^L */
+ uint64_t x, m, l;
+
+ x = rand32 ();
+ m = x * s;
+ l = m % limit;
+
+ if (l < s) {
+ const uint64_t t = (limit - s) % s;
+
+ while (l < t) {
+ x = rand32 ();
+ m = x * s;
+ l = m % limit;
+ }
+ }
+
+ return (uint32_t) (m / limit);
+}
+
+/* Java Algorithm (Algorithm 4): https://arxiv.org/abs/1805.10941
+ * The 64-bit version of the nearly divisionless algorithm requires 128-bit
+ * integer arithmetic. Instead of trying to deal with cross-platform support for
+ * `__int128`, fallback to using the Java algorithm for 64-bit instead. */
+static uint64_t
+_mongoc_rand_java64 (uint64_t s, uint64_t (*rand64) (void))
+{
+ const uint64_t limit = UINT64_MAX; /* 2^L */
+ uint64_t x, r;
+
+ x = rand64 ();
+ r = x % s;
+
+ while ((x - r) > (limit - s)) {
+ x = rand64 ();
+ r = x % s;
+ }
+
+ return r;
+}
+
+#if defined(MONGOC_ENABLE_CRYPTO)
+
+uint32_t
+_mongoc_crypto_rand_uint32_t (void)
+{
+ uint32_t res;
+
+ (void) _mongoc_rand_bytes ((uint8_t *) &res, sizeof (res));
+
+ return res;
+}
+
+uint64_t
+_mongoc_crypto_rand_uint64_t (void)
+{
+ uint64_t res;
+
+ (void) _mongoc_rand_bytes ((uint8_t *) &res, sizeof (res));
+
+ return res;
+}
+
+size_t
+_mongoc_crypto_rand_size_t (void)
+{
+ size_t res;
+
+ (void) _mongoc_rand_bytes ((uint8_t *) &res, sizeof (res));
+
+ return res;
+}
+
+#endif /* defined(MONGOC_ENABLE_CRYPTO) */
+
+static BSON_ONCE_FUN (_mongoc_simple_rand_init)
+{
+ struct timeval tv;
+ unsigned int seed = 0;
+
+ bson_gettimeofday (&tv);
+
+ seed ^= (unsigned int) tv.tv_sec;
+ seed ^= (unsigned int) tv.tv_usec;
+
+ srand (seed);
+
+ BSON_ONCE_RETURN;
+}
+
+static bson_once_t _mongoc_simple_rand_init_once = BSON_ONCE_INIT;
+
+uint32_t
+_mongoc_simple_rand_uint32_t (void)
+{
+ bson_once (&_mongoc_simple_rand_init_once, _mongoc_simple_rand_init);
+
+ /* Ensure *all* bits are random, as RAND_MAX is only required to be at least
+ * 32767 (2^15). */
+ return (((uint32_t) rand () & 0x7FFFu) << 0u) |
+ (((uint32_t) rand () & 0x7FFFu) << 15u) |
+ (((uint32_t) rand () & 0x0003u) << 30u);
+}
+
+uint64_t
+_mongoc_simple_rand_uint64_t (void)
+{
+ bson_once (&_mongoc_simple_rand_init_once, _mongoc_simple_rand_init);
+
+ /* Ensure *all* bits are random, as RAND_MAX is only required to be at least
+ * 32767 (2^15). */
+ return (((uint64_t) rand () & 0x7FFFu) << 0u) |
+ (((uint64_t) rand () & 0x7FFFu) << 15u) |
+ (((uint64_t) rand () & 0x7FFFu) << 30u) |
+ (((uint64_t) rand () & 0x7FFFu) << 45u) |
+ (((uint64_t) rand () & 0x0003u) << 60u);
+}
+
+uint32_t
+_mongoc_rand_uint32_t (uint32_t min, uint32_t max, uint32_t (*rand) (void))
+{
+ BSON_ASSERT (min <= max);
+ BSON_ASSERT (min != 0u || max != UINT32_MAX);
+
+ return _mongoc_rand_nduid32 (max - min + 1u, rand) + min;
+}
+
+uint64_t
+_mongoc_rand_uint64_t (uint64_t min, uint64_t max, uint64_t (*rand) (void))
+{
+ BSON_ASSERT (min <= max);
+ BSON_ASSERT (min != 0u || max != UINT64_MAX);
+
+ return _mongoc_rand_java64 (max - min + 1u, rand) + min;
+}
+
+#if SIZE_MAX == UINT64_MAX
+
+BSON_STATIC_ASSERT2 (_mongoc_simple_rand_size_t,
+ sizeof (size_t) == sizeof (uint64_t));
+
+size_t
+_mongoc_simple_rand_size_t (void)
+{
+ return (size_t) _mongoc_simple_rand_uint64_t ();
+}
+
+size_t
+_mongoc_rand_size_t (size_t min, size_t max, size_t (*rand) (void))
+{
+ BSON_ASSERT (min <= max);
+ BSON_ASSERT (min != 0u || max != UINT64_MAX);
+
+ return _mongoc_rand_java64 (max - min + 1u, (uint64_t (*) (void)) rand) +
+ min;
+}
+
+#elif SIZE_MAX == UINT32_MAX
+
+BSON_STATIC_ASSERT2 (_mongoc_simple_rand_size_t,
+ sizeof (size_t) == sizeof (uint32_t));
+
+size_t
+_mongoc_simple_rand_size_t (void)
+{
+ return (size_t) _mongoc_simple_rand_uint32_t ();
+}
+
+size_t
+_mongoc_rand_size_t (size_t min, size_t max, size_t (*rand) (void))
+{
+ BSON_ASSERT (min <= max);
+ BSON_ASSERT (min != 0u || max != UINT32_MAX);
+
+ return _mongoc_rand_nduid32 (max - min + 1u, (uint32_t (*) (void)) rand) +
+ min;
+}
+
+#else
+
+#error \
+ "Implementation of _mongoc_simple_rand_size_t() requires size_t be exactly 32-bit or 64-bit"
+
+#endif
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-version-functions.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-version-functions.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-version-functions.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-version-functions.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-version-functions.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-version-functions.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-version-functions.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-version-functions.h
diff --git a/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-version.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-version.h
new file mode 100644
index 00000000..f23dece8
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-version.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2013 MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#if !defined (MONGOC_INSIDE) && !defined (MONGOC_COMPILATION)
+#error "Only <mongoc/mongoc.h> can be included directly."
+#endif
+
+
+#ifndef MONGOC_VERSION_H
+#define MONGOC_VERSION_H
+
+
+/**
+ * MONGOC_MAJOR_VERSION:
+ *
+ * MONGOC major version component (e.g. 1 if %MONGOC_VERSION is 1.2.3)
+ */
+#define MONGOC_MAJOR_VERSION (1)
+
+
+/**
+ * MONGOC_MINOR_VERSION:
+ *
+ * MONGOC minor version component (e.g. 2 if %MONGOC_VERSION is 1.2.3)
+ */
+#define MONGOC_MINOR_VERSION (21)
+
+
+/**
+ * MONGOC_MICRO_VERSION:
+ *
+ * MONGOC micro version component (e.g. 3 if %MONGOC_VERSION is 1.2.3)
+ */
+#define MONGOC_MICRO_VERSION (1)
+
+
+/**
+ * MONGOC_PRERELEASE_VERSION:
+ *
+ * MONGOC prerelease version component (e.g. pre if %MONGOC_VERSION is 1.2.3-pre)
+ */
+#define MONGOC_PRERELEASE_VERSION ()
+
+
+/**
+ * MONGOC_VERSION:
+ *
+ * MONGOC version.
+ */
+#define MONGOC_VERSION (1.21.1)
+
+
+/**
+ * MONGOC_VERSION_S:
+ *
+ * MONGOC version, encoded as a string, useful for printing and
+ * concatenation.
+ */
+#define MONGOC_VERSION_S "1.21.1"
+
+
+/**
+ * MONGOC_VERSION_HEX:
+ *
+ * MONGOC version, encoded as an hexadecimal number, useful for
+ * integer comparisons.
+ */
+#define MONGOC_VERSION_HEX (MONGOC_MAJOR_VERSION << 24 | \
+ MONGOC_MINOR_VERSION << 16 | \
+ MONGOC_MICRO_VERSION << 8)
+
+
+/**
+ * MONGOC_CHECK_VERSION:
+ * @major: required major version
+ * @minor: required minor version
+ * @micro: required micro version
+ *
+ * Compile-time version checking. Evaluates to %TRUE if the version
+ * of MONGOC is greater than the required one.
+ */
+#define MONGOC_CHECK_VERSION(major,minor,micro) \
+ (MONGOC_MAJOR_VERSION > (major) || \
+ (MONGOC_MAJOR_VERSION == (major) && MONGOC_MINOR_VERSION > (minor)) || \
+ (MONGOC_MAJOR_VERSION == (major) && MONGOC_MINOR_VERSION == (minor) && \
+ MONGOC_MICRO_VERSION >= (micro)))
+
+#endif /* MONGOC_VERSION_H */
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-version.h.in b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-version.h.in
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-version.h.in
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-version.h.in
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-write-command-legacy-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-write-command-legacy-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-write-command-legacy-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-write-command-legacy-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-write-command-legacy.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-write-command-legacy.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-write-command-legacy.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-write-command-legacy.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-write-command-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-write-command-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-write-command-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-write-command-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-write-command.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-write-command.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-write-command.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-write-command.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-write-concern-private.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-write-concern-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-write-concern-private.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-write-concern-private.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-write-concern.c b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-write-concern.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-write-concern.c
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-write-concern.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-write-concern.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-write-concern.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-write-concern.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc-write-concern.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/mongoc.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/op-compressed.def b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/op-compressed.def
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/op-compressed.def
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/op-compressed.def
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/op-delete.def b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/op-delete.def
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/op-delete.def
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/op-delete.def
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/op-get-more.def b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/op-get-more.def
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/op-get-more.def
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/op-get-more.def
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/op-header.def b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/op-header.def
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/op-header.def
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/op-header.def
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/op-insert.def b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/op-insert.def
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/op-insert.def
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/op-insert.def
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/op-kill-cursors.def b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/op-kill-cursors.def
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/op-kill-cursors.def
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/op-kill-cursors.def
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/op-msg.def b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/op-msg.def
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/op-msg.def
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/op-msg.def
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/op-query.def b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/op-query.def
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/op-query.def
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/op-query.def
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/op-reply-header.def b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/op-reply-header.def
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/op-reply-header.def
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/op-reply-header.def
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/op-reply.def b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/op-reply.def
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/op-reply.def
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/op-reply.def
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/op-update.def b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/op-update.def
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/op-update.def
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/op-update.def
diff --git a/mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/utlist.h b/mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/utlist.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/libmongoc/src/mongoc/utlist.h
rename to mongodb-1.13.0/src/libmongoc/src/libmongoc/src/mongoc/utlist.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/zlib-1.2.11/adler32.c b/mongodb-1.13.0/src/libmongoc/src/zlib-1.2.11/adler32.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/zlib-1.2.11/adler32.c
rename to mongodb-1.13.0/src/libmongoc/src/zlib-1.2.11/adler32.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/zlib-1.2.11/compress.c b/mongodb-1.13.0/src/libmongoc/src/zlib-1.2.11/compress.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/zlib-1.2.11/compress.c
rename to mongodb-1.13.0/src/libmongoc/src/zlib-1.2.11/compress.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/zlib-1.2.11/crc32.c b/mongodb-1.13.0/src/libmongoc/src/zlib-1.2.11/crc32.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/zlib-1.2.11/crc32.c
rename to mongodb-1.13.0/src/libmongoc/src/zlib-1.2.11/crc32.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/zlib-1.2.11/crc32.h b/mongodb-1.13.0/src/libmongoc/src/zlib-1.2.11/crc32.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/zlib-1.2.11/crc32.h
rename to mongodb-1.13.0/src/libmongoc/src/zlib-1.2.11/crc32.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/zlib-1.2.11/deflate.c b/mongodb-1.13.0/src/libmongoc/src/zlib-1.2.11/deflate.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/zlib-1.2.11/deflate.c
rename to mongodb-1.13.0/src/libmongoc/src/zlib-1.2.11/deflate.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/zlib-1.2.11/deflate.h b/mongodb-1.13.0/src/libmongoc/src/zlib-1.2.11/deflate.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/zlib-1.2.11/deflate.h
rename to mongodb-1.13.0/src/libmongoc/src/zlib-1.2.11/deflate.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/zlib-1.2.11/gzclose.c b/mongodb-1.13.0/src/libmongoc/src/zlib-1.2.11/gzclose.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/zlib-1.2.11/gzclose.c
rename to mongodb-1.13.0/src/libmongoc/src/zlib-1.2.11/gzclose.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/zlib-1.2.11/gzguts.h b/mongodb-1.13.0/src/libmongoc/src/zlib-1.2.11/gzguts.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/zlib-1.2.11/gzguts.h
rename to mongodb-1.13.0/src/libmongoc/src/zlib-1.2.11/gzguts.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/zlib-1.2.11/gzlib.c b/mongodb-1.13.0/src/libmongoc/src/zlib-1.2.11/gzlib.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/zlib-1.2.11/gzlib.c
rename to mongodb-1.13.0/src/libmongoc/src/zlib-1.2.11/gzlib.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/zlib-1.2.11/gzread.c b/mongodb-1.13.0/src/libmongoc/src/zlib-1.2.11/gzread.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/zlib-1.2.11/gzread.c
rename to mongodb-1.13.0/src/libmongoc/src/zlib-1.2.11/gzread.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/zlib-1.2.11/gzwrite.c b/mongodb-1.13.0/src/libmongoc/src/zlib-1.2.11/gzwrite.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/zlib-1.2.11/gzwrite.c
rename to mongodb-1.13.0/src/libmongoc/src/zlib-1.2.11/gzwrite.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/zlib-1.2.11/infback.c b/mongodb-1.13.0/src/libmongoc/src/zlib-1.2.11/infback.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/zlib-1.2.11/infback.c
rename to mongodb-1.13.0/src/libmongoc/src/zlib-1.2.11/infback.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/zlib-1.2.11/inffast.c b/mongodb-1.13.0/src/libmongoc/src/zlib-1.2.11/inffast.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/zlib-1.2.11/inffast.c
rename to mongodb-1.13.0/src/libmongoc/src/zlib-1.2.11/inffast.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/zlib-1.2.11/inffast.h b/mongodb-1.13.0/src/libmongoc/src/zlib-1.2.11/inffast.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/zlib-1.2.11/inffast.h
rename to mongodb-1.13.0/src/libmongoc/src/zlib-1.2.11/inffast.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/zlib-1.2.11/inffixed.h b/mongodb-1.13.0/src/libmongoc/src/zlib-1.2.11/inffixed.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/zlib-1.2.11/inffixed.h
rename to mongodb-1.13.0/src/libmongoc/src/zlib-1.2.11/inffixed.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/zlib-1.2.11/inflate.c b/mongodb-1.13.0/src/libmongoc/src/zlib-1.2.11/inflate.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/zlib-1.2.11/inflate.c
rename to mongodb-1.13.0/src/libmongoc/src/zlib-1.2.11/inflate.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/zlib-1.2.11/inflate.h b/mongodb-1.13.0/src/libmongoc/src/zlib-1.2.11/inflate.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/zlib-1.2.11/inflate.h
rename to mongodb-1.13.0/src/libmongoc/src/zlib-1.2.11/inflate.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/zlib-1.2.11/inftrees.c b/mongodb-1.13.0/src/libmongoc/src/zlib-1.2.11/inftrees.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/zlib-1.2.11/inftrees.c
rename to mongodb-1.13.0/src/libmongoc/src/zlib-1.2.11/inftrees.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/zlib-1.2.11/inftrees.h b/mongodb-1.13.0/src/libmongoc/src/zlib-1.2.11/inftrees.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/zlib-1.2.11/inftrees.h
rename to mongodb-1.13.0/src/libmongoc/src/zlib-1.2.11/inftrees.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/zlib-1.2.11/trees.c b/mongodb-1.13.0/src/libmongoc/src/zlib-1.2.11/trees.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/zlib-1.2.11/trees.c
rename to mongodb-1.13.0/src/libmongoc/src/zlib-1.2.11/trees.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/zlib-1.2.11/trees.h b/mongodb-1.13.0/src/libmongoc/src/zlib-1.2.11/trees.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/zlib-1.2.11/trees.h
rename to mongodb-1.13.0/src/libmongoc/src/zlib-1.2.11/trees.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/zlib-1.2.11/uncompr.c b/mongodb-1.13.0/src/libmongoc/src/zlib-1.2.11/uncompr.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/zlib-1.2.11/uncompr.c
rename to mongodb-1.13.0/src/libmongoc/src/zlib-1.2.11/uncompr.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/zlib-1.2.11/zconf.h.in b/mongodb-1.13.0/src/libmongoc/src/zlib-1.2.11/zconf.h
similarity index 100%
copy from mongodb-1.12.0/src/libmongoc/src/zlib-1.2.11/zconf.h.in
copy to mongodb-1.13.0/src/libmongoc/src/zlib-1.2.11/zconf.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/zlib-1.2.11/zconf.h.in b/mongodb-1.13.0/src/libmongoc/src/zlib-1.2.11/zconf.h.in
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/zlib-1.2.11/zconf.h.in
rename to mongodb-1.13.0/src/libmongoc/src/zlib-1.2.11/zconf.h.in
diff --git a/mongodb-1.12.0/src/libmongoc/src/zlib-1.2.11/zlib.h b/mongodb-1.13.0/src/libmongoc/src/zlib-1.2.11/zlib.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/zlib-1.2.11/zlib.h
rename to mongodb-1.13.0/src/libmongoc/src/zlib-1.2.11/zlib.h
diff --git a/mongodb-1.12.0/src/libmongoc/src/zlib-1.2.11/zutil.c b/mongodb-1.13.0/src/libmongoc/src/zlib-1.2.11/zutil.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/zlib-1.2.11/zutil.c
rename to mongodb-1.13.0/src/libmongoc/src/zlib-1.2.11/zutil.c
diff --git a/mongodb-1.12.0/src/libmongoc/src/zlib-1.2.11/zutil.h b/mongodb-1.13.0/src/libmongoc/src/zlib-1.2.11/zutil.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongoc/src/zlib-1.2.11/zutil.h
rename to mongodb-1.13.0/src/libmongoc/src/zlib-1.2.11/zutil.h
diff --git a/mongodb-1.12.0/src/libmongocrypt-compat/mongocrypt-export.h b/mongodb-1.13.0/src/libmongocrypt-compat/mongocrypt-export.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt-compat/mongocrypt-export.h
rename to mongodb-1.13.0/src/libmongocrypt-compat/mongocrypt-export.h
diff --git a/mongodb-1.12.0/src/libmongocrypt-compat/mongocrypt/mongocrypt.h b/mongodb-1.13.0/src/libmongocrypt-compat/mongocrypt/mongocrypt.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt-compat/mongocrypt/mongocrypt.h
rename to mongodb-1.13.0/src/libmongocrypt-compat/mongocrypt/mongocrypt.h
diff --git a/mongodb-1.12.0/src/libmongocrypt/kms-message/src/hexlify.c b/mongodb-1.13.0/src/libmongocrypt/kms-message/src/hexlify.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/kms-message/src/hexlify.c
rename to mongodb-1.13.0/src/libmongocrypt/kms-message/src/hexlify.c
diff --git a/mongodb-1.12.0/src/libmongocrypt/kms-message/src/hexlify.h b/mongodb-1.13.0/src/libmongocrypt/kms-message/src/hexlify.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/kms-message/src/hexlify.h
rename to mongodb-1.13.0/src/libmongocrypt/kms-message/src/hexlify.h
diff --git a/mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_azure_request.c b/mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_azure_request.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_azure_request.c
rename to mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_azure_request.c
diff --git a/mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_b64.c b/mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_b64.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_b64.c
rename to mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_b64.c
diff --git a/mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_caller_identity_request.c b/mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_caller_identity_request.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_caller_identity_request.c
rename to mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_caller_identity_request.c
diff --git a/mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_crypto.h b/mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_crypto.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_crypto.h
rename to mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_crypto.h
diff --git a/mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_crypto_apple.c b/mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_crypto_apple.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_crypto_apple.c
rename to mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_crypto_apple.c
diff --git a/mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_crypto_libcrypto.c b/mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_crypto_libcrypto.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_crypto_libcrypto.c
rename to mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_crypto_libcrypto.c
diff --git a/mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_crypto_none.c b/mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_crypto_none.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_crypto_none.c
rename to mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_crypto_none.c
diff --git a/mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_crypto_windows.c b/mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_crypto_windows.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_crypto_windows.c
rename to mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_crypto_windows.c
diff --git a/mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_decrypt_request.c b/mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_decrypt_request.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_decrypt_request.c
rename to mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_decrypt_request.c
diff --git a/mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_encrypt_request.c b/mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_encrypt_request.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_encrypt_request.c
rename to mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_encrypt_request.c
diff --git a/mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_endian_private.h b/mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_endian_private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_endian_private.h
rename to mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_endian_private.h
diff --git a/mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_gcp_request.c b/mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_gcp_request.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_gcp_request.c
rename to mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_gcp_request.c
diff --git a/mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_kmip_item_type_private.h b/mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_kmip_item_type_private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_kmip_item_type_private.h
rename to mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_kmip_item_type_private.h
diff --git a/mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_kmip_reader_writer.c b/mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_kmip_reader_writer.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_kmip_reader_writer.c
rename to mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_kmip_reader_writer.c
diff --git a/mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_kmip_reader_writer_private.h b/mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_kmip_reader_writer_private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_kmip_reader_writer_private.h
rename to mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_kmip_reader_writer_private.h
diff --git a/mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_kmip_request.c b/mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_kmip_request.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_kmip_request.c
rename to mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_kmip_request.c
diff --git a/mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_kmip_response.c b/mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_kmip_response.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_kmip_response.c
rename to mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_kmip_response.c
diff --git a/mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_kmip_response_parser.c b/mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_kmip_response_parser.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_kmip_response_parser.c
rename to mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_kmip_response_parser.c
diff --git a/mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_kmip_response_parser_private.h b/mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_kmip_response_parser_private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_kmip_response_parser_private.h
rename to mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_kmip_response_parser_private.h
diff --git a/mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_kmip_result_reason_private.h b/mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_kmip_result_reason_private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_kmip_result_reason_private.h
rename to mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_kmip_result_reason_private.h
diff --git a/mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_kmip_result_status_private.h b/mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_kmip_result_status_private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_kmip_result_status_private.h
rename to mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_kmip_result_status_private.h
diff --git a/mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_kmip_tag_type_private.h b/mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_kmip_tag_type_private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_kmip_tag_type_private.h
rename to mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_kmip_tag_type_private.h
diff --git a/mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_kv_list.c b/mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_kv_list.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_kv_list.c
rename to mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_kv_list.c
diff --git a/mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_kv_list.h b/mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_kv_list.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_kv_list.h
rename to mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_kv_list.h
diff --git a/mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_message.c b/mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_message.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_message.c
rename to mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_message.c
diff --git a/mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_message/kms_azure_request.h b/mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_message/kms_azure_request.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_message/kms_azure_request.h
rename to mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_message/kms_azure_request.h
diff --git a/mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_message/kms_b64.h b/mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_message/kms_b64.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_message/kms_b64.h
rename to mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_message/kms_b64.h
diff --git a/mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_message/kms_caller_identity_request.h b/mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_message/kms_caller_identity_request.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_message/kms_caller_identity_request.h
rename to mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_message/kms_caller_identity_request.h
diff --git a/mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_message/kms_decrypt_request.h b/mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_message/kms_decrypt_request.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_message/kms_decrypt_request.h
rename to mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_message/kms_decrypt_request.h
diff --git a/mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_message/kms_encrypt_request.h b/mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_message/kms_encrypt_request.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_message/kms_encrypt_request.h
rename to mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_message/kms_encrypt_request.h
diff --git a/mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_message/kms_gcp_request.h b/mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_message/kms_gcp_request.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_message/kms_gcp_request.h
rename to mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_message/kms_gcp_request.h
diff --git a/mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_message/kms_kmip_request.h b/mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_message/kms_kmip_request.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_message/kms_kmip_request.h
rename to mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_message/kms_kmip_request.h
diff --git a/mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_message/kms_kmip_response.h b/mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_message/kms_kmip_response.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_message/kms_kmip_response.h
rename to mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_message/kms_kmip_response.h
diff --git a/mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_message/kms_kmip_response_parser.h b/mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_message/kms_kmip_response_parser.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_message/kms_kmip_response_parser.h
rename to mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_message/kms_kmip_response_parser.h
diff --git a/mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_message/kms_message.h b/mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_message/kms_message.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_message/kms_message.h
rename to mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_message/kms_message.h
diff --git a/mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_message/kms_message_defines.h b/mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_message/kms_message_defines.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_message/kms_message_defines.h
rename to mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_message/kms_message_defines.h
diff --git a/mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_message/kms_request.h b/mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_message/kms_request.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_message/kms_request.h
rename to mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_message/kms_request.h
diff --git a/mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_message/kms_request_opt.h b/mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_message/kms_request_opt.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_message/kms_request_opt.h
rename to mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_message/kms_request_opt.h
diff --git a/mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_message/kms_response.h b/mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_message/kms_response.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_message/kms_response.h
rename to mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_message/kms_response.h
diff --git a/mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_message/kms_response_parser.h b/mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_message/kms_response_parser.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_message/kms_response_parser.h
rename to mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_message/kms_response_parser.h
diff --git a/mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_message_private.h b/mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_message_private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_message_private.h
rename to mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_message_private.h
diff --git a/mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_port.c b/mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_port.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_port.c
rename to mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_port.c
diff --git a/mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_port.h b/mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_port.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_port.h
rename to mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_port.h
diff --git a/mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_request.c b/mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_request.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_request.c
rename to mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_request.c
diff --git a/mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_request_opt.c b/mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_request_opt.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_request_opt.c
rename to mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_request_opt.c
diff --git a/mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_request_opt_private.h b/mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_request_opt_private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_request_opt_private.h
rename to mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_request_opt_private.h
diff --git a/mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_request_str.c b/mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_request_str.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_request_str.c
rename to mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_request_str.c
diff --git a/mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_request_str.h b/mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_request_str.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_request_str.h
rename to mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_request_str.h
diff --git a/mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_response.c b/mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_response.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_response.c
rename to mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_response.c
diff --git a/mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_response_parser.c b/mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_response_parser.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/kms-message/src/kms_response_parser.c
rename to mongodb-1.13.0/src/libmongocrypt/kms-message/src/kms_response_parser.c
diff --git a/mongodb-1.12.0/src/libmongocrypt/kms-message/src/sort.c b/mongodb-1.13.0/src/libmongocrypt/kms-message/src/sort.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/kms-message/src/sort.c
rename to mongodb-1.13.0/src/libmongocrypt/kms-message/src/sort.c
diff --git a/mongodb-1.12.0/src/libmongocrypt/kms-message/src/sort.h b/mongodb-1.13.0/src/libmongocrypt/kms-message/src/sort.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/kms-message/src/sort.h
rename to mongodb-1.13.0/src/libmongocrypt/kms-message/src/sort.h
diff --git a/mongodb-1.13.0/src/libmongocrypt/src/crypto/cng.c b/mongodb-1.13.0/src/libmongocrypt/src/crypto/cng.c
new file mode 100644
index 00000000..901fe087
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongocrypt/src/crypto/cng.c
@@ -0,0 +1,326 @@
+/*
+ * Copyright 2019-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "../mongocrypt-crypto-private.h"
+#include "../mongocrypt-private.h"
+
+#ifdef MONGOCRYPT_ENABLE_CRYPTO_CNG
+
+#include <bcrypt.h>
+
+static BCRYPT_ALG_HANDLE _algo_sha512_hmac = 0;
+static BCRYPT_ALG_HANDLE _algo_aes256 = 0;
+static DWORD _aes256_key_blob_length;
+
+static BCRYPT_ALG_HANDLE _random;
+
+#define STATUS_SUCCESS 0
+
+bool _native_crypto_initialized = false;
+
+void
+_native_crypto_init ()
+{
+ DWORD cbOutput;
+ NTSTATUS nt_status;
+
+ /* Note, there is no mechanism for libmongocrypt to close these providers,
+ * If we ever add such a mechanism, call BCryptCloseAlgorithmProvider.
+ */
+ nt_status = BCryptOpenAlgorithmProvider (&_algo_sha512_hmac,
+ BCRYPT_SHA512_ALGORITHM,
+ MS_PRIMITIVE_PROVIDER,
+ BCRYPT_ALG_HANDLE_HMAC_FLAG);
+ if (nt_status != STATUS_SUCCESS) {
+ return;
+ }
+
+ nt_status = BCryptOpenAlgorithmProvider (
+ &_algo_aes256, BCRYPT_AES_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0);
+ if (nt_status != STATUS_SUCCESS) {
+ return;
+ }
+
+ nt_status = BCryptSetProperty (
+ _algo_aes256,
+ BCRYPT_CHAINING_MODE,
+ (PUCHAR) (BCRYPT_CHAIN_MODE_CBC),
+ (ULONG) (sizeof (wchar_t) * wcslen (BCRYPT_CHAIN_MODE_CBC)),
+ 0);
+ if (nt_status != STATUS_SUCCESS) {
+ return;
+ }
+
+ cbOutput = sizeof (_aes256_key_blob_length);
+ nt_status = BCryptGetProperty (_algo_aes256,
+ BCRYPT_OBJECT_LENGTH,
+ (PUCHAR) (&_aes256_key_blob_length),
+ cbOutput,
+ &cbOutput,
+ 0);
+ if (nt_status != STATUS_SUCCESS) {
+ return;
+ }
+
+ nt_status = BCryptOpenAlgorithmProvider (
+ &_random, BCRYPT_RNG_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0);
+ if (nt_status != STATUS_SUCCESS) {
+ return;
+ }
+
+ _native_crypto_initialized = true;
+}
+
+typedef struct {
+ unsigned char *key_object;
+ uint32_t key_object_length;
+
+ BCRYPT_KEY_HANDLE key_handle;
+
+ unsigned char *iv;
+ uint32_t iv_len;
+} cng_encrypt_state;
+
+static void
+_crypto_state_destroy (cng_encrypt_state *state);
+
+static cng_encrypt_state *
+_crypto_state_init (const _mongocrypt_buffer_t *key,
+ const _mongocrypt_buffer_t *iv,
+ mongocrypt_status_t *status)
+{
+ cng_encrypt_state *state;
+ uint32_t keyBlobLength;
+ unsigned char *keyBlob;
+ BCRYPT_KEY_DATA_BLOB_HEADER blobHeader;
+ NTSTATUS nt_status;
+
+ keyBlob = NULL;
+
+ state = bson_malloc0 (sizeof (*state));
+ BSON_ASSERT (state);
+
+ state->key_handle = INVALID_HANDLE_VALUE;
+
+ /* Initialize key storage buffer */
+ state->key_object = bson_malloc0 (_aes256_key_blob_length);
+ BSON_ASSERT (state->key_object);
+
+ state->key_object_length = _aes256_key_blob_length;
+
+ /* Allocate temporary buffer for key import */
+ keyBlobLength = sizeof (BCRYPT_KEY_DATA_BLOB_HEADER) + key->len;
+ keyBlob = bson_malloc0 (keyBlobLength);
+ BSON_ASSERT (keyBlob);
+
+
+ blobHeader.dwMagic = BCRYPT_KEY_DATA_BLOB_MAGIC;
+ blobHeader.dwVersion = BCRYPT_KEY_DATA_BLOB_VERSION1;
+ blobHeader.cbKeyData = key->len;
+
+ memcpy (keyBlob, &blobHeader, sizeof (BCRYPT_KEY_DATA_BLOB_HEADER));
+
+ memcpy (keyBlob + sizeof (BCRYPT_KEY_DATA_BLOB_HEADER), key->data, key->len);
+
+ nt_status = BCryptImportKey (_algo_aes256,
+ NULL,
+ BCRYPT_KEY_DATA_BLOB,
+ &(state->key_handle),
+ state->key_object,
+ state->key_object_length,
+ keyBlob,
+ keyBlobLength,
+ 0);
+ if (nt_status != STATUS_SUCCESS) {
+ CLIENT_ERR ("Import Key Failed: 0x%x", (int) nt_status);
+ goto fail;
+ }
+
+ bson_free (keyBlob);
+
+ state->iv = bson_malloc0 (iv->len);
+ BSON_ASSERT (state->iv);
+
+ state->iv_len = iv->len;
+ memcpy (state->iv, iv->data, iv->len);
+
+ return state;
+fail:
+ _crypto_state_destroy (state);
+ bson_free (keyBlob);
+
+ return NULL;
+}
+
+
+static void
+_crypto_state_destroy (cng_encrypt_state *state)
+{
+ if (state) {
+ /* Free the key handle before the key_object that contains it */
+ if (state->key_handle != INVALID_HANDLE_VALUE) {
+ BCryptDestroyKey (state->key_handle);
+ }
+
+ bson_free (state->key_object);
+ bson_free (state->iv);
+ bson_free (state);
+ }
+}
+
+
+bool
+_native_crypto_aes_256_cbc_encrypt (aes_256_args_t args)
+{
+ bool ret = false;
+ mongocrypt_status_t *status = args.status;
+ cng_encrypt_state *state = _crypto_state_init (args.key, args.iv, status);
+
+ NTSTATUS nt_status;
+
+ nt_status = BCryptEncrypt (state->key_handle,
+ (PUCHAR) (args.in->data),
+ args.in->len,
+ NULL,
+ state->iv,
+ state->iv_len,
+ args.out->data,
+ args.out->len,
+ args.bytes_written,
+ 0);
+
+ if (nt_status != STATUS_SUCCESS) {
+ CLIENT_ERR ("error initializing cipher: 0x%x", (int) nt_status);
+ goto done;
+ }
+
+ ret = true;
+done:
+ _crypto_state_destroy (state);
+ return ret;
+}
+
+
+bool
+_native_crypto_aes_256_cbc_decrypt (aes_256_args_t args)
+{
+ bool ret = false;
+ mongocrypt_status_t *status = args.status;
+ cng_encrypt_state *state = _crypto_state_init (args.key, args.iv, status);
+
+ NTSTATUS nt_status;
+
+ nt_status = BCryptDecrypt (state->key_handle,
+ (PUCHAR) (args.in->data),
+ args.in->len,
+ NULL,
+ state->iv,
+ state->iv_len,
+ args.out->data,
+ args.out->len,
+ args.bytes_written,
+ 0);
+
+
+ if (nt_status != STATUS_SUCCESS) {
+ CLIENT_ERR ("error initializing cipher: 0x%x", (int) nt_status);
+ goto done;
+ }
+
+ ret = true;
+done:
+ _crypto_state_destroy (state);
+ return ret;
+}
+
+
+bool
+_native_crypto_hmac_sha_512 (const _mongocrypt_buffer_t *key,
+ const _mongocrypt_buffer_t *in,
+ _mongocrypt_buffer_t *out,
+ mongocrypt_status_t *status)
+{
+ bool ret = false;
+ BCRYPT_HASH_HANDLE hHash;
+ NTSTATUS nt_status;
+
+ if (out->len != 64) {
+ CLIENT_ERR ("out does not contain 64 bytes");
+ return false;
+ }
+
+ nt_status = BCryptCreateHash (_algo_sha512_hmac,
+ &hHash,
+ NULL,
+ 0,
+ (PUCHAR) key->data,
+ (ULONG) key->len,
+ 0);
+ if (nt_status != STATUS_SUCCESS) {
+ CLIENT_ERR ("error initializing hmac: 0x%x", (int) nt_status);
+ goto done;
+ }
+
+ nt_status = BCryptHashData (hHash, (PUCHAR) in->data, (ULONG) in->len, 0);
+ if (nt_status != STATUS_SUCCESS) {
+ CLIENT_ERR ("error hashing data: 0x%x", (int) nt_status);
+ goto done;
+ }
+
+ nt_status = BCryptFinishHash (hHash, out->data, out->len, 0);
+ if (nt_status != STATUS_SUCCESS) {
+ CLIENT_ERR ("error finishing hmac: 0x%x", (int) nt_status);
+ goto done;
+ }
+
+ ret = true;
+done:
+ (void) BCryptDestroyHash (hHash);
+ return ret;
+}
+
+
+bool
+_native_crypto_random (_mongocrypt_buffer_t *out,
+ uint32_t count,
+ mongocrypt_status_t *status)
+{
+ NTSTATUS nt_status = BCryptGenRandom (_random, out->data, count, 0);
+ if (nt_status != STATUS_SUCCESS) {
+ CLIENT_ERR ("BCryptGenRandom Failed: 0x%x", (int) nt_status);
+ return false;
+ }
+
+ return true;
+}
+
+bool
+_native_crypto_aes_256_ctr_encrypt (aes_256_args_t args)
+{
+ mongocrypt_status_t *status = args.status;
+ CLIENT_ERR ("_native_crypto_aes_256_ctr_encrypt not implemented for CNG");
+ return false;
+}
+
+bool
+_native_crypto_aes_256_ctr_decrypt (aes_256_args_t args)
+{
+ mongocrypt_status_t *status = args.status;
+ CLIENT_ERR ("_native_crypto_aes_256_ctr_decrypt not implemented for CNG");
+ return false;
+}
+
+#endif /* MONGOCRYPT_ENABLE_CRYPTO_CNG */
\ No newline at end of file
diff --git a/mongodb-1.13.0/src/libmongocrypt/src/crypto/commoncrypto.c b/mongodb-1.13.0/src/libmongocrypt/src/crypto/commoncrypto.c
new file mode 100644
index 00000000..04f56563
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongocrypt/src/crypto/commoncrypto.c
@@ -0,0 +1,202 @@
+/*
+ * Copyright 2019-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "../mongocrypt-crypto-private.h"
+#include "../mongocrypt-private.h"
+
+#ifdef MONGOCRYPT_ENABLE_CRYPTO_COMMON_CRYPTO
+
+#include <CommonCrypto/CommonCryptor.h>
+#include <CommonCrypto/CommonHMAC.h>
+#include <CommonCrypto/CommonRandom.h>
+
+bool _native_crypto_initialized = false;
+
+void
+_native_crypto_init ()
+{
+ _native_crypto_initialized = true;
+}
+
+
+bool
+_native_crypto_aes_256_cbc_encrypt (aes_256_args_t args)
+{
+ bool ret = false;
+ CCCryptorRef ctx = NULL;
+ CCCryptorStatus cc_status;
+ size_t intermediate_bytes_written;
+ mongocrypt_status_t *status = args.status;
+
+ cc_status = CCCryptorCreate (kCCEncrypt,
+ kCCAlgorithmAES,
+ 0 /* defaults to CBC w/ no padding */,
+ args.key->data,
+ kCCKeySizeAES256,
+ args.iv->data,
+ &ctx);
+
+ if (cc_status != kCCSuccess) {
+ CLIENT_ERR ("error initializing cipher: %d", (int) cc_status);
+ goto done;
+ }
+
+ *args.bytes_written = 0;
+
+ cc_status = CCCryptorUpdate (ctx,
+ args.in->data,
+ args.in->len,
+ args.out->data,
+ args.out->len,
+ &intermediate_bytes_written);
+ if (cc_status != kCCSuccess) {
+ CLIENT_ERR ("error encrypting: %d", (int) cc_status);
+ goto done;
+ }
+ *args.bytes_written = intermediate_bytes_written;
+
+
+ cc_status = CCCryptorFinal (ctx,
+ args.out->data + *args.bytes_written,
+ args.out->len - *args.bytes_written,
+ &intermediate_bytes_written);
+ *args.bytes_written += intermediate_bytes_written;
+
+ if (cc_status != kCCSuccess) {
+ CLIENT_ERR ("error finalizing: %d", (int) cc_status);
+ goto done;
+ }
+
+ ret = true;
+done:
+ CCCryptorRelease (ctx);
+ return ret;
+}
+
+
+/* Note, the decrypt function is almost exactly the same as the encrypt
+ * functions except for the kCCDecrypt and the error message. */
+bool
+_native_crypto_aes_256_cbc_decrypt (aes_256_args_t args)
+{
+ bool ret = false;
+ CCCryptorRef ctx = NULL;
+ CCCryptorStatus cc_status;
+ size_t intermediate_bytes_written;
+ mongocrypt_status_t *status = args.status;
+
+ cc_status = CCCryptorCreate (kCCDecrypt,
+ kCCAlgorithmAES,
+ 0 /* defaults to CBC w/ no padding */,
+ args.key->data,
+ kCCKeySizeAES256,
+ args.iv->data,
+ &ctx);
+
+ if (cc_status != kCCSuccess) {
+ CLIENT_ERR ("error initializing cipher: %d", (int) cc_status);
+ goto done;
+ }
+
+ *args.bytes_written = 0;
+ cc_status = CCCryptorUpdate (ctx,
+ args.in->data,
+ args.in->len,
+ args.out->data,
+ args.out->len,
+ &intermediate_bytes_written);
+ if (cc_status != kCCSuccess) {
+ CLIENT_ERR ("error decrypting: %d", (int) cc_status);
+ goto done;
+ }
+ *args.bytes_written = intermediate_bytes_written;
+
+ cc_status = CCCryptorFinal (ctx,
+ args.out->data + *args.bytes_written,
+ args.out->len - *args.bytes_written,
+ &intermediate_bytes_written);
+ *args.bytes_written += intermediate_bytes_written;
+
+ if (cc_status != kCCSuccess) {
+ CLIENT_ERR ("error finalizing: %d", (int) cc_status);
+ goto done;
+ }
+
+ ret = true;
+done:
+ CCCryptorRelease (ctx);
+ return ret;
+}
+
+
+/* CCHmac functions don't return errors. */
+bool
+_native_crypto_hmac_sha_512 (const _mongocrypt_buffer_t *key,
+ const _mongocrypt_buffer_t *in,
+ _mongocrypt_buffer_t *out,
+ mongocrypt_status_t *status)
+{
+ CCHmacContext *ctx;
+
+ if (out->len != MONGOCRYPT_HMAC_SHA512_LEN) {
+ CLIENT_ERR ("out does not contain %d bytes", MONGOCRYPT_HMAC_SHA512_LEN);
+ return false;
+ }
+
+ ctx = bson_malloc0 (sizeof (*ctx));
+ BSON_ASSERT (ctx);
+
+
+ CCHmacInit (ctx, kCCHmacAlgSHA512, key->data, key->len);
+ CCHmacUpdate (ctx, in->data, in->len);
+ CCHmacFinal (ctx, out->data);
+ bson_free (ctx);
+ return true;
+}
+
+
+bool
+_native_crypto_random (_mongocrypt_buffer_t *out,
+ uint32_t count,
+ mongocrypt_status_t *status)
+{
+ CCRNGStatus ret = CCRandomGenerateBytes (out->data, (size_t) count);
+ if (ret != kCCSuccess) {
+ CLIENT_ERR ("failed to generate random iv: %d", (int) ret);
+ return false;
+ }
+ return true;
+}
+
+bool
+_native_crypto_aes_256_ctr_encrypt (aes_256_args_t args)
+{
+ mongocrypt_status_t *status = args.status;
+ CLIENT_ERR (
+ "_native_crypto_aes_256_ctr_encrypt not implemented for CommonCrypto");
+ return false;
+}
+
+bool
+_native_crypto_aes_256_ctr_decrypt (aes_256_args_t args)
+{
+ mongocrypt_status_t *status = args.status;
+ CLIENT_ERR (
+ "_native_crypto_aes_256_ctr_decrypt not implemented for CommonCrypto");
+ return false;
+}
+
+#endif /* MONGOCRYPT_ENABLE_CRYPTO_COMMON_CRYPTO */
diff --git a/mongodb-1.13.0/src/libmongocrypt/src/crypto/libcrypto.c b/mongodb-1.13.0/src/libmongocrypt/src/crypto/libcrypto.c
new file mode 100644
index 00000000..86fe3925
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongocrypt/src/crypto/libcrypto.c
@@ -0,0 +1,288 @@
+/*
+ * Copyright 2019-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Comments in this implementation refer to:
+ * [MCGREW] https://tools.ietf.org/html/draft-mcgrew-aead-aes-cbc-hmac-sha2-05
+ */
+
+#include "../mongocrypt-crypto-private.h"
+#include "../mongocrypt-private.h"
+#include "../mongocrypt-log-private.h"
+
+#ifdef MONGOCRYPT_ENABLE_CRYPTO_LIBCRYPTO
+
+#include <bson/bson.h>
+
+#include <openssl/crypto.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include <openssl/hmac.h>
+#include <openssl/rand.h>
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
+ (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000L)
+
+static HMAC_CTX *
+HMAC_CTX_new (void)
+{
+ return bson_malloc0 (sizeof (HMAC_CTX));
+}
+
+static void
+HMAC_CTX_free (HMAC_CTX *ctx)
+{
+ HMAC_CTX_cleanup (ctx);
+ bson_free (ctx);
+}
+#endif
+
+bool _native_crypto_initialized = false;
+
+void
+_native_crypto_init ()
+{
+ _native_crypto_initialized = true;
+}
+
+/* _encrypt_with_cipher encrypts @in with the OpenSSL cipher specified by
+ * @cipher.
+ * @key is the input key. @iv is the input IV.
+ * @out is the output ciphertext. @out must be allocated by the caller with
+ * enough room for the ciphertext.
+ * @bytes_written is the number of bytes that were written to @out.
+ * Returns false and sets @status on error. @status is required. */
+static bool
+_encrypt_with_cipher (const EVP_CIPHER *cipher, aes_256_args_t args)
+{
+ EVP_CIPHER_CTX *ctx;
+ bool ret = false;
+ int intermediate_bytes_written;
+ mongocrypt_status_t *status = args.status;
+
+ ctx = EVP_CIPHER_CTX_new ();
+
+ BSON_ASSERT (ctx);
+ BSON_ASSERT (cipher);
+ BSON_ASSERT (EVP_CIPHER_iv_length (cipher) == args.iv->len);
+ BSON_ASSERT (EVP_CIPHER_key_length (cipher) == args.key->len);
+
+ if (!EVP_EncryptInit_ex (
+ ctx, cipher, NULL /* engine */, args.key->data, args.iv->data)) {
+ CLIENT_ERR ("error in EVP_EncryptInit_ex: %s",
+ ERR_error_string (ERR_get_error (), NULL));
+ goto done;
+ }
+
+ /* Disable the default OpenSSL padding. */
+ EVP_CIPHER_CTX_set_padding (ctx, 0);
+
+ *args.bytes_written = 0;
+ if (!EVP_EncryptUpdate (ctx,
+ args.out->data,
+ &intermediate_bytes_written,
+ args.in->data,
+ args.in->len)) {
+ CLIENT_ERR ("error in EVP_EncryptUpdate: %s",
+ ERR_error_string (ERR_get_error (), NULL));
+ goto done;
+ }
+
+ *args.bytes_written = (uint32_t) intermediate_bytes_written;
+
+ if (!EVP_EncryptFinal_ex (
+ ctx, args.out->data, &intermediate_bytes_written)) {
+ CLIENT_ERR ("error in EVP_EncryptFinal_ex: %s",
+ ERR_error_string (ERR_get_error (), NULL));
+ goto done;
+ }
+
+ *args.bytes_written += (uint32_t) intermediate_bytes_written;
+
+ ret = true;
+done:
+ EVP_CIPHER_CTX_free (ctx);
+ return ret;
+}
+
+/* _decrypt_with_cipher decrypts @in with the OpenSSL cipher specified by
+ * @cipher.
+ * @key is the input key. @iv is the input IV.
+ * @out is the output plaintext. @out must be allocated by the caller with
+ * enough room for the plaintext.
+ * @bytes_written is the number of bytes that were written to @out.
+ * Returns false and sets @status on error. @status is required. */
+static bool
+_decrypt_with_cipher (const EVP_CIPHER *cipher, aes_256_args_t args)
+{
+ EVP_CIPHER_CTX *ctx;
+ bool ret = false;
+ int intermediate_bytes_written;
+ mongocrypt_status_t *status = args.status;
+
+ ctx = EVP_CIPHER_CTX_new ();
+
+ BSON_ASSERT (EVP_CIPHER_iv_length (cipher) == args.iv->len);
+ BSON_ASSERT (EVP_CIPHER_key_length (cipher) == args.key->len);
+
+ if (!EVP_DecryptInit_ex (
+ ctx, cipher, NULL /* engine */, args.key->data, args.iv->data)) {
+ CLIENT_ERR ("error in EVP_DecryptInit_ex: %s",
+ ERR_error_string (ERR_get_error (), NULL));
+ goto done;
+ }
+
+ /* Disable padding. */
+ EVP_CIPHER_CTX_set_padding (ctx, 0);
+
+ *args.bytes_written = 0;
+
+ if (!EVP_DecryptUpdate (ctx,
+ args.out->data,
+ &intermediate_bytes_written,
+ args.in->data,
+ args.in->len)) {
+ CLIENT_ERR ("error in EVP_DecryptUpdate: %s",
+ ERR_error_string (ERR_get_error (), NULL));
+ goto done;
+ }
+
+ *args.bytes_written = intermediate_bytes_written;
+
+ if (!EVP_DecryptFinal_ex (
+ ctx, args.out->data, &intermediate_bytes_written)) {
+ CLIENT_ERR ("error in EVP_DecryptFinal_ex: %s",
+ ERR_error_string (ERR_get_error (), NULL));
+ goto done;
+ }
+
+ *args.bytes_written += intermediate_bytes_written;
+
+ ret = true;
+done:
+ EVP_CIPHER_CTX_free (ctx);
+ return ret;
+}
+
+bool
+_native_crypto_aes_256_cbc_encrypt (aes_256_args_t args)
+{
+ return _encrypt_with_cipher (EVP_aes_256_cbc (), args);
+}
+
+bool
+_native_crypto_aes_256_cbc_decrypt (aes_256_args_t args)
+{
+ return _decrypt_with_cipher (EVP_aes_256_cbc (), args);
+}
+
+
+bool
+_native_crypto_hmac_sha_512 (const _mongocrypt_buffer_t *key,
+ const _mongocrypt_buffer_t *in,
+ _mongocrypt_buffer_t *out,
+ mongocrypt_status_t *status)
+{
+ const EVP_MD *algo;
+
+ algo = EVP_sha512 ();
+ BSON_ASSERT (EVP_MD_block_size (algo) == 128);
+ BSON_ASSERT (EVP_MD_size (algo) == MONGOCRYPT_HMAC_SHA512_LEN);
+
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+ if (!HMAC (algo,
+ key->data,
+ key->len,
+ in->data,
+ in->len,
+ out->data,
+ NULL /* unused out len */)) {
+ CLIENT_ERR ("error initializing HMAC: %s",
+ ERR_error_string (ERR_get_error (), NULL));
+ return false;
+ }
+ return true;
+#else
+ HMAC_CTX *ctx;
+ bool ret = false;
+
+ ctx = HMAC_CTX_new ();
+
+ if (out->len != MONGOCRYPT_HMAC_SHA512_LEN) {
+ CLIENT_ERR ("out does not contain %d bytes", MONGOCRYPT_HMAC_SHA512_LEN);
+ return false;
+ }
+
+ if (!HMAC_Init_ex (ctx, key->data, key->len, algo, NULL /* engine */)) {
+ CLIENT_ERR ("error initializing HMAC: %s",
+ ERR_error_string (ERR_get_error (), NULL));
+ goto done;
+ }
+
+ if (!HMAC_Update (ctx, in->data, in->len)) {
+ CLIENT_ERR ("error updating HMAC: %s",
+ ERR_error_string (ERR_get_error (), NULL));
+ goto done;
+ }
+
+ if (!HMAC_Final (ctx, out->data, NULL /* unused out len */)) {
+ CLIENT_ERR ("error finalizing: %s",
+ ERR_error_string (ERR_get_error (), NULL));
+ goto done;
+ }
+
+ ret = true;
+done:
+ HMAC_CTX_free (ctx);
+ return ret;
+#endif
+}
+
+
+bool
+_native_crypto_random (_mongocrypt_buffer_t *out,
+ uint32_t count,
+ mongocrypt_status_t *status)
+{
+ int ret = RAND_bytes (out->data, count);
+ /* From man page: "RAND_bytes() and RAND_priv_bytes() return 1 on success, -1
+ * if not supported by the current RAND method, or 0 on other failure. The
+ * error code can be obtained by ERR_get_error(3)" */
+ if (ret == -1) {
+ CLIENT_ERR ("secure random IV not supported: %s",
+ ERR_error_string (ERR_get_error (), NULL));
+ return false;
+ } else if (ret == 0) {
+ CLIENT_ERR ("failed to generate random IV: %s",
+ ERR_error_string (ERR_get_error (), NULL));
+ return false;
+ }
+ return true;
+}
+
+bool
+_native_crypto_aes_256_ctr_encrypt (aes_256_args_t args)
+{
+ return _encrypt_with_cipher (EVP_aes_256_ctr (), args);
+}
+
+bool
+_native_crypto_aes_256_ctr_decrypt (aes_256_args_t args)
+{
+ return _decrypt_with_cipher (EVP_aes_256_ctr (), args);
+}
+
+#endif /* MONGOCRYPT_ENABLE_CRYPTO_LIBCRYPTO */
diff --git a/mongodb-1.13.0/src/libmongocrypt/src/crypto/none.c b/mongodb-1.13.0/src/libmongocrypt/src/crypto/none.c
new file mode 100644
index 00000000..831cf2b3
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongocrypt/src/crypto/none.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2019-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* everything is a no-op */
+
+#include "../mongocrypt-crypto-private.h"
+#include "../mongocrypt-private.h"
+
+#ifndef MONGOCRYPT_ENABLE_CRYPTO
+
+bool _native_crypto_initialized = false;
+
+void
+_native_crypto_init ()
+{
+ _native_crypto_initialized = true;
+}
+
+
+bool
+_native_crypto_aes_256_cbc_encrypt (aes_256_args_t args)
+{
+ mongocrypt_status_t *status = args.status;
+ CLIENT_ERR ("hook not set for aes_256_cbc_encrypt");
+ return false;
+}
+
+
+bool
+_native_crypto_aes_256_cbc_decrypt (aes_256_args_t args)
+{
+ mongocrypt_status_t *status = args.status;
+ CLIENT_ERR ("hook not set for aes_256_cbc_decrypt");
+ return false;
+}
+
+
+bool
+_native_crypto_hmac_sha_512 (const _mongocrypt_buffer_t *key,
+ const _mongocrypt_buffer_t *in,
+ _mongocrypt_buffer_t *out,
+ mongocrypt_status_t *status)
+{
+ CLIENT_ERR ("hook not set for hmac_sha_512");
+ return false;
+}
+
+
+bool
+_native_crypto_random (_mongocrypt_buffer_t *out,
+ uint32_t count,
+ mongocrypt_status_t *status)
+{
+ CLIENT_ERR ("hook not set for random");
+ return false;
+}
+
+bool
+_native_crypto_aes_256_ctr_encrypt (aes_256_args_t args)
+{
+ mongocrypt_status_t *status = args.status;
+ CLIENT_ERR ("hook not set for _native_crypto_aes_256_ctr_encrypt");
+ return false;
+}
+
+bool
+_native_crypto_aes_256_ctr_decrypt (aes_256_args_t args)
+{
+ mongocrypt_status_t *status = args.status;
+ CLIENT_ERR ("hook not set for _native_crypto_aes_256_ctr_decrypt");
+ return false;
+}
+
+#endif /* MONGOCRYPT_ENABLE_CRYPTO */
\ No newline at end of file
diff --git a/mongodb-1.13.0/src/libmongocrypt/src/mlib/error.h b/mongodb-1.13.0/src/libmongocrypt/src/mlib/error.h
new file mode 100644
index 00000000..7dcb0bed
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongocrypt/src/mlib/error.h
@@ -0,0 +1,59 @@
+#ifndef MLIB_ERROR_PRIVATE_H
+#define MLIB_ERROR_PRIVATE_H
+
+#include "./user-check.h"
+
+#include "./str.h"
+
+#ifdef _WIN32
+#include "./windows-lean.h"
+#else
+#include <errno.h>
+#endif
+
+/**
+ * @brief Obtain a string containing an error message corresponding to an error
+ * code from the host platform.
+ *
+ * @param errn An error code for the system. (e.g. GetLastError() on Windows)
+ * @return mstr A new string containing the resulting error. Must be freed with
+ * @ref mstr_free().
+ */
+static inline mstr
+merror_system_error_string (int errn)
+{
+#ifdef _WIN32
+ wchar_t *wbuffer = NULL;
+ DWORD slen = FormatMessageW (FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ (DWORD) errn,
+ 0,
+ (LPWSTR) &wbuffer,
+ 0,
+ NULL);
+ if (slen == 0) {
+ return mstr_copy_cstr (
+ "[Error while getting error string from FormatMessageW()]");
+ }
+ mstr_narrow_result narrow = mstr_win32_narrow (wbuffer);
+ LocalFree (wbuffer);
+ assert (narrow.error == 0);
+ // Messages from FormatMessage contain an additional CR+LF
+ if (mstr_ends_with (narrow.string.view, mstrv_lit ("\r\n"))) {
+ mstr_inplace_remove_suffix (&narrow.string, 2);
+ }
+ return narrow.string;
+#else
+ errno = 0;
+ char *const str = strerror (errn);
+ if (errno) {
+ return mstr_copy_cstr (
+ "[Error while getting error string from strerror()]");
+ }
+ return mstr_copy_cstr (str);
+#endif
+}
+
+#endif // MLIB_ERROR_PRIVATE_H
\ No newline at end of file
diff --git a/mongodb-1.13.0/src/libmongocrypt/src/mlib/path.h b/mongodb-1.13.0/src/libmongocrypt/src/mlib/path.h
new file mode 100644
index 00000000..2967f461
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongocrypt/src/mlib/path.h
@@ -0,0 +1,379 @@
+#ifndef MONGOCRYPT_PATH_PRIVATE_H
+#define MONGOCRYPT_PATH_PRIVATE_H
+
+#include "./user-check.h"
+
+#include "./str.h"
+
+#include <inttypes.h>
+
+#ifndef _WIN32
+#include <unistd.h>
+#else
+#include "./windows-lean.h"
+#endif
+
+typedef enum mpath_format {
+ /// The POSIX path format
+ MPATH_POSIX = 'p',
+ /// The Win32 path format
+ MPATH_WIN32 = 'w',
+ /// The native path format for the current platform
+ MPATH_NATIVE =
+#ifdef _WIN32
+ MPATH_WIN32,
+#else
+ MPATH_POSIX,
+#endif
+} mpath_format;
+
+/**
+ * @brief Determine if the given character is a path separator for the given
+ * path format
+ *
+ * @param c A path character
+ * @param f The path format to use
+ */
+static inline bool
+mpath_is_sep (char c, mpath_format f)
+{
+ if (f == MPATH_WIN32) {
+ return c == '/' || c == '\\';
+ } else {
+ return c == '/';
+ }
+}
+
+/**
+ * @brief Obtain the preferred path separator character for the given format
+ */
+static inline char
+mpath_preferred_sep (mpath_format f)
+{
+ if (f == MPATH_WIN32) {
+ return '\\';
+ } else {
+ return '/';
+ }
+}
+
+/**
+ * @brief Obtain the path string denoting the application's current working
+ * directory
+ *
+ * @return mstr A new string which must be freed with mstr_free()
+ */
+static inline mstr
+mpath_current_path ()
+{
+#if _WIN32
+ while (1) {
+ DWORD len = GetCurrentDirectoryW (0, NULL);
+ wchar_t *wstr = calloc (sizeof (wchar_t), len);
+ DWORD got_len = GetCurrentDirectoryW (len, wstr);
+ if (got_len > len) {
+ free (wstr);
+ continue;
+ }
+ mstr_narrow_result nar = mstr_win32_narrow (wstr);
+ free (wstr);
+ assert (nar.error == 0);
+ return nar.string;
+ }
+#else
+ mstr_mut mut = mstr_new (8096);
+ char *p = getcwd (mut.data, mut.len);
+ if (p == NULL) {
+ mstr_free (mut.mstr);
+ return MSTR_NULL;
+ }
+ mstr ret = mstr_copy_cstr (mut.data);
+ mstr_free (mut.mstr);
+ return ret;
+#endif
+}
+
+/**
+ * @brief Determine whether the given path string has a trailing path separator
+ */
+static inline bool
+mpath_has_trailing_sep (mstr_view path, mpath_format f)
+{
+ return path.len && mpath_is_sep (path.data[path.len - 1], f);
+}
+
+/**
+ * @brief Obtain the parent path of the given path.
+ */
+static inline mstr_view
+mpath_parent (mstr_view path, mpath_format f)
+{
+ if (mpath_has_trailing_sep (path, f)) {
+ // Remove trailing separators:
+ while (mpath_has_trailing_sep (path, f)) {
+ path = mstrv_remove_suffix (path, 1);
+ }
+ return path;
+ }
+ // Remove everything that isn't a path separator:
+ while (path.len != 0 && !mpath_has_trailing_sep (path, f)) {
+ path = mstrv_remove_suffix (path, 1);
+ }
+ // Remove trailing separators again
+ while (path.len > 1 && mpath_has_trailing_sep (path, f)) {
+ path = mstrv_remove_suffix (path, 1);
+ }
+ // The result is the parent path.
+ return path;
+}
+
+/**
+ * @brief Obtain the filename denoted by the given path.
+ *
+ * The returned path will include no directory separators. If the given path
+ * ends with a directory separator, the single-dot '.' path is returned instead.
+ */
+static inline mstr_view
+mpath_filename (mstr_view path, mpath_format f)
+{
+ if (!path.len) {
+ return path;
+ }
+ const char *it = path.data + path.len;
+ while (it != path.data && !mpath_is_sep (it[-1], f)) {
+ --it;
+ }
+ size_t off = it - path.data;
+ mstr_view fname = mstrv_subview (path, off, path.len);
+ if (fname.len == 0) {
+ return mstrv_lit (".");
+ }
+ return fname;
+}
+
+/**
+ * @brief Join the two given paths into a single path
+ *
+ * The two strings will be combined into a single string with a path separator
+ * between them. If either string is empty, the other string will be copied
+ * without modification.
+ *
+ * @param base The left-hand of the join
+ * @param suffix The right-hand of the join
+ * @param f The path format to use
+ * @return mstr A new string resulting from the join
+ */
+static inline mstr
+mpath_join (mstr_view base, mstr_view suffix, mpath_format f)
+{
+ if (!base.len) {
+ return mstr_copy (suffix);
+ }
+ if (mpath_has_trailing_sep (base, f)) {
+ return mstr_append (base, suffix);
+ }
+ if (!suffix.len) {
+ return mstr_copy (base);
+ }
+ if (mpath_is_sep (suffix.data[0], f)) {
+ return mstr_append (base, suffix);
+ }
+ // We must insert a path separator between the two strings
+ mstr_mut r = mstr_new (base.len + suffix.len + 1);
+ char *p = r.data;
+ memcpy (p, base.data, base.len);
+ p += base.len;
+ *p++ = mpath_preferred_sep (f);
+ memcpy (p, suffix.data, suffix.len);
+ return r.mstr;
+}
+
+/**
+ * @brief Obtain the root name for the given path.
+ *
+ * For the Windows format, this will return the drive letter, if present.
+ * Otherwise, this will return an empty string.
+ */
+static inline mstr_view
+mpath_root_name (mstr_view path, mpath_format f)
+{
+ if (f == MPATH_WIN32 && path.len > 1) {
+ char c = path.data[0];
+ if (path.len > 2 && path.data[1] == ':' &&
+ ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))) {
+ return mstrv_subview (path, 0, 2);
+ }
+ }
+ return mstrv_subview (path, 0, 0);
+}
+
+/**
+ * @brief Return the root directory of the given path, if present.
+ *
+ * @note This will not include the drive letter of a Win32 path.
+ */
+static inline mstr_view
+mpath_root_directory (mstr_view path, mpath_format f)
+{
+ mstr_view rname = mpath_root_name (path, f);
+ path = mstrv_subview (path, rname.len, path.len);
+ if (path.len && mpath_is_sep (path.data[0], f)) {
+ return mstrv_subview (path, 0, 1);
+ } else {
+ return mstrv_subview (path, 0, 0);
+ }
+}
+
+/**
+ * @brief Obtain the root filepath of the given path.
+ *
+ * This will include both the root name and the root filepath, if present.
+ */
+static inline mstr_view
+mpath_root_path (mstr_view path, mpath_format f)
+{
+ mstr_view rname = mpath_root_name (path, f);
+ mstr_view rdir = mpath_root_directory (path, f);
+ return mstrv_subview (path, 0, rname.len + rdir.len);
+}
+
+/**
+ * @brief Determine whether the given filepath designates a single unambiguous
+ * filesystem location.
+ *
+ * @note A Win32 filepath without a drive letter is not absolute!
+ */
+static inline bool
+mpath_is_absolute (mstr_view path, mpath_format f)
+{
+ if (f == MPATH_WIN32) {
+ // Win32 requires both a root name and a root directory for an absolute
+ // path
+ return mpath_root_name (path, f).len &&
+ mpath_root_directory (path, f).len;
+ } else {
+ // POSIX doesn't have "root names"
+ return mpath_root_directory (path, f).len;
+ }
+}
+
+/**
+ * @brief Obtain a relative path from the given filepath
+ *
+ * If the path has a root path, returns the content of the path following that
+ * root path, otherwise returns the same path itself.
+ */
+static inline mstr_view
+mpath_relative_path (mstr_view path, mpath_format f)
+{
+ mstr_view root = mpath_root_path (path, f);
+ return mstrv_subview (path, root.len, path.len);
+}
+
+/**
+ * @brief Convert the filepath from one format to a preferred form in another
+ * format.
+ *
+ * @note The return value must be freed with mstr_free()
+ */
+static inline mstr
+mpath_to_format (mpath_format from, mstr_view path, mpath_format to)
+{
+ mstr_mut ret = mstr_new (path.len);
+ const char *p = path.data;
+ char *out = ret.data;
+ const char *stop = path.data + path.len;
+ for (; p != stop; ++p, ++out) {
+ if (mpath_is_sep (*p, from)) {
+ *out = mpath_preferred_sep (to);
+ } else {
+ *out = *p;
+ }
+ }
+ return ret.mstr;
+}
+
+/**
+ * @brief Determine whether the given path is relative (not absolute)
+ */
+static inline bool
+mpath_is_relative (mstr_view path, mpath_format f)
+{
+ return !mpath_is_absolute (path, f);
+}
+
+/**
+ * @brief Convert the given path to an absolute path, if it is not already.
+ *
+ * @note The return value must be freed with mstr_free()
+ */
+static inline mstr
+mpath_absolute (mstr_view path, mpath_format f);
+
+/**
+ * @brief Resolve a path to an absolute path from the given base path.
+ *
+ * @note This is not the same as mpath_join(): If the given path is already
+ * absolute, returns that path unchanged. Otherwise, resolves that path as being
+ * relative to `base`.
+ *
+ * @note If `base` is also a relative path, it will also be given to
+ * mpath_absolute() to resolve it.
+ */
+static inline mstr
+mpath_absolute_from (mstr_view path, mstr_view base, mpath_format f)
+{
+ mstr_view rname = mpath_root_name (path, f);
+ mstr_view rdir = mpath_root_directory (path, f);
+ if (rname.len) {
+ if (rdir.len) {
+ // The path is already fully absolute
+ return mstr_copy (path);
+ } else {
+ mstr abs_base = mpath_absolute (base, f);
+ mstr_view base_rdir = mpath_root_directory (abs_base.view, f);
+ mstr_view base_relpath = mpath_relative_path (abs_base.view, f);
+ mstr_view relpath = mpath_relative_path (path, f);
+ mstr ret = mstr_copy (rname);
+ mstr_assign (&ret, mpath_join (ret.view, base_rdir, f));
+ mstr_assign (&ret, mpath_join (ret.view, base_relpath, f));
+ mstr_assign (&ret, mpath_join (ret.view, relpath, f));
+ mstr_free (abs_base);
+ return ret;
+ }
+ } else {
+ // No root name
+ if (rdir.len) {
+ if (f == MPATH_POSIX) {
+ // No root name, but a root directory on a POSIX path indicates an
+ // absolute path
+ return mstr_copy (path);
+ }
+ mstr abs_base = mpath_absolute (base, f);
+ mstr_view base_rname = mpath_root_name (abs_base.view, f);
+ mstr ret = mpath_join (base_rname, path, f);
+ mstr_free (abs_base);
+ return ret;
+ } else {
+ mstr abs_base = mpath_absolute (base, f);
+ mstr r = mpath_join (abs_base.view, path, f);
+ mstr_free (abs_base);
+ return r;
+ }
+ }
+}
+
+static inline mstr
+mpath_absolute (mstr_view path, mpath_format f)
+{
+ if (mpath_is_absolute (path, f)) {
+ return mstr_copy (path);
+ }
+ mstr cur = mpath_current_path ();
+ mstr ret = mpath_absolute_from (path, cur.view, MPATH_NATIVE);
+ mstr_assign (&ret, mpath_to_format (MPATH_NATIVE, ret.view, f));
+ mstr_free (cur);
+ return ret;
+}
+
+#endif // MONGOCRYPT_PATH_PRIVATE_H
diff --git a/mongodb-1.13.0/src/libmongocrypt/src/mlib/str.h b/mongodb-1.13.0/src/libmongocrypt/src/mlib/str.h
new file mode 100644
index 00000000..33b4fb62
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongocrypt/src/mlib/str.h
@@ -0,0 +1,922 @@
+#ifndef MONGOCRYPT_STR_PRIVATE_H
+#define MONGOCRYPT_STR_PRIVATE_H
+
+#include "./user-check.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <inttypes.h>
+#include <stdbool.h>
+
+/**
+ * @brief A simple non-owning string-view type.
+ *
+ * The viewed string can be treated as an array of char. It's pointed-to data
+ * must not be freed or manipulated.
+ *
+ * @note The viewed string is NOT guaranteed to be null-terminated. It WILL
+ * be null-terminated if: Directly created from a string literal via
+ * @ref mstrv_lit, OR created by accessing the @ref mstr::view member of an
+ * @ref mstr object, OR returned from @ref mstrv_view_cstr.
+ */
+typedef struct mstr_view {
+ /**
+ * @brief Pointer to the beginning of the code unit array.
+ *
+ * @note DO NOT MODIFY
+ */
+ const char *data;
+ /**
+ * @brief Length of the pointed-to code unit array
+ *
+ * @note DO NOT MODIFY
+ */
+ size_t len;
+} mstr_view;
+
+/**
+ * @brief A simple string utility type.
+ *
+ * This string type has the following semantics:
+ *
+ * The member `data` is a pointer to the beginning of a read-only array of code
+ * units. This array will always be null-terminated, but MAY contain
+ * intermittent null characters. The member `len` is the length of the code unit
+ * array (not including the null terminator). These two members should not be
+ * modified.
+ *
+ * The `view` member is a union member that will view the `mstr` as an
+ * @ref mstr_view.
+ *
+ * If you create an @ref mstr, it MUST eventually be passed to @ref mstr_free()
+ *
+ * The pointed-to code units of an mstr are immutable. To initialize the
+ * contents of an mstr, @ref mstr_new returns an @ref mstr_mut, which can then
+ * be "sealed" by converting it to an @ref mstr through the @ref mstr_mut::mstr
+ * union member.
+ *
+ * By convention, passing/returning an `mstr` to/from a function should
+ * relinquish ownership of that `mstr` to the callee/caller, respectively.
+ * Passing or returning an `mstr_view` is non-owning.
+ */
+typedef struct mstr {
+ union {
+ struct {
+ /**
+ * @brief Pointer to the beginning of the code unit array.
+ *
+ * @note DO NOT MODIFY
+ */
+ const char *data;
+ /**
+ * @brief Length of the pointed-to code unit array
+ *
+ * @note DO NOT MODIFY
+ */
+ size_t len;
+ };
+ /**
+ * @brief A non-owning `mstr_view` of the string
+ */
+ mstr_view view;
+ };
+} mstr;
+
+/**
+ * @brief An interface for initializing the contents of an mstr.
+ *
+ * Returned by @ref mstr_new(). Once initialization is complete, the result can
+ * be used as an @ref mstr by accessing the @ref mstr_mut::mstr member.
+ */
+typedef struct mstr_mut {
+ union {
+ struct {
+ /**
+ * @brief Pointer to the beginning of the mutable code unit array.
+ *
+ * @note DO NOT MODIFY THE POINTER VALUE. Only modify the pointed-to
+ * characters.
+ */
+ char *data;
+ /**
+ * @brief Length of the pointed-to code unit array.
+ *
+ * @note DO NOT MODIFY
+ */
+ size_t len;
+ };
+ /// Convert the mutable string to an immutable string
+ struct mstr mstr;
+ /// Convert the mutable string to an immutable string view
+ mstr_view view;
+ };
+} mstr_mut;
+
+/**
+ * @brief A null @ref mstr
+ */
+#define MSTR_NULL ((mstr){{{.data = NULL, .len = 0}}})
+/**
+ * @brief A null @ref mstr_view
+ */
+#define MSTRV_NULL ((mstr_view){.data = NULL, .len = 0})
+
+/**
+ * @brief Create an @ref mstr_view that views the given string literal
+ */
+#define mstrv_lit(String) (mstrv_view_data (String "", (sizeof String) - 1))
+
+/**
+ * @brief Create a new mutable code-unit array of the given length,
+ * zero-initialized. The caller can then modify the code units in the array via
+ * the @ref mstr_mut::data member. Once finished modifying, can be converted to
+ * an immutable mstr by copying the @ref mtsr_mut::mstr union member.
+ *
+ * @param len The length of the new string.
+ * @return mstr_mut A new mstr_mut
+ *
+ * @note The @ref mstr_mut::mstr member MUST eventually be given to
+ * @ref mstr_free().
+ */
+static inline mstr_mut
+mstr_new (size_t len)
+{
+#ifndef __clang_analyzer__
+ return (mstr_mut){{{.data = calloc (1, len + 1), .len = len}}};
+#else
+ // Clang-analyzer is smart enough to see the calloc(), but not smart enough
+ // to link it to the free() in mstr_free()
+ return (mstr_mut){};
+#endif
+}
+
+/**
+ * @brief Create a non-owning @ref mstr_view from the given C string and length
+ *
+ * @param s A pointer to the beginning of a character array.
+ * @param len The length of the character array, in code units
+ * @return mstr_view A non-owning string.
+ */
+static inline mstr_view
+mstrv_view_data (const char *s, size_t len)
+{
+ return (mstr_view){.data = s, .len = len};
+}
+
+/**
+ * @brief Create a non-owning @ref mstr_view from a C-style null-terminated
+ * string.
+ *
+ * @param s A pointer to a null-terminated character array
+ * @return mstr_view A view of the pointed-to string
+ */
+static inline mstr_view
+mstrv_view_cstr (const char *s)
+{
+ return mstrv_view_data (s, strlen (s));
+}
+
+/**
+ * @brief Create an @ref mstr from the given character array and length.
+ *
+ * @param s A pointer to a character array
+ * @param len The length of the string to create
+ * @return mstr A new null-terminated string with the contents copied from the
+ * pointed-to array.
+ *
+ * @note The resulting string will be null-terminated.
+ */
+static inline mstr
+mstr_copy_data (const char *s, size_t len)
+{
+ mstr_mut r = mstr_new (len);
+ memcpy (r.data, s, len);
+ return r.mstr;
+}
+
+/**
+ * @brief Create an @ref mstr from A C-style null-terminated string.
+ *
+ * @param s A pointer to a null-terminated character array
+ * @return mstr A new string copied from the pointed-to string
+ */
+static inline mstr
+mstr_copy_cstr (const char *s)
+{
+ return mstr_copy_data (s, strlen (s));
+}
+
+/**
+ * @brief Copy the contents of the given string view
+ *
+ * @param s A string view to copy from
+ * @return mstr A new string copied from the given view
+ */
+static inline mstr
+mstr_copy (mstr_view s)
+{
+ return mstr_copy_data (s.data, s.len);
+}
+
+/**
+ * @brief Free the resources of the given string
+ *
+ * @param s The string to free
+ */
+static inline void
+mstr_free (mstr s)
+{
+ free ((char *) s.data);
+}
+
+/**
+ * @brief Resize the given mutable string, maintaining the existing content, and
+ * zero-initializing any added characters.
+ *
+ * @param s The @ref mstr_mut to update
+ * @param new_len The new length of the string
+ */
+static inline void
+mstrm_resize (mstr_mut *s, size_t new_len)
+{
+ if (new_len <= s->len) {
+ s->len = new_len;
+ } else {
+ const size_t old_len = s->len;
+#ifndef __clang_analyzer__
+ // Clang-analyzer is smart enough to see the calloc(), but not smart
+ // enough to link it to the free() in mstr_free()
+ s->data = realloc ((char *) s->data, new_len + 1);
+#endif
+ s->len = new_len;
+ memset (s->data + old_len, 0, new_len - old_len);
+ }
+ s->data[new_len] = (char) 0;
+}
+
+/**
+ * @brief Free and re-assign the given @ref mstr
+ *
+ * @param s Pointer to an @ref mstr. This will be freed, then updated to the
+ * value of @ref from
+ * @param from An @ref mstr to take from.
+ *
+ * @note Ownership of the resource is handed to the pointed-to @ref s.
+ * Equivalent to:
+ *
+ * ```c
+ * mstr s = some_mstr();
+ * mstr another = get_another_mstr();
+ * mstr_free(s);
+ * s = another;
+ * ```
+ *
+ * Intended as a convenience for rebinding an @ref mstr in a single statement
+ * from an expression returning a new @ref mstr, which may itself use @ref s,
+ * without requiring a temporary variable, for example:
+ *
+ * ```c
+ * mstr s = get_mstr();
+ * mstr_assign(&s, convert_to_uppercase(s.view));
+ * ```
+ */
+static inline void
+mstr_assign (mstr *s, mstr from)
+{
+ mstr_free (*s);
+ *s = from;
+}
+
+/**
+ * @brief Find the index of the first occurrence of the given "needle" as a
+ * substring of another string.
+ *
+ * @param given A string to search within
+ * @param needle The substring to search for
+ * @return int The zero-based index of the first instance of `needle` in
+ * `given`, or -1 if no substring is found.
+ */
+static inline int
+mstr_find (mstr_view given, mstr_view needle)
+{
+ const char *const scan_end = given.data + given.len;
+ const char *const needle_end = needle.data + needle.len;
+ for (const char *scan = given.data; scan != scan_end; ++scan) {
+ size_t remain = scan_end - scan;
+ if (remain < needle.len) {
+ break;
+ }
+ const char *subscan = scan;
+ for (const char *nscan = needle.data; nscan != needle_end;
+ ++nscan, ++subscan) {
+ if (*nscan == *subscan) {
+ continue;
+ } else {
+ goto skip;
+ }
+ }
+ // Got through the whole loop of scanning the needle
+ return (int) (scan - given.data);
+ skip:
+ (void) 0;
+ }
+ return -1;
+}
+
+/**
+ * @brief Find the index of the last occurrence of the given "needle" as a
+ * substring of another string.
+ *
+ * @param given A string to search within
+ * @param needle The substring to search for
+ * @return int The zero-based index of the last instance of `needle` in
+ * `given`, or -1 if no substring is found.
+ */
+static inline int
+mstr_rfind (mstr_view given, mstr_view needle)
+{
+ if (needle.len > given.len) {
+ return -1;
+ }
+ const char *scan = given.data + given.len - needle.len;
+ const char *const needle_end = needle.data + needle.len;
+ for (; scan >= given.data; --scan) {
+ const char *subscan = scan;
+ for (const char *nscan = needle.data; nscan != needle_end;
+ ++nscan, ++subscan) {
+ if (*nscan == *subscan) {
+ continue;
+ } else {
+ goto skip;
+ }
+ }
+ // Got through the whole loop of scanning the needle
+ return (int) (scan - given.data);
+ skip:
+ (void) 0;
+ }
+ return -1;
+}
+
+/**
+ * @brief Modify a string by deleting and/or inserting another string.
+ *
+ * @param s The string to modify
+ * @param at The position at which to insert and delete characters
+ * @param del_count The number of characters to delete. Clamped to the string
+ * length.
+ * @param insert The string to insert at `at`.
+ * @return mstr A new string that is the result of the splice
+ */
+static inline mstr
+mstr_splice (mstr_view s, size_t at, size_t del_count, mstr_view insert)
+{
+ assert (at <= s.len);
+ const size_t remain = s.len - at;
+ if (del_count > remain) {
+ del_count = remain;
+ }
+ const size_t new_size = s.len - del_count + insert.len;
+ mstr_mut ret = mstr_new (new_size);
+ char *p = ret.data;
+ memcpy (p, s.data, at);
+ p += at;
+ if (insert.data) {
+ memcpy (p, insert.data, insert.len);
+ p += insert.len;
+ }
+ memcpy (p, s.data + at + del_count, s.len - at - del_count);
+ return ret.mstr;
+}
+
+/**
+ * @brief Append the given suffix to the given string
+ */
+static inline mstr
+mstr_append (mstr_view s, mstr_view suffix)
+{
+ return mstr_splice (s, s.len, 0, suffix);
+}
+
+/**
+ * @brief Prepend the given prefix to the given string
+ */
+static inline mstr
+mstr_prepend (mstr_view s, mstr_view prefix)
+{
+ return mstr_splice (s, 0, 0, prefix);
+}
+
+/**
+ * @brief Insert the given string into another string
+ *
+ * @param s The string to start with
+ * @param at The position in `s` where `infix` will be inserted
+ * @param infix The string to insert into `s`
+ * @return mstr A new string with `infix` inserted
+ */
+static inline mstr
+mstr_insert (mstr_view s, size_t at, mstr_view infix)
+{
+ return mstr_splice (s, at, 0, infix);
+}
+
+/**
+ * @brief Erase characters from the given string
+ *
+ * @param s The string to start with
+ * @param at The position at which to begin deleting characters
+ * @param count The number of characters to remove
+ * @return mstr A new string with the deletion result.
+ */
+static inline mstr
+mstr_erase (mstr_view s, size_t at, size_t count)
+{
+ return mstr_splice (s, at, count, mstrv_view_cstr (""));
+}
+
+/**
+ * @brief Erase `len` characters from the beginning of the string
+ */
+static inline mstr
+mstr_remove_prefix (mstr_view s, size_t len)
+{
+ return mstr_erase (s, 0, len);
+}
+
+/**
+ * @brief Erase `len` characters from the end of the string
+ */
+static inline mstr
+mstr_remove_suffix (mstr_view s, size_t len)
+{
+ return mstr_erase (s, s.len - len, len);
+}
+
+/**
+ * @brief Obtain a substring of the given string
+ *
+ * @param s The string to start with
+ * @param at The beginning position of the new string
+ * @param len The number of characters to include. Automatically clamped to the
+ * remaining length.
+ * @return mstr A new string that is a substring of `s`
+ */
+static inline mstr
+mstr_substr (mstr_view s, size_t at, size_t len)
+{
+ assert (at <= s.len);
+ const size_t remain = s.len - at;
+ if (len > remain) {
+ len = remain;
+ }
+ mstr_mut r = mstr_new (len);
+ memcpy (r.data, s.data + at, len);
+ return r.mstr;
+}
+
+/**
+ * @brief Obtain a view of a substring of another string.
+ *
+ * @param s The string to view
+ * @param at The position at which the new view will begin
+ * @param len The number of characters to view. Automatically clamped to the
+ * remaining length.
+ * @return mstr_view A view of `s`.
+ */
+static inline mstr_view
+mstrv_subview (mstr_view s, size_t at, size_t len)
+{
+ assert (at <= s.len);
+ const size_t remain = s.len - at;
+ if (len > remain) {
+ len = remain;
+ }
+ return (mstr_view){.data = s.data + at, .len = len};
+}
+
+/**
+ * @brief Obtain a view of another string by removing `len` characters from the
+ * front
+ */
+static inline mstr_view
+mstrv_remove_prefix (mstr_view s, size_t len)
+{
+ return mstrv_subview (s, len, s.len);
+}
+
+/**
+ * @brief Obtain a view of another string by removing `len` characters from the
+ * end.
+ */
+static inline mstr_view
+mstrv_remove_suffix (mstr_view s, size_t len)
+{
+ return mstrv_subview (s, 0, s.len - len);
+}
+
+/**
+ * @brief Truncate the given string to `new_len` characters.
+ *
+ * @param s The string to truncate
+ * @param new_len The new length of the string
+ * @return mstr A new string copied from the beginning of `s`
+ */
+static inline mstr
+mstr_trunc (mstr_view s, size_t new_len)
+{
+ assert (new_len <= s.len);
+ return mstr_remove_suffix (s, s.len - new_len);
+}
+
+/**
+ * @brief Obtain a new string with all occurrences of a string replaced with a
+ * different string
+ *
+ * @param string The string to start with
+ * @param find The substring that will be replaced
+ * @param subst The string to insert in place of `find`
+ * @return mstr A new string modified from `string`
+ *
+ * @note If `find` is empty, returns a copy of `string`
+ */
+static inline mstr
+mstr_replace (const mstr_view string,
+ const mstr_view find,
+ const mstr_view subst)
+{
+ if (find.len == 0) {
+ // Finding an empty string would loop forever
+ return mstr_copy (string);
+ }
+ // First copy the string
+ mstr ret = mstr_copy (string);
+ // Keep an index of how far we have processed
+ size_t whence = 0;
+ for (;;) {
+ // Chop off the front that has already been processed
+ mstr_view tail = mstrv_subview (ret.view, whence, ~0);
+ // Find where in that tail is the next needle
+ int pos = mstr_find (tail, find);
+ if (pos == -1) {
+ // We're done
+ break;
+ }
+ // Do the replacement
+ mstr_assign (
+ &ret, mstr_splice (ret.view, (size_t) pos + whence, find.len, subst));
+ // Advance our position by how many chars we skipped and how many we
+ // inserted
+ whence += pos + subst.len;
+ }
+ return ret;
+}
+
+/**
+ * @brief Determine whether two strings are equivalent.
+ */
+static inline bool
+mstr_eq (mstr_view left, mstr_view right)
+{
+ if (left.len != right.len) {
+ return false;
+ }
+ return memcmp (left.data, right.data, left.len) == 0;
+}
+
+/// Determine whether the given character is an printable ASCII codepoint
+static inline bool
+mstr_is_printable (char c)
+{
+ return (c >= ' ' && c <= '~');
+}
+
+/// Write the given string to `out`, rendering non-printable characters as hex
+/// escapes
+static inline void
+_mstr_write_str_repr_ (FILE *out, mstr_view s)
+{
+ for (char const *it = s.data; it != s.data + s.len; ++it) {
+ if (mstr_is_printable (*it)) {
+ fputc (*it, out);
+ } else {
+ fprintf (out, "\\x%.2x", (unsigned) (unsigned char) *it);
+ }
+ }
+}
+
+static inline void
+_mstr_assert_fail_ (mstr_view left,
+ const char *predicate,
+ mstr_view right,
+ const char *file,
+ int line)
+{
+ fprintf (stderr, "%s:%d: ASSERTION FAILED: \"", file, line);
+ _mstr_write_str_repr_ (stderr, left);
+ fprintf (stderr, "\" %s \"", predicate);
+ _mstr_write_str_repr_ (stderr, right);
+ fprintf (stderr, "\"\n");
+ abort ();
+}
+
+static inline void
+_mstr_assert_ (mstr_view left,
+ mstr_view right,
+ bool (*pred) (mstr_view left, mstr_view right),
+ bool B,
+ const char *pred_str,
+ const char *file,
+ int line)
+{
+ if (pred (left, right) != B) {
+ mstr pstr = mstr_copy_cstr (pred_str);
+ if (!B) {
+ mstr_assign (&pstr, mstr_prepend (pstr.view, mstrv_lit ("not ")));
+ }
+ _mstr_assert_fail_ (left, pstr.data, right, file, line);
+ }
+}
+
+#define MSTR_ASSERT(Bool, Left, Pred, Right) \
+ (_mstr_assert_ ( \
+ (Left), (Right), mstr_##Pred, (Bool), #Pred, __FILE__, __LINE__))
+
+/**
+ * @brief Assert that two strings are equivalent.
+ *
+ * Prints and error message and aborts if they are not
+ */
+#define MSTR_ASSERT_EQ(Left, Right) MSTR_ASSERT (true, Left, eq, Right)
+
+/**
+ * @brief Determine whether the given string contains the given substring
+ *
+ * @param given A string to search within
+ * @param needle A substring to search for
+ * @return true If `given` contains at least one occurrence of `needle`
+ * @return false Otherwise
+ */
+static inline bool
+mstr_contains (mstr_view given, mstr_view needle)
+{
+ return mstr_find (given, needle) >= 0;
+}
+
+/**
+ * @brief Determine whether `given` starts with `prefix`
+ */
+static inline bool
+mstr_starts_with (mstr_view given, mstr_view prefix)
+{
+ given = mstrv_subview (given, 0, prefix.len);
+ return mstr_eq (given, prefix);
+}
+
+/**
+ * @brief Determine whether `given` ends with `suffix`
+ */
+static inline bool
+mstr_ends_with (mstr_view given, mstr_view suffix)
+{
+ if (suffix.len > given.len) {
+ return false;
+ }
+ given = mstrv_subview (given, given.len - suffix.len, ~0);
+ return mstr_eq (given, suffix);
+}
+
+/// Compound in-place version of @ref mstr_splice
+static inline void
+mstr_inplace_splice (mstr *s, size_t at, size_t del_count, mstr_view insert)
+{
+ mstr_assign (s, mstr_splice (s->view, at, del_count, insert));
+}
+
+/// Compound in-place version of @ref mstr_append
+static inline void
+mstr_inplace_append (mstr *s, mstr_view suffix)
+{
+ mstr_assign (s, mstr_append (s->view, suffix));
+}
+
+/// Compound in-place version of @ref mstr_prepend
+static inline void
+mstr_inplace_prepend (mstr *s, mstr_view prefix)
+{
+ mstr_assign (s, mstr_prepend (s->view, prefix));
+}
+
+/// Compound in-place version of @ref mstr_insert
+static inline void
+mstr_inplace_insert (mstr *s, size_t at, mstr_view infix)
+{
+ mstr_assign (s, mstr_insert (s->view, at, infix));
+}
+
+/// Compound in-place version of @ref mstr_erase
+static inline void
+mstr_inplace_erase (mstr *s, size_t at, size_t count)
+{
+ mstr_assign (s, mstr_erase (s->view, at, count));
+}
+
+/// Compound in-place version of @ref mstr_remove_prefix
+static inline void
+mstr_inplace_remove_prefix (mstr *s, size_t len)
+{
+ mstr_assign (s, mstr_remove_prefix (s->view, len));
+}
+
+/// Compound in-place version of @ref mstr_remove_suffix
+static inline void
+mstr_inplace_remove_suffix (mstr *s, size_t len)
+{
+ mstr_assign (s, mstr_remove_suffix (s->view, len));
+}
+
+/// Compound in-place version of @ref mstr_substr
+static inline void
+mstr_inplace_substr (mstr *s, size_t at, size_t count)
+{
+ mstr_assign (s, mstr_substr (s->view, at, count));
+}
+
+/// Compound in-place version of @ref mstr_trunc
+static inline void
+mstr_inplace_trunc (mstr *s, size_t new_len)
+{
+ mstr_assign (s, mstr_trunc (s->view, new_len));
+}
+
+/// Compound in-place version of @ref mstr_replace
+static inline void
+mstr_inplace_replace (mstr *s, mstr_view find, mstr_view subst)
+{
+ mstr_assign (s, mstr_replace (s->view, find, subst));
+}
+
+#ifdef _WIN32
+#include "./windows-lean.h"
+/**
+ * @brief The result type of mstr_win32_widen
+ */
+typedef struct mstr_widen_result {
+ wchar_t *wstring;
+ int error;
+} mstr_widen_result;
+
+/**
+ * @brief Widen a UTF-8 string using Win32 MultiBytetoWideChar
+ *
+ * @param str The UTF-8 string to widen.
+ * @return mstr_widen_result The result of widening, which may contain an error.
+ *
+ * @note The returned @ref mstr_widen_result::wstring must be given to free()
+ */
+static inline mstr_widen_result
+mstr_win32_widen (mstr_view str)
+{
+ int length = MultiByteToWideChar (
+ CP_UTF8, MB_ERR_INVALID_CHARS, str.data, (int) str.len, NULL, 0);
+ if (length == 0 && str.len != 0) {
+ return (mstr_widen_result){.wstring = NULL, .error = GetLastError ()};
+ }
+ wchar_t *ret = calloc (length + 1, sizeof (wchar_t));
+ int got_length = MultiByteToWideChar (
+ CP_UTF8, MB_ERR_INVALID_CHARS, str.data, (int) str.len, ret, length + 1);
+ assert (got_length == length);
+ return (mstr_widen_result){.wstring = ret, .error = 0};
+}
+
+/**
+ * @brief The result type of mstr_win32_narrow
+ */
+typedef struct mstr_narrow_result {
+ mstr string;
+ int error;
+} mstr_narrow_result;
+
+/**
+ * @brief Narrow a UTF-16 string to UTF-8 using Win32 WideCharToMultiByte
+ *
+ * @param wstring A null-terminated UTF-16 string to narrow
+ * @return mstr_narrow_result The result of narrowing, which may contain an
+ * error.
+ *
+ * @note The returned @ref mstr_narrow_result::string must be freed with
+ * mstr_free()
+ */
+static inline mstr_narrow_result
+mstr_win32_narrow (const wchar_t *wstring)
+{
+ int length = WideCharToMultiByte (CP_UTF8,
+ WC_ERR_INVALID_CHARS,
+ wstring,
+ -1 /* wstring is null-terminated */,
+ NULL,
+ 0,
+ NULL,
+ NULL);
+ if (length == 0 && wstring[0] != 0) {
+ return (mstr_narrow_result){.string = MSTR_NULL,
+ .error = GetLastError ()};
+ }
+ mstr_mut ret = mstr_new ((size_t) length);
+ int got_len = WideCharToMultiByte (CP_UTF8,
+ WC_ERR_INVALID_CHARS,
+ wstring,
+ -1,
+ ret.data,
+ (int) ret.len,
+ NULL,
+ NULL);
+ assert (length == got_len);
+ return (mstr_narrow_result){.string = ret.mstr, .error = 0};
+}
+#endif
+
+/// Iteration state for string splitting
+struct _mstr_split_iter_ {
+ /// What hasn't been parsed yet
+ mstr_view remaining;
+ /// The current part
+ mstr_view part;
+ /// The string that we split on
+ mstr_view splitter;
+ /// A once-var for the inner loop. Set to 1 by iter_next, then decremented
+ int once;
+ /// The loop state. Starts at zero. Set to one when we part the final split.
+ /// Set to two to break out of the loop.
+ int state;
+};
+
+/// Hidden function to advance a string-split iterator
+static inline void
+_mstr_split_iter_next_ (struct _mstr_split_iter_ *iter)
+{
+ if (iter->once == 1) {
+ // We only get here if the loop body hit a 'break', skipping the decrement
+ // of the 'once'. Break out of the whole loop, as the user expects.
+ iter->state = 2;
+ return;
+ }
+ if (iter->state == 1) {
+ // We just completed the final loop pass.
+ iter->state = 2;
+ return;
+ }
+ // Find the next occurence of the token
+ const int pos = mstr_find (iter->remaining, iter->splitter);
+ if (pos < 0) {
+ // There are no more occurences. yield the remaining string
+ iter->part = iter->remaining;
+ iter->remaining = mstrv_subview (iter->remaining, iter->remaining.len, 0);
+ // Set state to 1 to break on the next pass
+ iter->state = 1;
+ } else {
+ // Advance our parts:
+ iter->part = mstrv_subview (iter->remaining, 0, pos);
+ iter->remaining =
+ mstrv_subview (iter->remaining, pos + iter->splitter.len, ~0);
+ }
+ // Prime the inner "loop" to execute once
+ iter->once = 1;
+}
+
+/// init a new split iterator
+static inline struct _mstr_split_iter_
+_mstr_split_iter_begin_ (mstr_view str, mstr_view split)
+{
+ struct _mstr_split_iter_ iter = {.remaining = str, .splitter = split};
+ _mstr_split_iter_next_ (&iter);
+ return iter;
+}
+
+/// Check whether we are done iterating
+static inline bool
+_mstr_split_iter_done_ (struct _mstr_split_iter_ *iter)
+{
+ return iter->state == 2;
+}
+
+// clang-format off
+#define MSTR_ITER_SPLIT(LineVar, String, SplitToken) \
+ /* Open the main outer loop */ \
+ for (/* Declare an init the iterator */ \
+ struct _mstr_split_iter_ _iter_var_ = \
+ _mstr_split_iter_begin_ ((String), (SplitToken)); \
+ /* Iterate until it is marked as done */ \
+ !_mstr_split_iter_done_ (&_iter_var_); \
+ _mstr_split_iter_next_ (&_iter_var_)) \
+ /* This inner loop will only execute once, but gives us */ \
+ /* a point to declare the loop variable: */ \
+ for (mstr_view LineVar = _iter_var_.part; \
+ _iter_var_.once; \
+ --_iter_var_.once)
+// clang-format on
+
+#endif // MONGOCRYPT_STR_PRIVATE_H
diff --git a/mongodb-1.13.0/src/libmongocrypt/src/mlib/thread.h b/mongodb-1.13.0/src/libmongocrypt/src/mlib/thread.h
new file mode 100644
index 00000000..d93fa345
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongocrypt/src/mlib/thread.h
@@ -0,0 +1,88 @@
+#ifndef MLIB_THREAD_H
+#define MLIB_THREAD_H
+
+#include "./user-check.h"
+
+#ifdef _WIN32
+#include "./windows-lean.h"
+#else
+#include <pthread.h>
+#endif
+
+#include <stdbool.h>
+
+/**
+ * @brief A status object for @ref mlib_call_once.
+ */
+typedef struct mlib_once_flag {
+#ifdef _WIN32
+ INIT_ONCE _native;
+#else
+ pthread_once_t _native;
+#endif
+} mlib_once_flag;
+
+/**
+ * @brief A literal initializer suitable for static initializing an
+ * @ref mlib_once_flag object. Can also be used to dynamically initialize or
+ * "reset" a flag.
+ */
+#ifdef _WIN32
+#define MLIB_ONCE_INITIALIZER \
+ { \
+ ._native = INIT_ONCE_STATIC_INIT \
+ }
+#else
+#define MLIB_ONCE_INITIALIZER \
+ { \
+ ._native = PTHREAD_ONCE_INIT \
+ }
+#endif
+
+/**
+ * @brief The type of an mlib_call_once callback function.
+ */
+typedef void (*mlib_init_once_fn_t) (void);
+
+#if _WIN32
+/**
+ * An indirection layer for mlib_once on Windows platforms. Do not use directly.
+ */
+static inline BOOL WINAPI
+_mlib_win32_once_callthru (PINIT_ONCE once, PVOID param, PVOID *ctx)
+{
+ (void) once;
+ (void) ctx;
+ mlib_init_once_fn_t *fn = param;
+ (*fn) ();
+ return TRUE;
+}
+#endif
+
+/**
+ * @brief Perform thread-safe call-once semantics.
+ *
+ * For each thread that calls with the same given flag, no thread shall return
+ * from this function until the flag is in the "finished" state. If a thread
+ * class this function with a "non-finished" flag object, then that thread MIGHT
+ * execute the passed pointed-to function. Once any thread fully executes the
+ * function for the flag, the flag is marked as "finished".
+ *
+ * @param flag A once-state flag. Should have been initialized by @ref
+ * MLIB_ONCE_INITIALIZER.
+ * @param fn A callback to execute if the flag is not in the "finished" state
+ * @return true on success, false otherwise
+ */
+static inline bool
+mlib_call_once (mlib_once_flag *flag, mlib_init_once_fn_t fn)
+{
+#ifdef _WIN32
+ bool okay = InitOnceExecuteOnce (
+ &flag->_native, &_mlib_win32_once_callthru, &fn, NULL);
+ return okay;
+#else
+ return pthread_once (&flag->_native, fn) == 0;
+#endif
+}
+
+#endif // MLIB_THREAD_H
diff --git a/mongodb-1.13.0/src/libmongocrypt/src/mlib/user-check.h b/mongodb-1.13.0/src/libmongocrypt/src/mlib/user-check.h
new file mode 100644
index 00000000..708effa9
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongocrypt/src/mlib/user-check.h
@@ -0,0 +1,4 @@
+#ifndef MLIB_USER
+#error \
+ "The file being compiled transitively #include'd a mongo-mlib header, but is not a direct consumer of mlib, which is a private library for MongoDB C driver libraries"
+#endif
\ No newline at end of file
diff --git a/mongodb-1.13.0/src/libmongocrypt/src/mlib/windows-lean.h b/mongodb-1.13.0/src/libmongocrypt/src/mlib/windows-lean.h
new file mode 100644
index 00000000..249637b2
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongocrypt/src/mlib/windows-lean.h
@@ -0,0 +1,19 @@
+/**
+ * This file is simply a wrapper around <windows.h> and ensures that
+ * WIN32_LEAN_AND_MEAN is defined before including it.
+ */
+#ifndef MLIB_WINDOWS_LEAN_H
+#define MLIB_WINDOWS_LEAN_H
+
+#ifdef __has_include
+#if !__has_include(<windows.h>)
+#error "<mlib/windows-lean.h> is only available when <windows.h> in available."
+#endif
+#endif
+
+#pragma push_macro("WIN32_LEAN_AND_MEAN")
+#define WIN32_LEAN_AND_MEAN 1
+#include <windows.h>
+#pragma pop_macro("WIN32_LEAN_AND_MEAN")
+
+#endif // MLIB_WINDOWS_LEAN_H
diff --git a/mongodb-1.13.0/src/libmongocrypt/src/mongo_csfle-v1.h b/mongodb-1.13.0/src/libmongocrypt/src/mongo_csfle-v1.h
new file mode 100644
index 00000000..b4e7b99e
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongocrypt/src/mongo_csfle-v1.h
@@ -0,0 +1,319 @@
+/**
+ * Copyright (C) 2021-present MongoDB, Inc.
+ */
+
+
+#ifndef CSFLE_SUPPORT_H
+#define CSFLE_SUPPORT_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+#pragma push_macro("MONGO_API_CALL")
+#undef MONGO_API_CALL
+
+#pragma push_macro("MONGO_API_IMPORT")
+#undef MONGO_API_IMPORT
+
+#pragma push_macro("MONGO_API_EXPORT")
+#undef MONGO_API_EXPORT
+
+#pragma push_macro("CSFLE_SUPPORT_API")
+#undef CSFLE_SUPPORT_API
+
+#if defined(_WIN32)
+#define MONGO_API_CALL __cdecl
+#define MONGO_API_IMPORT __declspec(dllimport)
+#define MONGO_API_EXPORT __declspec(dllexport)
+#else
+#define MONGO_API_CALL
+#define MONGO_API_IMPORT __attribute__((visibility("default")))
+#define MONGO_API_EXPORT __attribute__((used, visibility("default")))
+#endif
+
+#if defined(CSFLE_SUPPORT_STATIC)
+#define MONGO_CSFLE_API
+#else
+#if defined(CSFLE_SUPPORT_COMPILING)
+#define MONGO_CSFLE_API MONGO_API_EXPORT
+#else
+#define MONGO_CSFLE_API MONGO_API_IMPORT
+#endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * An object which describes the details of the failure of an operation.
+ *
+ * The CSFLE Library uses allocated objects of this type to report the details of any
+ * failure, when an operation cannot be completed. Several `mongo_csfle_v1_status` functions are
+ * provided which permit observing the details of these failures. Further a construction function
+ * and a destruction function for these objects are also provided.
+ *
+ * The use of status objects from multiple threads is not thread safe unless all of the threads
+ * accessing a single status object are passing that object as a const-qualified (const
+ * mongo_csfle_v1_status *) pointer. If a single thread is passing a status object to a function
+ * taking it by non-const-qualified (mongo_csfle_v1_status*) pointer, then no other thread may
+ * access the status object.
+ *
+ * The `status` parameter is optional for all `mongo_csfle_v1_` functions that can take a status
+ * pointer. The caller may pass NULL instead of a valid `status` object, in which case the function
+ * will execute normally but will not provide any detailed error information in the caes of a
+ * failure.
+ *
+ * All `mongo_csfle_v1_status` functions can be used before the CSFLE library is
+ * initialized. This facilitates detailed error reporting from all library functions.
+ */
+typedef struct mongo_csfle_v1_status mongo_csfle_v1_status;
+
+/**
+ * Allocate and construct an API-return-status buffer object.
+ *
+ * Returns NULL when construction of a mongo_csfle_v1_status object fails.
+ *
+ * This function may be called before mongo_csfle_v1_lib_create().
+ */
+MONGO_CSFLE_API mongo_csfle_v1_status* MONGO_API_CALL mongo_csfle_v1_status_create(void);
+
+/**
+ * Destroys a valid status object.
+ *
+ * The status object must be a valid mongo_csfle_v1_status object or NULL.
+ *
+ * This function is not thread safe, and it must not execute concurrently with any other function
+ * that accesses the status object being destroyed. It is, however, safe to destroy distinct status
+ * objects on distinct threads.
+ *
+ * This function does not report failures.
+ *
+ * This function may be called before `mongo_csfle_v1_lib_create()`.
+ *
+ * This function causes all storage associated with the specified status object to be released,
+ * including the storage referenced by functions that returned observable storage buffers from this
+ * status, such as strings.
+ */
+MONGO_CSFLE_API void MONGO_API_CALL mongo_csfle_v1_status_destroy(mongo_csfle_v1_status* status);
+
+/**
+ * The error codes reported by `mongo_csfle_v1` functions will be given the symbolic names as
+ * mapped by this enum.
+ *
+ * When a `mongo_csfle_v1` function fails (and it has been documented to report errors) it will
+ * report that error in the form of an `int` status code. That status code will always be returned
+ * as the type `int`; however, the values in this enum can be used to classify the failure.
+ */
+typedef enum {
+ MONGO_CSFLE_V1_ERROR_IN_REPORTING_ERROR = -2,
+ MONGO_CSFLE_V1_ERROR_UNKNOWN = -1,
+
+ MONGO_CSFLE_V1_SUCCESS = 0,
+
+ MONGO_CSFLE_V1_ERROR_ENOMEM = 1,
+ MONGO_CSFLE_V1_ERROR_EXCEPTION = 2,
+ MONGO_CSFLE_V1_ERROR_LIBRARY_ALREADY_INITIALIZED = 3,
+ MONGO_CSFLE_V1_ERROR_LIBRARY_NOT_INITIALIZED = 4,
+ MONGO_CSFLE_V1_ERROR_INVALID_LIB_HANDLE = 5,
+ MONGO_CSFLE_V1_ERROR_REENTRANCY_NOT_ALLOWED = 6,
+} mongo_csfle_v1_error;
+
+/**
+ * Gets an error code from a `mongo_csfle_v1_status` object.
+ *
+ * When a `mongo_csfle_v1` function fails (and it has been documented to report errors) it will
+ * report its error in the form of an `int` status code which is stored into a supplied
+ * `mongo_csfle_v1_status` object, if provided. Some of these functions may also report extra
+ * information, which will be reported by other observer functions. Every `mongo_csfle_v1`
+ * function which reports errors will always update the `Error` code stored in a
+ * `mongo_csfle_v1_status` object, even upon success.
+ *
+ * This function does not report its own failures.
+ */
+MONGO_CSFLE_API int MONGO_API_CALL
+mongo_csfle_v1_status_get_error(const mongo_csfle_v1_status* status);
+
+/**
+ * Gets a descriptive error message from a `mongo_csfle_v1_status` object.
+ *
+ * For failures where the error is MONGO_CSFLE_V1_ERROR_EXCEPTION, this returns a string
+ * representation of the internal C++ exception.
+ *
+ * The function to which the specified status object was passed must not have returned
+ * MONGO_CSFLE_V1_SUCCESS as its error code.
+ *
+ * The storage for the returned string is associated with the specified status object, and therefore
+ * it will be deallocated when the status is destroyed using mongo_csfle_v1_status_destroy().
+ *
+ * This function does not report its own failures.
+ */
+MONGO_CSFLE_API const char* MONGO_API_CALL
+mongo_csfle_v1_status_get_explanation(const mongo_csfle_v1_status* status);
+
+/**
+ * Gets a status code from a `mongo_csfle_v1_status` object.
+ *
+ * Returns a numeric status code associated with the status parameter which indicates a sub-category
+ * of failure.
+ *
+ * For any status object that does not have MONGO_CSFLE_V1_ERROR_EXCEPTION as its error, the
+ * value of this code is unspecified.
+ *
+ * This function does not report its own failures.
+ */
+MONGO_CSFLE_API int MONGO_API_CALL
+mongo_csfle_v1_status_get_code(const mongo_csfle_v1_status* status);
+
+/**
+ * An object which describes the runtime state of the CSFLE Library.
+ *
+ * The CSFLE Library uses allocated objects of this type to indicate the present state of
+ * the library. Some operations which the library provides need access to this object. Further a
+ * construction function and a destruction function for these objects are also provided. No more
+ * than a single object instance of this type may exist at any given time.
+ *
+ * The use of `mongo_csfle_v1_lib` objects from multiple threads is not thread safe unless all of
+ * the threads accessing a single `mongo_csfle_v1_lib` object are not destroying this object. If
+ * a single thread is passing a `mongo_csfle_v1_lib` to its destruction function, then no other
+ * thread may access the `mongo_csfle_v1_lib` object.
+ */
+typedef struct mongo_csfle_v1_lib mongo_csfle_v1_lib;
+
+/**
+ * Creates a mongo_csfle_v1_lib object, which stores context for the CSFLE library. A
+ * process should only ever have one mongo_csfle_v1_lib instance.
+ *
+ * On failure, returns NULL and populates the 'status' object if it is not NULL.
+ */
+MONGO_CSFLE_API mongo_csfle_v1_lib* MONGO_API_CALL
+mongo_csfle_v1_lib_create(mongo_csfle_v1_status* status);
+
+/**
+ * Tears down the state of this library. Existing mongo_csfle_v1_status objects remain valid.
+ * Existing mongo_csfle_v1_query_analyzer objects created from this library MUST BE destroyed
+ * before destroying the library object.
+ *
+ * The 'lib' parameter must be a valid mongo_csfle_v1_lib instance and must not be NULL.
+ *
+ * The 'status' parameter may be NULL, but must be a valid mongo_csfle_v1_status instance if it
+ * is not NULL.
+ *
+ * Returns MONGO_CSFLE_V1_SUCCESS on success.
+ *
+ * Returns MONGO_CSFLE_V1_ERROR_LIBRARY_NOT_INITIALIZED and modifies 'status' if
+ * mongo_csfle_v1_lib_create() has not been called previously.
+ */
+MONGO_CSFLE_API int MONGO_API_CALL mongo_csfle_v1_lib_destroy(mongo_csfle_v1_lib* lib,
+ mongo_csfle_v1_status* status);
+
+
+/**
+ * Returns a product version in 64-bit integer in four 16-bit words, from high to low:
+ *
+ * - Major version
+ * - Minor version
+ * - Revision
+ * - Reserved
+ *
+ * For example, version 6.2.1 would be encoded as: 0x0006000200010000
+ *
+ */
+MONGO_CSFLE_API uint64_t MONGO_API_CALL mongo_csfle_v1_get_version(void);
+
+/**
+ * Returns a product version as a text string. The string should not be modified or released
+ *
+ * Examples:
+ * Dev Build/patch: mongo_csfle_v1-rhel80-6.2.1-alpha4-284-g8662e7d
+ * Release build: mongo_csfle_v1-rhel80-6.2.1
+ */
+MONGO_CSFLE_API const char* MONGO_API_CALL mongo_csfle_v1_get_version_str(void);
+
+
+/**
+ * A single query analyzer can be used across repeated calls to mongo_csfle_v1_analyze_query.
+ *
+ * It is not safe to simultaneously invoke mongo_csfle_v1_query_analyzer_create on the same
+ * query analyzer from multiple threads
+ *
+ * It is the client's responsibility to call mongo_csfle_v1_query_analyzer_destroy() to free up
+ * resources used by the query analyzer. Once a query analyzer is destroyed, it is not safe to
+ * call mongo_csfle_v1_analyze_query.
+ */
+typedef struct mongo_csfle_v1_query_analyzer mongo_csfle_v1_query_analyzer;
+
+/**
+ * Creates a mongo_csfle_v1_query_analyzer object, which stores a parsed collation.
+ *
+ * The 'lib' parameter must be a valid mongo_csfle_v1_lib instance and must not be NULL.
+ *
+ * On failure, it returns NULL and populates the 'status' object if it is not NULL.
+ */
+MONGO_CSFLE_API mongo_csfle_v1_query_analyzer* MONGO_API_CALL
+mongo_csfle_v1_query_analyzer_create(mongo_csfle_v1_lib* lib, mongo_csfle_v1_status* status);
+
+/**
+ * Destroys a valid mongo_csfle_v1_query_analyzer object.
+ *
+ * This function is not thread safe, and it must not execute concurrently with any other function
+ * that accesses the collation object being destroyed including those that access a matcher,
+ * projection or update object which references the collation object.
+ *
+ * This function does not report failures.
+ */
+MONGO_CSFLE_API void MONGO_API_CALL
+mongo_csfle_v1_query_analyzer_destroy(mongo_csfle_v1_query_analyzer* analyzer);
+
+
+/**
+ * Analyzes the 'documentBSON' input document which includes a JSON schema for namespace 'ns_str'
+ * and returns a new BSON document that replaces fields that need encryption with BinData
+ * (subtype 6, first byte 0) placeholders.
+ *
+ * The input document must be a valid OP_MSG document supports aggregate, count, delete, distinct,
+ * explain, find, findAndModify, insert and update.
+ * In addition, the input document must include two additional top-level fields:
+ * - jsonSchema : document - contains a valid JSON schema
+ * - isRemoteSchema : bool - true if schema comes from MongoD as opposed to client-side
+ *
+ * The 'analyzer' and 'documentBSON' parameters must point to initialized objects of their
+ * respective types.
+ *
+ * When the analysis is successful, this function returns non-null value which points to a valid
+ * BSON document and updates bson_len with the length of the BSON document
+ */
+MONGO_CSFLE_API uint8_t* MONGO_API_CALL
+mongo_csfle_v1_analyze_query(mongo_csfle_v1_query_analyzer* analyzer,
+ const uint8_t* documentBSON,
+ const char* ns_str,
+ uint32_t ns_len,
+ uint32_t* bson_len,
+ mongo_csfle_v1_status* status);
+
+/**
+ * Free the memory of a BSON buffer returned by mongo_csfle_v1_analyze_query(). This function can be
+ * safely called on a NULL pointer.
+ *
+ * This function can be called at any time to deallocate a BSON buffer and will not invalidate any
+ * library object.
+ */
+MONGO_CSFLE_API void MONGO_API_CALL mongo_csfle_v1_bson_free(uint8_t* bson);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#undef CSFLE_SUPPORT_API
+#pragma pop_macro("CSFLE_SUPPORT_API")
+
+#undef MONGO_API_EXPORT
+#pragma push_macro("MONGO_API_EXPORT")
+
+#undef MONGO_API_IMPORT
+#pragma push_macro("MONGO_API_IMPORT")
+
+#undef MONGO_API_CALL
+#pragma pop_macro("MONGO_API_CALL")
+
+#endif // CSFLE_SUPPORT_H
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-binary-private.h b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-binary-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-binary-private.h
rename to mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-binary-private.h
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-binary.c b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-binary.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-binary.c
rename to mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-binary.c
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-buffer-private.h b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-buffer-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-buffer-private.h
rename to mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-buffer-private.h
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-buffer.c b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-buffer.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-buffer.c
rename to mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-buffer.c
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-cache-collinfo-private.h b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-cache-collinfo-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-cache-collinfo-private.h
rename to mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-cache-collinfo-private.h
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-cache-collinfo.c b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-cache-collinfo.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-cache-collinfo.c
rename to mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-cache-collinfo.c
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-cache-key-private.h b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-cache-key-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-cache-key-private.h
rename to mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-cache-key-private.h
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-cache-key.c b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-cache-key.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-cache-key.c
rename to mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-cache-key.c
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-cache-oauth-private.h b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-cache-oauth-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-cache-oauth-private.h
rename to mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-cache-oauth-private.h
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-cache-oauth.c b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-cache-oauth.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-cache-oauth.c
rename to mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-cache-oauth.c
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-cache-private.h b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-cache-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-cache-private.h
rename to mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-cache-private.h
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-cache.c b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-cache.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-cache.c
rename to mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-cache.c
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-ciphertext-private.h b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-ciphertext-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-ciphertext-private.h
rename to mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-ciphertext-private.h
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-ciphertext.c b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-ciphertext.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-ciphertext.c
rename to mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-ciphertext.c
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-compat.h b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-compat.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-compat.h
rename to mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-compat.h
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-config.h b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-config.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-config.h
rename to mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-config.h
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-config.h.in b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-config.h.in
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-config.h.in
rename to mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-config.h.in
diff --git a/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-crypto-private.h b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-crypto-private.h
new file mode 100644
index 00000000..53a06023
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-crypto-private.h
@@ -0,0 +1,174 @@
+/*
+ * Copyright 2019-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef MONGOCRYPT_CRYPTO_PRIVATE_H
+#define MONGOCRYPT_CRYPTO_PRIVATE_H
+
+#include "mongocrypt.h"
+#include "mongocrypt-buffer-private.h"
+
+#define MONGOCRYPT_KEY_LEN 96
+#define MONGOCRYPT_IV_KEY_LEN 32
+#define MONGOCRYPT_MAC_KEY_LEN 32
+#define MONGOCRYPT_ENC_KEY_LEN 32
+#define MONGOCRYPT_IV_LEN 16
+#define MONGOCRYPT_HMAC_SHA512_LEN 64
+#define MONGOCRYPT_HMAC_LEN 32
+#define MONGOCRYPT_BLOCK_SIZE 16
+
+typedef struct {
+ int hooks_enabled;
+ mongocrypt_crypto_fn aes_256_cbc_encrypt;
+ mongocrypt_crypto_fn aes_256_cbc_decrypt;
+ mongocrypt_random_fn random;
+ mongocrypt_hmac_fn hmac_sha_512;
+ mongocrypt_hmac_fn hmac_sha_256;
+ mongocrypt_hash_fn sha_256;
+ void *ctx;
+} _mongocrypt_crypto_t;
+
+uint32_t
+_mongocrypt_calculate_ciphertext_len (uint32_t plaintext_len);
+
+uint32_t
+_mongocrypt_calculate_plaintext_len (uint32_t ciphertext_len);
+
+bool
+_mongocrypt_do_encryption (_mongocrypt_crypto_t *crypto,
+ const _mongocrypt_buffer_t *iv,
+ const _mongocrypt_buffer_t *associated_data,
+ const _mongocrypt_buffer_t *key,
+ const _mongocrypt_buffer_t *plaintext,
+ _mongocrypt_buffer_t *ciphertext,
+ uint32_t *bytes_written,
+ mongocrypt_status_t *status)
+ MONGOCRYPT_WARN_UNUSED_RESULT;
+
+bool
+_mongocrypt_do_decryption (_mongocrypt_crypto_t *crypto,
+ const _mongocrypt_buffer_t *associated_data,
+ const _mongocrypt_buffer_t *key,
+ const _mongocrypt_buffer_t *ciphertext,
+ _mongocrypt_buffer_t *plaintext,
+ uint32_t *bytes_written,
+ mongocrypt_status_t *status)
+ MONGOCRYPT_WARN_UNUSED_RESULT;
+
+bool
+_mongocrypt_random (_mongocrypt_crypto_t *crypto,
+ _mongocrypt_buffer_t *out,
+ uint32_t count,
+ mongocrypt_status_t *status) MONGOCRYPT_WARN_UNUSED_RESULT;
+
+/* Returns 0 if equal, non-zero otherwise */
+int
+_mongocrypt_memequal (const void *const b1, const void *const b2, size_t len);
+
+
+/*
+ * _mongocrypt_wrap_key encrypts a DEK with a KEK.
+
+ * kek is an input Key Encryption Key.
+ * dek is an input Data Encryption Key.
+ * encrypted_dek the result of encrypting dek with kek.
+ * encrypted_dek is always initialized.
+ * Returns true if no error occurred.
+ * Returns false and sets @status if an error occurred.
+ */
+bool
+_mongocrypt_wrap_key (_mongocrypt_crypto_t *crypto,
+ _mongocrypt_buffer_t *kek,
+ _mongocrypt_buffer_t *dek,
+ _mongocrypt_buffer_t *encrypted_dek,
+ mongocrypt_status_t *status)
+ MONGOCRYPT_WARN_UNUSED_RESULT;
+
+/*
+ * _mongocrypt_unwrap_key decrypts an encrypted DEK with a KEK.
+ *
+ * kek is an input Key Encryption Key.
+ * encrypted_dek is an input encrypted Data Encryption Key.
+ * dek is the result of decrypting encrypted_dek with kek.
+ * dek is always initialized.
+ * Returns true if no error occurred.
+ * Returns false and sets @status if an error occurred.
+ */
+bool
+_mongocrypt_unwrap_key (_mongocrypt_crypto_t *crypto,
+ _mongocrypt_buffer_t *kek,
+ _mongocrypt_buffer_t *encrypted_dek,
+ _mongocrypt_buffer_t *dek,
+ mongocrypt_status_t *status)
+ MONGOCRYPT_WARN_UNUSED_RESULT;
+
+bool
+_mongocrypt_calculate_deterministic_iv (
+ _mongocrypt_crypto_t *crypto,
+ const _mongocrypt_buffer_t *key,
+ const _mongocrypt_buffer_t *plaintext,
+ const _mongocrypt_buffer_t *associated_data,
+ _mongocrypt_buffer_t *out,
+ mongocrypt_status_t *status) MONGOCRYPT_WARN_UNUSED_RESULT;
+
+/* Crypto implementations must implement these functions. */
+
+/* This variable must be defined in implementation
+ files, and must be set to true when _crypto_init
+ is successful. */
+extern bool _native_crypto_initialized;
+
+void
+_native_crypto_init ();
+
+typedef struct {
+ const _mongocrypt_buffer_t *key;
+ const _mongocrypt_buffer_t *iv;
+ const _mongocrypt_buffer_t *in;
+ _mongocrypt_buffer_t *out;
+ uint32_t *bytes_written;
+ mongocrypt_status_t *status;
+} aes_256_args_t;
+
+bool
+_native_crypto_aes_256_cbc_encrypt (aes_256_args_t args)
+ MONGOCRYPT_WARN_UNUSED_RESULT;
+
+bool
+_native_crypto_aes_256_cbc_decrypt (aes_256_args_t args)
+ MONGOCRYPT_WARN_UNUSED_RESULT;
+
+bool
+_native_crypto_hmac_sha_512 (const _mongocrypt_buffer_t *key,
+ const _mongocrypt_buffer_t *in,
+ _mongocrypt_buffer_t *out,
+ mongocrypt_status_t *status)
+ MONGOCRYPT_WARN_UNUSED_RESULT;
+
+bool
+_native_crypto_random (_mongocrypt_buffer_t *out,
+ uint32_t count,
+ mongocrypt_status_t *status)
+ MONGOCRYPT_WARN_UNUSED_RESULT;
+
+bool
+_native_crypto_aes_256_ctr_encrypt (aes_256_args_t args)
+ MONGOCRYPT_WARN_UNUSED_RESULT;
+
+bool
+_native_crypto_aes_256_ctr_decrypt (aes_256_args_t args)
+ MONGOCRYPT_WARN_UNUSED_RESULT;
+
+#endif /* MONGOCRYPT_CRYPTO_PRIVATE_H */
diff --git a/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-crypto.c b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-crypto.c
new file mode 100644
index 00000000..5ac0bec7
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-crypto.c
@@ -0,0 +1,993 @@
+/*
+ * Copyright 2019-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Comments in this implementation refer to:
+ * [MCGREW] https://tools.ietf.org/html/draft-mcgrew-aead-aes-cbc-hmac-sha2-05
+ */
+
+#include <bson/bson.h>
+
+#include "mongocrypt-binary-private.h"
+#include "mongocrypt-buffer-private.h"
+#include "mongocrypt-crypto-private.h"
+#include "mongocrypt-log-private.h"
+#include "mongocrypt-private.h"
+#include "mongocrypt-status-private.h"
+
+#include <inttypes.h>
+
+/* Crypto primitives. These either call the native built in crypto primitives or
+ * user supplied hooks. */
+static bool
+_crypto_aes_256_cbc_encrypt (_mongocrypt_crypto_t *crypto,
+ aes_256_args_t args)
+{
+ mongocrypt_status_t *status = args.status;
+ if (args.key->len != MONGOCRYPT_ENC_KEY_LEN) {
+ CLIENT_ERR ("invalid encryption key length");
+ return false;
+ }
+
+ if (args.iv->len != MONGOCRYPT_IV_LEN) {
+ CLIENT_ERR ("invalid iv length");
+ return false;
+ }
+
+ if (crypto->hooks_enabled) {
+ mongocrypt_binary_t enc_key_bin, iv_bin, out_bin, in_bin;
+ bool ret;
+
+ _mongocrypt_buffer_to_binary (args.key, &enc_key_bin);
+ _mongocrypt_buffer_to_binary (args.iv, &iv_bin);
+ _mongocrypt_buffer_to_binary (args.out, &out_bin);
+ _mongocrypt_buffer_to_binary (args.in, &in_bin);
+
+ ret = crypto->aes_256_cbc_encrypt (crypto->ctx,
+ &enc_key_bin,
+ &iv_bin,
+ &in_bin,
+ &out_bin,
+ args.bytes_written,
+ status);
+ return ret;
+ }
+ return _native_crypto_aes_256_cbc_encrypt (args);
+}
+
+
+static bool
+_crypto_aes_256_cbc_decrypt (_mongocrypt_crypto_t *crypto,
+ aes_256_args_t args)
+{
+ mongocrypt_status_t *status = args.status;
+ if (args.key->len != MONGOCRYPT_ENC_KEY_LEN) {
+ CLIENT_ERR ("invalid encryption key length");
+ return false;
+ }
+
+ if (crypto->hooks_enabled) {
+ mongocrypt_binary_t enc_key_bin, iv_bin, out_bin, in_bin;
+ bool ret;
+
+ _mongocrypt_buffer_to_binary (args.key, &enc_key_bin);
+ _mongocrypt_buffer_to_binary (args.iv, &iv_bin);
+ _mongocrypt_buffer_to_binary (args.out, &out_bin);
+ _mongocrypt_buffer_to_binary (args.in, &in_bin);
+
+ ret = crypto->aes_256_cbc_decrypt (crypto->ctx,
+ &enc_key_bin,
+ &iv_bin,
+ &in_bin,
+ &out_bin,
+ args.bytes_written,
+ status);
+ return ret;
+ }
+ return _native_crypto_aes_256_cbc_decrypt (args);
+}
+
+
+static bool
+_crypto_hmac_sha_512 (_mongocrypt_crypto_t *crypto,
+ const _mongocrypt_buffer_t *hmac_key,
+ const _mongocrypt_buffer_t *in,
+ _mongocrypt_buffer_t *out,
+ mongocrypt_status_t *status)
+{
+ if (hmac_key->len != MONGOCRYPT_MAC_KEY_LEN) {
+ CLIENT_ERR ("invalid hmac key length");
+ return false;
+ }
+
+ if (out->len != MONGOCRYPT_HMAC_SHA512_LEN) {
+ CLIENT_ERR ("out does not contain %d bytes", MONGOCRYPT_HMAC_SHA512_LEN);
+ return false;
+ }
+
+ if (crypto->hooks_enabled) {
+ mongocrypt_binary_t hmac_key_bin, out_bin, in_bin;
+ bool ret;
+
+ _mongocrypt_buffer_to_binary (hmac_key, &hmac_key_bin);
+ _mongocrypt_buffer_to_binary (out, &out_bin);
+ _mongocrypt_buffer_to_binary (in, &in_bin);
+
+ ret = crypto->hmac_sha_512 (
+ crypto->ctx, &hmac_key_bin, &in_bin, &out_bin, status);
+ return ret;
+ }
+ return _native_crypto_hmac_sha_512 (hmac_key, in, out, status);
+}
+
+
+static bool
+_crypto_random (_mongocrypt_crypto_t *crypto,
+ _mongocrypt_buffer_t *out,
+ uint32_t count,
+ mongocrypt_status_t *status)
+{
+ if (out->len != count) {
+ CLIENT_ERR ("out does not contain %u bytes", count);
+ return false;
+ }
+
+ if (crypto->hooks_enabled) {
+ mongocrypt_binary_t out_bin;
+
+ _mongocrypt_buffer_to_binary (out, &out_bin);
+ return crypto->random (crypto->ctx, &out_bin, count, status);
+ }
+ return _native_crypto_random (out, count, status);
+}
+
+
+/*
+ * Secure memcmp copied from the C driver.
+ */
+int
+_mongocrypt_memequal (const void *const b1, const void *const b2, size_t len)
+{
+ const unsigned char *p1 = b1, *p2 = b2;
+ int ret = 0;
+
+ for (; len > 0; len--) {
+ ret |= *p1++ ^ *p2++;
+ }
+
+ return ret;
+}
+
+/* ----------------------------------------------------------------------------
+ *
+ * _mongocrypt_calculate_ciphertext_len --
+ *
+ * For a given plaintext length, return the length of the ciphertext.
+ * This includes IV and HMAC.
+ *
+ * To compute that I'm following section 2.3 in [MCGREW]:
+ * L = 16 * ( floor(M / 16) + 2)
+ * This formula includes space for the IV, but not the sha512 HMAC.
+ * Add 32 for the sha512 HMAC.
+ *
+ * Parameters:
+ * @plaintext_len then length of the plaintext.
+ *
+ * Returns:
+ * The calculated length of the ciphertext.
+ *
+ * ----------------------------------------------------------------------------
+ */
+uint32_t
+_mongocrypt_calculate_ciphertext_len (uint32_t plaintext_len)
+{
+ return 16 * ((plaintext_len / 16) + 2) + MONGOCRYPT_HMAC_LEN;
+}
+
+
+/* ----------------------------------------------------------------------------
+ *
+ * _mongocrypt_calculate_plaintext_len --
+ *
+ * For a given ciphertext length, return the length of the plaintext.
+ * This excludes the IV and HMAC, but includes the padding.
+ *
+ * Parameters:
+ * @ciphertext_len then length of the ciphertext.
+ *
+ * Returns:
+ * The calculated length of the plaintext.
+ *
+ * ----------------------------------------------------------------------------
+ */
+uint32_t
+_mongocrypt_calculate_plaintext_len (uint32_t ciphertext_len)
+{
+ BSON_ASSERT (ciphertext_len >= MONGOCRYPT_HMAC_LEN + MONGOCRYPT_IV_LEN +
+ MONGOCRYPT_BLOCK_SIZE);
+ return ciphertext_len - (MONGOCRYPT_IV_LEN + MONGOCRYPT_HMAC_LEN);
+}
+
+
+/* ----------------------------------------------------------------------------
+ *
+ * _aes256_cbc_encrypt --
+ *
+ * Encrypts using AES256 CBC using a secret key and a known IV.
+ *
+ * Parameters:
+ * @iv a 16 byte IV.
+ * @enc_key a 32 byte key.
+ * @plaintext the plaintext to encrypt.
+ * @ciphertext the resulting ciphertext.
+ * @bytes_written a location for the resulting number of bytes written into
+ * ciphertext->data.
+ * @status set on error.
+ *
+ * Returns:
+ * True on success. On error, sets @status and returns false.
+ *
+ * Preconditions:
+ * 1. ciphertext->data has been pre-allocated with enough space for the
+ * resulting ciphertext.
+ *
+ * Postconditions:
+ * 1. bytes_written is set to the length of the written ciphertext. This
+ * is the same as _mongocrypt_calculate_ciphertext_len (plaintext->len).
+ *
+ * ----------------------------------------------------------------------------
+ */
+static bool
+_encrypt_step (_mongocrypt_crypto_t *crypto,
+ const _mongocrypt_buffer_t *iv,
+ const _mongocrypt_buffer_t *enc_key,
+ const _mongocrypt_buffer_t *plaintext,
+ _mongocrypt_buffer_t *ciphertext,
+ uint32_t *bytes_written,
+ mongocrypt_status_t *status)
+{
+ uint32_t unaligned;
+ uint32_t padding_byte;
+ _mongocrypt_buffer_t intermediates[2];
+ _mongocrypt_buffer_t to_encrypt;
+ uint8_t final_block_storage[MONGOCRYPT_BLOCK_SIZE];
+ bool ret = false;
+
+ _mongocrypt_buffer_init (&to_encrypt);
+
+ BSON_ASSERT (bytes_written);
+ *bytes_written = 0;
+
+ if (MONGOCRYPT_IV_LEN != iv->len) {
+ CLIENT_ERR ("IV should have length %d, but has length %d",
+ MONGOCRYPT_IV_LEN,
+ iv->len);
+ goto done;
+ }
+
+ if (MONGOCRYPT_ENC_KEY_LEN != enc_key->len) {
+ CLIENT_ERR ("Encryption key should have length %d, but has length %d",
+ MONGOCRYPT_ENC_KEY_LEN,
+ enc_key->len);
+ goto done;
+ }
+
+ /* calculate how many extra bytes there are after a block boundary */
+ unaligned = plaintext->len % MONGOCRYPT_BLOCK_SIZE;
+
+ /* Some crypto providers disallow variable length inputs, and require
+ * the input to be a multiple of the block size. So add everything up
+ * to but excluding the last block if not block aligned, then add
+ * the last block with padding. */
+ _mongocrypt_buffer_init (&intermediates[0]);
+ _mongocrypt_buffer_init (&intermediates[1]);
+ intermediates[0].data = (uint8_t *) plaintext->data;
+ intermediates[0].len = plaintext->len - unaligned;
+ intermediates[1].data = final_block_storage;
+ intermediates[1].len = sizeof (final_block_storage);
+
+ /* [MCGREW]: "Prior to CBC encryption, the plaintext P is padded by appending
+ * a padding string PS to that data, to ensure that len(P || PS) is a
+ * multiple of 128". This is also known as PKCS #7 padding. */
+ if (unaligned) {
+ /* Copy the unaligned bytes. */
+ memcpy (intermediates[1].data,
+ plaintext->data + (plaintext->len - unaligned),
+ unaligned);
+ /* Fill the rest with the padding byte. */
+ padding_byte = MONGOCRYPT_BLOCK_SIZE - unaligned;
+ memset (intermediates[1].data + unaligned, padding_byte, padding_byte);
+ } else {
+ /* Fill the rest with the padding byte. */
+ padding_byte = MONGOCRYPT_BLOCK_SIZE;
+ memset (intermediates[1].data, padding_byte, padding_byte);
+ }
+
+ if (!_mongocrypt_buffer_concat (&to_encrypt, intermediates, 2)) {
+ CLIENT_ERR ("failed to allocate buffer");
+ goto done;
+ }
+
+ if (!_crypto_aes_256_cbc_encrypt (
+ crypto,
+ (aes_256_args_t){.key = enc_key,
+ .iv = iv,
+ .in = &to_encrypt,
+ .out = ciphertext,
+ .bytes_written = bytes_written,
+ .status = status})) {
+ goto done;
+ }
+
+
+ if (*bytes_written % MONGOCRYPT_BLOCK_SIZE != 0) {
+ CLIENT_ERR ("encryption failure, wrote %d bytes, not a multiple of %d",
+ *bytes_written,
+ MONGOCRYPT_BLOCK_SIZE);
+ goto done;
+ }
+
+ ret = true;
+done:
+ _mongocrypt_buffer_cleanup (&to_encrypt);
+ return ret;
+}
+
+
+/* ----------------------------------------------------------------------------
+ *
+ * _hmac_sha512 --
+ *
+ * Compute the SHA512 HMAC with a secret key.
+ *
+ * Parameters:
+ * @mac_key a 32 byte key.
+ * @associated_data associated data to add into the HMAC. This may be
+ * an empty buffer.
+ * @ciphertext the ciphertext to add into the HMAC.
+ * @out a location for the resulting HMAC tag.
+ * @status set on error.
+ *
+ * Returns:
+ * True on success. On error, sets @status and returns false.
+ *
+ * Preconditions:
+ * 1. out->data has been pre-allocated with at least 64 bytes.
+ *
+ * Postconditions:
+ * 1. out->data will have a 64 byte tag appended.
+ *
+ * ----------------------------------------------------------------------------
+ */
+static bool
+_hmac_step (_mongocrypt_crypto_t *crypto,
+ const _mongocrypt_buffer_t *mac_key,
+ const _mongocrypt_buffer_t *associated_data,
+ const _mongocrypt_buffer_t *ciphertext,
+ _mongocrypt_buffer_t *out,
+ mongocrypt_status_t *status)
+{
+ _mongocrypt_buffer_t intermediates[3];
+ _mongocrypt_buffer_t to_hmac;
+ uint64_t associated_data_len_be;
+ uint8_t tag_storage[64];
+ _mongocrypt_buffer_t tag;
+ bool ret = false;
+
+ _mongocrypt_buffer_init (&to_hmac);
+
+ if (MONGOCRYPT_MAC_KEY_LEN != mac_key->len) {
+ CLIENT_ERR ("HMAC key wrong length: %d", mac_key->len);
+ goto done;
+ }
+
+ if (out->len != MONGOCRYPT_HMAC_LEN) {
+ CLIENT_ERR ("out wrong length: %d", out->len);
+ goto done;
+ }
+
+ /* [MCGREW]:
+ * """
+ * 4. The octet string AL is equal to the number of bits in A expressed as a
+ * 64-bit unsigned integer in network byte order.
+ * 5. A message authentication tag T is computed by applying HMAC [RFC2104]
+ * to the following data, in order:
+ * the associated data A,
+ * the ciphertext S computed in the previous step, and
+ * the octet string AL defined above.
+ * """
+ */
+
+ /* Add associated data. */
+ _mongocrypt_buffer_init (&intermediates[0]);
+ _mongocrypt_buffer_init (&intermediates[1]);
+ _mongocrypt_buffer_init (&intermediates[2]);
+ intermediates[0].data = associated_data->data;
+ intermediates[0].len = associated_data->len;
+ /* Add ciphertext. */
+ intermediates[1].data = ciphertext->data;
+ intermediates[1].len = ciphertext->len;
+ /* Add associated data length in bits. */
+ associated_data_len_be = 8 * (uint64_t) associated_data->len;
+ associated_data_len_be = BSON_UINT64_TO_BE (associated_data_len_be);
+ intermediates[2].data = (uint8_t *) &associated_data_len_be;
+ intermediates[2].len = sizeof (uint64_t);
+ tag.data = tag_storage;
+ tag.len = sizeof (tag_storage);
+
+
+ if (!_mongocrypt_buffer_concat (&to_hmac, intermediates, 3)) {
+ CLIENT_ERR ("failed to allocate buffer");
+ goto done;
+ }
+ if (!_crypto_hmac_sha_512 (crypto, mac_key, &to_hmac, &tag, status)) {
+ goto done;
+ }
+
+ /* [MCGREW 2.7] "The HMAC-SHA-512 value is truncated to T_LEN=32 octets" */
+ memcpy (out->data, tag.data, MONGOCRYPT_HMAC_LEN);
+ ret = true;
+done:
+ _mongocrypt_buffer_cleanup (&to_hmac);
+ return ret;
+}
+
+/* ----------------------------------------------------------------------------
+ *
+ * _mongocrypt_do_encryption --
+ *
+ * Defer encryption to whichever crypto library libmongocrypt is using.
+ *
+ * Parameters:
+ * @iv a 16 byte IV.
+ * @associated_data associated data for the HMAC. May be NULL.
+ * @key a 96 byte key.
+ * @plaintext the plaintext to encrypt.
+ * @ciphertext a location for the resulting ciphertext and HMAC tag.
+ * @bytes_written a location for the resulting bytes written.
+ * @status set on error.
+ *
+ * Returns:
+ * True on success. On error, sets @status and returns false.
+ *
+ * Preconditions:
+ * 1. ciphertext->data has been pre-allocated with enough space for the
+ * resulting ciphertext. Use _mongocrypt_calculate_ciphertext_len.
+ *
+ * Postconditions:
+ * 1. bytes_written is set to the length of the written ciphertext. This
+ * is the same as _mongocrypt_calculate_ciphertext_len (plaintext->len).
+ *
+ * ----------------------------------------------------------------------------
+ */
+bool
+_mongocrypt_do_encryption (_mongocrypt_crypto_t *crypto,
+ const _mongocrypt_buffer_t *iv,
+ const _mongocrypt_buffer_t *associated_data,
+ const _mongocrypt_buffer_t *key,
+ const _mongocrypt_buffer_t *plaintext,
+ _mongocrypt_buffer_t *ciphertext,
+ uint32_t *bytes_written,
+ mongocrypt_status_t *status)
+{
+ _mongocrypt_buffer_t mac_key = {0}, enc_key = {0}, intermediate = {0},
+ intermediate_hmac = {0}, empty_buffer = {0};
+ uint32_t intermediate_bytes_written = 0;
+
+ memset (ciphertext->data, 0, ciphertext->len);
+
+ BSON_ASSERT (iv);
+ BSON_ASSERT (key);
+ BSON_ASSERT (plaintext);
+ BSON_ASSERT (ciphertext);
+ if (ciphertext->len !=
+ _mongocrypt_calculate_ciphertext_len (plaintext->len)) {
+ CLIENT_ERR ("output ciphertext should have been allocated with %d bytes",
+ _mongocrypt_calculate_ciphertext_len (plaintext->len));
+ return false;
+ }
+
+ *bytes_written = 0;
+
+ if (MONGOCRYPT_IV_LEN != iv->len) {
+ CLIENT_ERR ("IV should have length %d, but has length %d",
+ MONGOCRYPT_IV_LEN,
+ iv->len);
+ return false;
+ }
+ if (MONGOCRYPT_KEY_LEN != key->len) {
+ CLIENT_ERR ("key should have length %d, but has length %d",
+ MONGOCRYPT_KEY_LEN,
+ key->len);
+ return false;
+ }
+
+ intermediate.len = ciphertext->len;
+ intermediate.data = ciphertext->data;
+
+ /* [MCGREW]: Step 1. "MAC_KEY consists of the initial MAC_KEY_LEN octets of
+ * K, in order. ENC_KEY consists of the final ENC_KEY_LEN octets of K, in
+ * order." */
+ mac_key.data = (uint8_t *) key->data;
+ mac_key.len = MONGOCRYPT_MAC_KEY_LEN;
+ enc_key.data = (uint8_t *) key->data + MONGOCRYPT_MAC_KEY_LEN;
+ enc_key.len = MONGOCRYPT_ENC_KEY_LEN;
+
+ /* Prepend the IV. */
+ memcpy (intermediate.data, iv->data, iv->len);
+ intermediate.data += iv->len;
+ intermediate.len -= iv->len;
+ *bytes_written += iv->len;
+
+ /* [MCGREW]: Steps 2 & 3. */
+ if (!_encrypt_step (crypto,
+ iv,
+ &enc_key,
+ plaintext,
+ &intermediate,
+ &intermediate_bytes_written,
+ status)) {
+ return false;
+ }
+
+ *bytes_written += intermediate_bytes_written;
+
+ /* Append the HMAC tag. */
+ intermediate_hmac.data = ciphertext->data + *bytes_written;
+ intermediate_hmac.len = MONGOCRYPT_HMAC_LEN;
+
+ intermediate.data = ciphertext->data;
+ intermediate.len = *bytes_written;
+
+ /* [MCGREW]: Steps 4 & 5, compute the HMAC. */
+ if (!_hmac_step (crypto,
+ &mac_key,
+ associated_data ? associated_data : &empty_buffer,
+ &intermediate,
+ &intermediate_hmac,
+ status)) {
+ return false;
+ }
+
+ *bytes_written += MONGOCRYPT_HMAC_LEN;
+ return true;
+}
+
+
+/* ----------------------------------------------------------------------------
+ *
+ * _aes256_cbc_decrypt --
+ *
+ * Decrypts using AES256 CBC using a secret key and a known IV.
+ *
+ * Parameters:
+ * @enc_key a 32 byte key.
+ * @ciphertext the ciphertext to decrypt.
+ * @plaintext the resulting plaintext.
+ * @bytes_written a location for the resulting number of bytes written into
+ * plaintext->data.
+ * @status set on error.
+ *
+ * Returns:
+ * True on success. On error, sets @status and returns false.
+ *
+ * Preconditions:
+ * 1. plaintext->data has been pre-allocated with enough space for the
+ * resulting plaintext.
+ *
+ * Postconditions:
+ * 1. bytes_written is set to the length of the written plaintext, excluding
+ * padding. This may be less than
+ * _mongocrypt_calculate_plaintext_len (ciphertext->len).
+ *
+ * ----------------------------------------------------------------------------
+ */
+static bool
+_decrypt_step (_mongocrypt_crypto_t *crypto,
+ const _mongocrypt_buffer_t *iv,
+ const _mongocrypt_buffer_t *enc_key,
+ const _mongocrypt_buffer_t *ciphertext,
+ _mongocrypt_buffer_t *plaintext,
+ uint32_t *bytes_written,
+ mongocrypt_status_t *status)
+{
+ uint8_t padding_byte;
+
+ BSON_ASSERT (bytes_written);
+ *bytes_written = 0;
+
+ if (MONGOCRYPT_IV_LEN != iv->len) {
+ CLIENT_ERR ("IV should have length %d, but has length %d",
+ MONGOCRYPT_IV_LEN,
+ iv->len);
+ return false;
+ }
+ if (MONGOCRYPT_ENC_KEY_LEN != enc_key->len) {
+ CLIENT_ERR ("encryption key should have length %d, but has length %d",
+ MONGOCRYPT_ENC_KEY_LEN,
+ enc_key->len);
+ return false;
+ }
+
+
+ if (ciphertext->len % MONGOCRYPT_BLOCK_SIZE > 0) {
+ CLIENT_ERR ("error, ciphertext length is not a multiple of block size");
+ return false;
+ }
+
+ if (!_crypto_aes_256_cbc_decrypt (
+ crypto,
+ (aes_256_args_t){.iv = iv,
+ .key = enc_key,
+ .in = ciphertext,
+ .out = plaintext,
+ .bytes_written = bytes_written,
+ .status = status})) {
+ return false;
+ }
+
+ padding_byte = plaintext->data[*bytes_written - 1];
+ if (padding_byte > 16) {
+ CLIENT_ERR ("error, ciphertext malformed padding");
+ return false;
+ }
+ *bytes_written -= padding_byte;
+ return true;
+}
+
+
+/* ----------------------------------------------------------------------------
+ *
+ * _mongocrypt_do_decryption --
+ *
+ * Defer decryption to whichever crypto library libmongocrypt is using.
+ *
+ * Parameters:
+ * @associated_data associated data for the HMAC. May be NULL.
+ * @key a 96 byte key.
+ * @ciphertext the ciphertext to decrypt. This contains the IV prepended.
+ * @plaintext a location for the resulting plaintext.
+ * @bytes_written a location for the resulting bytes written.
+ * @status set on error.
+ *
+ * Returns:
+ * True on success. On error, sets @status and returns false.
+ *
+ * Preconditions:
+ * 1. plaintext->data has been pre-allocated with enough space for the
+ * resulting plaintext and padding. See _mongocrypt_calculate_plaintext_len.
+ *
+ * Postconditions:
+ * 1. bytes_written is set to the length of the written plaintext, excluding
+ * padding. This may be less than
+ * _mongocrypt_calculate_plaintext_len (ciphertext->len).
+ *
+ * ----------------------------------------------------------------------------
+ */
+bool
+_mongocrypt_do_decryption (_mongocrypt_crypto_t *crypto,
+ const _mongocrypt_buffer_t *associated_data,
+ const _mongocrypt_buffer_t *key,
+ const _mongocrypt_buffer_t *ciphertext,
+ _mongocrypt_buffer_t *plaintext,
+ uint32_t *bytes_written,
+ mongocrypt_status_t *status)
+{
+ bool ret = false;
+ _mongocrypt_buffer_t mac_key = {0}, enc_key = {0}, intermediate = {0},
+ hmac_tag = {0}, iv = {0}, empty_buffer = {0};
+ uint8_t hmac_tag_storage[MONGOCRYPT_HMAC_LEN];
+
+ BSON_ASSERT (key);
+ BSON_ASSERT (ciphertext);
+ BSON_ASSERT (plaintext);
+ BSON_ASSERT (bytes_written);
+ BSON_ASSERT (status);
+
+ if (plaintext->len !=
+ _mongocrypt_calculate_plaintext_len (ciphertext->len)) {
+ CLIENT_ERR ("output plaintext should have been allocated with %d bytes, "
+ "but has: %d",
+ _mongocrypt_calculate_plaintext_len (ciphertext->len),
+ plaintext->len);
+ return false;
+ }
+
+ if (MONGOCRYPT_KEY_LEN != key->len) {
+ CLIENT_ERR ("key should have length %d, but has length %d",
+ MONGOCRYPT_KEY_LEN,
+ key->len);
+ return false;
+ }
+
+ if (ciphertext->len <
+ MONGOCRYPT_HMAC_LEN + MONGOCRYPT_IV_LEN + MONGOCRYPT_BLOCK_SIZE) {
+ CLIENT_ERR ("corrupt ciphertext - must be > %d bytes",
+ MONGOCRYPT_HMAC_LEN + MONGOCRYPT_IV_LEN +
+ MONGOCRYPT_BLOCK_SIZE);
+ goto done;
+ }
+
+ mac_key.data = (uint8_t *) key->data;
+ mac_key.len = MONGOCRYPT_MAC_KEY_LEN;
+ enc_key.data = (uint8_t *) key->data + MONGOCRYPT_MAC_KEY_LEN;
+ enc_key.len = MONGOCRYPT_ENC_KEY_LEN;
+
+ iv.data = ciphertext->data;
+ iv.len = MONGOCRYPT_IV_LEN;
+
+ intermediate.data = (uint8_t *) ciphertext->data;
+ intermediate.len = ciphertext->len - MONGOCRYPT_HMAC_LEN;
+
+ hmac_tag.data = hmac_tag_storage;
+ hmac_tag.len = MONGOCRYPT_HMAC_LEN;
+
+ /* [MCGREW 2.2]: Step 3: HMAC check. */
+ if (!_hmac_step (crypto,
+ &mac_key,
+ associated_data ? associated_data : &empty_buffer,
+ &intermediate,
+ &hmac_tag,
+ status)) {
+ goto done;
+ }
+
+ /* [MCGREW] "using a comparison routine that takes constant time". */
+ if (0 != _mongocrypt_memequal (hmac_tag.data,
+ ciphertext->data +
+ (ciphertext->len - MONGOCRYPT_HMAC_LEN),
+ MONGOCRYPT_HMAC_LEN)) {
+ CLIENT_ERR ("HMAC validation failure");
+ goto done;
+ }
+
+ /* Decrypt data excluding IV + HMAC. */
+ intermediate.data = (uint8_t *) ciphertext->data + MONGOCRYPT_IV_LEN;
+ intermediate.len =
+ ciphertext->len - (MONGOCRYPT_IV_LEN + MONGOCRYPT_HMAC_LEN);
+
+ if (!_decrypt_step (crypto,
+ &iv,
+ &enc_key,
+ &intermediate,
+ plaintext,
+ bytes_written,
+ status)) {
+ goto done;
+ }
+
+ ret = true;
+done:
+ return ret;
+}
+
+
+/* ----------------------------------------------------------------------------
+ *
+ * _mongocrypt_random --
+ *
+ * Generates a string of random bytes.
+ *
+ * Parameters:
+ * @out an output buffer that has been pre-allocated.
+ * @status set on error.
+ * @count the size of the random string in bytes.
+ *
+ * Returns:
+ * True on success. On error, sets @status and returns false.
+ *
+ * Preconditions:
+ * 1. out has been pre-allocated with at least 'count' bytes of space.
+ *
+ * ----------------------------------------------------------------------------
+ */
+bool
+_mongocrypt_random (_mongocrypt_crypto_t *crypto,
+ _mongocrypt_buffer_t *out,
+ uint32_t count,
+ mongocrypt_status_t *status)
+{
+ BSON_ASSERT (out);
+ BSON_ASSERT (status);
+ if (count != out->len) {
+ CLIENT_ERR (
+ "out should have length %d, but has length %d", count, out->len);
+ return false;
+ }
+
+ return _crypto_random (crypto, out, count, status);
+}
+
+
+/* ----------------------------------------------------------------------------
+ *
+ * _mongocrypt_calculate_deterministic_iv --
+ *
+ * Compute the IV for deterministic encryption from the plaintext and IV
+ * key by using HMAC function.
+ *
+ * Parameters:
+ * @key the 96 byte key. The last 32 represent the IV key.
+ * @plaintext the plaintext to be encrypted.
+ * @associated_data associated data to include in the HMAC.
+ * @out an output buffer that has been pre-allocated.
+ * @status set on error.
+ *
+ * Returns:
+ * True on success. On error, sets @status and returns false.
+ *
+ * Preconditions:
+ * 1. out has been pre-allocated with at least MONGOCRYPT_IV_LEN bytes.
+ *
+ * ----------------------------------------------------------------------------
+ */
+bool
+_mongocrypt_calculate_deterministic_iv (
+ _mongocrypt_crypto_t *crypto,
+ const _mongocrypt_buffer_t *key,
+ const _mongocrypt_buffer_t *plaintext,
+ const _mongocrypt_buffer_t *associated_data,
+ _mongocrypt_buffer_t *out,
+ mongocrypt_status_t *status)
+{
+ _mongocrypt_buffer_t intermediates[3];
+ _mongocrypt_buffer_t to_hmac;
+ _mongocrypt_buffer_t iv_key;
+ uint64_t associated_data_len_be;
+ uint8_t tag_storage[64];
+ _mongocrypt_buffer_t tag;
+ bool ret = false;
+
+ _mongocrypt_buffer_init (&to_hmac);
+
+ BSON_ASSERT (key);
+ BSON_ASSERT (plaintext);
+ BSON_ASSERT (associated_data);
+ BSON_ASSERT (out);
+ BSON_ASSERT (status);
+
+ if (MONGOCRYPT_KEY_LEN != key->len) {
+ CLIENT_ERR ("key should have length %d, but has length %d\n",
+ MONGOCRYPT_KEY_LEN,
+ key->len);
+ goto done;
+ }
+ if (MONGOCRYPT_IV_LEN != out->len) {
+ CLIENT_ERR ("out should have length %d, but has length %d\n",
+ MONGOCRYPT_IV_LEN,
+ out->len);
+ goto done;
+ }
+
+ _mongocrypt_buffer_init (&iv_key);
+ iv_key.data = key->data + MONGOCRYPT_ENC_KEY_LEN + MONGOCRYPT_MAC_KEY_LEN;
+ iv_key.len = MONGOCRYPT_IV_KEY_LEN;
+
+ _mongocrypt_buffer_init (&intermediates[0]);
+ _mongocrypt_buffer_init (&intermediates[1]);
+ _mongocrypt_buffer_init (&intermediates[2]);
+ /* Add associated data. */
+ intermediates[0].data = associated_data->data;
+ intermediates[0].len = associated_data->len;
+ /* Add associated data length in bits. */
+ associated_data_len_be = 8 * (uint64_t) associated_data->len;
+ associated_data_len_be = BSON_UINT64_TO_BE (associated_data_len_be);
+ intermediates[1].data = (uint8_t *) &associated_data_len_be;
+ intermediates[1].len = sizeof (uint64_t);
+ /* Add plaintext. */
+ intermediates[2].data = (uint8_t *) plaintext->data;
+ intermediates[2].len = plaintext->len;
+
+ tag.data = tag_storage;
+ tag.len = sizeof (tag_storage);
+
+ if (!_mongocrypt_buffer_concat (&to_hmac, intermediates, 3)) {
+ CLIENT_ERR ("failed to allocate buffer");
+ goto done;
+ }
+
+ if (!_crypto_hmac_sha_512 (crypto, &iv_key, &to_hmac, &tag, status)) {
+ goto done;
+ }
+
+ /* Truncate to IV length */
+ memcpy (out->data, tag.data, MONGOCRYPT_IV_LEN);
+
+ ret = true;
+done:
+ _mongocrypt_buffer_cleanup (&to_hmac);
+ return ret;
+}
+
+bool
+_mongocrypt_wrap_key (_mongocrypt_crypto_t *crypto,
+ _mongocrypt_buffer_t *kek,
+ _mongocrypt_buffer_t *dek,
+ _mongocrypt_buffer_t *encrypted_dek,
+ mongocrypt_status_t *status)
+{
+ uint32_t bytes_written;
+ _mongocrypt_buffer_t iv = {0};
+ bool ret = false;
+
+ _mongocrypt_buffer_init (encrypted_dek);
+
+ if (dek->len != MONGOCRYPT_KEY_LEN) {
+ CLIENT_ERR ("data encryption key is incorrect length, expected: %" PRIu32
+ ", got: %" PRIu32,
+ MONGOCRYPT_KEY_LEN,
+ dek->len);
+ goto done;
+ }
+
+ _mongocrypt_buffer_resize (encrypted_dek,
+ _mongocrypt_calculate_ciphertext_len (dek->len));
+ _mongocrypt_buffer_resize (&iv, MONGOCRYPT_IV_LEN);
+
+ if (!_mongocrypt_random (crypto, &iv, MONGOCRYPT_IV_LEN, status)) {
+ goto done;
+ }
+
+ if (!_mongocrypt_do_encryption (crypto,
+ &iv,
+ NULL /* associated data. */,
+ kek,
+ dek,
+ encrypted_dek,
+ &bytes_written,
+ status)) {
+ goto done;
+ }
+
+ ret = true;
+done:
+ _mongocrypt_buffer_cleanup (&iv);
+ return ret;
+}
+
+bool
+_mongocrypt_unwrap_key (_mongocrypt_crypto_t *crypto,
+ _mongocrypt_buffer_t *kek,
+ _mongocrypt_buffer_t *encrypted_dek,
+ _mongocrypt_buffer_t *dek,
+ mongocrypt_status_t *status)
+{
+ uint32_t bytes_written;
+
+ _mongocrypt_buffer_init (dek);
+ _mongocrypt_buffer_resize (
+ dek, _mongocrypt_calculate_plaintext_len (encrypted_dek->len));
+
+ if (!_mongocrypt_do_decryption (crypto,
+ NULL /* associated data. */,
+ kek,
+ encrypted_dek,
+ dek,
+ &bytes_written,
+ status)) {
+ return false;
+ }
+ dek->len = bytes_written;
+
+ if (dek->len != MONGOCRYPT_KEY_LEN) {
+ CLIENT_ERR ("decrypted key is incorrect length, expected: %" PRIu32
+ ", got: %" PRIu32,
+ MONGOCRYPT_KEY_LEN,
+ dek->len);
+ return false;
+ }
+ return true;
+}
diff --git a/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-ctx-datakey.c b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-ctx-datakey.c
new file mode 100644
index 00000000..b7c7adb8
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-ctx-datakey.c
@@ -0,0 +1,502 @@
+/*
+ * Copyright 2019-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mongocrypt.h"
+#include "mongocrypt-private.h"
+#include "mongocrypt-ctx-private.h"
+#include "mongocrypt-crypto-private.h"
+
+static void
+_cleanup (mongocrypt_ctx_t *ctx)
+{
+ _mongocrypt_ctx_datakey_t *dkctx;
+
+ dkctx = (_mongocrypt_ctx_datakey_t *) ctx;
+ _mongocrypt_buffer_cleanup (&dkctx->key_doc);
+ _mongocrypt_kms_ctx_cleanup (&dkctx->kms);
+ _mongocrypt_buffer_cleanup (&dkctx->encrypted_key_material);
+ _mongocrypt_buffer_cleanup (&dkctx->plaintext_key_material);
+ _mongocrypt_buffer_cleanup (&dkctx->kmip_secretdata);
+ bson_free ((void *) dkctx->kmip_unique_identifier);
+}
+
+static mongocrypt_kms_ctx_t *
+_next_kms_ctx (mongocrypt_ctx_t *ctx)
+{
+ _mongocrypt_ctx_datakey_t *dkctx;
+
+ dkctx = (_mongocrypt_ctx_datakey_t *) ctx;
+ if (dkctx->kms_returned) {
+ return NULL;
+ }
+ dkctx->kms_returned = true;
+ return &dkctx->kms;
+}
+
+static bool
+_kms_kmip_start (mongocrypt_ctx_t *ctx)
+{
+ bool ret = false;
+ _mongocrypt_ctx_datakey_t *dkctx = (_mongocrypt_ctx_datakey_t *) ctx;
+ char *user_supplied_keyid = NULL;
+ _mongocrypt_endpoint_t *endpoint = NULL;
+ mongocrypt_status_t *status = ctx->status;
+ _mongocrypt_buffer_t secretdata = {0};
+
+ if (ctx->opts.kek.kms_provider != MONGOCRYPT_KMS_PROVIDER_KMIP) {
+ CLIENT_ERR ("KMS provider is not KMIP");
+ goto fail;
+ }
+
+ user_supplied_keyid = ctx->opts.kek.provider.kmip.key_id;
+
+ if (ctx->opts.kek.provider.kmip.endpoint) {
+ endpoint = ctx->opts.kek.provider.kmip.endpoint;
+ } else if (ctx->crypt->opts.kms_provider_kmip.endpoint) {
+ endpoint = ctx->crypt->opts.kms_provider_kmip.endpoint;
+ } else {
+ CLIENT_ERR ("endpoint not set for KMIP request");
+ goto fail;
+ }
+
+ /* The KMIP createDataKey flow is the following:
+ *
+ * 1. Send a KMIP Register request with a new 96 byte key as a SecretData
+ * managed object. This returns a Unique Identifier.
+ * 2. Send a KMIP Activate request with the Unique Identifier.
+ * This returns the same Unique Identifier.
+ * 3. Send a KMIP Get request with the Unique Identifier.
+ * This returns the 96 byte SecretData.
+ * 4. Use the 96 byte SecretData to encrypt a new DEK.
+ *
+ * If the user set a 'keyId' to use, the flow begins at step 3.
+ */
+
+ if (user_supplied_keyid && !dkctx->kmip_unique_identifier) {
+ /* User set a 'keyId'. */
+ dkctx->kmip_unique_identifier = bson_strdup (user_supplied_keyid);
+ dkctx->kmip_activated = true;
+ /* Fall through to Step 3. */
+ }
+
+ if (!dkctx->kmip_unique_identifier) {
+ /* User did not set a 'keyId'. */
+ /* Step 1. Send a KMIP Register request with a new 96 byte SecretData. */
+ _mongocrypt_buffer_init (&secretdata);
+ _mongocrypt_buffer_resize (&secretdata, MONGOCRYPT_KEY_LEN);
+ if (!_mongocrypt_random (ctx->crypt->crypto,
+ &secretdata,
+ MONGOCRYPT_KEY_LEN,
+ ctx->status)) {
+ goto fail;
+ }
+
+ if (!_mongocrypt_kms_ctx_init_kmip_register (&dkctx->kms,
+ endpoint,
+ secretdata.data,
+ secretdata.len,
+ &ctx->crypt->log)) {
+ mongocrypt_kms_ctx_status (&dkctx->kms, ctx->status);
+ goto fail;
+ }
+
+ ctx->state = MONGOCRYPT_CTX_NEED_KMS;
+ goto success;
+ }
+
+ if (!dkctx->kmip_activated) {
+ /* Step 2. Send a KMIP Activate request. */
+ if (!_mongocrypt_kms_ctx_init_kmip_activate (
+ &dkctx->kms,
+ endpoint,
+ dkctx->kmip_unique_identifier,
+ &ctx->crypt->log)) {
+ mongocrypt_kms_ctx_status (&dkctx->kms, ctx->status);
+ goto fail;
+ }
+ ctx->state = MONGOCRYPT_CTX_NEED_KMS;
+ goto success;
+ }
+
+ if (!dkctx->kmip_secretdata.data) {
+ /* Step 3. Send a KMIP Get request with the Unique Identifier. */
+ if (!_mongocrypt_kms_ctx_init_kmip_get (&dkctx->kms,
+ endpoint,
+ dkctx->kmip_unique_identifier,
+ &ctx->crypt->log)) {
+ mongocrypt_kms_ctx_status (&dkctx->kms, ctx->status);
+ goto fail;
+ }
+ ctx->state = MONGOCRYPT_CTX_NEED_KMS;
+ goto success;
+ }
+
+ /* Step 4. Use the 96 byte SecretData to encrypt a new DEK. */
+ if (!_mongocrypt_wrap_key (ctx->crypt->crypto,
+ &dkctx->kmip_secretdata,
+ &dkctx->plaintext_key_material,
+ &dkctx->encrypted_key_material,
+ ctx->status)) {
+ goto fail;
+ }
+
+ if (!ctx->opts.kek.provider.kmip.key_id) {
+ /* If there was no user supplied key_id, set it from the
+ * UniqueIdentifer of the newly registered SecretData. */
+ ctx->opts.kek.provider.kmip.key_id =
+ bson_strdup (dkctx->kmip_unique_identifier);
+ }
+ ctx->state = MONGOCRYPT_CTX_READY;
+
+success:
+ ret = true;
+fail:
+ if (!ret) {
+ _mongocrypt_ctx_fail (ctx);
+ }
+ _mongocrypt_buffer_cleanup (&secretdata);
+ return ret;
+}
+
+/* For local, immediately encrypt.
+ * For AWS, create the KMS request to encrypt.
+ * For Azure/GCP, auth first if needed, otherwise encrypt.
+ */
+static bool
+_kms_start (mongocrypt_ctx_t *ctx)
+{
+ bool ret = false;
+ _mongocrypt_ctx_datakey_t *dkctx;
+ char *access_token = NULL;
+
+ dkctx = (_mongocrypt_ctx_datakey_t *) ctx;
+
+ /* Clear out any pre-existing initialized KMS context, and zero it (so it is
+ * safe to call cleanup again). */
+ _mongocrypt_kms_ctx_cleanup (&dkctx->kms);
+ memset (&dkctx->kms, 0, sizeof (dkctx->kms));
+ dkctx->kms_returned = false;
+ if (ctx->opts.kek.kms_provider == MONGOCRYPT_KMS_PROVIDER_LOCAL) {
+ if (!_mongocrypt_wrap_key (ctx->crypt->crypto,
+ &ctx->crypt->opts.kms_provider_local.key,
+ &dkctx->plaintext_key_material,
+ &dkctx->encrypted_key_material,
+ ctx->status)) {
+ _mongocrypt_ctx_fail (ctx);
+ goto done;
+ }
+ ctx->state = MONGOCRYPT_CTX_READY;
+ } else if (ctx->opts.kek.kms_provider == MONGOCRYPT_KMS_PROVIDER_AWS) {
+ /* For AWS provider, AWS credentials are supplied in
+ * mongocrypt_setopt_kms_provider_aws. Data keys are encrypted with an
+ * "encrypt" HTTP message to KMS. */
+ if (!_mongocrypt_kms_ctx_init_aws_encrypt (&dkctx->kms,
+ &ctx->crypt->opts,
+ &ctx->opts,
+ &dkctx->plaintext_key_material,
+ &ctx->crypt->log,
+ ctx->crypt->crypto)) {
+ mongocrypt_kms_ctx_status (&dkctx->kms, ctx->status);
+ _mongocrypt_ctx_fail (ctx);
+ goto done;
+ }
+
+ ctx->state = MONGOCRYPT_CTX_NEED_KMS;
+ } else if (ctx->opts.kek.kms_provider == MONGOCRYPT_KMS_PROVIDER_AZURE) {
+ access_token =
+ _mongocrypt_cache_oauth_get (ctx->crypt->cache_oauth_azure);
+ if (access_token) {
+ if (!_mongocrypt_kms_ctx_init_azure_wrapkey (
+ &dkctx->kms,
+ &ctx->crypt->log,
+ &ctx->crypt->opts,
+ &ctx->opts,
+ access_token,
+ &dkctx->plaintext_key_material)) {
+ mongocrypt_kms_ctx_status (&dkctx->kms, ctx->status);
+ _mongocrypt_ctx_fail (ctx);
+ goto done;
+ }
+ } else {
+ if (!_mongocrypt_kms_ctx_init_azure_auth (
+ &dkctx->kms,
+ &ctx->crypt->log,
+ &ctx->crypt->opts,
+ ctx->opts.kek.provider.azure.key_vault_endpoint)) {
+ mongocrypt_kms_ctx_status (&dkctx->kms, ctx->status);
+ _mongocrypt_ctx_fail (ctx);
+ goto done;
+ }
+ }
+ ctx->state = MONGOCRYPT_CTX_NEED_KMS;
+ } else if (ctx->opts.kek.kms_provider == MONGOCRYPT_KMS_PROVIDER_GCP) {
+ access_token = _mongocrypt_cache_oauth_get (ctx->crypt->cache_oauth_gcp);
+ if (access_token) {
+ if (!_mongocrypt_kms_ctx_init_gcp_encrypt (
+ &dkctx->kms,
+ &ctx->crypt->log,
+ &ctx->crypt->opts,
+ &ctx->opts,
+ access_token,
+ &dkctx->plaintext_key_material)) {
+ mongocrypt_kms_ctx_status (&dkctx->kms, ctx->status);
+ _mongocrypt_ctx_fail (ctx);
+ goto done;
+ }
+ } else {
+ if (!_mongocrypt_kms_ctx_init_gcp_auth (
+ &dkctx->kms,
+ &ctx->crypt->log,
+ &ctx->crypt->opts,
+ ctx->opts.kek.provider.gcp.endpoint)) {
+ mongocrypt_kms_ctx_status (&dkctx->kms, ctx->status);
+ _mongocrypt_ctx_fail (ctx);
+ goto done;
+ }
+ }
+ ctx->state = MONGOCRYPT_CTX_NEED_KMS;
+ } else if (ctx->opts.kek.kms_provider == MONGOCRYPT_KMS_PROVIDER_KMIP) {
+ if (!_kms_kmip_start (ctx)) {
+ goto done;
+ }
+ } else {
+ _mongocrypt_ctx_fail_w_msg (ctx, "unsupported KMS provider");
+ goto done;
+ }
+
+ ret = true;
+done:
+ bson_free (access_token);
+ return ret;
+}
+
+static bool
+_kms_done (mongocrypt_ctx_t *ctx)
+{
+ _mongocrypt_ctx_datakey_t *dkctx;
+ mongocrypt_status_t *status;
+
+ dkctx = (_mongocrypt_ctx_datakey_t *) ctx;
+ status = ctx->status;
+ if (!mongocrypt_kms_ctx_status (&dkctx->kms, ctx->status)) {
+ return _mongocrypt_ctx_fail (ctx);
+ }
+
+ if (mongocrypt_kms_ctx_bytes_needed (&dkctx->kms) != 0) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "KMS response unfinished");
+ }
+
+ /* If this was an oauth request, store the response and proceed to encrypt.
+ */
+ if (dkctx->kms.req_type == MONGOCRYPT_KMS_AZURE_OAUTH) {
+ bson_t oauth_response;
+
+ BSON_ASSERT (
+ _mongocrypt_buffer_to_bson (&dkctx->kms.result, &oauth_response));
+ if (!_mongocrypt_cache_oauth_add (
+ ctx->crypt->cache_oauth_azure, &oauth_response, status)) {
+ return _mongocrypt_ctx_fail (ctx);
+ }
+ return _kms_start (ctx);
+ } else if (dkctx->kms.req_type == MONGOCRYPT_KMS_GCP_OAUTH) {
+ bson_t oauth_response;
+
+ BSON_ASSERT (
+ _mongocrypt_buffer_to_bson (&dkctx->kms.result, &oauth_response));
+ if (!_mongocrypt_cache_oauth_add (
+ ctx->crypt->cache_oauth_gcp, &oauth_response, status)) {
+ return _mongocrypt_ctx_fail (ctx);
+ }
+ return _kms_start (ctx);
+ } else if (dkctx->kms.req_type == MONGOCRYPT_KMS_KMIP_REGISTER) {
+ dkctx->kmip_unique_identifier =
+ bson_strdup ((const char *) dkctx->kms.result.data);
+ return _kms_start (ctx);
+ } else if (dkctx->kms.req_type == MONGOCRYPT_KMS_KMIP_ACTIVATE) {
+ dkctx->kmip_activated = true;
+ return _kms_start (ctx);
+ } else if (dkctx->kms.req_type == MONGOCRYPT_KMS_KMIP_GET) {
+ _mongocrypt_buffer_copy_to (&dkctx->kms.result, &dkctx->kmip_secretdata);
+ return _kms_start (ctx);
+ }
+
+ /* Store the result. */
+ if (!_mongocrypt_kms_ctx_result (&dkctx->kms,
+ &dkctx->encrypted_key_material)) {
+ BSON_ASSERT (!mongocrypt_kms_ctx_status (&dkctx->kms, ctx->status));
+ return _mongocrypt_ctx_fail (ctx);
+ }
+
+ /* The encrypted key material must be at least as large as the plaintext. */
+ if (dkctx->encrypted_key_material.len < MONGOCRYPT_KEY_LEN) {
+ return _mongocrypt_ctx_fail_w_msg (ctx,
+ "key material not expected length");
+ }
+
+ ctx->state = MONGOCRYPT_CTX_READY;
+ return true;
+}
+
+/* Append a UUID _id. Confer with libmongoc's `_mongoc_server_session_uuid`. */
+static bool
+_append_id (mongocrypt_t *crypt, bson_t *bson, mongocrypt_status_t *status)
+{
+ _mongocrypt_buffer_t uuid;
+#define UUID_LEN 16
+
+ _mongocrypt_buffer_init (&uuid);
+ uuid.data = bson_malloc (UUID_LEN);
+ BSON_ASSERT (uuid.data);
+
+ uuid.len = UUID_LEN;
+ uuid.subtype = BSON_SUBTYPE_UUID;
+ uuid.owned = true;
+
+ if (!_mongocrypt_random (crypt->crypto, &uuid, UUID_LEN, status)) {
+ _mongocrypt_buffer_cleanup (&uuid);
+ return false;
+ }
+
+ uuid.data[6] = (uint8_t) (0x40 | (uuid.data[6] & 0xf));
+ uuid.data[8] = (uint8_t) (0x80 | (uuid.data[8] & 0x3f));
+ if (!_mongocrypt_buffer_append (&uuid, bson, "_id", 3)) {
+ _mongocrypt_buffer_cleanup (&uuid);
+ return false;
+ }
+
+ _mongocrypt_buffer_cleanup (&uuid);
+
+ return true;
+}
+
+static bool
+_finalize (mongocrypt_ctx_t *ctx, mongocrypt_binary_t *out)
+{
+ _mongocrypt_ctx_datakey_t *dkctx;
+ bson_t key_doc, child;
+ struct timeval tp;
+
+#define BSON_CHECK(_stmt) \
+ if (!(_stmt)) { \
+ bson_destroy (&key_doc); \
+ return _mongocrypt_ctx_fail_w_msg (ctx, "unable to construct BSON doc"); \
+ }
+
+ dkctx = (_mongocrypt_ctx_datakey_t *) ctx;
+
+ bson_init (&key_doc);
+ if (!_append_id (ctx->crypt, &key_doc, ctx->status)) {
+ return _mongocrypt_ctx_fail (ctx);
+ }
+
+ if (ctx->opts.key_alt_names) {
+ _mongocrypt_key_alt_name_t *alt_name = ctx->opts.key_alt_names;
+ int i;
+
+ bson_append_array_begin (&key_doc, "keyAltNames", -1, &child);
+ for (i = 0; alt_name; i++) {
+ char *key = bson_strdup_printf ("%d", i);
+ bson_append_value (&child, key, -1, &alt_name->value);
+ bson_free (key);
+ alt_name = alt_name->next;
+ }
+ bson_append_array_end (&key_doc, &child);
+ }
+ if (!_mongocrypt_buffer_append (&dkctx->encrypted_key_material,
+ &key_doc,
+ MONGOCRYPT_STR_AND_LEN ("keyMaterial"))) {
+ bson_destroy (&key_doc);
+ return _mongocrypt_ctx_fail_w_msg (ctx, "could not append keyMaterial");
+ }
+ bson_gettimeofday (&tp);
+ BSON_CHECK (bson_append_timeval (
+ &key_doc, MONGOCRYPT_STR_AND_LEN ("creationDate"), &tp));
+ BSON_CHECK (bson_append_timeval (
+ &key_doc, MONGOCRYPT_STR_AND_LEN ("updateDate"), &tp));
+ BSON_CHECK (bson_append_int32 (
+ &key_doc, MONGOCRYPT_STR_AND_LEN ("status"), 0)); /* 0 = enabled. */
+ BSON_CHECK (bson_append_document_begin (
+ &key_doc, MONGOCRYPT_STR_AND_LEN ("masterKey"), &child));
+ if (!_mongocrypt_kek_append (&ctx->opts.kek, &child, ctx->status)) {
+ bson_destroy (&key_doc);
+ return _mongocrypt_ctx_fail (ctx);
+ }
+ BSON_CHECK (bson_append_document_end (&key_doc, &child));
+ _mongocrypt_buffer_steal_from_bson (&dkctx->key_doc, &key_doc);
+ _mongocrypt_buffer_to_binary (&dkctx->key_doc, out);
+ ctx->state = MONGOCRYPT_CTX_DONE;
+ return true;
+}
+
+bool
+mongocrypt_ctx_datakey_init (mongocrypt_ctx_t *ctx)
+{
+ _mongocrypt_ctx_datakey_t *dkctx;
+ _mongocrypt_ctx_opts_spec_t opts_spec;
+ bool ret;
+
+ if (!ctx) {
+ return false;
+ }
+ ret = false;
+ memset (&opts_spec, 0, sizeof (opts_spec));
+ opts_spec.kek = OPT_REQUIRED;
+ opts_spec.key_alt_names = OPT_OPTIONAL;
+ opts_spec.key_material = OPT_OPTIONAL;
+
+ if (!_mongocrypt_ctx_init (ctx, &opts_spec)) {
+ return false;
+ }
+
+ dkctx = (_mongocrypt_ctx_datakey_t *) ctx;
+ ctx->type = _MONGOCRYPT_TYPE_CREATE_DATA_KEY;
+ ctx->vtable.mongo_op_keys = NULL;
+ ctx->vtable.mongo_feed_keys = NULL;
+ ctx->vtable.mongo_done_keys = NULL;
+ ctx->vtable.next_kms_ctx = _next_kms_ctx;
+ ctx->vtable.kms_done = _kms_done;
+ ctx->vtable.finalize = _finalize;
+ ctx->vtable.cleanup = _cleanup;
+
+ _mongocrypt_buffer_init (&dkctx->plaintext_key_material);
+
+ if (ctx->opts.key_material.owned) {
+ /* Use keyMaterial provided by user via DataKeyOpts. */
+ _mongocrypt_buffer_steal (&dkctx->plaintext_key_material,
+ &ctx->opts.key_material);
+ } else {
+ /* Generate keyMaterial instead. */
+ dkctx->plaintext_key_material.data = bson_malloc (MONGOCRYPT_KEY_LEN);
+ BSON_ASSERT (dkctx->plaintext_key_material.data);
+ dkctx->plaintext_key_material.len = MONGOCRYPT_KEY_LEN;
+ dkctx->plaintext_key_material.owned = true;
+ if (!_mongocrypt_random (ctx->crypt->crypto,
+ &dkctx->plaintext_key_material,
+ MONGOCRYPT_KEY_LEN,
+ ctx->status)) {
+ _mongocrypt_ctx_fail (ctx);
+ goto done;
+ }
+ }
+
+ if (!_kms_start (ctx)) {
+ goto done;
+ }
+
+ ret = true;
+done:
+ return ret;
+}
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-ctx-decrypt.c b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-ctx-decrypt.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-ctx-decrypt.c
rename to mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-ctx-decrypt.c
diff --git a/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-ctx-encrypt.c b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-ctx-encrypt.c
new file mode 100644
index 00000000..7cba8113
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-ctx-encrypt.c
@@ -0,0 +1,919 @@
+/*
+ * Copyright 2019-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mongocrypt-ciphertext-private.h"
+#include "mongocrypt-crypto-private.h"
+#include "mongocrypt-ctx-private.h"
+#include "mongocrypt-key-broker-private.h"
+#include "mongocrypt-marking-private.h"
+#include "mongocrypt-traverse-util-private.h"
+
+/* Construct the list collections command to send. */
+static bool
+_mongo_op_collinfo (mongocrypt_ctx_t *ctx, mongocrypt_binary_t *out)
+{
+ _mongocrypt_ctx_encrypt_t *ectx;
+ bson_t *cmd;
+
+ ectx = (_mongocrypt_ctx_encrypt_t *) ctx;
+ cmd = BCON_NEW ("name", BCON_UTF8 (ectx->coll_name));
+ CRYPT_TRACEF (&ectx->parent.crypt->log, "constructed: %s\n", tmp_json (cmd));
+ _mongocrypt_buffer_steal_from_bson (&ectx->list_collections_filter, cmd);
+ out->data = ectx->list_collections_filter.data;
+ out->len = ectx->list_collections_filter.len;
+ return true;
+}
+
+static bool
+_set_schema_from_collinfo (mongocrypt_ctx_t *ctx, bson_t *collinfo)
+{
+ bson_iter_t iter;
+ _mongocrypt_ctx_encrypt_t *ectx;
+ bool found_jsonschema = false;
+
+ /* Parse out the schema. */
+ ectx = (_mongocrypt_ctx_encrypt_t *) ctx;
+
+ /* Disallow views. */
+ if (bson_iter_init_find (&iter, collinfo, "type") &&
+ BSON_ITER_HOLDS_UTF8 (&iter) && bson_iter_utf8 (&iter, NULL) &&
+ 0 == strcmp ("view", bson_iter_utf8 (&iter, NULL))) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "cannot auto encrypt a view");
+ }
+
+ if (!bson_iter_init (&iter, collinfo)) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "BSON malformed");
+ }
+
+ if (bson_iter_find_descendant (&iter, "options.validator", &iter) &&
+ BSON_ITER_HOLDS_DOCUMENT (&iter)) {
+ if (!bson_iter_recurse (&iter, &iter)) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "BSON malformed");
+ }
+ while (bson_iter_next (&iter)) {
+ const char *key;
+
+ key = bson_iter_key (&iter);
+ BSON_ASSERT (key);
+ if (0 == strcmp ("$jsonSchema", key)) {
+ if (found_jsonschema) {
+ return _mongocrypt_ctx_fail_w_msg (
+ ctx, "duplicate $jsonSchema fields found");
+ }
+ if (!_mongocrypt_buffer_copy_from_document_iter (&ectx->schema,
+ &iter)) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "malformed $jsonSchema");
+ }
+ found_jsonschema = true;
+ } else {
+ ectx->collinfo_has_siblings = true;
+ }
+ }
+ }
+
+ if (!found_jsonschema) {
+ bson_t empty = BSON_INITIALIZER;
+
+ _mongocrypt_buffer_steal_from_bson (&ectx->schema, &empty);
+ }
+
+
+ return true;
+}
+
+static bool
+_mongo_feed_collinfo (mongocrypt_ctx_t *ctx, mongocrypt_binary_t *in)
+{
+ bson_t as_bson;
+
+ _mongocrypt_ctx_encrypt_t *ectx;
+
+ ectx = (_mongocrypt_ctx_encrypt_t *) ctx;
+ if (!bson_init_static (&as_bson, in->data, in->len)) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "BSON malformed");
+ }
+
+ /* Cache the received collinfo. */
+ if (!_mongocrypt_cache_add_copy (
+ &ctx->crypt->cache_collinfo, ectx->ns, &as_bson, ctx->status)) {
+ return _mongocrypt_ctx_fail (ctx);
+ }
+
+ if (!_set_schema_from_collinfo (ctx, &as_bson)) {
+ return false;
+ }
+
+ return true;
+}
+
+
+static bool
+_mongo_done_collinfo (mongocrypt_ctx_t *ctx)
+{
+ _mongocrypt_ctx_encrypt_t *ectx;
+
+ ectx = (_mongocrypt_ctx_encrypt_t *) ctx;
+ if (_mongocrypt_buffer_empty (&ectx->schema)) {
+ bson_t empty_collinfo = BSON_INITIALIZER;
+
+ /* If no collinfo was fed, cache an empty collinfo. */
+ if (!_mongocrypt_cache_add_copy (&ctx->crypt->cache_collinfo,
+ ectx->ns,
+ &empty_collinfo,
+ ctx->status)) {
+ bson_destroy (&empty_collinfo);
+ return _mongocrypt_ctx_fail (ctx);
+ }
+ bson_destroy (&empty_collinfo);
+ }
+
+ ectx->parent.state = MONGOCRYPT_CTX_NEED_MONGO_MARKINGS;
+ return true;
+}
+
+
+static bool
+_mongo_op_markings (mongocrypt_ctx_t *ctx, mongocrypt_binary_t *out)
+{
+ _mongocrypt_ctx_encrypt_t *ectx;
+ bson_t cmd_bson, schema_bson, mongocryptd_cmd_bson;
+
+ ectx = (_mongocrypt_ctx_encrypt_t *) ctx;
+ if (_mongocrypt_buffer_empty (&ectx->mongocryptd_cmd)) {
+ /* first, get the original command. */
+ if (!_mongocrypt_buffer_to_bson (&ectx->original_cmd, &cmd_bson)) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "invalid BSON cmd");
+ }
+
+ if (_mongocrypt_buffer_empty (&ectx->schema)) {
+ bson_init (&schema_bson);
+ } else if (!_mongocrypt_buffer_to_bson (&ectx->schema, &schema_bson)) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "invalid BSON schema");
+ }
+
+ bson_copy_to (&cmd_bson, &mongocryptd_cmd_bson);
+ BSON_APPEND_DOCUMENT (&mongocryptd_cmd_bson, "jsonSchema", &schema_bson);
+
+ /* if a local schema was not set, set isRemoteSchema=true */
+ BSON_APPEND_BOOL (
+ &mongocryptd_cmd_bson, "isRemoteSchema", !ectx->used_local_schema);
+ _mongocrypt_buffer_steal_from_bson (&ectx->mongocryptd_cmd,
+ &mongocryptd_cmd_bson);
+
+ bson_destroy (&cmd_bson);
+ bson_destroy (&schema_bson);
+ }
+ out->data = ectx->mongocryptd_cmd.data;
+ out->len = ectx->mongocryptd_cmd.len;
+ return true;
+}
+
+
+static bool
+_collect_key_from_marking (void *ctx,
+ _mongocrypt_buffer_t *in,
+ mongocrypt_status_t *status)
+{
+ _mongocrypt_marking_t marking;
+ _mongocrypt_key_broker_t *kb;
+ bool res;
+
+ kb = (_mongocrypt_key_broker_t *) ctx;
+
+ if (!_mongocrypt_marking_parse_unowned (in, &marking, status)) {
+ _mongocrypt_marking_cleanup (&marking);
+ return false;
+ }
+
+ if (marking.has_alt_name) {
+ res = _mongocrypt_key_broker_request_name (kb, &marking.key_alt_name);
+ } else {
+ res = _mongocrypt_key_broker_request_id (kb, &marking.key_id);
+ }
+
+ if (!res) {
+ _mongocrypt_key_broker_status (kb, status);
+ _mongocrypt_marking_cleanup (&marking);
+ return false;
+ }
+
+ _mongocrypt_marking_cleanup (&marking);
+
+ return true;
+}
+
+
+static bool
+_mongo_feed_markings (mongocrypt_ctx_t *ctx, mongocrypt_binary_t *in)
+{
+ /* Find keys. */
+ bson_t as_bson;
+ bson_iter_t iter;
+ _mongocrypt_ctx_encrypt_t *ectx;
+
+ ectx = (_mongocrypt_ctx_encrypt_t *) ctx;
+ if (!_mongocrypt_binary_to_bson (in, &as_bson)) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "malformed BSON");
+ }
+
+ if (bson_iter_init_find (&iter, &as_bson, "schemaRequiresEncryption") &&
+ !bson_iter_as_bool (&iter)) {
+ /* TODO: update cache: this schema does not require encryption. */
+
+ /* If using a local schema, warn if there are no encrypted fields. */
+ if (ectx->used_local_schema) {
+ _mongocrypt_log (
+ &ctx->crypt->log,
+ MONGOCRYPT_LOG_LEVEL_WARNING,
+ "local schema used but does not have encryption specifiers");
+ }
+ return true;
+ } else {
+ /* if the schema requires encryption, but has sibling validators, error.
+ */
+ if (ectx->collinfo_has_siblings) {
+ return _mongocrypt_ctx_fail_w_msg (ctx,
+ "schema requires encryption, "
+ "but collection JSON schema "
+ "validator has siblings");
+ }
+ }
+
+ if (bson_iter_init_find (&iter, &as_bson, "hasEncryptedPlaceholders") &&
+ !bson_iter_as_bool (&iter)) {
+ return true;
+ }
+
+ if (!bson_iter_init_find (&iter, &as_bson, "result")) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "malformed marking, no 'result'");
+ }
+
+ if (!_mongocrypt_buffer_copy_from_document_iter (&ectx->marked_cmd, &iter)) {
+ return _mongocrypt_ctx_fail_w_msg (
+ ctx, "malformed marking, 'result' must be a document");
+ }
+
+ if (!bson_iter_recurse (&iter, &iter)) {
+ return _mongocrypt_ctx_fail_w_msg (
+ ctx, "malformed marking, could not recurse into 'result'");
+ }
+ if (!_mongocrypt_traverse_binary_in_bson (_collect_key_from_marking,
+ (void *) &ctx->kb,
+ TRAVERSE_MATCH_MARKING,
+ &iter,
+ ctx->status)) {
+ return _mongocrypt_ctx_fail (ctx);
+ }
+
+ return true;
+}
+
+
+static bool
+_mongo_done_markings (mongocrypt_ctx_t *ctx)
+{
+ (void) _mongocrypt_key_broker_requests_done (&ctx->kb);
+ return _mongocrypt_ctx_state_from_key_broker (ctx);
+}
+
+
+static bool
+_marking_to_bson_value (void *ctx,
+ _mongocrypt_marking_t *marking,
+ bson_value_t *out,
+ mongocrypt_status_t *status)
+{
+ _mongocrypt_ciphertext_t ciphertext;
+ _mongocrypt_buffer_t serialized_ciphertext = {0};
+ bool ret = false;
+
+ BSON_ASSERT (out);
+
+ _mongocrypt_ciphertext_init (&ciphertext);
+
+ if (!_mongocrypt_marking_to_ciphertext (ctx, marking, &ciphertext, status)) {
+ goto fail;
+ }
+
+ if (!_mongocrypt_serialize_ciphertext (&ciphertext,
+ &serialized_ciphertext)) {
+ CLIENT_ERR ("malformed ciphertext");
+ goto fail;
+ };
+
+ /* ownership of serialized_ciphertext is transferred to caller. */
+ out->value_type = BSON_TYPE_BINARY;
+ out->value.v_binary.data = serialized_ciphertext.data;
+ out->value.v_binary.data_len = serialized_ciphertext.len;
+ out->value.v_binary.subtype = (bson_subtype_t) 6;
+
+ ret = true;
+
+fail:
+ _mongocrypt_ciphertext_cleanup (&ciphertext);
+ return ret;
+}
+
+
+static bool
+_replace_marking_with_ciphertext (void *ctx,
+ _mongocrypt_buffer_t *in,
+ bson_value_t *out,
+ mongocrypt_status_t *status)
+{
+ _mongocrypt_marking_t marking;
+ bool ret;
+
+ BSON_ASSERT (in);
+
+ memset (&marking, 0, sizeof (marking));
+
+ if (!_mongocrypt_marking_parse_unowned (in, &marking, status)) {
+ _mongocrypt_marking_cleanup (&marking);
+ return false;
+ }
+
+ ret = _marking_to_bson_value (ctx, &marking, out, status);
+ _mongocrypt_marking_cleanup (&marking);
+ return ret;
+}
+
+static bool
+_finalize (mongocrypt_ctx_t *ctx, mongocrypt_binary_t *out)
+{
+ bson_t as_bson, converted;
+ bson_iter_t iter;
+ _mongocrypt_ctx_encrypt_t *ectx;
+ bool res;
+
+ ectx = (_mongocrypt_ctx_encrypt_t *) ctx;
+
+ if (!ectx->explicit) {
+ if (ctx->nothing_to_do) {
+ _mongocrypt_buffer_to_binary (&ectx->original_cmd, out);
+ ctx->state = MONGOCRYPT_CTX_DONE;
+ return true;
+ }
+ if (!_mongocrypt_buffer_to_bson (&ectx->marked_cmd, &as_bson)) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "malformed bson");
+ }
+
+ bson_iter_init (&iter, &as_bson);
+ bson_init (&converted);
+ if (!_mongocrypt_transform_binary_in_bson (
+ _replace_marking_with_ciphertext,
+ &ctx->kb,
+ TRAVERSE_MATCH_MARKING,
+ &iter,
+ &converted,
+ ctx->status)) {
+ return _mongocrypt_ctx_fail (ctx);
+ }
+ } else {
+ /* For explicit encryption, we have no marking, but we can fake one */
+ _mongocrypt_marking_t marking;
+ bson_value_t value;
+
+ memset (&value, 0, sizeof (value));
+
+ _mongocrypt_marking_init (&marking);
+
+ if (!_mongocrypt_buffer_to_bson (&ectx->original_cmd, &as_bson)) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "malformed bson");
+ }
+
+ if (!bson_iter_init_find (&iter, &as_bson, "v")) {
+ return _mongocrypt_ctx_fail_w_msg (ctx,
+ "invalid msg, must contain 'v'");
+ }
+
+
+ memcpy (&marking.v_iter, &iter, sizeof (bson_iter_t));
+ marking.algorithm = ctx->opts.algorithm;
+ _mongocrypt_buffer_set_to (&ctx->opts.key_id, &marking.key_id);
+ if (ctx->opts.key_alt_names) {
+ bson_value_copy (&ctx->opts.key_alt_names->value,
+ &marking.key_alt_name);
+ marking.has_alt_name = true;
+ }
+
+ bson_init (&converted);
+ res = _marking_to_bson_value (&ctx->kb, &marking, &value, ctx->status);
+ if (res) {
+ bson_append_value (&converted, MONGOCRYPT_STR_AND_LEN ("v"), &value);
+ }
+
+ bson_value_destroy (&value);
+ _mongocrypt_marking_cleanup (&marking);
+
+ if (!res) {
+ bson_destroy (&converted);
+ return _mongocrypt_ctx_fail (ctx);
+ }
+ }
+
+ _mongocrypt_buffer_steal_from_bson (&ectx->encrypted_cmd, &converted);
+ _mongocrypt_buffer_to_binary (&ectx->encrypted_cmd, out);
+ ctx->state = MONGOCRYPT_CTX_DONE;
+
+ return true;
+}
+
+
+static void
+_cleanup (mongocrypt_ctx_t *ctx)
+{
+ _mongocrypt_ctx_encrypt_t *ectx;
+
+ ectx = (_mongocrypt_ctx_encrypt_t *) ctx;
+ bson_free (ectx->ns);
+ bson_free (ectx->db_name);
+ bson_free (ectx->coll_name);
+ _mongocrypt_buffer_cleanup (&ectx->list_collections_filter);
+ _mongocrypt_buffer_cleanup (&ectx->schema);
+ _mongocrypt_buffer_cleanup (&ectx->original_cmd);
+ _mongocrypt_buffer_cleanup (&ectx->mongocryptd_cmd);
+ _mongocrypt_buffer_cleanup (&ectx->marked_cmd);
+ _mongocrypt_buffer_cleanup (&ectx->encrypted_cmd);
+}
+
+
+static bool
+_try_schema_from_schema_map (mongocrypt_ctx_t *ctx)
+{
+ mongocrypt_t *crypt;
+ _mongocrypt_ctx_encrypt_t *ectx;
+ bson_t schema_map;
+ bson_iter_t iter;
+
+ crypt = ctx->crypt;
+ ectx = (_mongocrypt_ctx_encrypt_t *) ctx;
+
+ if (_mongocrypt_buffer_empty (&crypt->opts.schema_map)) {
+ /* No schema map set. */
+ return true;
+ }
+
+ if (!_mongocrypt_buffer_to_bson (&crypt->opts.schema_map, &schema_map)) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "malformed schema map");
+ }
+
+ if (bson_iter_init_find (&iter, &schema_map, ectx->ns)) {
+ if (!_mongocrypt_buffer_copy_from_document_iter (&ectx->schema, &iter)) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "malformed schema map");
+ }
+ ectx->used_local_schema = true;
+ ctx->state = MONGOCRYPT_CTX_NEED_MONGO_MARKINGS;
+ }
+
+ /* No schema found in map. */
+ return true;
+}
+
+
+static bool
+_try_schema_from_cache (mongocrypt_ctx_t *ctx)
+{
+ _mongocrypt_ctx_encrypt_t *ectx;
+ bson_t *collinfo = NULL;
+
+ ectx = (_mongocrypt_ctx_encrypt_t *) ctx;
+
+ /* Otherwise, we need a remote schema. Check if we have a response to
+ * listCollections cached. */
+ if (!_mongocrypt_cache_get (&ctx->crypt->cache_collinfo,
+ ectx->ns /* null terminated */,
+ (void **) &collinfo)) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "failed to retrieve from cache");
+ }
+
+ if (collinfo) {
+ if (!_set_schema_from_collinfo (ctx, collinfo)) {
+ return _mongocrypt_ctx_fail (ctx);
+ }
+ ctx->state = MONGOCRYPT_CTX_NEED_MONGO_MARKINGS;
+ } else {
+ /* we need to get it. */
+ ctx->state = MONGOCRYPT_CTX_NEED_MONGO_COLLINFO;
+ }
+
+ bson_destroy (collinfo);
+ return true;
+}
+
+static bool
+_permitted_for_encryption (bson_iter_t *iter,
+ mongocrypt_encryption_algorithm_t algo,
+ mongocrypt_status_t *status)
+{
+ bson_type_t bson_type;
+ const bson_value_t *bson_value = bson_iter_value (iter);
+ bool ret = false;
+
+ if (!bson_value) {
+ CLIENT_ERR ("Unknown BSON type");
+ goto fail;
+ }
+ bson_type = bson_value->value_type;
+ switch (bson_type) {
+ case BSON_TYPE_NULL:
+ case BSON_TYPE_MINKEY:
+ case BSON_TYPE_MAXKEY:
+ case BSON_TYPE_UNDEFINED:
+ CLIENT_ERR ("BSON type invalid for encryption");
+ goto fail;
+ case BSON_TYPE_BINARY:
+ if (bson_value->value.v_binary.subtype == 6) {
+ CLIENT_ERR ("BSON binary subtype 6 is invalid for encryption");
+ goto fail;
+ }
+ /* ok */
+ break;
+ case BSON_TYPE_DOUBLE:
+ case BSON_TYPE_DOCUMENT:
+ case BSON_TYPE_ARRAY:
+ case BSON_TYPE_CODEWSCOPE:
+ case BSON_TYPE_BOOL:
+ case BSON_TYPE_DECIMAL128:
+ if (algo == MONGOCRYPT_ENCRYPTION_ALGORITHM_DETERMINISTIC) {
+ CLIENT_ERR ("BSON type invalid for deterministic encryption");
+ goto fail;
+ }
+ break;
+ case BSON_TYPE_UTF8:
+ case BSON_TYPE_OID:
+ case BSON_TYPE_DATE_TIME:
+ case BSON_TYPE_REGEX:
+ case BSON_TYPE_DBPOINTER:
+ case BSON_TYPE_CODE:
+ case BSON_TYPE_SYMBOL:
+ case BSON_TYPE_INT32:
+ case BSON_TYPE_TIMESTAMP:
+ case BSON_TYPE_INT64:
+ /* ok */
+ break;
+ case BSON_TYPE_EOD:
+ default:
+ CLIENT_ERR ("invalid BSON value type 00");
+ goto fail;
+ }
+
+ ret = true;
+fail:
+ return ret;
+}
+
+bool
+mongocrypt_ctx_explicit_encrypt_init (mongocrypt_ctx_t *ctx,
+ mongocrypt_binary_t *msg)
+{
+ _mongocrypt_ctx_encrypt_t *ectx;
+ bson_t as_bson;
+ bson_iter_t iter;
+ _mongocrypt_ctx_opts_spec_t opts_spec;
+
+ if (!ctx) {
+ return false;
+ }
+ memset (&opts_spec, 0, sizeof (opts_spec));
+ opts_spec.key_descriptor = OPT_REQUIRED;
+ opts_spec.algorithm = OPT_REQUIRED;
+
+ if (!_mongocrypt_ctx_init (ctx, &opts_spec)) {
+ return false;
+ }
+
+ ectx = (_mongocrypt_ctx_encrypt_t *) ctx;
+ ctx->type = _MONGOCRYPT_TYPE_ENCRYPT;
+ ectx->explicit = true;
+ ctx->vtable.finalize = _finalize;
+ ctx->vtable.cleanup = _cleanup;
+
+ if (!msg || !msg->data) {
+ return _mongocrypt_ctx_fail_w_msg (
+ ctx, "msg required for explicit encryption");
+ }
+
+ if (ctx->opts.key_alt_names) {
+ if (!_mongocrypt_key_broker_request_name (
+ &ctx->kb, &ctx->opts.key_alt_names->value)) {
+ return _mongocrypt_ctx_fail (ctx);
+ }
+ } else {
+ if (!_mongocrypt_key_broker_request_id (&ctx->kb, &ctx->opts.key_id)) {
+ return _mongocrypt_ctx_fail (ctx);
+ }
+ }
+
+ _mongocrypt_buffer_init (&ectx->original_cmd);
+
+ _mongocrypt_buffer_copy_from_binary (&ectx->original_cmd, msg);
+ if (!_mongocrypt_buffer_to_bson (&ectx->original_cmd, &as_bson)) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "msg must be bson");
+ }
+
+ if (ctx->crypt->log.trace_enabled) {
+ char *cmd_val;
+ cmd_val = _mongocrypt_new_json_string_from_binary (msg);
+ _mongocrypt_log (&ctx->crypt->log,
+ MONGOCRYPT_LOG_LEVEL_TRACE,
+ "%s (%s=\"%s\")",
+ BSON_FUNC,
+ "msg",
+ cmd_val);
+ bson_free (cmd_val);
+ }
+
+ if (!bson_iter_init_find (&iter, &as_bson, "v")) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "invalid msg, must contain 'v'");
+ }
+
+ if (!_permitted_for_encryption (&iter, ctx->opts.algorithm, ctx->status)) {
+ return _mongocrypt_ctx_fail (ctx);
+ }
+
+ (void) _mongocrypt_key_broker_requests_done (&ctx->kb);
+ return _mongocrypt_ctx_state_from_key_broker (ctx);
+}
+
+static bool
+_check_cmd_for_auto_encrypt (mongocrypt_binary_t *cmd,
+ bool *bypass,
+ char **collname,
+ mongocrypt_status_t *status)
+{
+ bson_t as_bson;
+ bson_iter_t iter, ns_iter;
+ const char *cmd_name;
+ bool eligible = false;
+
+ *bypass = false;
+
+ if (!_mongocrypt_binary_to_bson (cmd, &as_bson) ||
+ !bson_iter_init (&iter, &as_bson)) {
+ CLIENT_ERR ("invalid BSON");
+ return false;
+ }
+
+ /* The command name is the first key. */
+ if (!bson_iter_next (&iter)) {
+ CLIENT_ERR ("invalid empty BSON");
+ return false;
+ }
+
+ cmd_name = bson_iter_key (&iter);
+ BSON_ASSERT (cmd_name);
+
+ /* get the collection name (or NULL if database/client command). */
+ if (0 == strcmp (cmd_name, "explain")) {
+ if (!BSON_ITER_HOLDS_DOCUMENT (&iter)) {
+ CLIENT_ERR ("explain value is not a document");
+ return false;
+ }
+ if (!bson_iter_recurse (&iter, &ns_iter)) {
+ CLIENT_ERR ("malformed BSON for encrypt command");
+ return false;
+ }
+ if (!bson_iter_next (&ns_iter)) {
+ CLIENT_ERR ("invalid empty BSON");
+ return false;
+ }
+ } else {
+ memcpy (&ns_iter, &iter, sizeof (iter));
+ }
+
+ if (BSON_ITER_HOLDS_UTF8 (&ns_iter)) {
+ *collname = bson_strdup (bson_iter_utf8 (&ns_iter, NULL));
+ } else {
+ *collname = NULL;
+ }
+
+ /* check if command is eligible for auto encryption, bypassed, or ineligible.
+ */
+ if (0 == strcmp (cmd_name, "aggregate")) {
+ /* collection level aggregate ok, database/client is not. */
+ eligible = true;
+ } else if (0 == strcmp (cmd_name, "count")) {
+ eligible = true;
+ } else if (0 == strcmp (cmd_name, "distinct")) {
+ eligible = true;
+ } else if (0 == strcmp (cmd_name, "delete")) {
+ eligible = true;
+ } else if (0 == strcmp (cmd_name, "find")) {
+ eligible = true;
+ } else if (0 == strcmp (cmd_name, "findAndModify")) {
+ eligible = true;
+ } else if (0 == strcmp (cmd_name, "getMore")) {
+ *bypass = true;
+ } else if (0 == strcmp (cmd_name, "insert")) {
+ eligible = true;
+ } else if (0 == strcmp (cmd_name, "update")) {
+ eligible = true;
+ } else if (0 == strcmp (cmd_name, "authenticate")) {
+ *bypass = true;
+ } else if (0 == strcmp (cmd_name, "getnonce")) {
+ *bypass = true;
+ } else if (0 == strcmp (cmd_name, "logout")) {
+ *bypass = true;
+ } else if (0 == bson_strcasecmp (cmd_name, "isMaster")) {
+ /* use case insensitive compare for ismaster, since some drivers send
+ * "ismaster" and others send "isMaster" */
+ *bypass = true;
+ } else if (0 == strcmp (cmd_name, "abortTransaction")) {
+ *bypass = true;
+ } else if (0 == strcmp (cmd_name, "commitTransaction")) {
+ *bypass = true;
+ } else if (0 == strcmp (cmd_name, "endSessions")) {
+ *bypass = true;
+ } else if (0 == strcmp (cmd_name, "startSession")) {
+ *bypass = true;
+ } else if (0 == strcmp (cmd_name, "create")) {
+ *bypass = true;
+ } else if (0 == strcmp (cmd_name, "createIndexes")) {
+ *bypass = true;
+ } else if (0 == strcmp (cmd_name, "drop")) {
+ *bypass = true;
+ } else if (0 == strcmp (cmd_name, "dropDatabase")) {
+ *bypass = true;
+ } else if (0 == strcmp (cmd_name, "dropIndexes")) {
+ *bypass = true;
+ } else if (0 == strcmp (cmd_name, "killCursors")) {
+ *bypass = true;
+ } else if (0 == strcmp (cmd_name, "listCollections")) {
+ *bypass = true;
+ } else if (0 == strcmp (cmd_name, "listDatabases")) {
+ *bypass = true;
+ } else if (0 == strcmp (cmd_name, "listIndexes")) {
+ *bypass = true;
+ } else if (0 == strcmp (cmd_name, "renameCollection")) {
+ *bypass = true;
+ } else if (0 == strcmp (cmd_name, "explain")) {
+ eligible = true;
+ } else if (0 == strcmp (cmd_name, "ping")) {
+ *bypass = true;
+ } else if (0 == strcmp (cmd_name, "saslStart")) {
+ *bypass = true;
+ } else if (0 == strcmp (cmd_name, "saslContinue")) {
+ *bypass = true;
+ } else if (0 == strcmp (cmd_name, "killAllSessions")) {
+ *bypass = true;
+ } else if (0 == strcmp (cmd_name, "killSessions")) {
+ *bypass = true;
+ } else if (0 == strcmp (cmd_name, "killAllSessionsByPattern")) {
+ *bypass = true;
+ } else if (0 == strcmp (cmd_name, "refreshSessions")) {
+ *bypass = true;
+ }
+
+ /* database/client commands are ineligible. */
+ if (eligible) {
+ if (!*collname) {
+ CLIENT_ERR (
+ "non-collection command not supported for auto encryption: %s",
+ cmd_name);
+ return false;
+ }
+ if (0 == strlen (*collname)) {
+ CLIENT_ERR ("empty collection name on command: %s", cmd_name);
+ return false;
+ }
+ }
+
+ if (eligible || *bypass) {
+ return true;
+ }
+
+ CLIENT_ERR ("command not supported for auto encryption: %s", cmd_name);
+ return false;
+}
+
+bool
+mongocrypt_ctx_encrypt_init (mongocrypt_ctx_t *ctx,
+ const char *db,
+ int32_t db_len,
+ mongocrypt_binary_t *cmd)
+{
+ _mongocrypt_ctx_encrypt_t *ectx;
+ _mongocrypt_ctx_opts_spec_t opts_spec;
+ bool bypass;
+
+ if (!ctx) {
+ return false;
+ }
+ memset (&opts_spec, 0, sizeof (opts_spec));
+ opts_spec.schema = OPT_OPTIONAL;
+ if (!_mongocrypt_ctx_init (ctx, &opts_spec)) {
+ return false;
+ }
+
+ ectx = (_mongocrypt_ctx_encrypt_t *) ctx;
+ ctx->type = _MONGOCRYPT_TYPE_ENCRYPT;
+ ectx->explicit = false;
+ ctx->vtable.mongo_op_collinfo = _mongo_op_collinfo;
+ ctx->vtable.mongo_feed_collinfo = _mongo_feed_collinfo;
+ ctx->vtable.mongo_done_collinfo = _mongo_done_collinfo;
+ ctx->vtable.mongo_op_collinfo = _mongo_op_collinfo;
+ ctx->vtable.mongo_op_markings = _mongo_op_markings;
+ ctx->vtable.mongo_feed_markings = _mongo_feed_markings;
+ ctx->vtable.mongo_done_markings = _mongo_done_markings;
+ ctx->vtable.finalize = _finalize;
+ ctx->vtable.cleanup = _cleanup;
+ ctx->vtable.mongo_op_collinfo = _mongo_op_collinfo;
+ ctx->vtable.mongo_feed_collinfo = _mongo_feed_collinfo;
+ ctx->vtable.mongo_done_collinfo = _mongo_done_collinfo;
+
+
+ if (!cmd || !cmd->data) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "invalid command");
+ }
+
+ _mongocrypt_buffer_copy_from_binary (&ectx->original_cmd, cmd);
+
+ if (!_check_cmd_for_auto_encrypt (
+ cmd, &bypass, &ectx->coll_name, ctx->status)) {
+ return _mongocrypt_ctx_fail (ctx);
+ }
+
+ if (bypass) {
+ ctx->nothing_to_do = true;
+ ctx->state = MONGOCRYPT_CTX_READY;
+ return true;
+ }
+
+ /* if _check_cmd_for_auto_encrypt did not bypass or error, a collection name
+ * must have been set. */
+ if (!ectx->coll_name) {
+ return _mongocrypt_ctx_fail_w_msg (
+ ctx,
+ "unexpected error: did not bypass or error but no collection name");
+ }
+
+ if (!_mongocrypt_validate_and_copy_string (db, db_len, &ectx->db_name) ||
+ 0 == strlen (ectx->db_name)) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "invalid db");
+ }
+
+ ectx->ns = bson_strdup_printf ("%s.%s", ectx->db_name, ectx->coll_name);
+
+ if (ctx->opts.kek.provider.aws.region || ctx->opts.kek.provider.aws.cmk) {
+ return _mongocrypt_ctx_fail_w_msg (
+ ctx, "aws masterkey options must not be set");
+ }
+
+ if (!_mongocrypt_buffer_empty (&ctx->opts.key_id)) {
+ return _mongocrypt_ctx_fail_w_msg (
+ ctx, "key_id must not be set for auto encryption");
+ }
+
+ if (ctx->opts.algorithm != MONGOCRYPT_ENCRYPTION_ALGORITHM_NONE) {
+ return _mongocrypt_ctx_fail_w_msg (
+ ctx, "algorithm must not be set for auto encryption");
+ }
+
+ if (ctx->crypt->log.trace_enabled) {
+ char *cmd_val;
+ cmd_val = _mongocrypt_new_json_string_from_binary (cmd);
+ _mongocrypt_log (&ctx->crypt->log,
+ MONGOCRYPT_LOG_LEVEL_TRACE,
+ "%s (%s=\"%s\", %s=%d, %s=\"%s\")",
+ BSON_FUNC,
+ "db",
+ ectx->db_name,
+ "db_len",
+ db_len,
+ "cmd",
+ cmd_val);
+ bson_free (cmd_val);
+ }
+
+ /* Check if we have a local schema from schema_map */
+ if (!_try_schema_from_schema_map (ctx)) {
+ return false;
+ }
+
+ /* If we didn't have a local schema, try the cache. */
+ if (_mongocrypt_buffer_empty (&ectx->schema)) {
+ if (!_try_schema_from_cache (ctx)) {
+ return false;
+ }
+ }
+
+ /* Otherwise, we need the the driver to fetch the schema. */
+ if (_mongocrypt_buffer_empty (&ectx->schema)) {
+ ctx->state = MONGOCRYPT_CTX_NEED_MONGO_COLLINFO;
+ }
+ return true;
+}
diff --git a/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-ctx-private.h b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-ctx-private.h
new file mode 100644
index 00000000..68459aae
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-ctx-private.h
@@ -0,0 +1,174 @@
+/*
+ * Copyright 2019-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef MONGOCRYPT_CTX_PRIVATE_H
+#define MONGOCRYPT_CTX_PRIVATE_H
+
+#include "mongocrypt.h"
+#include "mongocrypt-private.h"
+#include "mongocrypt-buffer-private.h"
+#include "mongocrypt-key-broker-private.h"
+#include "mongocrypt-key-private.h"
+#include "mongocrypt-endpoint-private.h"
+
+typedef enum {
+ _MONGOCRYPT_TYPE_NONE,
+ _MONGOCRYPT_TYPE_ENCRYPT,
+ _MONGOCRYPT_TYPE_DECRYPT,
+ _MONGOCRYPT_TYPE_CREATE_DATA_KEY,
+} _mongocrypt_ctx_type_t;
+
+/* Option values are validated when set.
+ * Different contexts accept/require different options,
+ * validated when a context is initialized.
+ */
+typedef struct __mongocrypt_ctx_opts_t {
+ _mongocrypt_buffer_t key_id;
+ _mongocrypt_key_alt_name_t *key_alt_names;
+ _mongocrypt_buffer_t key_material;
+ mongocrypt_encryption_algorithm_t algorithm;
+ _mongocrypt_kek_t kek;
+} _mongocrypt_ctx_opts_t;
+
+
+/* All derived contexts may override these methods. */
+typedef struct {
+ bool (*mongo_op_collinfo) (mongocrypt_ctx_t *ctx, mongocrypt_binary_t *out);
+ bool (*mongo_feed_collinfo) (mongocrypt_ctx_t *ctx, mongocrypt_binary_t *in);
+ bool (*mongo_done_collinfo) (mongocrypt_ctx_t *ctx);
+ bool (*mongo_op_markings) (mongocrypt_ctx_t *ctx, mongocrypt_binary_t *out);
+ bool (*mongo_feed_markings) (mongocrypt_ctx_t *ctx, mongocrypt_binary_t *in);
+ bool (*mongo_done_markings) (mongocrypt_ctx_t *ctx);
+ bool (*mongo_op_keys) (mongocrypt_ctx_t *ctx, mongocrypt_binary_t *out);
+ bool (*mongo_feed_keys) (mongocrypt_ctx_t *ctx, mongocrypt_binary_t *in);
+ bool (*mongo_done_keys) (mongocrypt_ctx_t *ctx);
+ mongocrypt_kms_ctx_t *(*next_kms_ctx) (mongocrypt_ctx_t *ctx);
+ bool (*kms_done) (mongocrypt_ctx_t *ctx);
+ bool (*finalize) (mongocrypt_ctx_t *ctx, mongocrypt_binary_t *out);
+ void (*cleanup) (mongocrypt_ctx_t *ctx);
+} _mongocrypt_vtable_t;
+
+
+struct _mongocrypt_ctx_t {
+ mongocrypt_t *crypt;
+ mongocrypt_ctx_state_t state;
+ _mongocrypt_ctx_type_t type;
+ mongocrypt_status_t *status;
+ _mongocrypt_key_broker_t kb;
+ _mongocrypt_vtable_t vtable;
+ _mongocrypt_ctx_opts_t opts;
+ bool initialized;
+ bool
+ nothing_to_do; /* set to true if no encryption/decryption is required. */
+};
+
+
+/* Transition to the error state. An error status must have been set. */
+bool
+_mongocrypt_ctx_fail (mongocrypt_ctx_t *ctx);
+
+
+/* Set an error status and transition to the error state. */
+bool
+_mongocrypt_ctx_fail_w_msg (mongocrypt_ctx_t *ctx, const char *msg);
+
+
+typedef struct {
+ mongocrypt_ctx_t parent;
+ bool explicit;
+ char *coll_name;
+ char *db_name;
+ char *ns;
+ _mongocrypt_buffer_t list_collections_filter;
+ _mongocrypt_buffer_t schema;
+ /* TODO CDRIVER-3150: audit + rename these buffers.
+ * original_cmd for explicit is {v: <BSON value>}, for auto is the command to
+ * be encrypted.
+ *
+ * mongocryptd_cmd is only applicable for auto encryption. It is the original
+ * command with JSONSchema appended.
+ *
+ * marked_cmd is the value of the 'result' field in mongocryptd response
+ *
+ * encrypted_cmd is the final output, the original command encrypted, or for
+ * explicit, the {v: <ciphertext>} doc.
+ */
+ _mongocrypt_buffer_t original_cmd;
+ _mongocrypt_buffer_t mongocryptd_cmd;
+ _mongocrypt_buffer_t marked_cmd;
+ _mongocrypt_buffer_t encrypted_cmd;
+ _mongocrypt_buffer_t key_id;
+ bool used_local_schema;
+ /* collinfo_has_siblings is true if the schema came from a remote JSON
+ * schema, and there were siblings. */
+ bool collinfo_has_siblings;
+} _mongocrypt_ctx_encrypt_t;
+
+
+typedef struct {
+ mongocrypt_ctx_t parent;
+ bool explicit;
+ /* TODO CDRIVER-3150: audit + rename these buffers.
+ * Unlike ctx_encrypt, unwrapped_doc holds the binary value of the {v:
+ * <ciphertext>} doc.
+ * */
+ _mongocrypt_buffer_t original_doc;
+ _mongocrypt_buffer_t unwrapped_doc; /* explicit only */
+ _mongocrypt_buffer_t decrypted_doc;
+} _mongocrypt_ctx_decrypt_t;
+
+
+typedef struct {
+ mongocrypt_ctx_t parent;
+ mongocrypt_kms_ctx_t kms;
+ bool kms_returned;
+ _mongocrypt_buffer_t key_doc;
+ _mongocrypt_buffer_t plaintext_key_material;
+ _mongocrypt_buffer_t encrypted_key_material;
+
+ const char *kmip_unique_identifier;
+ bool kmip_activated;
+ _mongocrypt_buffer_t kmip_secretdata;
+} _mongocrypt_ctx_datakey_t;
+
+
+/* Used for option validation. True means required. False means prohibited. */
+typedef enum {
+ OPT_PROHIBITED = 0,
+ OPT_REQUIRED,
+ OPT_OPTIONAL
+} _mongocrypt_ctx_opt_spec_t;
+typedef struct {
+ _mongocrypt_ctx_opt_spec_t kek;
+ _mongocrypt_ctx_opt_spec_t schema;
+ _mongocrypt_ctx_opt_spec_t key_descriptor; /* a key_id or key_alt_name */
+ _mongocrypt_ctx_opt_spec_t key_alt_names;
+ _mongocrypt_ctx_opt_spec_t key_material;
+ _mongocrypt_ctx_opt_spec_t algorithm;
+} _mongocrypt_ctx_opts_spec_t;
+
+/* Common initialization. */
+bool
+_mongocrypt_ctx_init (mongocrypt_ctx_t *ctx,
+ _mongocrypt_ctx_opts_spec_t *opt_spec)
+ MONGOCRYPT_WARN_UNUSED_RESULT;
+
+/* Set the state of the context from the state of keys in the key broker. */
+bool
+_mongocrypt_ctx_state_from_key_broker (mongocrypt_ctx_t *ctx)
+ MONGOCRYPT_WARN_UNUSED_RESULT;
+
+#endif /* MONGOCRYPT_CTX_PRIVATE_H */
diff --git a/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-ctx.c b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-ctx.c
new file mode 100644
index 00000000..06b16d07
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-ctx.c
@@ -0,0 +1,967 @@
+/*
+ * Copyright 2019-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <bson/bson.h>
+
+#include "mongocrypt-ctx-private.h"
+#include "mongocrypt-key-broker-private.h"
+
+#define ALGORITHM_DETERMINISTIC "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic"
+#define ALGORITHM_DETERMINISTIC_LEN 43
+#define ALGORITHM_RANDOM "AEAD_AES_256_CBC_HMAC_SHA_512-Random"
+#define ALGORITHM_RANDOM_LEN 36
+
+bool
+_mongocrypt_ctx_fail_w_msg (mongocrypt_ctx_t *ctx, const char *msg)
+{
+ _mongocrypt_set_error (ctx->status,
+ MONGOCRYPT_STATUS_ERROR_CLIENT,
+ MONGOCRYPT_GENERIC_ERROR_CODE,
+ "%s",
+ msg);
+ return _mongocrypt_ctx_fail (ctx);
+}
+
+/* A failure status has already been set. */
+bool
+_mongocrypt_ctx_fail (mongocrypt_ctx_t *ctx)
+{
+ if (mongocrypt_status_ok (ctx->status)) {
+ return _mongocrypt_ctx_fail_w_msg (
+ ctx, "unexpected, failing but no error status set");
+ }
+ ctx->state = MONGOCRYPT_CTX_ERROR;
+ return false;
+}
+
+
+static bool
+_set_binary_opt (mongocrypt_ctx_t *ctx,
+ mongocrypt_binary_t *binary,
+ _mongocrypt_buffer_t *buf,
+ bson_subtype_t subtype)
+{
+ BSON_ASSERT (ctx);
+
+ if (ctx->state == MONGOCRYPT_CTX_ERROR) {
+ return false;
+ }
+
+ if (!binary || !binary->data) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "option must be non-NULL");
+ }
+
+ if (!_mongocrypt_buffer_empty (buf)) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "option already set");
+ }
+
+ if (ctx->initialized) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "cannot set options after init");
+ }
+
+ if (subtype == BSON_SUBTYPE_UUID && binary->len != 16) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "expected 16 byte UUID");
+ }
+
+ _mongocrypt_buffer_copy_from_binary (buf, binary);
+ buf->subtype = subtype;
+
+ return true;
+}
+
+
+bool
+mongocrypt_ctx_setopt_key_id (mongocrypt_ctx_t *ctx,
+ mongocrypt_binary_t *key_id)
+{
+ if (!ctx) {
+ return false;
+ }
+
+ if (ctx->crypt->log.trace_enabled && key_id && key_id->data) {
+ char *key_id_val;
+ key_id_val =
+ _mongocrypt_new_string_from_bytes (key_id->data, key_id->len);
+ _mongocrypt_log (&ctx->crypt->log,
+ MONGOCRYPT_LOG_LEVEL_TRACE,
+ "%s (%s=\"%s\")",
+ BSON_FUNC,
+ "key_id",
+ key_id_val);
+ bson_free (key_id_val);
+ }
+
+ return _set_binary_opt (ctx, key_id, &ctx->opts.key_id, BSON_SUBTYPE_UUID);
+}
+
+
+bool
+mongocrypt_ctx_setopt_key_alt_name (mongocrypt_ctx_t *ctx,
+ mongocrypt_binary_t *key_alt_name)
+{
+ bson_t as_bson;
+ bson_iter_t iter;
+ _mongocrypt_key_alt_name_t *new_key_alt_name;
+ const char *key;
+
+ if (!ctx) {
+ return false;
+ }
+
+ if (ctx->initialized) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "cannot set options after init");
+ }
+
+ if (ctx->state == MONGOCRYPT_CTX_ERROR) {
+ return false;
+ }
+
+ if (!key_alt_name || !key_alt_name->data) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "option must be non-NULL");
+ }
+
+ if (!_mongocrypt_binary_to_bson (key_alt_name, &as_bson)) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "invalid keyAltName bson object");
+ }
+
+ if (!bson_iter_init (&iter, &as_bson) || !bson_iter_next (&iter)) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "invalid bson");
+ }
+
+ key = bson_iter_key (&iter);
+ BSON_ASSERT (key);
+ if (0 != strcmp (key, "keyAltName")) {
+ return _mongocrypt_ctx_fail_w_msg (
+ ctx, "keyAltName must have field 'keyAltName'");
+ }
+
+ if (!BSON_ITER_HOLDS_UTF8 (&iter)) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "keyAltName expected to be UTF8");
+ }
+
+ new_key_alt_name = _mongocrypt_key_alt_name_new (bson_iter_value (&iter));
+
+ if (ctx->opts.key_alt_names &&
+ _mongocrypt_key_alt_name_intersects (ctx->opts.key_alt_names,
+ new_key_alt_name)) {
+ _mongocrypt_key_alt_name_destroy_all (new_key_alt_name);
+ return _mongocrypt_ctx_fail_w_msg (ctx, "duplicate keyAltNames found");
+ }
+ new_key_alt_name->next = ctx->opts.key_alt_names;
+ ctx->opts.key_alt_names = new_key_alt_name;
+
+ if (bson_iter_next (&iter)) {
+ return _mongocrypt_ctx_fail_w_msg (
+ ctx, "unrecognized field, only keyAltName expected");
+ }
+
+ return true;
+}
+
+
+bool
+mongocrypt_ctx_setopt_key_material (mongocrypt_ctx_t *ctx,
+ mongocrypt_binary_t *key_material)
+{
+ bson_t as_bson;
+ bson_iter_t iter;
+ const char *key;
+ _mongocrypt_buffer_t buffer;
+
+ if (!ctx) {
+ return false;
+ }
+
+ if (ctx->initialized) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "cannot set options after init");
+ }
+
+ if (ctx->opts.key_material.owned) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "keyMaterial already set");
+ }
+
+ if (ctx->state == MONGOCRYPT_CTX_ERROR) {
+ return false;
+ }
+
+ if (!key_material || !key_material->data) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "option must be non-NULL");
+ }
+
+ if (!_mongocrypt_binary_to_bson (key_material, &as_bson)) {
+ return _mongocrypt_ctx_fail_w_msg (ctx,
+ "invalid keyMaterial bson object");
+ }
+
+ /* TODO: use _mongocrypt_parse_required_binary once MONGOCRYPT-380 is
+ * resolved.*/
+ if (!bson_iter_init (&iter, &as_bson) || !bson_iter_next (&iter)) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "invalid bson");
+ }
+
+ key = bson_iter_key (&iter);
+ BSON_ASSERT (key);
+ if (0 != strcmp (key, "keyMaterial")) {
+ return _mongocrypt_ctx_fail_w_msg (
+ ctx, "keyMaterial must have field 'keyMaterial'");
+ }
+
+ if (!_mongocrypt_buffer_from_binary_iter (&buffer, &iter)) {
+ return _mongocrypt_ctx_fail_w_msg (ctx,
+ "keyMaterial must be binary data");
+ }
+
+ if (buffer.len != MONGOCRYPT_KEY_LEN) {
+ _mongocrypt_set_error (
+ ctx->status,
+ MONGOCRYPT_STATUS_ERROR_CLIENT,
+ MONGOCRYPT_GENERIC_ERROR_CODE,
+ "keyMaterial should have length %d, but has length %" PRIu32,
+ MONGOCRYPT_KEY_LEN,
+ buffer.len);
+ return _mongocrypt_ctx_fail (ctx);
+ }
+
+ _mongocrypt_buffer_steal (&ctx->opts.key_material, &buffer);
+
+ if (bson_iter_next (&iter)) {
+ return _mongocrypt_ctx_fail_w_msg (
+ ctx, "unrecognized field, only keyMaterial expected");
+ }
+
+ return true;
+}
+
+
+bool
+mongocrypt_ctx_setopt_algorithm (mongocrypt_ctx_t *ctx,
+ const char *algorithm,
+ int len)
+{
+ size_t calculated_len;
+
+ if (!ctx) {
+ return false;
+ }
+
+ if (ctx->initialized) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "cannot set options after init");
+ }
+
+ if (ctx->state == MONGOCRYPT_CTX_ERROR) {
+ return false;
+ }
+
+ if (ctx->opts.algorithm != MONGOCRYPT_ENCRYPTION_ALGORITHM_NONE) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "already set algorithm");
+ }
+
+ if (len < -1) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "invalid algorithm length");
+ }
+
+ if (!algorithm) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "passed null algorithm");
+ }
+
+ calculated_len = len == -1 ? strlen (algorithm) : (size_t) len;
+ if (ctx->crypt->log.trace_enabled) {
+ _mongocrypt_log (&ctx->crypt->log,
+ MONGOCRYPT_LOG_LEVEL_TRACE,
+ "%s (%s=\"%.*s\")",
+ BSON_FUNC,
+ "algorithm",
+ (int) calculated_len,
+ algorithm);
+ }
+
+ if (calculated_len == ALGORITHM_DETERMINISTIC_LEN &&
+ strncmp (algorithm,
+ ALGORITHM_DETERMINISTIC,
+ ALGORITHM_DETERMINISTIC_LEN) == 0) {
+ ctx->opts.algorithm = MONGOCRYPT_ENCRYPTION_ALGORITHM_DETERMINISTIC;
+ return true;
+ }
+
+ if (calculated_len == ALGORITHM_RANDOM_LEN &&
+ strncmp (algorithm, ALGORITHM_RANDOM, ALGORITHM_RANDOM_LEN) == 0) {
+ ctx->opts.algorithm = MONGOCRYPT_ENCRYPTION_ALGORITHM_RANDOM;
+ return true;
+ }
+
+ return _mongocrypt_ctx_fail_w_msg (ctx, "unsupported algorithm");
+}
+
+
+mongocrypt_ctx_t *
+mongocrypt_ctx_new (mongocrypt_t *crypt)
+{
+ mongocrypt_ctx_t *ctx;
+ size_t ctx_size;
+
+ if (!crypt) {
+ return NULL;
+ }
+ if (!crypt->initialized) {
+ mongocrypt_status_t *status;
+
+ status = crypt->status;
+ CLIENT_ERR ("cannot create context from uninitialized crypt");
+ return NULL;
+ }
+ ctx_size = sizeof (_mongocrypt_ctx_encrypt_t);
+ if (sizeof (_mongocrypt_ctx_decrypt_t) > ctx_size) {
+ ctx_size = sizeof (_mongocrypt_ctx_decrypt_t);
+ }
+ if (sizeof (_mongocrypt_ctx_datakey_t) > ctx_size) {
+ ctx_size = sizeof (_mongocrypt_ctx_datakey_t);
+ }
+ ctx = bson_malloc0 (ctx_size);
+ BSON_ASSERT (ctx);
+
+ ctx->crypt = crypt;
+ ctx->status = mongocrypt_status_new ();
+ ctx->opts.algorithm = MONGOCRYPT_ENCRYPTION_ALGORITHM_NONE;
+ ctx->state = MONGOCRYPT_CTX_DONE;
+ return ctx;
+}
+
+#define CHECK_AND_CALL(fn, ...) \
+ do { \
+ if (!ctx->vtable.fn) { \
+ return _mongocrypt_ctx_fail_w_msg (ctx, "not applicable to context"); \
+ } \
+ return ctx->vtable.fn (__VA_ARGS__); \
+ } while (0)
+
+/* Common to both encrypt and decrypt context. */
+static bool
+_mongo_op_keys (mongocrypt_ctx_t *ctx, mongocrypt_binary_t *out)
+{
+ /* Construct the find filter to fetch keys. */
+ if (!_mongocrypt_key_broker_filter (&ctx->kb, out)) {
+ BSON_ASSERT (!_mongocrypt_key_broker_status (&ctx->kb, ctx->status));
+ return _mongocrypt_ctx_fail (ctx);
+ }
+ return true;
+}
+
+
+static bool
+_mongo_feed_keys (mongocrypt_ctx_t *ctx, mongocrypt_binary_t *in)
+{
+ _mongocrypt_buffer_t buf;
+
+ _mongocrypt_buffer_from_binary (&buf, in);
+ if (!_mongocrypt_key_broker_add_doc (&ctx->kb, &buf)) {
+ BSON_ASSERT (!_mongocrypt_key_broker_status (&ctx->kb, ctx->status));
+ return _mongocrypt_ctx_fail (ctx);
+ }
+ return true;
+}
+
+
+static bool
+_mongo_done_keys (mongocrypt_ctx_t *ctx)
+{
+ (void) _mongocrypt_key_broker_docs_done (&ctx->kb);
+ return _mongocrypt_ctx_state_from_key_broker (ctx);
+}
+
+static mongocrypt_kms_ctx_t *
+_next_kms_ctx (mongocrypt_ctx_t *ctx)
+{
+ return _mongocrypt_key_broker_next_kms (&ctx->kb);
+}
+
+
+static bool
+_kms_done (mongocrypt_ctx_t *ctx)
+{
+ if (!_mongocrypt_key_broker_kms_done (&ctx->kb)) {
+ BSON_ASSERT (!_mongocrypt_key_broker_status (&ctx->kb, ctx->status));
+ return _mongocrypt_ctx_fail (ctx);
+ }
+ return _mongocrypt_ctx_state_from_key_broker (ctx);
+}
+
+
+bool
+mongocrypt_ctx_mongo_op (mongocrypt_ctx_t *ctx, mongocrypt_binary_t *out)
+{
+ if (!ctx) {
+ return false;
+ }
+ if (!ctx->initialized) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "ctx NULL or uninitialized");
+ }
+
+ if (!out) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "invalid NULL input");
+ }
+
+ switch (ctx->state) {
+ case MONGOCRYPT_CTX_NEED_MONGO_COLLINFO:
+ CHECK_AND_CALL (mongo_op_collinfo, ctx, out);
+ case MONGOCRYPT_CTX_NEED_MONGO_MARKINGS:
+ CHECK_AND_CALL (mongo_op_markings, ctx, out);
+ case MONGOCRYPT_CTX_NEED_MONGO_KEYS:
+ CHECK_AND_CALL (mongo_op_keys, ctx, out);
+ case MONGOCRYPT_CTX_ERROR:
+ return false;
+ default:
+ return _mongocrypt_ctx_fail_w_msg (ctx, "wrong state");
+ }
+}
+
+
+bool
+mongocrypt_ctx_mongo_feed (mongocrypt_ctx_t *ctx, mongocrypt_binary_t *in)
+{
+ if (!ctx) {
+ return false;
+ }
+ if (!ctx->initialized) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "ctx NULL or uninitialized");
+ }
+
+ if (!in) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "invalid NULL input");
+ }
+
+ if (ctx->crypt->log.trace_enabled) {
+ char *in_val;
+
+ in_val = _mongocrypt_new_json_string_from_binary (in);
+ _mongocrypt_log (&ctx->crypt->log,
+ MONGOCRYPT_LOG_LEVEL_TRACE,
+ "%s (%s=\"%s\")",
+ BSON_FUNC,
+ "in",
+ in_val);
+ bson_free (in_val);
+ }
+
+ switch (ctx->state) {
+ case MONGOCRYPT_CTX_NEED_MONGO_COLLINFO:
+ CHECK_AND_CALL (mongo_feed_collinfo, ctx, in);
+ case MONGOCRYPT_CTX_NEED_MONGO_MARKINGS:
+ CHECK_AND_CALL (mongo_feed_markings, ctx, in);
+ case MONGOCRYPT_CTX_NEED_MONGO_KEYS:
+ CHECK_AND_CALL (mongo_feed_keys, ctx, in);
+ case MONGOCRYPT_CTX_ERROR:
+ return false;
+ default:
+ return _mongocrypt_ctx_fail_w_msg (ctx, "wrong state");
+ }
+}
+
+
+bool
+mongocrypt_ctx_mongo_done (mongocrypt_ctx_t *ctx)
+{
+ if (!ctx) {
+ return false;
+ }
+ if (!ctx->initialized) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "ctx NULL or uninitialized");
+ }
+
+ switch (ctx->state) {
+ case MONGOCRYPT_CTX_NEED_MONGO_COLLINFO:
+ CHECK_AND_CALL (mongo_done_collinfo, ctx);
+ case MONGOCRYPT_CTX_NEED_MONGO_MARKINGS:
+ CHECK_AND_CALL (mongo_done_markings, ctx);
+ case MONGOCRYPT_CTX_NEED_MONGO_KEYS:
+ CHECK_AND_CALL (mongo_done_keys, ctx);
+ case MONGOCRYPT_CTX_ERROR:
+ return false;
+ default:
+ return _mongocrypt_ctx_fail_w_msg (ctx, "wrong state");
+ }
+}
+
+
+mongocrypt_ctx_state_t
+mongocrypt_ctx_state (mongocrypt_ctx_t *ctx)
+{
+ if (!ctx) {
+ return MONGOCRYPT_CTX_ERROR;
+ }
+ if (!ctx->initialized) {
+ _mongocrypt_ctx_fail_w_msg (ctx, "ctx NULL or uninitialized");
+ return MONGOCRYPT_CTX_ERROR;
+ }
+
+ return ctx->state;
+}
+
+
+mongocrypt_kms_ctx_t *
+mongocrypt_ctx_next_kms_ctx (mongocrypt_ctx_t *ctx)
+{
+ if (!ctx) {
+ return NULL;
+ }
+ if (!ctx->initialized) {
+ _mongocrypt_ctx_fail_w_msg (ctx, "ctx NULL or uninitialized");
+ return NULL;
+ }
+
+ if (!ctx->vtable.next_kms_ctx) {
+ _mongocrypt_ctx_fail_w_msg (ctx, "not applicable to context");
+ return NULL;
+ }
+
+ switch (ctx->state) {
+ case MONGOCRYPT_CTX_NEED_KMS:
+ return ctx->vtable.next_kms_ctx (ctx);
+ case MONGOCRYPT_CTX_ERROR:
+ return NULL;
+ default:
+ _mongocrypt_ctx_fail_w_msg (ctx, "wrong state");
+ return NULL;
+ }
+}
+
+
+bool
+mongocrypt_ctx_kms_done (mongocrypt_ctx_t *ctx)
+{
+ if (!ctx) {
+ return false;
+ }
+ if (!ctx->initialized) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "ctx NULL or uninitialized");
+ }
+
+ if (!ctx->vtable.kms_done) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "not applicable to context");
+ }
+
+ switch (ctx->state) {
+ case MONGOCRYPT_CTX_NEED_KMS:
+ return ctx->vtable.kms_done (ctx);
+ case MONGOCRYPT_CTX_ERROR:
+ return false;
+ default:
+ return _mongocrypt_ctx_fail_w_msg (ctx, "wrong state");
+ }
+}
+
+
+bool
+mongocrypt_ctx_finalize (mongocrypt_ctx_t *ctx, mongocrypt_binary_t *out)
+{
+ if (!ctx) {
+ return false;
+ }
+ if (!ctx->initialized) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "ctx NULL or uninitialized");
+ }
+
+ if (!out) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "invalid NULL input");
+ }
+
+ if (!ctx->vtable.finalize) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "not applicable to context");
+ }
+
+ switch (ctx->state) {
+ case MONGOCRYPT_CTX_READY:
+ return ctx->vtable.finalize (ctx, out);
+ case MONGOCRYPT_CTX_ERROR:
+ return false;
+ default:
+ return _mongocrypt_ctx_fail_w_msg (ctx, "wrong state");
+ }
+}
+
+bool
+mongocrypt_ctx_status (mongocrypt_ctx_t *ctx, mongocrypt_status_t *out)
+{
+ if (!ctx) {
+ return false;
+ }
+
+ if (!mongocrypt_status_ok (ctx->status)) {
+ _mongocrypt_status_copy_to (ctx->status, out);
+ return false;
+ }
+ _mongocrypt_status_reset (out);
+ return true;
+}
+
+
+void
+mongocrypt_ctx_destroy (mongocrypt_ctx_t *ctx)
+{
+ if (!ctx) {
+ return;
+ }
+
+ if (ctx->vtable.cleanup) {
+ ctx->vtable.cleanup (ctx);
+ }
+
+ _mongocrypt_kek_cleanup (&ctx->opts.kek);
+ mongocrypt_status_destroy (ctx->status);
+ _mongocrypt_key_broker_cleanup (&ctx->kb);
+ _mongocrypt_buffer_cleanup (&ctx->opts.key_material);
+ _mongocrypt_key_alt_name_destroy_all (ctx->opts.key_alt_names);
+ _mongocrypt_buffer_cleanup (&ctx->opts.key_id);
+ bson_free (ctx);
+ return;
+}
+
+
+bool
+mongocrypt_ctx_setopt_masterkey_aws (mongocrypt_ctx_t *ctx,
+ const char *region,
+ int32_t region_len,
+ const char *cmk,
+ int32_t cmk_len)
+{
+ mongocrypt_binary_t *bin;
+ bson_t as_bson;
+ bool ret;
+ char *temp = NULL;
+
+ if (!ctx) {
+ return false;
+ }
+ if (ctx->initialized) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "cannot set options after init");
+ }
+
+ if (ctx->state == MONGOCRYPT_CTX_ERROR) {
+ return false;
+ }
+
+ if (ctx->opts.kek.kms_provider != MONGOCRYPT_KMS_PROVIDER_AWS &&
+ ctx->opts.kek.kms_provider != MONGOCRYPT_KMS_PROVIDER_NONE) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "master key already set");
+ }
+
+ if (ctx->opts.kek.kms_provider == MONGOCRYPT_KMS_PROVIDER_AWS &&
+ ctx->opts.kek.provider.aws.region) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "master key already set");
+ }
+
+ if (!_mongocrypt_validate_and_copy_string (region, region_len, &temp) ||
+ region_len == 0) {
+ bson_free (temp);
+ return _mongocrypt_ctx_fail_w_msg (ctx, "invalid region");
+ }
+ bson_free (temp);
+
+ temp = NULL;
+ if (!_mongocrypt_validate_and_copy_string (cmk, cmk_len, &temp) ||
+ cmk_len == 0) {
+ bson_free (temp);
+ return _mongocrypt_ctx_fail_w_msg (ctx, "invalid cmk");
+ }
+ bson_free (temp);
+
+ bson_init (&as_bson);
+ bson_append_utf8 (&as_bson,
+ MONGOCRYPT_STR_AND_LEN ("provider"),
+ MONGOCRYPT_STR_AND_LEN ("aws"));
+ bson_append_utf8 (
+ &as_bson, MONGOCRYPT_STR_AND_LEN ("region"), region, region_len);
+ bson_append_utf8 (&as_bson, MONGOCRYPT_STR_AND_LEN ("key"), cmk, cmk_len);
+ bin = mongocrypt_binary_new_from_data ((uint8_t *) bson_get_data (&as_bson),
+ as_bson.len);
+
+ ret = mongocrypt_ctx_setopt_key_encryption_key (ctx, bin);
+ mongocrypt_binary_destroy (bin);
+ bson_destroy (&as_bson);
+
+ if (ctx->crypt->log.trace_enabled) {
+ _mongocrypt_log (&ctx->crypt->log,
+ MONGOCRYPT_LOG_LEVEL_TRACE,
+ "%s (%s=\"%s\", %s=%d, %s=\"%s\", %s=%d)",
+ BSON_FUNC,
+ "region",
+ ctx->opts.kek.provider.aws.region,
+ "region_len",
+ region_len,
+ "cmk",
+ ctx->opts.kek.provider.aws.cmk,
+ "cmk_len",
+ cmk_len);
+ }
+
+ return ret;
+}
+
+
+bool
+mongocrypt_ctx_setopt_masterkey_local (mongocrypt_ctx_t *ctx)
+{
+ if (!ctx) {
+ return false;
+ }
+ if (ctx->initialized) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "cannot set options after init");
+ }
+
+ if (ctx->state == MONGOCRYPT_CTX_ERROR) {
+ return false;
+ }
+
+ if (ctx->opts.kek.kms_provider) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "master key already set");
+ }
+
+ ctx->opts.kek.kms_provider = MONGOCRYPT_KMS_PROVIDER_LOCAL;
+ return true;
+}
+
+
+bool
+_mongocrypt_ctx_init (mongocrypt_ctx_t *ctx,
+ _mongocrypt_ctx_opts_spec_t *opts_spec)
+{
+ bool has_id = false, has_alt_name = false, has_multiple_alt_names = false;
+
+ if (ctx->initialized) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "cannot double initialize");
+ }
+ ctx->initialized = true;
+
+ if (ctx->state == MONGOCRYPT_CTX_ERROR) {
+ return false;
+ }
+ /* Set some default functions */
+ ctx->vtable.mongo_op_keys = _mongo_op_keys;
+ ctx->vtable.mongo_feed_keys = _mongo_feed_keys;
+ ctx->vtable.mongo_done_keys = _mongo_done_keys;
+ ctx->vtable.next_kms_ctx = _next_kms_ctx;
+ ctx->vtable.kms_done = _kms_done;
+
+ /* Check that required options are included and prohibited options are
+ * not.
+ */
+
+ if (opts_spec->kek == OPT_REQUIRED) {
+ if (!ctx->opts.kek.kms_provider) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "master key required");
+ }
+ if (!(ctx->opts.kek.kms_provider & ctx->crypt->opts.kms_providers)) {
+ return _mongocrypt_ctx_fail_w_msg (
+ ctx, "requested kms provider not configured");
+ }
+ }
+
+ if (opts_spec->kek == OPT_PROHIBITED && ctx->opts.kek.kms_provider) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "master key prohibited");
+ }
+
+ /* Special case. key_descriptor applies to explicit encryption. It must be
+ * either a key id or *one* key alt name, but not both.
+ * key_alt_names applies to creating a data key. It may be one or multiple
+ * key alt names.
+ */
+ has_id = !_mongocrypt_buffer_empty (&ctx->opts.key_id);
+ has_alt_name = !!(ctx->opts.key_alt_names);
+ has_multiple_alt_names = has_alt_name && !!(ctx->opts.key_alt_names->next);
+
+ if (opts_spec->key_descriptor == OPT_REQUIRED) {
+ if (!has_id && !has_alt_name) {
+ return _mongocrypt_ctx_fail_w_msg (
+ ctx, "either key id or key alt name required");
+ }
+
+ if (has_id && has_alt_name) {
+ return _mongocrypt_ctx_fail_w_msg (
+ ctx, "cannot have both key id and key alt name");
+ }
+
+ if (has_multiple_alt_names) {
+ return _mongocrypt_ctx_fail_w_msg (
+ ctx, "must not specify multiple key alt names");
+ }
+ }
+
+ if (opts_spec->key_descriptor == OPT_PROHIBITED) {
+ /* still okay if key_alt_names are allowed and only alt names were
+ * specified. */
+ if ((opts_spec->key_alt_names == OPT_PROHIBITED && has_alt_name) ||
+ has_id) {
+ return _mongocrypt_ctx_fail_w_msg (ctx,
+ "key id and alt name prohibited");
+ }
+ }
+
+ if (opts_spec->key_material == OPT_PROHIBITED &&
+ ctx->opts.key_material.owned) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "key material prohibited");
+ }
+
+ if (opts_spec->algorithm == OPT_REQUIRED &&
+ ctx->opts.algorithm == MONGOCRYPT_ENCRYPTION_ALGORITHM_NONE) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "algorithm required");
+ }
+
+ if (opts_spec->algorithm == OPT_PROHIBITED &&
+ ctx->opts.algorithm != MONGOCRYPT_ENCRYPTION_ALGORITHM_NONE) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "algorithm prohibited");
+ }
+
+ _mongocrypt_key_broker_init (&ctx->kb, ctx->crypt);
+ return true;
+}
+
+bool
+_mongocrypt_ctx_state_from_key_broker (mongocrypt_ctx_t *ctx)
+{
+ _mongocrypt_key_broker_t *kb;
+ mongocrypt_status_t *status;
+ mongocrypt_ctx_state_t new_state = MONGOCRYPT_CTX_ERROR;
+ bool ret = false;
+
+ status = ctx->status;
+ kb = &ctx->kb;
+
+ if (ctx->state == MONGOCRYPT_CTX_ERROR) {
+ return false;
+ }
+
+
+ switch (kb->state) {
+ case KB_ERROR:
+ _mongocrypt_status_copy_to (kb->status, status);
+ new_state = MONGOCRYPT_CTX_ERROR;
+ ret = false;
+ break;
+ case KB_ADDING_DOCS:
+ /* Require key documents from driver. */
+ new_state = MONGOCRYPT_CTX_NEED_MONGO_KEYS;
+ ret = true;
+ break;
+ case KB_AUTHENTICATING:
+ case KB_DECRYPTING_KEY_MATERIAL:
+ /* Encrypted keys need KMS. */
+ new_state = MONGOCRYPT_CTX_NEED_KMS;
+ ret = true;
+ break;
+ case KB_DONE:
+ new_state = MONGOCRYPT_CTX_READY;
+ if (kb->key_requests == NULL) {
+ /* No key requests were ever added. */
+ ctx->nothing_to_do = true; /* nothing to encrypt/decrypt */
+ }
+ ret = true;
+ break;
+ /* As currently implemented, we do not expect to ever be in KB_REQUESTING
+ * state when calling this function. */
+ case KB_REQUESTING:
+ CLIENT_ERR ("key broker in unexpected state");
+ new_state = MONGOCRYPT_CTX_ERROR;
+ ret = false;
+ break;
+ }
+
+ if (new_state != ctx->state) {
+ ctx->state = new_state;
+ }
+
+ return ret;
+}
+
+
+bool
+mongocrypt_ctx_setopt_masterkey_aws_endpoint (mongocrypt_ctx_t *ctx,
+ const char *endpoint,
+ int32_t endpoint_len)
+{
+ if (!ctx) {
+ return false;
+ }
+
+ if (ctx->initialized) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "cannot set options after init");
+ }
+
+ if (ctx->state == MONGOCRYPT_CTX_ERROR) {
+ return false;
+ }
+
+ if (ctx->opts.kek.kms_provider != MONGOCRYPT_KMS_PROVIDER_AWS &&
+ ctx->opts.kek.kms_provider != MONGOCRYPT_KMS_PROVIDER_NONE) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "endpoint prohibited");
+ }
+
+ ctx->opts.kek.kms_provider = MONGOCRYPT_KMS_PROVIDER_AWS;
+
+ if (ctx->opts.kek.provider.aws.endpoint) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "already set masterkey endpoint");
+ }
+
+ ctx->opts.kek.provider.aws.endpoint = _mongocrypt_endpoint_new (
+ endpoint, endpoint_len, NULL /* opts */, ctx->status);
+ if (!ctx->opts.kek.provider.aws.endpoint) {
+ return _mongocrypt_ctx_fail (ctx);
+ }
+
+ return true;
+}
+
+bool
+mongocrypt_ctx_setopt_key_encryption_key (mongocrypt_ctx_t *ctx,
+ mongocrypt_binary_t *bin)
+{
+ bson_t as_bson;
+
+ if (!ctx) {
+ return false;
+ }
+
+ if (ctx->initialized) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "cannot set options after init");
+ }
+
+ if (ctx->state == MONGOCRYPT_CTX_ERROR) {
+ return false;
+ }
+
+ if (ctx->opts.kek.kms_provider) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "key encryption key already set");
+ }
+
+ if (!_mongocrypt_binary_to_bson (bin, &as_bson)) {
+ return _mongocrypt_ctx_fail_w_msg (ctx, "invalid BSON");
+ }
+
+ if (!_mongocrypt_kek_parse_owned (&as_bson, &ctx->opts.kek, ctx->status)) {
+ return _mongocrypt_ctx_fail (ctx);
+ }
+
+ if (ctx->crypt->log.trace_enabled) {
+ char *bin_str = bson_as_canonical_extended_json (&as_bson, NULL);
+ _mongocrypt_log (&ctx->crypt->log,
+ MONGOCRYPT_LOG_LEVEL_TRACE,
+ "%s (%s=\"%s\")",
+ BSON_FUNC,
+ "bin",
+ bin_str);
+ bson_free (bin_str);
+ }
+
+ return true;
+}
diff --git a/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-dll-private.h b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-dll-private.h
new file mode 100644
index 00000000..1f4f68d0
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-dll-private.h
@@ -0,0 +1,79 @@
+#ifndef MONGOCRYPT_DLL_PRIVATE_H
+#define MONGOCRYPT_DLL_PRIVATE_H
+
+#include <mlib/str.h>
+
+#include <stdlib.h>
+
+#if _WIN32
+#define MCR_DLL_SUFFIX ".dll"
+#elif __APPLE__
+#define MCR_DLL_SUFFIX ".dylib"
+#else
+#define MCR_DLL_SUFFIX ".so"
+#endif
+
+#define MCR_DLL_NULL \
+ ((mcr_dll){._native_handle = NULL, .error_string = MSTR_NULL})
+
+/**
+ * @brief A dynamically-loaded library i.e. returned by LoadLibrary() or
+ * dlopen()
+ */
+typedef struct mcr_dll {
+ // (All supported platforms use a void* as the library handle type)
+ void *_native_handle;
+ mstr error_string;
+} mcr_dll;
+
+/**
+ * @brief Open and load a dynamic library
+ *
+ * @param lib A path or name of a library, suitable for encoding as a
+ * filepath on the host system.
+ *
+ * @return mcr_dll A newly opened dynamic library, which must be
+ * released using @ref mcr_dll_close()
+ *
+ * If the given `lib` is a qualified path (either relative or absolute) and not
+ * just a filename, then the system will search for the library on the system's
+ * default library search paths. If `lib` is a qualified relative path (not just
+ * a filename), it will be resolved relative to the application's working
+ * directory.
+ */
+mcr_dll
+mcr_dll_open (const char *lib);
+
+/**
+ * @brief Close a dynamic library opened with @ref mcr_dll_open
+ *
+ * @param dll A dynamic library handle
+ */
+static inline void
+mcr_dll_close (mcr_dll dll)
+{
+ extern void mcr_dll_close_handle (mcr_dll);
+ mcr_dll_close_handle (dll);
+ mstr_free (dll.error_string);
+}
+
+/**
+ * @brief Obtain a pointer to an exported entity from the given dynamic library.
+ *
+ * @param dll A library opened with @ref mcr_dll_open
+ * @param symbol The name of a symbol to open
+ * @return void* A pointer to that symbol, or NULL if not found
+ */
+void *
+mcr_dll_sym (mcr_dll dll, const char *symbol);
+
+/**
+ * @brief Determine whether the given DLL is a handle to an open library
+ */
+static inline bool
+mcr_dll_is_open (mcr_dll dll)
+{
+ return dll._native_handle != NULL;
+}
+
+#endif // MONGOCRYPT_DLL_PRIVATE_H
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-endpoint-private.h b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-endpoint-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-endpoint-private.h
rename to mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-endpoint-private.h
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-endpoint.c b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-endpoint.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-endpoint.c
rename to mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-endpoint.c
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-kek-private.h b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-kek-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-kek-private.h
rename to mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-kek-private.h
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-kek.c b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-kek.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-kek.c
rename to mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-kek.c
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-key-broker-private.h b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-key-broker-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-key-broker-private.h
rename to mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-key-broker-private.h
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-key-broker.c b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-key-broker.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-key-broker.c
rename to mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-key-broker.c
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-key-private.h b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-key-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-key-private.h
rename to mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-key-private.h
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-key.c b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-key.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-key.c
rename to mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-key.c
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-kms-ctx-private.h b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-kms-ctx-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-kms-ctx-private.h
rename to mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-kms-ctx-private.h
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-kms-ctx.c b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-kms-ctx.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-kms-ctx.c
rename to mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-kms-ctx.c
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-log-private.h b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-log-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-log-private.h
rename to mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-log-private.h
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-log.c b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-log.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-log.c
rename to mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-log.c
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-marking-private.h b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-marking-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-marking-private.h
rename to mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-marking-private.h
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-marking.c b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-marking.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-marking.c
rename to mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-marking.c
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-mutex-private.h b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-mutex-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-mutex-private.h
rename to mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-mutex-private.h
diff --git a/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-opts-private.h b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-opts-private.h
new file mode 100644
index 00000000..e7a99719
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-opts-private.h
@@ -0,0 +1,200 @@
+/*
+ * Copyright 2018-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef MONGOCRYPT_OPTS_PRIVATE_H
+#define MONGOCRYPT_OPTS_PRIVATE_H
+
+#include <bson/bson.h>
+
+#include "mlib/str.h"
+
+#include "mongocrypt.h"
+#include "mongocrypt-buffer-private.h"
+#include "mongocrypt-log-private.h"
+#include "mongocrypt-endpoint-private.h"
+#include "mongocrypt-kek-private.h"
+
+typedef struct {
+ char *tenant_id;
+ char *client_id;
+ char *client_secret;
+ _mongocrypt_endpoint_t *identity_platform_endpoint;
+} _mongocrypt_opts_kms_provider_azure_t;
+
+typedef struct {
+ char *email;
+ _mongocrypt_buffer_t private_key;
+ _mongocrypt_endpoint_t *endpoint;
+} _mongocrypt_opts_kms_provider_gcp_t;
+
+typedef struct {
+ char *secret_access_key;
+ char *access_key_id;
+ char *session_token;
+} _mongocrypt_opts_kms_provider_aws_t;
+
+typedef struct {
+ _mongocrypt_buffer_t key;
+} _mongocrypt_opts_kms_provider_local_t;
+
+typedef struct {
+ _mongocrypt_endpoint_t *endpoint;
+} _mongocrypt_opts_kms_provider_kmip_t;
+
+typedef struct {
+ mongocrypt_log_fn_t log_fn;
+ void *log_ctx;
+ _mongocrypt_buffer_t schema_map;
+
+ int kms_providers; /* A bit set of _mongocrypt_kms_provider_t */
+ _mongocrypt_opts_kms_provider_local_t kms_provider_local;
+ _mongocrypt_opts_kms_provider_aws_t kms_provider_aws;
+ _mongocrypt_opts_kms_provider_azure_t kms_provider_azure;
+ _mongocrypt_opts_kms_provider_gcp_t kms_provider_gcp;
+ _mongocrypt_opts_kms_provider_kmip_t kms_provider_kmip;
+ mongocrypt_hmac_fn sign_rsaes_pkcs1_v1_5;
+ void *sign_ctx;
+
+ /// Keep an array of search paths for finding the CSFLE dynamic library
+ /// during mongocrypt_init()
+ int n_cselib_search_paths;
+ mstr *cselib_search_paths;
+ /// Optionally, a user may override the default search behavior by specifying
+ /// a specifiy path to the library. If this is set, this suppresses the
+ /// search behavior.
+ mstr csfle_lib_override_path;
+} _mongocrypt_opts_t;
+
+
+void
+_mongocrypt_opts_init (_mongocrypt_opts_t *opts);
+
+
+void
+_mongocrypt_opts_cleanup (_mongocrypt_opts_t *opts);
+
+
+bool
+_mongocrypt_opts_validate (_mongocrypt_opts_t *opts,
+ mongocrypt_status_t *status)
+ MONGOCRYPT_WARN_UNUSED_RESULT;
+
+/*
+ * Parse an optional UTF-8 value from BSON.
+ * @dotkey may be a dot separated key like: "a.b.c".
+ * @*out is set to a copy of the string if found, NULL otherwise. Caller must
+ * clean up with bson_free (*out).
+ * Returns true if no error occured.
+ */
+bool
+_mongocrypt_parse_optional_utf8 (const bson_t *bson,
+ const char *dotkey,
+ char **out,
+ mongocrypt_status_t *status);
+
+/*
+ * Parse a required UTF-8 value from BSON.
+ * @dotkey may be a dot separated key like: "a.b.c".
+ * @*out is set to a copy of the string if found, NULL otherwise. Caller must
+ * clean up with bson_free (*out).
+ * Returns true if no error occured.
+ */
+bool
+_mongocrypt_parse_required_utf8 (const bson_t *bson,
+ const char *dotkey,
+ char **out,
+ mongocrypt_status_t *status);
+
+/*
+ * Parse an optional endpoint UTF-8 from BSON.
+ * @dotkey may be a dot separated key like: "a.b.c".
+ * @*out is set to a new _mongocrypt_endpoint_t of the if found, NULL otherwise.
+ * @*opts may be set to configure endpoint parsing. It is optional and may be NULL.
+ * Caller must clean up with _mongocrypt_endpoint_destroy (*out).
+ * Returns true if no error occured.
+ */
+bool
+_mongocrypt_parse_optional_endpoint (const bson_t *bson,
+ const char *dotkey,
+ _mongocrypt_endpoint_t **out,
+ _mongocrypt_endpoint_parse_opts_t *opts,
+ mongocrypt_status_t *status);
+
+/*
+ * Parse a required endpoint UTF-8 from BSON.
+ * @dotkey may be a dot separated key like: "a.b.c".
+ * @*out is set to a new _mongocrypt_endpoint_t of the if found, NULL otherwise.
+ * @*opts may be set to configure endpoint parsing. It is optional and may be NULL.
+ * Caller must clean up with _mongocrypt_endpoint_destroy (*out).
+ * Returns true if no error occured.
+ */
+bool
+_mongocrypt_parse_required_endpoint (const bson_t *bson,
+ const char *dotkey,
+ _mongocrypt_endpoint_t **out,
+ _mongocrypt_endpoint_parse_opts_t *opts,
+ mongocrypt_status_t *status);
+
+/*
+ * Parse an optional binary type from BSON.
+ * The field parsed is accepted as:
+ * - A BSON binary value (of any subtype).
+ * - A BSON UTF-8 value, set to base64 encoded data.
+ *
+ * @dotkey may be a dot separated key like: "a.b.c"
+ * @out is initialized with the parsed data, or initialized to empty on error.
+ * Caller must clean up with _mongocrypt_buffer_cleanup (out).
+ * Returns true if no error occurred.
+ */
+bool
+_mongocrypt_parse_optional_binary (const bson_t *bson,
+ const char *dotkey,
+ _mongocrypt_buffer_t *out,
+ mongocrypt_status_t *status);
+
+/*
+ * Parse a required binary type from BSON.
+ * The field parsed is accepted as:
+ * - A BSON binary value (of any subtype).
+ * - A BSON UTF-8 value, set to base64 encoded data.
+ *
+ * @dotkey may be a dot separated key like: "a.b.c"
+ * @out is initialized with the parsed data, or initialized to empty on error.
+ * Caller must clean up with _mongocrypt_buffer_cleanup (out).
+ * Returns true if no error occurred.
+ */
+bool
+_mongocrypt_parse_required_binary (const bson_t *bson,
+ const char *dotkey,
+ _mongocrypt_buffer_t *out,
+ mongocrypt_status_t *status);
+
+/*
+ * Checks for unrecognized fields in parsing @bson.
+ * @dotkey is a dot separated path to a document field, like "a.b.c" or NULL.
+ * Pass a list of allowed fields.
+ * Returns true if no error occurred.
+ */
+bool
+_mongocrypt_check_allowed_fields_va (const bson_t *bson,
+ const char *dotkey,
+ mongocrypt_status_t *status,
+ ...);
+
+#define _mongocrypt_check_allowed_fields(bson, path, status, ...) \
+ _mongocrypt_check_allowed_fields_va (bson, path, status, __VA_ARGS__, NULL)
+
+#endif /* MONGOCRYPT_OPTS_PRIVATE_H */
diff --git a/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-opts.c b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-opts.c
new file mode 100644
index 00000000..8bf30a8c
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-opts.c
@@ -0,0 +1,296 @@
+/*
+ * Copyright 2018-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <bson/bson.h>
+
+#include "mongocrypt-opts-private.h"
+#include "mongocrypt-log-private.h"
+#include "mongocrypt-private.h"
+
+#include <kms_message/kms_b64.h>
+
+void
+_mongocrypt_opts_init (_mongocrypt_opts_t *opts)
+{
+ memset (opts, 0, sizeof (*opts));
+}
+
+static void
+_mongocrypt_opts_kms_provider_azure_cleanup (
+ _mongocrypt_opts_kms_provider_azure_t *kms_provider_azure)
+{
+ bson_free (kms_provider_azure->client_id);
+ bson_free (kms_provider_azure->client_secret);
+ bson_free (kms_provider_azure->tenant_id);
+ _mongocrypt_endpoint_destroy (
+ kms_provider_azure->identity_platform_endpoint);
+}
+
+static void
+_mongocrypt_opts_kms_provider_gcp_cleanup (
+ _mongocrypt_opts_kms_provider_gcp_t *kms_provider_gcp)
+{
+ bson_free (kms_provider_gcp->email);
+ _mongocrypt_endpoint_destroy (kms_provider_gcp->endpoint);
+ _mongocrypt_buffer_cleanup (&kms_provider_gcp->private_key);
+}
+
+void
+_mongocrypt_opts_cleanup (_mongocrypt_opts_t *opts)
+{
+ bson_free (opts->kms_provider_aws.secret_access_key);
+ bson_free (opts->kms_provider_aws.access_key_id);
+ bson_free (opts->kms_provider_aws.session_token);
+ _mongocrypt_buffer_cleanup (&opts->kms_provider_local.key);
+ _mongocrypt_buffer_cleanup (&opts->schema_map);
+ _mongocrypt_opts_kms_provider_azure_cleanup (&opts->kms_provider_azure);
+ _mongocrypt_opts_kms_provider_gcp_cleanup (&opts->kms_provider_gcp);
+ _mongocrypt_endpoint_destroy (opts->kms_provider_kmip.endpoint);
+ // Free any lib search paths added by the caller
+ for (int i = 0; i < opts->n_cselib_search_paths; ++i) {
+ mstr_free (opts->cselib_search_paths[i]);
+ }
+ bson_free (opts->cselib_search_paths);
+ mstr_free (opts->csfle_lib_override_path);
+}
+
+
+bool
+_mongocrypt_opts_validate (_mongocrypt_opts_t *opts,
+ mongocrypt_status_t *status)
+{
+ if (!opts->kms_providers) {
+ CLIENT_ERR ("no kms provider set");
+ return false;
+ }
+
+ if (opts->kms_providers & MONGOCRYPT_KMS_PROVIDER_AWS) {
+ if (!opts->kms_provider_aws.access_key_id ||
+ !opts->kms_provider_aws.secret_access_key) {
+ CLIENT_ERR ("aws credentials unset");
+ return false;
+ }
+ }
+
+ if (opts->kms_providers & MONGOCRYPT_KMS_PROVIDER_LOCAL) {
+ if (_mongocrypt_buffer_empty (&opts->kms_provider_local.key)) {
+ CLIENT_ERR ("local data key unset");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool
+_mongocrypt_parse_optional_utf8 (const bson_t *bson,
+ const char *dotkey,
+ char **out,
+ mongocrypt_status_t *status)
+{
+ bson_iter_t iter;
+ bson_iter_t child;
+
+ *out = NULL;
+
+ if (!bson_iter_init (&iter, bson)) {
+ CLIENT_ERR ("invalid BSON");
+ return false;
+ }
+ if (!bson_iter_find_descendant (&iter, dotkey, &child)) {
+ /* Not found. Not an error. */
+ return true;
+ }
+ if (!BSON_ITER_HOLDS_UTF8 (&child)) {
+ CLIENT_ERR ("expected UTF-8 %s", dotkey);
+ return false;
+ }
+
+ *out = bson_strdup (bson_iter_utf8 (&child, NULL));
+ return true;
+}
+
+
+bool
+_mongocrypt_parse_required_utf8 (const bson_t *bson,
+ const char *dotkey,
+ char **out,
+ mongocrypt_status_t *status)
+{
+ if (!_mongocrypt_parse_optional_utf8 (bson, dotkey, out, status)) {
+ return false;
+ }
+
+ if (!*out) {
+ CLIENT_ERR ("expected UTF-8 %s", dotkey);
+ return false;
+ }
+
+ return true;
+}
+
+bool
+_mongocrypt_parse_optional_endpoint (const bson_t *bson,
+ const char *dotkey,
+ _mongocrypt_endpoint_t **out,
+ _mongocrypt_endpoint_parse_opts_t *opts,
+ mongocrypt_status_t *status)
+{
+ char *endpoint_raw;
+
+ *out = NULL;
+
+ if (!_mongocrypt_parse_optional_utf8 (bson, dotkey, &endpoint_raw, status)) {
+ return false;
+ }
+
+ /* Not found. Not an error. */
+ if (!endpoint_raw) {
+ return true;
+ }
+
+ *out = _mongocrypt_endpoint_new (endpoint_raw, -1, opts, status);
+ bson_free (endpoint_raw);
+ return (*out) != NULL;
+}
+
+bool
+_mongocrypt_parse_required_endpoint (const bson_t *bson,
+ const char *dotkey,
+ _mongocrypt_endpoint_t **out,
+ _mongocrypt_endpoint_parse_opts_t *opts,
+ mongocrypt_status_t *status)
+{
+ if (!_mongocrypt_parse_optional_endpoint (bson, dotkey, out, opts, status)) {
+ return false;
+ }
+
+ if (!*out) {
+ CLIENT_ERR ("expected endpoint %s", dotkey);
+ return false;
+ }
+
+ return true;
+}
+
+
+bool
+_mongocrypt_parse_optional_binary (const bson_t *bson,
+ const char *dotkey,
+ _mongocrypt_buffer_t *out,
+ mongocrypt_status_t *status)
+{
+ bson_iter_t iter;
+ bson_iter_t child;
+
+ _mongocrypt_buffer_init (out);
+
+ if (!bson_iter_init (&iter, bson)) {
+ CLIENT_ERR ("invalid BSON");
+ return false;
+ }
+ if (!bson_iter_find_descendant (&iter, dotkey, &child)) {
+ /* Not found. Not an error. */
+ return true;
+ }
+ if (BSON_ITER_HOLDS_UTF8 (&child)) {
+ size_t out_len;
+ /* Attempt to base64 decode. */
+ out->data =
+ kms_message_b64_to_raw (bson_iter_utf8 (&child, NULL), &out_len);
+ if (!out->data) {
+ CLIENT_ERR ("unable to parse base64 from UTF-8 field %s", dotkey);
+ return false;
+ }
+ out->len = (uint32_t) out_len;
+ out->owned = true;
+ } else if (BSON_ITER_HOLDS_BINARY (&child)) {
+ if (!_mongocrypt_buffer_copy_from_binary_iter (out, &child)) {
+ CLIENT_ERR ("unable to parse binary from field %s", dotkey);
+ return false;
+ }
+ } else {
+ CLIENT_ERR ("expected UTF-8 or binary %s", dotkey);
+ return false;
+ }
+
+
+ return true;
+}
+
+bool
+_mongocrypt_parse_required_binary (const bson_t *bson,
+ const char *dotkey,
+ _mongocrypt_buffer_t *out,
+ mongocrypt_status_t *status)
+{
+ if (!_mongocrypt_parse_optional_binary (bson, dotkey, out, status)) {
+ return false;
+ }
+
+ if (out->len == 0) {
+ CLIENT_ERR ("expected UTF-8 or binary %s", dotkey);
+ return false;
+ }
+
+ return true;
+}
+
+bool
+_mongocrypt_check_allowed_fields_va (const bson_t *bson,
+ const char *dotkey,
+ mongocrypt_status_t *status,
+ ...)
+{
+ va_list args;
+ const char *field;
+ bson_iter_t iter;
+
+ if (dotkey) {
+ bson_iter_t parent;
+
+ bson_iter_init (&parent, bson);
+ if (!bson_iter_find_descendant (&parent, dotkey, &iter) ||
+ !BSON_ITER_HOLDS_DOCUMENT (&iter)) {
+ CLIENT_ERR ("invalid BSON, expected %s", dotkey);
+ return false;
+ }
+ bson_iter_recurse (&iter, &iter);
+ } else {
+ bson_iter_init (&iter, bson);
+ }
+
+ while (bson_iter_next (&iter)) {
+ bool found = false;
+
+ va_start (args, status);
+ field = va_arg (args, const char *);
+ while (field) {
+ if (0 == strcmp (field, bson_iter_key (&iter))) {
+ found = true;
+ break;
+ }
+ field = va_arg (args, const char *);
+ }
+ va_end (args);
+
+ if (!found) {
+ CLIENT_ERR ("Unexpected field: '%s'", bson_iter_key (&iter));
+ return false;
+ }
+ }
+ return true;
+}
\ No newline at end of file
diff --git a/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-private.h b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-private.h
new file mode 100644
index 00000000..97916000
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-private.h
@@ -0,0 +1,158 @@
+/*
+ * Copyright 2019-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef MONGOCRYPT_PRIVATE_H
+#define MONGOCRYPT_PRIVATE_H
+
+#include "mongocrypt.h"
+#include "mongocrypt-config.h"
+#include "bson/bson.h"
+
+#include "mongocrypt-dll-private.h"
+#include "mongocrypt-log-private.h"
+#include "mongocrypt-buffer-private.h"
+#include "mongocrypt-cache-private.h"
+#include "mongocrypt-cache-key-private.h"
+#include "mongocrypt-mutex-private.h"
+#include "mongocrypt-opts-private.h"
+#include "mongocrypt-crypto-private.h"
+#include "mongocrypt-cache-oauth-private.h"
+
+#include "mongo_csfle-v1.h"
+
+
+#define MONGOCRYPT_GENERIC_ERROR_CODE 1
+
+#define CLIENT_ERR_W_CODE(code, ...) \
+ _mongocrypt_set_error ( \
+ status, MONGOCRYPT_STATUS_ERROR_CLIENT, code, __VA_ARGS__)
+
+#define CLIENT_ERR(...) \
+ CLIENT_ERR_W_CODE (MONGOCRYPT_GENERIC_ERROR_CODE, __VA_ARGS__)
+
+#define KMS_ERR_W_CODE(code, ...) \
+ _mongocrypt_set_error ( \
+ status, MONGOCRYPT_STATUS_ERROR_KMS, code, __VA_ARGS__)
+
+#define KMS_ERR(...) KMS_ERR_W_CODE (MONGOCRYPT_GENERIC_ERROR_CODE, __VA_ARGS__)
+
+#define MONGOCRYPT_STR_AND_LEN(x) (x), (sizeof (x) / sizeof ((x)[0]) - 1)
+
+#define MONGOCRYPT_DATA_AND_LEN(x) \
+ ((uint8_t *) x), (sizeof (x) / sizeof ((x)[0]) - 1)
+
+/* TODO: remove after integrating into libmongoc */
+#define BSON_SUBTYPE_ENCRYPTED 6
+
+/* TODO: Move these to mongocrypt-log-private.h? */
+const char *
+tmp_json (const bson_t *bson);
+
+const char *
+tmp_buf (const _mongocrypt_buffer_t *buf);
+
+
+void
+_mongocrypt_set_error (mongocrypt_status_t *status,
+ mongocrypt_status_type_t type,
+ uint32_t code,
+ const char *format,
+ ...);
+
+typedef struct _mcr_csfle_v1_vtable {
+#define MONGOC_CSFLE_FUNCTIONS_X \
+ /* status methods */ \
+ X_FUNC (status_create, mongo_csfle_v1_status *, void) \
+ X_FUNC (status_destroy, void, mongo_csfle_v1_status *status) \
+ X_FUNC (status_get_error, int, const mongo_csfle_v1_status *status) \
+ X_FUNC (status_get_explanation, \
+ const char *, \
+ const mongo_csfle_v1_status *status) \
+ X_FUNC (status_get_code, int, const mongo_csfle_v1_status *status) \
+ /* lib methods */ \
+ X_FUNC (lib_create, mongo_csfle_v1_lib *, mongo_csfle_v1_status *status) \
+ X_FUNC (lib_destroy, \
+ int, \
+ mongo_csfle_v1_lib *lib, \
+ mongo_csfle_v1_status *status) \
+ /* query_analyzer methods */ \
+ X_FUNC (query_analyzer_create, \
+ mongo_csfle_v1_query_analyzer *, \
+ mongo_csfle_v1_lib *lib, \
+ mongo_csfle_v1_status *status) \
+ X_FUNC ( \
+ query_analyzer_destroy, void, mongo_csfle_v1_query_analyzer *analyzer) \
+ X_FUNC (analyze_query, \
+ uint8_t *, \
+ mongo_csfle_v1_query_analyzer *analyer, \
+ const uint8_t *documentBSON, \
+ const char *ns_str, \
+ uint32_t ns_len, \
+ uint32_t *bson_len, \
+ mongo_csfle_v1_status *status) \
+ /* Free bson data created by csfle */ \
+ X_FUNC (bson_free, void, uint8_t *bson)
+
+ /// At time of writing, these two symbols seem to be missing from the CSFLE
+ /// build, despite documentation in the csfle header (Refer: SERVER-63680):
+ // X_FUNC (get_version, uint64_t, void)
+ // X_FUNC (get_version_str, const char *, void)
+
+#define X_FUNC(Name, RetType, ...) RetType (*Name) (__VA_ARGS__);
+ MONGOC_CSFLE_FUNCTIONS_X
+#undef X_FUNC
+
+} _mcr_csfle_v1_vtable;
+
+
+struct _mongocrypt_t {
+ bool initialized;
+ _mongocrypt_opts_t opts;
+ mongocrypt_mutex_t mutex;
+ /* The collinfo and key cache are protected with an internal mutex. */
+ _mongocrypt_cache_t cache_collinfo;
+ _mongocrypt_cache_t cache_key;
+ _mongocrypt_log_t log;
+ mongocrypt_status_t *status;
+ _mongocrypt_crypto_t *crypto;
+ /* A counter, protected by mutex, for generating unique context ids */
+ uint32_t ctx_counter;
+ _mongocrypt_cache_oauth_t *cache_oauth_azure;
+ _mongocrypt_cache_oauth_t *cache_oauth_gcp;
+ /// A CSFLE DLL, initialized by mongocrypt_init
+ mcr_dll csfle_lib;
+ _mcr_csfle_v1_vtable csfle_vtable;
+};
+
+typedef enum {
+ MONGOCRYPT_ENCRYPTION_ALGORITHM_NONE = 0,
+ MONGOCRYPT_ENCRYPTION_ALGORITHM_DETERMINISTIC = 1,
+ MONGOCRYPT_ENCRYPTION_ALGORITHM_RANDOM = 2
+} mongocrypt_encryption_algorithm_t;
+
+
+bool
+_mongocrypt_validate_and_copy_string (const char *in,
+ int32_t in_len,
+ char **out) MONGOCRYPT_WARN_UNUSED_RESULT;
+
+char *
+_mongocrypt_new_string_from_bytes (const void *in, int len);
+
+char *
+_mongocrypt_new_json_string_from_binary (mongocrypt_binary_t *binary);
+
+#endif /* MONGOCRYPT_PRIVATE_H */
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-status-private.h b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-status-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-status-private.h
rename to mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-status-private.h
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-status.c b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-status.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-status.c
rename to mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-status.c
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-traverse-util-private.h b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-traverse-util-private.h
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-traverse-util-private.h
rename to mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-traverse-util-private.h
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-traverse-util.c b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-traverse-util.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/src/mongocrypt-traverse-util.c
rename to mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-traverse-util.c
diff --git a/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-util-private.h b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-util-private.h
new file mode 100644
index 00000000..1f13941e
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-util-private.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2021-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef MONGOCRYPT_UTIL_PRIVATE_H
+#define MONGOCRYPT_UTIL_PRIVATE_H
+
+#include "mlib/str.h"
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+/* A utility for safely casting from size_t to uint32_t.
+ * Returns false if @in exceeds the maximum value of a uint32_t. */
+bool
+size_to_uint32 (size_t in, uint32_t *out);
+
+
+/**
+ * @brief The result type of mpath_current_exe_path()
+ *
+ * The @ref current_module_result::path member must be freed with mstr_free()
+ */
+typedef struct current_module_result {
+ /// The resulting executable path
+ mstr path;
+ /// An error, if the path could not be obtained
+ int error;
+} current_module_result;
+
+/**
+ * @brief Obtain the path to the calling executable module
+ *
+ * If this function is contained in a dynamic library, this will return the path
+ * to that library file, otherwise it will return the path to the running
+ * executable.
+ *
+ * @return current_module_result A result object of the operation. Check the
+ * `.error` member for non-zero. The `.path` member must be freed with
+ * mtsr_free()
+ */
+current_module_result
+current_module_path ();
+
+#endif /* MONGOCRYPT_UTIL_PRIVATE_H */
diff --git a/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-util.c b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-util.c
new file mode 100644
index 00000000..bd77a02d
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt-util.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2021-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Turn on libc extensions so that we can use dladdr() on Unix-like systems
+#if defined(__has_include) && \
+ !(defined(_GNU_SOURCE) || defined(_DARWIN_C_SOURCE))
+#if __has_include(<features.h>)
+// We're using a glibc-compatible library
+#define _GNU_SOURCE
+#elif __has_include(<Availability.h>)
+// We're on Apple/Darwin
+#define _DARWIN_C_SOURCE
+#endif
+#else // No __has_include
+#if __GNUC__ < 5
+// Best guess on older GCC is that we are using glibc
+#define _GNU_SOURCE
+#endif
+#endif
+
+#include "mongocrypt-util-private.h"
+
+#include "mlib/thread.h"
+
+#include <errno.h>
+
+#ifdef _WIN32
+#include <windows.h>
+#else
+#include <dlfcn.h>
+#endif
+
+bool
+size_to_uint32 (size_t in, uint32_t *out)
+{
+ if (in > UINT32_MAX) {
+ return false;
+ }
+ *out = (uint32_t) in;
+ return true;
+}
+
+current_module_result
+current_module_path ()
+{
+ mstr ret_str = MSTR_NULL;
+ int ret_error = 0;
+#ifdef _WIN32
+ DWORD acc_size = 512;
+ while (!ret_str.data && !ret_error) {
+ // Loop until we allocate a large enough buffer or get an error
+ wchar_t *path = calloc (acc_size + 1, sizeof (wchar_t));
+ SetLastError (0);
+ GetModuleFileNameW (NULL, path, acc_size);
+ if (GetLastError () == ERROR_INSUFFICIENT_BUFFER) {
+ // Try again with more buffer
+ acc_size *= 2;
+ } else if (GetLastError () != 0) {
+ ret_error = GetLastError ();
+ } else {
+ mstr_narrow_result narrow = mstr_win32_narrow (path);
+ // GetModuleFileNameW should never return invalid Unicode:
+ assert (narrow.error == 0);
+ ret_str = narrow.string;
+ }
+ free (path);
+ }
+#elif defined(_GNU_SOURCE) || defined(_DARWIN_C_SOURCE)
+ // Darwin/BSD/glibc define extensions for finding dynamic library info from
+ // the address of a symbol.
+ Dl_info info;
+ int rc = dladdr ((const void *) current_module_path, &info);
+ if (rc == 0) {
+ // Failed to resolve the symbol
+ ret_error = ENOENT;
+ } else {
+ ret_str = mstr_copy_cstr (info.dli_fname);
+ }
+#else
+#error "Don't know how to get the module path on this platform"
+#endif
+ return (current_module_result){.path = ret_str, .error = ret_error};
+}
diff --git a/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt.c b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt.c
new file mode 100644
index 00000000..7292e287
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt.c
@@ -0,0 +1,1008 @@
+/*
+ * Copyright 2018-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mlib/thread.h"
+#include "mlib/path.h"
+#include "mlib/error.h"
+
+#include <kms_message/kms_message.h>
+#include <bson/bson.h>
+
+#include "mongocrypt-private.h"
+#include "mongocrypt-binary-private.h"
+#include "mongocrypt-cache-collinfo-private.h"
+#include "mongocrypt-cache-key-private.h"
+#include "mongocrypt-config.h"
+#include "mongocrypt-crypto-private.h"
+#include "mongocrypt-log-private.h"
+#include "mongocrypt-opts-private.h"
+#include "mongocrypt-status-private.h"
+#include "mongocrypt-util-private.h"
+
+/* Assert size for interop with wrapper purposes */
+BSON_STATIC_ASSERT (sizeof (mongocrypt_log_level_t) == 4);
+
+
+const char *
+mongocrypt_version (uint32_t *len)
+{
+ if (len) {
+ *len = (uint32_t) strlen (MONGOCRYPT_VERSION);
+ }
+ return MONGOCRYPT_VERSION;
+}
+
+
+void
+_mongocrypt_set_error (mongocrypt_status_t *status,
+ mongocrypt_status_type_t type,
+ uint32_t code,
+ const char *format,
+ ...)
+{
+ va_list args;
+ char *prepared_message;
+
+ if (status) {
+ va_start (args, format);
+ prepared_message = bson_strdupv_printf (format, args);
+ if (!prepared_message) {
+ mongocrypt_status_set (status, type, code, "Out of memory", -1);
+ } else {
+ mongocrypt_status_set (status, type, code, prepared_message, -1);
+ bson_free (prepared_message);
+ }
+ va_end (args);
+ }
+}
+
+
+const char *
+tmp_json (const bson_t *bson)
+{
+ static char storage[1024];
+ char *json;
+
+ memset (storage, 0, 1024);
+ json = bson_as_canonical_extended_json (bson, NULL);
+ bson_snprintf (storage, sizeof (storage), "%s", json);
+ bson_free (json);
+ return (const char *) storage;
+}
+
+
+const char *
+tmp_buf (const _mongocrypt_buffer_t *buf)
+{
+ static char storage[1024];
+ uint32_t i, n;
+
+ memset (storage, 0, 1024);
+ /* capped at two characters per byte, minus 1 for trailing \0 */
+ n = sizeof (storage) / 2 - 1;
+ if (buf->len < n) {
+ n = buf->len;
+ }
+
+ for (i = 0; i < n; i++) {
+ bson_snprintf (storage + (i * 2), 3, "%02x", buf->data[i]);
+ }
+
+ return (const char *) storage;
+}
+
+void
+_mongocrypt_do_init (void)
+{
+ (void) kms_message_init ();
+ _native_crypto_init ();
+}
+
+
+mongocrypt_t *
+mongocrypt_new (void)
+{
+ mongocrypt_t *crypt;
+
+ crypt = bson_malloc0 (sizeof (mongocrypt_t));
+ BSON_ASSERT (crypt);
+
+ _mongocrypt_mutex_init (&crypt->mutex);
+ _mongocrypt_cache_collinfo_init (&crypt->cache_collinfo);
+ _mongocrypt_cache_key_init (&crypt->cache_key);
+ crypt->status = mongocrypt_status_new ();
+ _mongocrypt_opts_init (&crypt->opts);
+ _mongocrypt_log_init (&crypt->log);
+ crypt->ctx_counter = 1;
+ crypt->cache_oauth_azure = _mongocrypt_cache_oauth_new ();
+ crypt->cache_oauth_gcp = _mongocrypt_cache_oauth_new ();
+ crypt->csfle_lib = MCR_DLL_NULL;
+
+ static mlib_once_flag init_flag = MLIB_ONCE_INITIALIZER;
+
+ if (!mlib_call_once (&init_flag, _mongocrypt_do_init) ||
+ !_native_crypto_initialized) {
+ mongocrypt_status_t *status = crypt->status;
+
+ CLIENT_ERR ("failed to initialize");
+ /* Return crypt with failure status so caller can obtain error when
+ * calling mongocrypt_init */
+ }
+
+ return crypt;
+}
+
+
+bool
+mongocrypt_setopt_log_handler (mongocrypt_t *crypt,
+ mongocrypt_log_fn_t log_fn,
+ void *log_ctx)
+{
+ if (!crypt) {
+ return false;
+ }
+
+ if (crypt->initialized) {
+ mongocrypt_status_t *status = crypt->status;
+ CLIENT_ERR ("options cannot be set after initialization");
+ return false;
+ }
+ crypt->opts.log_fn = log_fn;
+ crypt->opts.log_ctx = log_ctx;
+ return true;
+}
+
+bool
+mongocrypt_setopt_kms_provider_aws (mongocrypt_t *crypt,
+ const char *aws_access_key_id,
+ int32_t aws_access_key_id_len,
+ const char *aws_secret_access_key,
+ int32_t aws_secret_access_key_len)
+{
+ mongocrypt_status_t *status;
+
+ if (!crypt) {
+ return false;
+ }
+ status = crypt->status;
+
+ if (crypt->initialized) {
+ CLIENT_ERR ("options cannot be set after initialization");
+ return false;
+ }
+
+ if (0 != (crypt->opts.kms_providers & MONGOCRYPT_KMS_PROVIDER_AWS)) {
+ CLIENT_ERR ("aws kms provider already set");
+ return false;
+ }
+
+ if (!_mongocrypt_validate_and_copy_string (
+ aws_access_key_id,
+ aws_access_key_id_len,
+ &crypt->opts.kms_provider_aws.access_key_id)) {
+ CLIENT_ERR ("invalid aws access key id");
+ return false;
+ }
+
+ if (!_mongocrypt_validate_and_copy_string (
+ aws_secret_access_key,
+ aws_secret_access_key_len,
+ &crypt->opts.kms_provider_aws.secret_access_key)) {
+ CLIENT_ERR ("invalid aws secret access key");
+ return false;
+ }
+
+ if (crypt->log.trace_enabled) {
+ _mongocrypt_log (&crypt->log,
+ MONGOCRYPT_LOG_LEVEL_TRACE,
+ "%s (%s=\"%s\", %s=%d, %s=\"%s\", %s=%d)",
+ BSON_FUNC,
+ "aws_access_key_id",
+ crypt->opts.kms_provider_aws.access_key_id,
+ "aws_access_key_id_len",
+ aws_access_key_id_len,
+ "aws_secret_access_key",
+ crypt->opts.kms_provider_aws.secret_access_key,
+ "aws_secret_access_key_len",
+ aws_secret_access_key_len);
+ }
+ crypt->opts.kms_providers |= MONGOCRYPT_KMS_PROVIDER_AWS;
+ return true;
+}
+
+char *
+_mongocrypt_new_string_from_bytes (const void *in, int len)
+{
+ const int max_bytes = 100;
+ const int chars_per_byte = 2;
+ int out_size = max_bytes * chars_per_byte;
+ const unsigned char *src = in;
+ char *out;
+ char *ret;
+
+ out_size += len > max_bytes ? sizeof ("...") : 1 /* for null */;
+ out = bson_malloc0 (out_size);
+ BSON_ASSERT (out);
+
+ ret = out;
+
+ for (int i = 0; i < len && i < max_bytes; i++, out += chars_per_byte) {
+ sprintf (out, "%02X", src[i]);
+ }
+
+ sprintf (out, (len > max_bytes) ? "..." : "");
+ return ret;
+}
+
+char *
+_mongocrypt_new_json_string_from_binary (mongocrypt_binary_t *binary)
+{
+ bson_t bson;
+ uint32_t len;
+
+ if (!_mongocrypt_binary_to_bson (binary, &bson) ||
+ !bson_validate (&bson, BSON_VALIDATE_NONE, NULL)) {
+ char *hex;
+ char *full_str;
+
+ hex = _mongocrypt_new_string_from_bytes (binary->data, binary->len);
+ full_str = bson_strdup_printf ("(malformed) %s", hex);
+ bson_free (hex);
+ return full_str;
+ }
+ return bson_as_canonical_extended_json (&bson, (size_t *) &len);
+}
+
+bool
+mongocrypt_setopt_schema_map (mongocrypt_t *crypt,
+ mongocrypt_binary_t *schema_map)
+{
+ bson_t tmp;
+ bson_error_t bson_err;
+ mongocrypt_status_t *status;
+
+ if (!crypt) {
+ return false;
+ }
+ status = crypt->status;
+
+ if (crypt->initialized) {
+ CLIENT_ERR ("options cannot be set after initialization");
+ return false;
+ }
+
+ if (!schema_map || !mongocrypt_binary_data (schema_map)) {
+ CLIENT_ERR ("passed null schema map");
+ return false;
+ }
+
+ if (!_mongocrypt_buffer_empty (&crypt->opts.schema_map)) {
+ CLIENT_ERR ("already set schema map");
+ return false;
+ }
+
+ _mongocrypt_buffer_copy_from_binary (&crypt->opts.schema_map, schema_map);
+
+ /* validate bson */
+ if (!_mongocrypt_buffer_to_bson (&crypt->opts.schema_map, &tmp)) {
+ CLIENT_ERR ("invalid bson");
+ return false;
+ }
+
+ if (!bson_validate_with_error (&tmp, BSON_VALIDATE_NONE, &bson_err)) {
+ CLIENT_ERR (bson_err.message);
+ return false;
+ }
+
+ return true;
+}
+
+
+bool
+mongocrypt_setopt_kms_provider_local (mongocrypt_t *crypt,
+ mongocrypt_binary_t *key)
+{
+ mongocrypt_status_t *status;
+
+ if (!crypt) {
+ return false;
+ }
+ status = crypt->status;
+
+ if (crypt->initialized) {
+ CLIENT_ERR ("options cannot be set after initialization");
+ return false;
+ }
+
+ if (0 != (crypt->opts.kms_providers & MONGOCRYPT_KMS_PROVIDER_LOCAL)) {
+ CLIENT_ERR ("local kms provider already set");
+ return false;
+ }
+
+ if (!key) {
+ CLIENT_ERR ("passed null key");
+ return false;
+ }
+
+ if (mongocrypt_binary_len (key) != MONGOCRYPT_KEY_LEN) {
+ CLIENT_ERR ("local key must be %d bytes", MONGOCRYPT_KEY_LEN);
+ return false;
+ }
+
+ if (crypt->log.trace_enabled) {
+ char *key_val;
+ key_val = _mongocrypt_new_string_from_bytes (key->data, key->len);
+
+ _mongocrypt_log (&crypt->log,
+ MONGOCRYPT_LOG_LEVEL_TRACE,
+ "%s (%s=\"%s\")",
+ BSON_FUNC,
+ "key",
+ key_val);
+ bson_free (key_val);
+ }
+
+ _mongocrypt_buffer_copy_from_binary (&crypt->opts.kms_provider_local.key,
+ key);
+ crypt->opts.kms_providers |= MONGOCRYPT_KMS_PROVIDER_LOCAL;
+ return true;
+}
+
+typedef struct {
+ /// Whether the load is successful
+ bool okay;
+ /// The DLL handle to the opened library.
+ mcr_dll lib;
+ /// A vtable for the functions in the DLL
+ _mcr_csfle_v1_vtable vtable;
+} _loaded_csfle;
+
+/**
+ * @brief Attempt to open the CSFLE dynamic library and initialize a vtable for
+ * it.
+ */
+static _loaded_csfle
+_try_load_csfle (const char *filepath, _mongocrypt_log_t *log)
+{
+ // Try to open the dynamic lib
+ mcr_dll lib = mcr_dll_open (filepath);
+ // Check for errors, which are represented by strings
+ if (lib.error_string.data) {
+ // Error opening candidate
+ _mongocrypt_log (
+ log,
+ MONGOCRYPT_LOG_LEVEL_WARNING,
+ "Error while opening candidate for CSFLE dynamic library [%s]: %s",
+ filepath,
+ lib.error_string.data);
+ // Free resources, which will include the error string
+ mcr_dll_close (lib);
+ // Bad:
+ return (_loaded_csfle){.okay = false};
+ }
+
+ // Successfully opened DLL
+ _mongocrypt_log (log,
+ MONGOCRYPT_LOG_LEVEL_TRACE,
+ "Loading CSFLE dynamic library [%s]",
+ filepath);
+
+ // Construct the library vtable
+ bool vtable_okay = true;
+ _mcr_csfle_v1_vtable vtable;
+#define X_FUNC(Name, RetType, ...) \
+ { \
+ /* Symbol names are qualified by the lib name and version: */ \
+ const char *symname = "mongo_csfle_v1_" #Name; \
+ vtable.Name = mcr_dll_sym (lib, symname); \
+ if (vtable.Name == NULL) { \
+ /* The requested symbol is not present */ \
+ _mongocrypt_log ( \
+ log, \
+ MONGOCRYPT_LOG_LEVEL_ERROR, \
+ "Missing required symbol '%s' from CSFLE dynamic library [%s]", \
+ symname, \
+ filepath); \
+ /* Mark the vtable as broken, but keep trying to load more symbols to \
+ * produce error messages for all missing symbols */ \
+ vtable_okay = false; \
+ } \
+ }
+ MONGOC_CSFLE_FUNCTIONS_X
+#undef X_FUNC
+
+ if (!vtable_okay) {
+ mcr_dll_close (lib);
+ _mongocrypt_log (
+ log,
+ MONGOCRYPT_LOG_LEVEL_ERROR,
+ "One or more required symbols are missing from CSFLE dynamic library "
+ "[%s], so this dynamic library will not be used.",
+ filepath);
+ return (_loaded_csfle){.okay = false};
+ }
+
+ // Success!
+ _mongocrypt_log (log,
+ MONGOCRYPT_LOG_LEVEL_INFO,
+ "Opened CSFLE dynamic library [%s]",
+ filepath);
+ return (_loaded_csfle){.okay = true, .lib = lib, .vtable = vtable};
+}
+
+/**
+ * @brief If the leading path element in `filepath` is $ORIGIN, replace that
+ * with the directory containing the current executing module.
+ *
+ * @return true If no error occurred and the path is valid
+ * @return false If there was an error and `filepath` cannot be processed
+ */
+bool
+_try_replace_dollar_origin (mstr *filepath, _mongocrypt_log_t *log)
+{
+ const mstr_view dollar_origin = mstrv_lit ("$ORIGIN");
+ if (!mstr_starts_with (filepath->view, dollar_origin)) {
+ // Nothing to replace
+ return true;
+ }
+ // Check that the next char is a path separator or end-of-string:
+ char peek = filepath->data[dollar_origin.len];
+ if (peek != 0 && !mpath_is_sep (peek, MPATH_NATIVE)) {
+ // Not a single path element
+ return true;
+ }
+ // Replace $ORIGIN with the directory of the current module
+ const current_module_result self_exe_r = current_module_path ();
+ if (self_exe_r.error) {
+ // Failed to get the current module to load replace $ORIGIN
+ mstr error = merror_system_error_string (self_exe_r.error);
+ _mongocrypt_log (log,
+ MONGOCRYPT_LOG_LEVEL_WARNING,
+ "Error while loading the executable module path for "
+ "substitution of $ORIGIN in CSFLE search path [%s]: %s",
+ filepath->data,
+ error.data);
+ mstr_free (error);
+ return false;
+ }
+ const mstr_view self_dir = mpath_parent (self_exe_r.path.view, MPATH_NATIVE);
+ mstr_inplace_splice (filepath, 0, dollar_origin.len, self_dir);
+ mstr_free (self_exe_r.path);
+ return true;
+}
+
+bool
+mongocrypt_init (mongocrypt_t *crypt)
+{
+ mongocrypt_status_t *status;
+
+ if (!crypt) {
+ return false;
+ }
+ status = crypt->status;
+ if (crypt->initialized) {
+ CLIENT_ERR ("already initialized");
+ return false;
+ }
+
+ crypt->initialized = true;
+
+ if (!mongocrypt_status_ok (crypt->status)) {
+ return false;
+ }
+
+ if (!_mongocrypt_opts_validate (&crypt->opts, status)) {
+ return false;
+ }
+
+ if (crypt->opts.log_fn) {
+ _mongocrypt_log_set_fn (
+ &crypt->log, crypt->opts.log_fn, crypt->opts.log_ctx);
+ }
+
+ if (!crypt->crypto) {
+#ifndef MONGOCRYPT_ENABLE_CRYPTO
+ CLIENT_ERR ("libmongocrypt built with native crypto disabled. crypto "
+ "hooks required");
+ return false;
+#else
+ /* set default hooks. */
+ crypt->crypto = bson_malloc0 (sizeof (*crypt->crypto));
+ BSON_ASSERT (crypt->crypto);
+#endif
+ }
+
+ mcr_dll_close (crypt->csfle_lib);
+
+ mstr csfle_cand_filepath = MSTR_NULL;
+ if (crypt->opts.csfle_lib_override_path.data) {
+ // If an override path was specified, skip the library searching behavior
+ csfle_cand_filepath =
+ mstr_copy (crypt->opts.csfle_lib_override_path.view);
+ if (_try_replace_dollar_origin (&csfle_cand_filepath, &crypt->log)) {
+ // Succesfully substituted $ORIGIN
+ // Do not allow a plain filename to go through, as that will cause the
+ // DLL load to search the system.
+ mstr_assign (&csfle_cand_filepath,
+ mpath_absolute (csfle_cand_filepath.view, MPATH_NATIVE));
+ _loaded_csfle candidate =
+ _try_load_csfle (csfle_cand_filepath.data, &crypt->log);
+ if (candidate.okay) {
+ // Successfully loaded
+ crypt->csfle_vtable = candidate.vtable;
+ crypt->csfle_lib = candidate.lib;
+ }
+ }
+ } else {
+ // No override path was specified, so try to find it on the provided
+ // search paths.
+ for (int i = 0; i < crypt->opts.n_cselib_search_paths; ++i) {
+ mstr_view cand_dir = crypt->opts.cselib_search_paths[i].view;
+ mstr_view csfle_filename = mstrv_lit ("mongo_csfle_v1" MCR_DLL_SUFFIX);
+ if (mstr_eq (cand_dir, mstrv_lit ("$SYSTEM"))) {
+ // Caller wants us to search for the library on the system's default
+ // library paths. Pass only the library's filename to cause dll_open
+ // to search on the library paths.
+ mstr_assign (&csfle_cand_filepath, mstr_copy (csfle_filename));
+ } else {
+ // Compose the candidate filepath:
+ mstr_assign (&csfle_cand_filepath,
+ mpath_join (cand_dir, csfle_filename, MPATH_NATIVE));
+ if (!_try_replace_dollar_origin (&csfle_cand_filepath,
+ &crypt->log)) {
+ // Error while substituting $ORIGIN
+ continue;
+ }
+ }
+ // Try to load the file:
+ _loaded_csfle candidate =
+ _try_load_csfle (csfle_cand_filepath.data, &crypt->log);
+ if (candidate.okay) {
+ // We got one:
+ crypt->csfle_vtable = candidate.vtable;
+ crypt->csfle_lib = candidate.lib;
+ // Stop searching:
+ break;
+ }
+ }
+ }
+ mstr_free (csfle_cand_filepath);
+
+ // If a CSFLE override path was specified, but we did not succeed in loading
+ // CSFLE, that is a hard-error.
+ if (crypt->opts.csfle_lib_override_path.data &&
+ !mcr_dll_is_open (crypt->csfle_lib)) {
+ CLIENT_ERR ("A CSFLE override path was specified [%s], but we failed to "
+ "open a dynamic library at that location",
+ crypt->opts.csfle_lib_override_path.data);
+ return false;
+ }
+
+ return true;
+}
+
+
+bool
+mongocrypt_status (mongocrypt_t *crypt, mongocrypt_status_t *out)
+{
+ if (!crypt) {
+ return false;
+ }
+
+ if (!out) {
+ mongocrypt_status_t *status = crypt->status;
+ CLIENT_ERR ("argument 'out' is required");
+ return false;
+ }
+
+ if (!mongocrypt_status_ok (crypt->status)) {
+ _mongocrypt_status_copy_to (crypt->status, out);
+ return false;
+ }
+ _mongocrypt_status_reset (out);
+ return true;
+}
+
+
+void
+mongocrypt_destroy (mongocrypt_t *crypt)
+{
+ if (!crypt) {
+ return;
+ }
+ _mongocrypt_opts_cleanup (&crypt->opts);
+ _mongocrypt_cache_cleanup (&crypt->cache_collinfo);
+ _mongocrypt_cache_cleanup (&crypt->cache_key);
+ _mongocrypt_mutex_cleanup (&crypt->mutex);
+ _mongocrypt_log_cleanup (&crypt->log);
+ mongocrypt_status_destroy (crypt->status);
+ bson_free (crypt->crypto);
+ _mongocrypt_cache_oauth_destroy (crypt->cache_oauth_azure);
+ _mongocrypt_cache_oauth_destroy (crypt->cache_oauth_gcp);
+
+#ifndef __linux__
+ mcr_dll_close (crypt->csfle_lib);
+#else
+ /// NOTE: On Linux, skip closing the CSFLE library itself, since a bug in the
+ /// way ld-linux and GCC interact causes static destructors to not run during
+ /// dlclose(). Still, free the error string that may be non-null:
+ mstr_free (crypt->csfle_lib.error_string);
+#endif
+
+ bson_free (crypt);
+}
+
+
+bool
+_mongocrypt_validate_and_copy_string (const char *in,
+ int32_t in_len,
+ char **out)
+{
+ if (!in) {
+ return false;
+ }
+
+ if (in_len < -1) {
+ return false;
+ }
+
+ if (in_len == -1) {
+ in_len = (uint32_t) strlen (in);
+ }
+
+ if (!bson_utf8_validate (in, in_len, false)) {
+ return false;
+ }
+ *out = bson_strndup (in, in_len);
+ return true;
+}
+
+
+bool
+mongocrypt_setopt_crypto_hooks (mongocrypt_t *crypt,
+ mongocrypt_crypto_fn aes_256_cbc_encrypt,
+ mongocrypt_crypto_fn aes_256_cbc_decrypt,
+ mongocrypt_random_fn random,
+ mongocrypt_hmac_fn hmac_sha_512,
+ mongocrypt_hmac_fn hmac_sha_256,
+ mongocrypt_hash_fn sha_256,
+ void *ctx)
+{
+ mongocrypt_status_t *status;
+
+ if (!crypt) {
+ return false;
+ }
+
+ status = crypt->status;
+
+ if (crypt->initialized) {
+ CLIENT_ERR ("options cannot be set after initialization");
+ return false;
+ }
+
+ if (crypt->crypto) {
+ CLIENT_ERR ("crypto_hooks already set");
+ return false;
+ }
+
+ crypt->crypto = bson_malloc0 (sizeof (*crypt->crypto));
+ BSON_ASSERT (crypt->crypto);
+
+ crypt->crypto->hooks_enabled = true;
+ crypt->crypto->ctx = ctx;
+
+ if (!aes_256_cbc_encrypt) {
+ CLIENT_ERR ("aes_256_cbc_encrypt not set");
+ return false;
+ }
+ crypt->crypto->aes_256_cbc_encrypt = aes_256_cbc_encrypt;
+
+ if (!aes_256_cbc_decrypt) {
+ CLIENT_ERR ("aes_256_cbc_decrypt not set");
+ return false;
+ }
+ crypt->crypto->aes_256_cbc_decrypt = aes_256_cbc_decrypt;
+
+ if (!random) {
+ CLIENT_ERR ("random not set");
+ return false;
+ }
+ crypt->crypto->random = random;
+
+ if (!hmac_sha_512) {
+ CLIENT_ERR ("hmac_sha_512 not set");
+ return false;
+ }
+ crypt->crypto->hmac_sha_512 = hmac_sha_512;
+
+ if (!hmac_sha_256) {
+ CLIENT_ERR ("hmac_sha_256 not set");
+ return false;
+ }
+ crypt->crypto->hmac_sha_256 = hmac_sha_256;
+
+ if (!sha_256) {
+ CLIENT_ERR ("sha_256 not set");
+ return false;
+ }
+ crypt->crypto->sha_256 = sha_256;
+
+ return true;
+}
+
+bool
+mongocrypt_setopt_crypto_hook_sign_rsaes_pkcs1_v1_5 (
+ mongocrypt_t *crypt,
+ mongocrypt_hmac_fn sign_rsaes_pkcs1_v1_5,
+ void *sign_ctx)
+{
+ mongocrypt_status_t *status;
+
+ if (!crypt) {
+ return false;
+ }
+
+ status = crypt->status;
+
+ if (crypt->initialized) {
+ CLIENT_ERR ("options cannot be set after initialization");
+ return false;
+ }
+
+ if (crypt->opts.sign_rsaes_pkcs1_v1_5) {
+ CLIENT_ERR ("signature hook already set");
+ return false;
+ }
+
+ crypt->opts.sign_rsaes_pkcs1_v1_5 = sign_rsaes_pkcs1_v1_5;
+ crypt->opts.sign_ctx = sign_ctx;
+ return true;
+}
+
+bool
+mongocrypt_setopt_kms_providers (mongocrypt_t *crypt,
+ mongocrypt_binary_t *kms_providers)
+{
+ mongocrypt_status_t *status;
+ bson_t as_bson;
+ bson_iter_t iter;
+
+ if (!crypt) {
+ return false;
+ }
+ status = crypt->status;
+
+ if (crypt->initialized) {
+ CLIENT_ERR ("options cannot be set after initialization");
+ return false;
+ }
+
+ if (!_mongocrypt_binary_to_bson (kms_providers, &as_bson) ||
+ !bson_iter_init (&iter, &as_bson)) {
+ CLIENT_ERR ("invalid BSON");
+ return false;
+ }
+
+ while (bson_iter_next (&iter)) {
+ const char *field_name;
+
+ field_name = bson_iter_key (&iter);
+
+ if (0 == strcmp (field_name, "azure")) {
+ if (0 != (crypt->opts.kms_providers & MONGOCRYPT_KMS_PROVIDER_AZURE)) {
+ CLIENT_ERR ("azure KMS provider already set");
+ return false;
+ }
+
+ if (!_mongocrypt_parse_required_utf8 (
+ &as_bson,
+ "azure.tenantId",
+ &crypt->opts.kms_provider_azure.tenant_id,
+ crypt->status)) {
+ return false;
+ }
+
+ if (!_mongocrypt_parse_required_utf8 (
+ &as_bson,
+ "azure.clientId",
+ &crypt->opts.kms_provider_azure.client_id,
+ crypt->status)) {
+ return false;
+ }
+
+ if (!_mongocrypt_parse_required_utf8 (
+ &as_bson,
+ "azure.clientSecret",
+ &crypt->opts.kms_provider_azure.client_secret,
+ crypt->status)) {
+ return false;
+ }
+
+ if (!_mongocrypt_parse_optional_endpoint (
+ &as_bson,
+ "azure.identityPlatformEndpoint",
+ &crypt->opts.kms_provider_azure.identity_platform_endpoint,
+ NULL /* opts */,
+ crypt->status)) {
+ return false;
+ }
+
+ if (!_mongocrypt_check_allowed_fields (&as_bson,
+ "azure",
+ crypt->status,
+ "tenantId",
+ "clientId",
+ "clientSecret",
+ "identityPlatformEndpoint")) {
+ return false;
+ }
+ crypt->opts.kms_providers |= MONGOCRYPT_KMS_PROVIDER_AZURE;
+ } else if (0 == strcmp (field_name, "gcp")) {
+ if (0 != (crypt->opts.kms_providers & MONGOCRYPT_KMS_PROVIDER_GCP)) {
+ CLIENT_ERR ("gcp KMS provider already set");
+ return false;
+ }
+
+ if (!_mongocrypt_parse_required_utf8 (
+ &as_bson,
+ "gcp.email",
+ &crypt->opts.kms_provider_gcp.email,
+ crypt->status)) {
+ return false;
+ }
+
+ if (!_mongocrypt_parse_required_binary (
+ &as_bson,
+ "gcp.privateKey",
+ &crypt->opts.kms_provider_gcp.private_key,
+ crypt->status)) {
+ return false;
+ }
+
+ if (!_mongocrypt_parse_optional_endpoint (
+ &as_bson,
+ "gcp.endpoint",
+ &crypt->opts.kms_provider_gcp.endpoint,
+ NULL /* opts */,
+ crypt->status)) {
+ return false;
+ }
+
+ if (!_mongocrypt_check_allowed_fields (&as_bson,
+ "gcp",
+ crypt->status,
+ "email",
+ "privateKey",
+ "endpoint")) {
+ return false;
+ }
+ crypt->opts.kms_providers |= MONGOCRYPT_KMS_PROVIDER_GCP;
+ } else if (0 == strcmp (field_name, "local")) {
+ if (!_mongocrypt_parse_required_binary (
+ &as_bson,
+ "local.key",
+ &crypt->opts.kms_provider_local.key,
+ crypt->status)) {
+ return false;
+ }
+
+ if (crypt->opts.kms_provider_local.key.len != MONGOCRYPT_KEY_LEN) {
+ CLIENT_ERR ("local key must be %d bytes", MONGOCRYPT_KEY_LEN);
+ return false;
+ }
+
+ if (!_mongocrypt_check_allowed_fields (
+ &as_bson, "local", crypt->status, "key")) {
+ return false;
+ }
+ crypt->opts.kms_providers |= MONGOCRYPT_KMS_PROVIDER_LOCAL;
+ } else if (0 == strcmp (field_name, "aws")) {
+ if (!_mongocrypt_parse_required_utf8 (
+ &as_bson,
+ "aws.accessKeyId",
+ &crypt->opts.kms_provider_aws.access_key_id,
+ crypt->status)) {
+ return false;
+ }
+ if (!_mongocrypt_parse_required_utf8 (
+ &as_bson,
+ "aws.secretAccessKey",
+ &crypt->opts.kms_provider_aws.secret_access_key,
+ crypt->status)) {
+ return false;
+ }
+
+ if (!_mongocrypt_parse_optional_utf8 (
+ &as_bson,
+ "aws.sessionToken",
+ &crypt->opts.kms_provider_aws.session_token,
+ crypt->status)) {
+ return false;
+ }
+
+ if (!_mongocrypt_check_allowed_fields (&as_bson,
+ "aws",
+ crypt->status,
+ "accessKeyId",
+ "secretAccessKey",
+ "sessionToken")) {
+ return false;
+ }
+ crypt->opts.kms_providers |= MONGOCRYPT_KMS_PROVIDER_AWS;
+ } else if (0 == strcmp (field_name, "kmip")) {
+ _mongocrypt_endpoint_parse_opts_t opts = {0};
+
+ opts.allow_empty_subdomain = true;
+ if (!_mongocrypt_parse_required_endpoint (
+ &as_bson,
+ "kmip.endpoint",
+ &crypt->opts.kms_provider_kmip.endpoint,
+ &opts,
+ crypt->status)) {
+ return false;
+ }
+
+ if (!_mongocrypt_check_allowed_fields (
+ &as_bson, "kmip", crypt->status, "endpoint")) {
+ return false;
+ }
+ crypt->opts.kms_providers |= MONGOCRYPT_KMS_PROVIDER_KMIP;
+ } else {
+ CLIENT_ERR ("unsupported KMS provider: %s", field_name);
+ return false;
+ }
+ }
+
+ if (crypt->log.trace_enabled) {
+ char *as_str = bson_as_json (&as_bson, NULL);
+ _mongocrypt_log (&crypt->log,
+ MONGOCRYPT_LOG_LEVEL_TRACE,
+ "%s (%s=\"%s\")",
+ BSON_FUNC,
+ "kms_providers",
+ as_str);
+ bson_free (as_str);
+ }
+
+ return true;
+}
+
+
+void
+mongocrypt_setopt_append_csfle_search_path (mongocrypt_t *crypt,
+ const char *path)
+{
+ // Dup the path string for us to manage
+ mstr pathdup = mstr_copy_cstr (path);
+ // Increase array len
+ const int new_len = crypt->opts.n_cselib_search_paths + 1;
+ mstr *const new_array =
+ bson_realloc (crypt->opts.cselib_search_paths, sizeof (mstr) * new_len);
+ // Store the path
+ new_array[new_len - 1] = pathdup;
+ // Write back opts
+ crypt->opts.cselib_search_paths = new_array;
+ crypt->opts.n_cselib_search_paths = new_len;
+}
+
+
+void
+mongocrypt_setopt_set_csfle_lib_path_override (mongocrypt_t *crypt,
+ const char *path)
+{
+ mstr_assign (&crypt->opts.csfle_lib_override_path, mstr_copy_cstr (path));
+}
diff --git a/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt.h b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt.h
new file mode 100644
index 00000000..8bc49bc7
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt.h
@@ -0,0 +1,1255 @@
+/*
+ * Copyright 2019-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef MONGOCRYPT_H
+#define MONGOCRYPT_H
+
+/** @file mongocrypt.h The top-level handle to libmongocrypt. */
+
+/**
+ * @mainpage libmongocrypt
+ * See all public API documentation in: @ref mongocrypt.h
+ */
+
+#include "mongocrypt-export.h"
+#include "mongocrypt-compat.h"
+#include "mongocrypt-config.h"
+
+/**
+ * @def MONGOCRYPT_VERSION
+ * The version string describing libmongocrypt.
+ * Has the form x.y.z-<pre>+<date>+git<sha>.
+ */
+#define MONGOCRYPT_VERSION "1.3.2"
+
+/**
+ * Returns the version string for libmongocrypt.
+ *
+ * @param[out] len An optional length of the returned string. May be NULL.
+ * @returns a NULL terminated version string for libmongocrypt.
+ */
+MONGOCRYPT_EXPORT
+const char *
+mongocrypt_version (uint32_t *len);
+
+
+/**
+ * A non-owning view of a byte buffer.
+ *
+ * When constructing a mongocrypt_binary_t it is the responsibility of the
+ * caller to maintain the lifetime of the viewed data. However, all public
+ * functions that take a mongocrypt_binary_t as an argument will make a copy of
+ * the viewed data. For example, the following is valid:
+ *
+ * @code{.c}
+ * mongocrypt_binary_t bin = mongocrypt_binary_new_from_data(mydata, mylen);
+ * assert (mongocrypt_setopt_kms_provider_local (crypt), bin);
+ * // The viewed data of bin has been copied. Ok to free the view and the data.
+ * mongocrypt_binary_destroy (bin);
+ * my_free_fn (mydata);
+ * @endcode
+ *
+ * Functions with a mongocrypt_binary_t* out guarantee the lifetime of the
+ * viewed data to live as long as the parent object. For example, @ref
+ * mongocrypt_ctx_mongo_op guarantees that the viewed data of
+ * mongocrypt_binary_t is valid until the parent ctx is destroyed with @ref
+ * mongocrypt_ctx_destroy.
+ */
+typedef struct _mongocrypt_binary_t mongocrypt_binary_t;
+
+
+/**
+ * Create a new non-owning view of a buffer (data + length).
+ *
+ * Use this to create a mongocrypt_binary_t used for output parameters.
+ *
+ * @returns A new mongocrypt_binary_t.
+ */
+MONGOCRYPT_EXPORT
+mongocrypt_binary_t *
+mongocrypt_binary_new (void);
+
+
+/**
+ * Create a new non-owning view of a buffer (data + length).
+ *
+ * @param[in] data A pointer to an array of bytes. This data is not copied. @p
+ * data must outlive the binary object.
+ * @param[in] len The length of the @p data byte array.
+ *
+ * @returns A new @ref mongocrypt_binary_t.
+ */
+MONGOCRYPT_EXPORT
+mongocrypt_binary_t *
+mongocrypt_binary_new_from_data (uint8_t *data, uint32_t len);
+
+
+/**
+ * Get a pointer to the viewed data.
+ *
+ * @param[in] binary The @ref mongocrypt_binary_t.
+ *
+ * @returns A pointer to the viewed data.
+ */
+MONGOCRYPT_EXPORT
+uint8_t *
+mongocrypt_binary_data (const mongocrypt_binary_t *binary);
+
+
+/**
+ * Get the length of the viewed data.
+ *
+ * @param[in] binary The @ref mongocrypt_binary_t.
+ *
+ * @returns The length of the viewed data.
+ */
+MONGOCRYPT_EXPORT
+uint32_t
+mongocrypt_binary_len (const mongocrypt_binary_t *binary);
+
+
+/**
+ * Free the @ref mongocrypt_binary_t.
+ *
+ * This does not free the viewed data.
+ *
+ * @param[in] binary The mongocrypt_binary_t destroy.
+ */
+MONGOCRYPT_EXPORT
+void
+mongocrypt_binary_destroy (mongocrypt_binary_t *binary);
+
+
+/**
+ * Indicates success or contains error information.
+ *
+ * Functions like @ref mongocrypt_ctx_encrypt_init follow a pattern to expose a
+ * status. A boolean is returned. True indicates success, and false indicates
+ * failure. On failure a status on the handle is set, and is accessible with a
+ * corresponding (handle)_status function. E.g. @ref mongocrypt_ctx_status.
+ */
+typedef struct _mongocrypt_status_t mongocrypt_status_t;
+
+/**
+ * Indicates the type of error.
+ */
+typedef enum {
+ MONGOCRYPT_STATUS_OK = 0,
+ MONGOCRYPT_STATUS_ERROR_CLIENT = 1,
+ MONGOCRYPT_STATUS_ERROR_KMS = 2
+} mongocrypt_status_type_t;
+
+
+/**
+ * Create a new status object.
+ *
+ * Use a new status object to retrieve the status from a handle by passing
+ * this as an out-parameter to functions like @ref mongocrypt_ctx_status.
+ * When done, destroy it with @ref mongocrypt_status_destroy.
+ *
+ * @returns A new status object.
+ */
+MONGOCRYPT_EXPORT
+mongocrypt_status_t *
+mongocrypt_status_new (void);
+
+
+/**
+ * Set a status object with message, type, and code.
+ *
+ * Use this to set the @ref mongocrypt_status_t given in the crypto hooks.
+ *
+ * @param[in] type The status type.
+ * @param[in] code The status code.
+ * @param[in] message The message.
+ * @param[in] message_len Due to historical behavior, pass 1 + the string length
+ * of @p message (which differs from other functions accepting string
+ * arguments).
+ * Alternatively, if message is NULL terminated this may be -1 to tell
+ * mongocrypt
+ * to determine the string's length with strlen.
+ *
+ */
+MONGOCRYPT_EXPORT
+void
+mongocrypt_status_set (mongocrypt_status_t *status,
+ mongocrypt_status_type_t type,
+ uint32_t code,
+ const char *message,
+ int32_t message_len);
+
+
+/**
+ * Indicates success or the type of error.
+ *
+ * @param[in] status The status object.
+ *
+ * @returns A @ref mongocrypt_status_type_t.
+ */
+MONGOCRYPT_EXPORT
+mongocrypt_status_type_t
+mongocrypt_status_type (mongocrypt_status_t *status);
+
+
+/**
+ * Get an error code or 0.
+ *
+ * @param[in] status The status object.
+ *
+ * @returns An error code.
+ */
+MONGOCRYPT_EXPORT
+uint32_t
+mongocrypt_status_code (mongocrypt_status_t *status);
+
+
+/**
+ * Get the error message associated with a status or NULL.
+ *
+ * @param[in] status The status object.
+ * @param[out] len An optional length of the returned string (excluding the
+ * trailing NULL byte). May be NULL.
+ *
+ * @returns A NULL terminated error message or NULL.
+ */
+MONGOCRYPT_EXPORT
+const char *
+mongocrypt_status_message (mongocrypt_status_t *status, uint32_t *len);
+
+
+/**
+ * Returns true if the status indicates success.
+ *
+ * @param[in] status The status to check.
+ *
+ * @returns A boolean indicating success. If false, an error status is set.
+ * Retrieve it with @ref mongocrypt_ctx_status
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_status_ok (mongocrypt_status_t *status);
+
+
+/**
+ * Free the memory for a status object.
+ *
+ * @param[in] status The status to destroy.
+ */
+MONGOCRYPT_EXPORT
+void
+mongocrypt_status_destroy (mongocrypt_status_t *status);
+
+/**
+ * Indicates the type of log message.
+ */
+typedef enum {
+ MONGOCRYPT_LOG_LEVEL_FATAL = 0,
+ MONGOCRYPT_LOG_LEVEL_ERROR = 1,
+ MONGOCRYPT_LOG_LEVEL_WARNING = 2,
+ MONGOCRYPT_LOG_LEVEL_INFO = 3,
+ MONGOCRYPT_LOG_LEVEL_TRACE = 4
+} mongocrypt_log_level_t;
+
+
+/**
+ * A log callback function. Set a custom log callback with @ref
+ * mongocrypt_setopt_log_handler.
+ *
+ * @param[in] message A NULL terminated message.
+ * @param[in] message_len The length of message.
+ * @param[in] ctx A context provided by the caller of @ref
+ * mongocrypt_setopt_log_handler.
+ */
+typedef void (*mongocrypt_log_fn_t) (mongocrypt_log_level_t level,
+ const char *message,
+ uint32_t message_len,
+ void *ctx);
+
+
+/**
+ * The top-level handle to libmongocrypt.
+ *
+ * Create a mongocrypt_t handle to perform operations within libmongocrypt:
+ * encryption, decryption, registering log callbacks, etc.
+ *
+ * Functions on a mongocrypt_t are thread safe, though functions on derived
+ * handles (e.g. mongocrypt_ctx_t) are not and must be owned by a single
+ * thread. See each handle's documentation for thread-safety considerations.
+ *
+ * Multiple mongocrypt_t handles may be created.
+ */
+typedef struct _mongocrypt_t mongocrypt_t;
+
+
+/**
+ * Allocate a new @ref mongocrypt_t object.
+ *
+ * Set options using mongocrypt_setopt_* functions, then initialize with @ref
+ * mongocrypt_init. When done with the @ref mongocrypt_t, free with @ref
+ * mongocrypt_destroy.
+ *
+ * @returns A new @ref mongocrypt_t object.
+ */
+MONGOCRYPT_EXPORT
+mongocrypt_t *
+mongocrypt_new (void);
+
+
+/**
+ * Set a handler on the @ref mongocrypt_t object to get called on every log
+ * message.
+ *
+ * @param[in] crypt The @ref mongocrypt_t object.
+ * @param[in] log_fn The log callback.
+ * @param[in] log_ctx A context passed as an argument to the log callback every
+ * invocation.
+ * @pre @ref mongocrypt_init has not been called on @p crypt.
+ * @returns A boolean indicating success. If false, an error status is set.
+ * Retrieve it with @ref mongocrypt_ctx_status
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_setopt_log_handler (mongocrypt_t *crypt,
+ mongocrypt_log_fn_t log_fn,
+ void *log_ctx);
+
+
+/**
+ * Configure an AWS KMS provider on the @ref mongocrypt_t object.
+ *
+ * This has been superseded by the more flexible:
+ * @ref mongocrypt_setopt_kms_providers
+ *
+ * @param[in] crypt The @ref mongocrypt_t object.
+ * @param[in] aws_access_key_id The AWS access key ID used to generate KMS
+ * messages.
+ * @param[in] aws_access_key_id_len The string length (in bytes) of @p
+ * aws_access_key_id. Pass -1 to determine the string length with strlen (must
+ * be NULL terminated).
+ * @param[in] aws_secret_access_key The AWS secret access key used to generate
+ * KMS messages.
+ * @param[in] aws_secret_access_key_len The string length (in bytes) of @p
+ * aws_secret_access_key. Pass -1 to determine the string length with strlen
+ * (must be NULL terminated).
+ * @pre @ref mongocrypt_init has not been called on @p crypt.
+ * @returns A boolean indicating success. If false, an error status is set.
+ * Retrieve it with @ref mongocrypt_ctx_status
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_setopt_kms_provider_aws (mongocrypt_t *crypt,
+ const char *aws_access_key_id,
+ int32_t aws_access_key_id_len,
+ const char *aws_secret_access_key,
+ int32_t aws_secret_access_key_len);
+
+
+/**
+ * Configure a local KMS provider on the @ref mongocrypt_t object.
+ *
+ * This has been superseded by the more flexible:
+ * @ref mongocrypt_setopt_kms_providers
+ *
+ * @param[in] crypt The @ref mongocrypt_t object.
+ * @param[in] key A 96 byte master key used to encrypt and decrypt key vault
+ * keys. The viewed data is copied. It is valid to destroy @p key with @ref
+ * mongocrypt_binary_destroy immediately after.
+ * @pre @ref mongocrypt_init has not been called on @p crypt.
+ * @returns A boolean indicating success. If false, an error status is set.
+ * Retrieve it with @ref mongocrypt_ctx_status
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_setopt_kms_provider_local (mongocrypt_t *crypt,
+ mongocrypt_binary_t *key);
+
+/**
+ * Configure KMS providers with a BSON document.
+ *
+ * @param[in] crypt The @ref mongocrypt_t object.
+ * @param[in] kms_providers A BSON document mapping the KMS provider names
+ * to credentials.
+ * @pre @ref mongocrypt_init has not been called on @p crypt.
+ * @returns A boolean indicating success. If false, an error status is set.
+ * Retrieve it with @ref mongocrypt_ctx_status
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_setopt_kms_providers (mongocrypt_t *crypt,
+ mongocrypt_binary_t *kms_providers);
+
+/**
+ * Set a local schema map for encryption.
+ *
+ * @param[in] crypt The @ref mongocrypt_t object.
+ * @param[in] schema_map A BSON document representing the schema map supplied by
+ * the user. The keys are collection namespaces and values are JSON schemas. The
+ * viewed data copied. It is valid to destroy @p schema_map with @ref
+ * mongocrypt_binary_destroy immediately after.
+ * @pre @p crypt has not been initialized.
+ * @returns A boolean indicating success. If false, an error status is set.
+ * Retrieve it with @ref mongocrypt_status
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_setopt_schema_map (mongocrypt_t *crypt,
+ mongocrypt_binary_t *schema_map);
+
+
+/**
+ * @brief Append an additional search directory to the search path for loading
+ * the CSFLE dynamic library.
+ *
+ * @param[in] crypt The @ref mongocrypt_t object to update
+ * @param[in] path A null-terminated sequence of bytes for the search path. On
+ * some filesystems, this may be arbitrary bytes. On other filesystems, this may
+ * be required to be a valid UTF-8 code unit sequence. If the leading element of
+ * the path is the literal string "$ORIGIN", that substring will be replaced
+ * with the directory path containing the executable libmongocrypt module. If
+ * the path string is literal "$SYSTEM", then libmongocrypt will defer to the
+ * system's library resolution mechanism to find the CSFLE library.
+ *
+ * @note If no CSFLE dynamic library is found in any of the directories
+ * specified by the search paths loaded here, @ref mongocrypt_init() will still
+ * succeed and continue to operate without CSFLE.
+ *
+ * @note The search paths are searched in the order that they are appended. This
+ * allows one to provide a precedence in how the library will be discovered. For
+ * example, appending known directories before appending "$SYSTEM" will allow
+ * one to supersede the system's installed library, but still fall-back to it if
+ * the library wasn't found otherwise. If one does not ever append "$SYSTEM",
+ * then the system's library-search mechanism will never be consulted.
+ *
+ * @note If an absolute path to the library is specified using
+ * @ref mongocrypt_setopt_set_csfle_lib_path_override, then paths appended here
+ * will have no effect.
+ */
+MONGOCRYPT_EXPORT
+void
+mongocrypt_setopt_append_csfle_search_path (mongocrypt_t *crypt,
+ const char *path);
+
+
+/**
+ * @brief Set a single override path for loading the CSFLE dynamic library.
+ *
+ * @param[in] crypt The @ref mongocrypt_t object to update
+ * @param[in] path A null-terminated sequence of bytes for a path to the CSFLE
+ * dynamic library. On some filesystems, this may be arbitrary bytes. On other
+ * filesystems, this may be required to be a valid UTF-8 code unit sequence. If
+ * the leading element of the path is the literal string `$ORIGIN`, that
+ * substring will be replaced with the directory path containing the executable
+ * libmongocrypt module.
+ *
+ * @note This function will do no IO nor path validation. All validation will
+ * occur during the call to @ref mongocrypt_init.
+ *
+ * @note If a CSFLE library path override is specified here, then no paths given
+ * to @ref mongocrypt_setopt_append_csfle_search_path will be consulted when
+ * opening the CSFLE library.
+ *
+ * @note If a path is provided via this API and @ref mongocrypt_init fails to
+ * initialize a valid CSFLE library instance for the path specified, then
+ * the initialization of mongocrypt_t will fail with an error.
+ */
+MONGOCRYPT_EXPORT
+void
+mongocrypt_setopt_set_csfle_lib_path_override (mongocrypt_t *crypt,
+ const char *path);
+
+
+/**
+ * Initialize new @ref mongocrypt_t object.
+ *
+ * Set options before using @ref mongocrypt_setopt_kms_provider_local, @ref
+ * mongocrypt_setopt_kms_provider_aws, or @ref mongocrypt_setopt_log_handler.
+ *
+ * @param[in] crypt The @ref mongocrypt_t object.
+ *
+ * @returns A boolean indicating success. If false, an error status is set.
+ * Retrieve it with @ref mongocrypt_ctx_status Failure may occur if previously
+ * set
+ * options are invalid.
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_init (mongocrypt_t *crypt);
+
+
+/**
+ * Get the status associated with a @ref mongocrypt_t object.
+ *
+ * @param[in] crypt The @ref mongocrypt_t object.
+ * @param[out] status Receives the status.
+ *
+ * @returns A boolean indicating success. If false, an error status is set.
+ * Retrieve it with @ref mongocrypt_ctx_status
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_status (mongocrypt_t *crypt, mongocrypt_status_t *status);
+
+
+/**
+ * Destroy the @ref mongocrypt_t object.
+ *
+ * @param[in] crypt The @ref mongocrypt_t object to destroy.
+ */
+MONGOCRYPT_EXPORT
+void
+mongocrypt_destroy (mongocrypt_t *crypt);
+
+
+/**
+ * Manages the state machine for encryption or decryption.
+ */
+typedef struct _mongocrypt_ctx_t mongocrypt_ctx_t;
+
+
+/**
+ * Create a new uninitialized @ref mongocrypt_ctx_t.
+ *
+ * Initialize the context with functions like @ref mongocrypt_ctx_encrypt_init.
+ * When done, destroy it with @ref mongocrypt_ctx_destroy.
+ *
+ * @param[in] crypt The @ref mongocrypt_t object.
+ * @returns A new context.
+ */
+MONGOCRYPT_EXPORT
+mongocrypt_ctx_t *
+mongocrypt_ctx_new (mongocrypt_t *crypt);
+
+
+/**
+ * Get the status associated with a @ref mongocrypt_ctx_t object.
+ *
+ * @param[in] ctx The @ref mongocrypt_ctx_t object.
+ * @param[out] status Receives the status.
+ *
+ * @returns True if the output is an ok status, false if it is an error
+ * status.
+ *
+ * @see mongocrypt_status_ok
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_ctx_status (mongocrypt_ctx_t *ctx, mongocrypt_status_t *status);
+
+
+/**
+ * Set the key id to use for explicit encryption.
+ *
+ * It is an error to set both this and the key alt name.
+ *
+ * @param[in] ctx The @ref mongocrypt_ctx_t object.
+ * @param[in] key_id The binary corresponding to the _id (a UUID) of the data
+ * key to use from the key vault collection. Note, the UUID must be encoded with
+ * RFC-4122 byte order. The viewed data is copied. It is valid to destroy
+ * @p key_id with @ref mongocrypt_binary_destroy immediately after.
+ * @pre @p ctx has not been initialized.
+ * @returns A boolean indicating success. If false, an error status is set.
+ * Retrieve it with @ref mongocrypt_ctx_status
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_ctx_setopt_key_id (mongocrypt_ctx_t *ctx,
+ mongocrypt_binary_t *key_id);
+
+/**
+ * Set the keyAltName to use for explicit encryption or
+ * data key creation.
+ *
+ * Pass the binary encoding a BSON document like the following:
+ *
+ * { "keyAltName" : (BSON UTF8 value) }
+ *
+ * For explicit encryption, it is an error to set both the keyAltName
+ * and the key id.
+ *
+ * For creating data keys, call this function repeatedly to set
+ * multiple keyAltNames.
+ *
+ * @param[in] ctx The @ref mongocrypt_ctx_t object.
+ * @param[in] key_alt_name The name to use. The viewed data is copied. It is
+ * valid to destroy @p key_alt_name with @ref mongocrypt_binary_destroy
+ * immediately after.
+ * @pre @p ctx has not been initialized.
+ * @returns A boolean indicating success. If false, an error status is set.
+ * Retrieve it with @ref mongocrypt_ctx_status
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_ctx_setopt_key_alt_name (mongocrypt_ctx_t *ctx,
+ mongocrypt_binary_t *key_alt_name);
+
+/**
+ * Set the keyMaterial to use for encrypting data.
+ *
+ * Pass the binary encoding of a BSON document like the following:
+ *
+ * { "keyMaterial" : (BSON BINARY value) }
+ *
+ * @param[in] ctx The @ref mongocrypt_ctx_t object.
+ * @param[in] key_material The data encryption key to use. The viewed data is
+ * copied. It is valid to destroy @p key_material with @ref
+ * mongocrypt_binary_destroy immediately after.
+ * @pre @p ctx has not been initialized.
+ * @returns A boolean indicating success. If false, an error status is set.
+ * Retrieve it with @ref mongocrypt_ctx_status
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_ctx_setopt_key_material (mongocrypt_ctx_t *ctx,
+ mongocrypt_binary_t *key_material);
+
+/**
+ * Set the algorithm used for encryption to either
+ * deterministic or random encryption. This value
+ * should only be set when using explicit encryption.
+ *
+ * If -1 is passed in for "len", then "algorithm" is
+ * assumed to be a null-terminated string.
+ *
+ * Valid values for algorithm are:
+ * "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic"
+ * "AEAD_AES_256_CBC_HMAC_SHA_512-Random"
+ *
+ * @param[in] ctx The @ref mongocrypt_ctx_t object.
+ * @param[in] algorithm A string specifying the algorithm to
+ * use for encryption.
+ * @param[in] len The length of the algorithm string.
+ * @pre @p ctx has not been initialized.
+ * @returns A boolean indicating success. If false, an error status is set.
+ * Retrieve it with @ref mongocrypt_ctx_status
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_ctx_setopt_algorithm (mongocrypt_ctx_t *ctx,
+ const char *algorithm,
+ int len);
+
+
+/**
+ * Identify the AWS KMS master key to use for creating a data key.
+ *
+ * This has been superseded by the more flexible:
+ * @ref mongocrypt_ctx_setopt_key_encryption_key
+ *
+ * @param[in] ctx The @ref mongocrypt_ctx_t object.
+ * @param[in] region The AWS region.
+ * @param[in] region_len The string length of @p region. Pass -1 to determine
+ * the string length with strlen (must be NULL terminated).
+ * @param[in] cmk The Amazon Resource Name (ARN) of the customer master key
+ * (CMK).
+ * @param[in] cmk_len The string length of @p cmk_len. Pass -1 to determine the
+ * string length with strlen (must be NULL terminated).
+ * @pre @p ctx has not been initialized.
+ * @returns A boolean indicating success. If false, an error status is set.
+ * Retrieve it with @ref mongocrypt_ctx_status
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_ctx_setopt_masterkey_aws (mongocrypt_ctx_t *ctx,
+ const char *region,
+ int32_t region_len,
+ const char *cmk,
+ int32_t cmk_len);
+
+
+/**
+ * Identify a custom AWS endpoint when creating a data key.
+ * This is used internally to construct the correct HTTP request
+ * (with the Host header set to this endpoint). This endpoint
+ * is persisted in the new data key, and will be returned via
+ * @ref mongocrypt_kms_ctx_endpoint.
+ *
+ * This has been superseded by the more flexible:
+ * @ref mongocrypt_ctx_setopt_key_encryption_key
+ *
+ * @param[in] ctx The @ref mongocrypt_ctx_t object.
+ * @param[in] endpoint The endpoint.
+ * @param[in] endpoint_len The string length of @p endpoint. Pass -1 to
+ * determine the string length with strlen (must be NULL terminated).
+ * @returns A boolean indicating success. If false, an error status is set.
+ * Retrieve it with @ref mongocrypt_ctx_status
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_ctx_setopt_masterkey_aws_endpoint (mongocrypt_ctx_t *ctx,
+ const char *endpoint,
+ int32_t endpoint_len);
+
+/**
+ * Set the master key to "local" for creating a data key.
+ * This has been superseded by the more flexible:
+ * @ref mongocrypt_ctx_setopt_key_encryption_key
+ *
+ * @param[in] ctx The @ref mongocrypt_ctx_t object.
+ * @pre @p ctx has not been initialized.
+ * @returns A boolean indicating success. If false, an error status is set.
+ * Retrieve it with @ref mongocrypt_ctx_status
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_ctx_setopt_masterkey_local (mongocrypt_ctx_t *ctx);
+
+/**
+ * Set key encryption key document for creating a data key.
+ *
+ * @param[in] ctx The @ref mongocrypt_ctx_t object.
+ * @param[in] bin BSON representing the key encryption key document with
+ * an additional "provider" field. The following forms are accepted:
+ *
+ * AWS
+ * {
+ * provider: "aws",
+ * region: <string>,
+ * key: <string>,
+ * endpoint: <optional string>
+ * }
+ *
+ * Azure
+ * {
+ * provider: "azure",
+ * keyVaultEndpoint: <string>,
+ * keyName: <string>,
+ * keyVersion: <optional string>
+ * }
+ *
+ * GCP
+ * {
+ * provider: "gcp",
+ * projectId: <string>,
+ * location: <string>,
+ * keyRing: <string>,
+ * keyName: <string>,
+ * keyVersion: <string>,
+ * endpoint: <optional string>
+ * }
+ *
+ * Local
+ * {
+ * provider: "local"
+ * }
+ *
+ * KMIP
+ * {
+ * provider: "kmip",
+ * keyId: <optional string>
+ * endpoint: <string>
+ * }
+ *
+ * @pre @p ctx has not been initialized.
+ * @returns A boolean indicating success. If false, and error status is set.
+ * Retrieve it with @ref mongocrypt_ctx_status.
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_ctx_setopt_key_encryption_key (mongocrypt_ctx_t *ctx,
+ mongocrypt_binary_t *bin);
+
+
+/**
+ * Initialize a context to create a data key.
+ *
+ * Associated options:
+ * - @ref mongocrypt_ctx_setopt_masterkey_aws
+ * - @ref mongocrypt_ctx_setopt_masterkey_aws_endpoint
+ * - @ref mongocrypt_ctx_setopt_masterkey_local
+ *
+ * @param[in] ctx The @ref mongocrypt_ctx_t object.
+ * @returns A boolean indicating success. If false, an error status is set.
+ * Retrieve it with @ref mongocrypt_ctx_status
+ * @pre A master key option has been set, and an associated KMS provider
+ * has been set on the parent @ref mongocrypt_t.
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_ctx_datakey_init (mongocrypt_ctx_t *ctx);
+
+/**
+ * Initialize a context for encryption.
+ *
+ * @param[in] ctx The @ref mongocrypt_ctx_t object.
+ * @param[in] db The database name.
+ * @param[in] db_len The byte length of @p db. Pass -1 to determine the string
+ * length with strlen (must
+ * be NULL terminated).
+ * @param[in] cmd The BSON command to be encrypted. The viewed data is copied.
+ * It is valid to destroy @p cmd with @ref mongocrypt_binary_destroy immediately
+ * after.
+ * @returns A boolean indicating success. If false, an error status is set.
+ * Retrieve it with @ref mongocrypt_ctx_status
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_ctx_encrypt_init (mongocrypt_ctx_t *ctx,
+ const char *db,
+ int32_t db_len,
+ mongocrypt_binary_t *cmd);
+
+/**
+ * Explicit helper method to encrypt a single BSON object. Contexts
+ * created for explicit encryption will not go through mongocryptd.
+ *
+ * To specify a key_id, algorithm, or iv to use, please use the
+ * corresponding mongocrypt_setopt methods before calling this.
+ *
+ * This method expects the passed-in BSON to be of the form:
+ * { "v" : BSON value to encrypt }
+ *
+ * Associated options:
+ * - @ref mongocrypt_ctx_setopt_key_id
+ * - @ref mongocrypt_ctx_setopt_key_alt_name
+ * - @ref mongocrypt_ctx_setopt_algorithm
+ *
+ * @param[in] ctx A @ref mongocrypt_ctx_t.
+ * @param[in] msg A @ref mongocrypt_binary_t the plaintext BSON value. The
+ * viewed data is copied. It is valid to destroy @p msg with @ref
+ * mongocrypt_binary_destroy immediately after.
+ * @returns A boolean indicating success. If false, an error status is set.
+ * Retrieve it with @ref mongocrypt_ctx_status
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_ctx_explicit_encrypt_init (mongocrypt_ctx_t *ctx,
+ mongocrypt_binary_t *msg);
+
+
+/**
+ * Initialize a context for decryption.
+ *
+ * This method expects the passed-in BSON to be of the form:
+ * { "v" : BSON value to encrypt }
+ *
+ * @param[in] ctx The @ref mongocrypt_ctx_t object.
+ * @param[in] doc The document to be decrypted. The viewed data is copied. It is
+ * valid to destroy @p doc with @ref mongocrypt_binary_destroy immediately
+ * after.
+ * @returns A boolean indicating success. If false, an error status is set.
+ * Retrieve it with @ref mongocrypt_ctx_status
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_ctx_decrypt_init (mongocrypt_ctx_t *ctx, mongocrypt_binary_t *doc);
+
+
+/**
+ * Explicit helper method to decrypt a single BSON object.
+ *
+ *
+ * @param[in] ctx A @ref mongocrypt_ctx_t.
+ * @param[in] msg A @ref mongocrypt_binary_t the encrypted BSON. The viewed data
+ * is copied. It is valid to destroy @p msg with @ref mongocrypt_binary_destroy
+ * immediately after.
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_ctx_explicit_decrypt_init (mongocrypt_ctx_t *ctx,
+ mongocrypt_binary_t *msg);
+
+
+/**
+ * Indicates the state of the @ref mongocrypt_ctx_t. Each state requires
+ * different handling. See [the integration
+ * guide](https://github.com/mongodb/libmongocrypt/blob/master/integrating.md#state-machine)
+ * for information on what to do for each state.
+ */
+typedef enum {
+ MONGOCRYPT_CTX_ERROR = 0,
+ MONGOCRYPT_CTX_NEED_MONGO_COLLINFO = 1, /* run on main MongoClient */
+ MONGOCRYPT_CTX_NEED_MONGO_MARKINGS = 2, /* run on mongocryptd. */
+ MONGOCRYPT_CTX_NEED_MONGO_KEYS = 3, /* run on key vault */
+ MONGOCRYPT_CTX_NEED_KMS = 4,
+ MONGOCRYPT_CTX_READY = 5, /* ready for encryption/decryption */
+ MONGOCRYPT_CTX_DONE = 6
+} mongocrypt_ctx_state_t;
+
+
+/**
+ * Get the current state of a context.
+ *
+ * @param[in] ctx The @ref mongocrypt_ctx_t object.
+ * @returns A @ref mongocrypt_ctx_state_t.
+ */
+MONGOCRYPT_EXPORT
+mongocrypt_ctx_state_t
+mongocrypt_ctx_state (mongocrypt_ctx_t *ctx);
+
+
+/**
+ * Get BSON necessary to run the mongo operation when mongocrypt_ctx_t
+ * is in MONGOCRYPT_CTX_NEED_MONGO_* states.
+ *
+ * @p op_bson is a BSON document to be used for the operation.
+ * - For MONGOCRYPT_CTX_NEED_MONGO_COLLINFO it is a listCollections filter.
+ * - For MONGOCRYPT_CTX_NEED_MONGO_KEYS it is a find filter.
+ * - For MONGOCRYPT_CTX_NEED_MONGO_MARKINGS it is a command to send to
+ * mongocryptd.
+ *
+ * The lifetime of @p op_bson is tied to the lifetime of @p ctx. It is valid
+ * until @ref mongocrypt_ctx_destroy is called.
+ *
+ * @param[in] ctx The @ref mongocrypt_ctx_t object.
+ * @param[out] op_bson A BSON document for the MongoDB operation. The data
+ * viewed by @p op_bson is guaranteed to be valid until @p ctx is destroyed with
+ * @ref mongocrypt_ctx_destroy.
+ * @returns A boolean indicating success. If false, an error status is set.
+ * Retrieve it with @ref mongocrypt_ctx_status
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_ctx_mongo_op (mongocrypt_ctx_t *ctx, mongocrypt_binary_t *op_bson);
+
+
+/**
+ * Feed a BSON reply or result when mongocrypt_ctx_t is in
+ * MONGOCRYPT_CTX_NEED_MONGO_* states. This may be called multiple times
+ * depending on the operation.
+ *
+ * reply is a BSON document result being fed back for this operation.
+ * - For MONGOCRYPT_CTX_NEED_MONGO_COLLINFO it is a doc from a listCollections
+ * cursor. (Note, if listCollections returned no result, do not call this
+ * function.)
+ * - For MONGOCRYPT_CTX_NEED_MONGO_KEYS it is a doc from a find cursor.
+ * (Note, if find returned no results, do not call this function. reply must
+ * not
+ * be NULL.)
+ * - For MONGOCRYPT_CTX_NEED_MONGO_MARKINGS it is a reply from mongocryptd.
+ *
+ * @param[in] ctx The @ref mongocrypt_ctx_t object.
+ * @param[in] reply A BSON document for the MongoDB operation. The viewed data
+ * is copied. It is valid to destroy @p reply with @ref
+ * mongocrypt_binary_destroy immediately after.
+ * @returns A boolean indicating success. If false, an error status is set.
+ * Retrieve it with @ref mongocrypt_ctx_status
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_ctx_mongo_feed (mongocrypt_ctx_t *ctx, mongocrypt_binary_t *reply);
+
+
+/**
+ * Call when done feeding the reply (or replies) back to the context.
+ *
+ * @param[in] ctx The @ref mongocrypt_ctx_t object.
+ * @returns A boolean indicating success. If false, an error status is set.
+ * Retrieve it with @ref mongocrypt_ctx_status
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_ctx_mongo_done (mongocrypt_ctx_t *ctx);
+
+
+/**
+ * Manages a single KMS HTTP request/response.
+ */
+typedef struct _mongocrypt_kms_ctx_t mongocrypt_kms_ctx_t;
+
+
+/**
+ * Get the next KMS handle.
+ *
+ * Multiple KMS handles may be retrieved at once. Drivers may do this to fan
+ * out multiple concurrent KMS HTTP requests. Feeding multiple KMS requests
+ * is thread-safe.
+ *
+ * If KMS handles are being handled synchronously, the driver can reuse the same
+ * TLS socket to send HTTP requests and receive responses.
+ *
+ * @param[in] ctx A @ref mongocrypt_ctx_t.
+ * @returns a new @ref mongocrypt_kms_ctx_t or NULL.
+ */
+MONGOCRYPT_EXPORT
+mongocrypt_kms_ctx_t *
+mongocrypt_ctx_next_kms_ctx (mongocrypt_ctx_t *ctx);
+
+
+/**
+ * Get the HTTP request message for a KMS handle.
+ *
+ * The lifetime of @p msg is tied to the lifetime of @p kms. It is valid
+ * until @ref mongocrypt_ctx_kms_done is called.
+ *
+ * @param[in] kms A @ref mongocrypt_kms_ctx_t.
+ * @param[out] msg The HTTP request to send to KMS. The data viewed by @p msg is
+ * guaranteed to be valid until the call of @ref mongocrypt_ctx_kms_done of the
+ * parent @ref mongocrypt_ctx_t.
+ * @returns A boolean indicating success. If false, an error status is set.
+ * Retrieve it with @ref mongocrypt_kms_ctx_status
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_kms_ctx_message (mongocrypt_kms_ctx_t *kms,
+ mongocrypt_binary_t *msg);
+
+
+/**
+ * Get the hostname from which to connect over TLS.
+ *
+ * The storage for @p endpoint is not owned by the caller, but
+ * is valid until calling @ref mongocrypt_ctx_kms_done.
+ *
+ * @param[in] kms A @ref mongocrypt_kms_ctx_t.
+ * @param[out] endpoint The output endpoint as a NULL terminated string.
+ * The endpoint consists of a hostname and port separated by a colon.
+ * E.g. "example.com:123". A port is always present.
+ *
+ * @returns A boolean indicating success. If false, an error status is set.
+ * Retrieve it with @ref mongocrypt_kms_ctx_status
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_kms_ctx_endpoint (mongocrypt_kms_ctx_t *kms, const char **endpoint);
+
+
+/**
+ * Indicates how many bytes to feed into @ref mongocrypt_kms_ctx_feed.
+ *
+ * @param[in] kms The @ref mongocrypt_kms_ctx_t.
+ * @returns The number of requested bytes.
+ */
+MONGOCRYPT_EXPORT
+uint32_t
+mongocrypt_kms_ctx_bytes_needed (mongocrypt_kms_ctx_t *kms);
+
+
+/**
+ * Feed bytes from the HTTP response.
+ *
+ * Feeding more bytes than what has been returned in @ref
+ * mongocrypt_kms_ctx_bytes_needed is an error.
+ *
+ * @param[in] kms The @ref mongocrypt_kms_ctx_t.
+ * @param[in] bytes The bytes to feed. The viewed data is copied. It is valid to
+ * destroy @p bytes with @ref mongocrypt_binary_destroy immediately after.
+ * @returns A boolean indicating success. If false, an error status is set.
+ * Retrieve it with @ref mongocrypt_kms_ctx_status
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_kms_ctx_feed (mongocrypt_kms_ctx_t *kms, mongocrypt_binary_t *bytes);
+
+
+/**
+ * Get the status associated with a @ref mongocrypt_kms_ctx_t object.
+ *
+ * @param[in] kms The @ref mongocrypt_kms_ctx_t object.
+ * @param[out] status Receives the status.
+ *
+ * @returns A boolean indicating success. If false, an error status is set.
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_kms_ctx_status (mongocrypt_kms_ctx_t *kms,
+ mongocrypt_status_t *status);
+
+/**
+ * Get the KMS provider identifier associated with this KMS request.
+ *
+ * This is used to conditionally configure TLS connections based on the KMS
+ * request. It is useful for KMIP, which authenticates with a client
+ * certificate.
+ *
+ * @param[in] kms The @ref mongocrypt_kms_ctx_t object.
+ * @param[out] len Receives the length of the returned string. It may be NULL.
+ * If it is not NULL, it is set to the length of the returned string without
+ * the NULL terminator.
+ *
+ * @returns One of the NULL terminated static strings: "aws", "azure", "gcp", or
+ * "kmip".
+ */
+MONGOCRYPT_EXPORT
+const char *
+mongocrypt_kms_ctx_get_kms_provider (mongocrypt_kms_ctx_t *kms, uint32_t *len);
+
+
+/**
+ * Call when done handling all KMS contexts.
+ *
+ * @param[in] ctx The @ref mongocrypt_ctx_t object.
+ *
+ * @returns A boolean indicating success. If false, an error status is set.
+ * Retrieve it with @ref mongocrypt_ctx_status
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_ctx_kms_done (mongocrypt_ctx_t *ctx);
+
+
+/**
+ * Perform the final encryption or decryption.
+ *
+ * @param[in] ctx A @ref mongocrypt_ctx_t.
+ * @param[out] out The final BSON. The data viewed by @p out is guaranteed
+ * to be valid until @p ctx is destroyed with @ref mongocrypt_ctx_destroy.
+ * The meaning of this BSON depends on the type of @p ctx.
+ *
+ * If @p ctx was initialized with @ref mongocrypt_ctx_encrypt_init, then
+ * this BSON is the (possibly) encrypted command to send to the server.
+ *
+ * If @p ctx was initialized with @ref mongocrypt_ctx_decrypt_init, then
+ * this BSON is the decrypted result to return to the user.
+ *
+ * If @p ctx was initialized with @ref mongocrypt_ctx_explicit_encrypt_init,
+ * then this BSON has the form { "v": (BSON binary) } where the BSON binary
+ * is the resulting encrypted value.
+ *
+ * If @p ctx was initialized with @ref mongocrypt_ctx_explicit_decrypt_init,
+ * then this BSON has the form { "v": (BSON value) } where the BSON value
+ * is the resulting decrypted value.
+ *
+ * If @p ctx was initialized with @ref mongocrypt_ctx_datakey_init, then
+ * this BSON is the document containing the new data key to be inserted into
+ * the key vault collection.
+ *
+ * @returns a bool indicating success. If false, an error status is set.
+ * Retrieve it with @ref mongocrypt_ctx_status
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_ctx_finalize (mongocrypt_ctx_t *ctx, mongocrypt_binary_t *out);
+
+
+/**
+ * Destroy and free all memory associated with a @ref mongocrypt_ctx_t.
+ *
+ * @param[in] ctx A @ref mongocrypt_ctx_t.
+ */
+MONGOCRYPT_EXPORT
+void
+mongocrypt_ctx_destroy (mongocrypt_ctx_t *ctx);
+
+/**
+ * An crypto AES-256-CBC encrypt or decrypt function.
+ *
+ * Note, @p in is already padded. Encrypt with padding disabled.
+ * @param[in] ctx An optional context object that may have been set when hooks
+ * were enabled.
+ * @param[in] key An encryption key (32 bytes for AES_256).
+ * @param[in] iv An initialization vector (16 bytes for AES_256);
+ * @param[in] in The input.
+ * @param[out] out A preallocated byte array for the output. See @ref
+ * mongocrypt_binary_data.
+ * @param[out] bytes_written Set this to the number of bytes written to @p out.
+ * @param[out] status An optional status to pass error messages. See @ref
+ * mongocrypt_status_set.
+ * @returns A boolean indicating success. If returning false, set @p status
+ * with a message indiciating the error using @ref mongocrypt_status_set.
+ */
+typedef bool (*mongocrypt_crypto_fn) (void *ctx,
+ mongocrypt_binary_t *key,
+ mongocrypt_binary_t *iv,
+ mongocrypt_binary_t *in,
+ mongocrypt_binary_t *out,
+ uint32_t *bytes_written,
+ mongocrypt_status_t *status);
+
+/**
+ * A crypto signature or HMAC function.
+ *
+ * Currently used in callbacks for HMAC SHA-512, HMAC SHA-256, and RSA SHA-256
+ * signature.
+ *
+ * @param[in] ctx An optional context object that may have been set when hooks
+ * were enabled.
+ * @param[in] key An encryption key (32 bytes for HMAC_SHA512).
+ * @param[in] in The input.
+ * @param[out] out A preallocated byte array for the output. See @ref
+ * mongocrypt_binary_data.
+ * @param[out] status An optional status to pass error messages. See @ref
+ * mongocrypt_status_set.
+ * @returns A boolean indicating success. If returning false, set @p status
+ * with a message indiciating the error using @ref mongocrypt_status_set.
+ */
+typedef bool (*mongocrypt_hmac_fn) (void *ctx,
+ mongocrypt_binary_t *key,
+ mongocrypt_binary_t *in,
+ mongocrypt_binary_t *out,
+ mongocrypt_status_t *status);
+
+
+/**
+ * A crypto hash (SHA-256) function.
+ *
+ * @param[in] ctx An optional context object that may have been set when hooks
+ * were enabled.
+ * @param[in] in The input.
+ * @param[out] out A preallocated byte array for the output. See @ref
+ * mongocrypt_binary_data.
+ * @param[out] status An optional status to pass error messages. See @ref
+ * mongocrypt_status_set.
+ * @returns A boolean indicating success. If returning false, set @p status
+ * with a message indiciating the error using @ref mongocrypt_status_set.
+ */
+typedef bool (*mongocrypt_hash_fn) (void *ctx,
+ mongocrypt_binary_t *in,
+ mongocrypt_binary_t *out,
+ mongocrypt_status_t *status);
+
+/**
+ * A crypto secure random function.
+ *
+ * @param[in] ctx An optional context object that may have been set when hooks
+ * were enabled.
+ * @param[out] out A preallocated byte array for the output. See @ref
+ * mongocrypt_binary_data.
+ * @param[in] count The number of random bytes requested.
+ * @param[out] status An optional status to pass error messages. See @ref
+ * mongocrypt_status_set.
+ * @returns A boolean indicating success. If returning false, set @p status
+ * with a message indiciating the error using @ref mongocrypt_status_set.
+ */
+typedef bool (*mongocrypt_random_fn) (void *ctx,
+ mongocrypt_binary_t *out,
+ uint32_t count,
+ mongocrypt_status_t *status);
+
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_setopt_crypto_hooks (mongocrypt_t *crypt,
+ mongocrypt_crypto_fn aes_256_cbc_encrypt,
+ mongocrypt_crypto_fn aes_256_cbc_decrypt,
+ mongocrypt_random_fn random,
+ mongocrypt_hmac_fn hmac_sha_512,
+ mongocrypt_hmac_fn hmac_sha_256,
+ mongocrypt_hash_fn sha_256,
+ void *ctx);
+
+/**
+ * Set a crypto hook for the RSASSA-PKCS1-v1_5 algorithm with a SHA-256 hash.
+ *
+ * See: https://tools.ietf.org/html/rfc3447#section-8.2
+ *
+ * Note: this function has the wrong name. It should be:
+ * mongocrypt_setopt_crypto_hook_sign_rsassa_pkcs1_v1_5
+ *
+ * @param[in] crypt The @ref mongocrypt_t object.
+ * @param[in] sign_rsaes_pkcs1_v1_5 The crypto callback function.
+ * @param[in] sign_ctx A context passed as an argument to the crypto callback
+ * every invocation.
+ * @pre @ref mongocrypt_init has not been called on @p crypt.
+ * @returns A boolean indicating success. If false, an error status is set.
+ * Retrieve it with @ref mongocrypt_status
+ *
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_setopt_crypto_hook_sign_rsaes_pkcs1_v1_5 (
+ mongocrypt_t *crypt,
+ mongocrypt_hmac_fn sign_rsaes_pkcs1_v1_5,
+ void *sign_ctx);
+
+#endif /* MONGOCRYPT_H */
diff --git a/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt.h.in b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt.h.in
new file mode 100644
index 00000000..6e2b8f04
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongocrypt/src/mongocrypt.h.in
@@ -0,0 +1,1255 @@
+/*
+ * Copyright 2019-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef MONGOCRYPT_H
+#define MONGOCRYPT_H
+
+/** @file mongocrypt.h The top-level handle to libmongocrypt. */
+
+/**
+ * @mainpage libmongocrypt
+ * See all public API documentation in: @ref mongocrypt.h
+ */
+
+#include "mongocrypt-export.h"
+#include "mongocrypt-compat.h"
+#include "mongocrypt-config.h"
+
+/**
+ * @def MONGOCRYPT_VERSION
+ * The version string describing libmongocrypt.
+ * Has the form x.y.z-<pre>+<date>+git<sha>.
+ */
+#define MONGOCRYPT_VERSION "@MONGOCRYPT_BUILD_VERSION@"
+
+/**
+ * Returns the version string for libmongocrypt.
+ *
+ * @param[out] len An optional length of the returned string. May be NULL.
+ * @returns a NULL terminated version string for libmongocrypt.
+ */
+MONGOCRYPT_EXPORT
+const char *
+mongocrypt_version (uint32_t *len);
+
+
+/**
+ * A non-owning view of a byte buffer.
+ *
+ * When constructing a mongocrypt_binary_t it is the responsibility of the
+ * caller to maintain the lifetime of the viewed data. However, all public
+ * functions that take a mongocrypt_binary_t as an argument will make a copy of
+ * the viewed data. For example, the following is valid:
+ *
+ * @code{.c}
+ * mongocrypt_binary_t bin = mongocrypt_binary_new_from_data(mydata, mylen);
+ * assert (mongocrypt_setopt_kms_provider_local (crypt), bin);
+ * // The viewed data of bin has been copied. Ok to free the view and the data.
+ * mongocrypt_binary_destroy (bin);
+ * my_free_fn (mydata);
+ * @endcode
+ *
+ * Functions with a mongocrypt_binary_t* out guarantee the lifetime of the
+ * viewed data to live as long as the parent object. For example, @ref
+ * mongocrypt_ctx_mongo_op guarantees that the viewed data of
+ * mongocrypt_binary_t is valid until the parent ctx is destroyed with @ref
+ * mongocrypt_ctx_destroy.
+ */
+typedef struct _mongocrypt_binary_t mongocrypt_binary_t;
+
+
+/**
+ * Create a new non-owning view of a buffer (data + length).
+ *
+ * Use this to create a mongocrypt_binary_t used for output parameters.
+ *
+ * @returns A new mongocrypt_binary_t.
+ */
+MONGOCRYPT_EXPORT
+mongocrypt_binary_t *
+mongocrypt_binary_new (void);
+
+
+/**
+ * Create a new non-owning view of a buffer (data + length).
+ *
+ * @param[in] data A pointer to an array of bytes. This data is not copied. @p
+ * data must outlive the binary object.
+ * @param[in] len The length of the @p data byte array.
+ *
+ * @returns A new @ref mongocrypt_binary_t.
+ */
+MONGOCRYPT_EXPORT
+mongocrypt_binary_t *
+mongocrypt_binary_new_from_data (uint8_t *data, uint32_t len);
+
+
+/**
+ * Get a pointer to the viewed data.
+ *
+ * @param[in] binary The @ref mongocrypt_binary_t.
+ *
+ * @returns A pointer to the viewed data.
+ */
+MONGOCRYPT_EXPORT
+uint8_t *
+mongocrypt_binary_data (const mongocrypt_binary_t *binary);
+
+
+/**
+ * Get the length of the viewed data.
+ *
+ * @param[in] binary The @ref mongocrypt_binary_t.
+ *
+ * @returns The length of the viewed data.
+ */
+MONGOCRYPT_EXPORT
+uint32_t
+mongocrypt_binary_len (const mongocrypt_binary_t *binary);
+
+
+/**
+ * Free the @ref mongocrypt_binary_t.
+ *
+ * This does not free the viewed data.
+ *
+ * @param[in] binary The mongocrypt_binary_t destroy.
+ */
+MONGOCRYPT_EXPORT
+void
+mongocrypt_binary_destroy (mongocrypt_binary_t *binary);
+
+
+/**
+ * Indicates success or contains error information.
+ *
+ * Functions like @ref mongocrypt_ctx_encrypt_init follow a pattern to expose a
+ * status. A boolean is returned. True indicates success, and false indicates
+ * failure. On failure a status on the handle is set, and is accessible with a
+ * corresponding (handle)_status function. E.g. @ref mongocrypt_ctx_status.
+ */
+typedef struct _mongocrypt_status_t mongocrypt_status_t;
+
+/**
+ * Indicates the type of error.
+ */
+typedef enum {
+ MONGOCRYPT_STATUS_OK = 0,
+ MONGOCRYPT_STATUS_ERROR_CLIENT = 1,
+ MONGOCRYPT_STATUS_ERROR_KMS = 2
+} mongocrypt_status_type_t;
+
+
+/**
+ * Create a new status object.
+ *
+ * Use a new status object to retrieve the status from a handle by passing
+ * this as an out-parameter to functions like @ref mongocrypt_ctx_status.
+ * When done, destroy it with @ref mongocrypt_status_destroy.
+ *
+ * @returns A new status object.
+ */
+MONGOCRYPT_EXPORT
+mongocrypt_status_t *
+mongocrypt_status_new (void);
+
+
+/**
+ * Set a status object with message, type, and code.
+ *
+ * Use this to set the @ref mongocrypt_status_t given in the crypto hooks.
+ *
+ * @param[in] type The status type.
+ * @param[in] code The status code.
+ * @param[in] message The message.
+ * @param[in] message_len Due to historical behavior, pass 1 + the string length
+ * of @p message (which differs from other functions accepting string
+ * arguments).
+ * Alternatively, if message is NULL terminated this may be -1 to tell
+ * mongocrypt
+ * to determine the string's length with strlen.
+ *
+ */
+MONGOCRYPT_EXPORT
+void
+mongocrypt_status_set (mongocrypt_status_t *status,
+ mongocrypt_status_type_t type,
+ uint32_t code,
+ const char *message,
+ int32_t message_len);
+
+
+/**
+ * Indicates success or the type of error.
+ *
+ * @param[in] status The status object.
+ *
+ * @returns A @ref mongocrypt_status_type_t.
+ */
+MONGOCRYPT_EXPORT
+mongocrypt_status_type_t
+mongocrypt_status_type (mongocrypt_status_t *status);
+
+
+/**
+ * Get an error code or 0.
+ *
+ * @param[in] status The status object.
+ *
+ * @returns An error code.
+ */
+MONGOCRYPT_EXPORT
+uint32_t
+mongocrypt_status_code (mongocrypt_status_t *status);
+
+
+/**
+ * Get the error message associated with a status or NULL.
+ *
+ * @param[in] status The status object.
+ * @param[out] len An optional length of the returned string (excluding the
+ * trailing NULL byte). May be NULL.
+ *
+ * @returns A NULL terminated error message or NULL.
+ */
+MONGOCRYPT_EXPORT
+const char *
+mongocrypt_status_message (mongocrypt_status_t *status, uint32_t *len);
+
+
+/**
+ * Returns true if the status indicates success.
+ *
+ * @param[in] status The status to check.
+ *
+ * @returns A boolean indicating success. If false, an error status is set.
+ * Retrieve it with @ref mongocrypt_ctx_status
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_status_ok (mongocrypt_status_t *status);
+
+
+/**
+ * Free the memory for a status object.
+ *
+ * @param[in] status The status to destroy.
+ */
+MONGOCRYPT_EXPORT
+void
+mongocrypt_status_destroy (mongocrypt_status_t *status);
+
+/**
+ * Indicates the type of log message.
+ */
+typedef enum {
+ MONGOCRYPT_LOG_LEVEL_FATAL = 0,
+ MONGOCRYPT_LOG_LEVEL_ERROR = 1,
+ MONGOCRYPT_LOG_LEVEL_WARNING = 2,
+ MONGOCRYPT_LOG_LEVEL_INFO = 3,
+ MONGOCRYPT_LOG_LEVEL_TRACE = 4
+} mongocrypt_log_level_t;
+
+
+/**
+ * A log callback function. Set a custom log callback with @ref
+ * mongocrypt_setopt_log_handler.
+ *
+ * @param[in] message A NULL terminated message.
+ * @param[in] message_len The length of message.
+ * @param[in] ctx A context provided by the caller of @ref
+ * mongocrypt_setopt_log_handler.
+ */
+typedef void (*mongocrypt_log_fn_t) (mongocrypt_log_level_t level,
+ const char *message,
+ uint32_t message_len,
+ void *ctx);
+
+
+/**
+ * The top-level handle to libmongocrypt.
+ *
+ * Create a mongocrypt_t handle to perform operations within libmongocrypt:
+ * encryption, decryption, registering log callbacks, etc.
+ *
+ * Functions on a mongocrypt_t are thread safe, though functions on derived
+ * handles (e.g. mongocrypt_ctx_t) are not and must be owned by a single
+ * thread. See each handle's documentation for thread-safety considerations.
+ *
+ * Multiple mongocrypt_t handles may be created.
+ */
+typedef struct _mongocrypt_t mongocrypt_t;
+
+
+/**
+ * Allocate a new @ref mongocrypt_t object.
+ *
+ * Set options using mongocrypt_setopt_* functions, then initialize with @ref
+ * mongocrypt_init. When done with the @ref mongocrypt_t, free with @ref
+ * mongocrypt_destroy.
+ *
+ * @returns A new @ref mongocrypt_t object.
+ */
+MONGOCRYPT_EXPORT
+mongocrypt_t *
+mongocrypt_new (void);
+
+
+/**
+ * Set a handler on the @ref mongocrypt_t object to get called on every log
+ * message.
+ *
+ * @param[in] crypt The @ref mongocrypt_t object.
+ * @param[in] log_fn The log callback.
+ * @param[in] log_ctx A context passed as an argument to the log callback every
+ * invocation.
+ * @pre @ref mongocrypt_init has not been called on @p crypt.
+ * @returns A boolean indicating success. If false, an error status is set.
+ * Retrieve it with @ref mongocrypt_ctx_status
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_setopt_log_handler (mongocrypt_t *crypt,
+ mongocrypt_log_fn_t log_fn,
+ void *log_ctx);
+
+
+/**
+ * Configure an AWS KMS provider on the @ref mongocrypt_t object.
+ *
+ * This has been superseded by the more flexible:
+ * @ref mongocrypt_setopt_kms_providers
+ *
+ * @param[in] crypt The @ref mongocrypt_t object.
+ * @param[in] aws_access_key_id The AWS access key ID used to generate KMS
+ * messages.
+ * @param[in] aws_access_key_id_len The string length (in bytes) of @p
+ * aws_access_key_id. Pass -1 to determine the string length with strlen (must
+ * be NULL terminated).
+ * @param[in] aws_secret_access_key The AWS secret access key used to generate
+ * KMS messages.
+ * @param[in] aws_secret_access_key_len The string length (in bytes) of @p
+ * aws_secret_access_key. Pass -1 to determine the string length with strlen
+ * (must be NULL terminated).
+ * @pre @ref mongocrypt_init has not been called on @p crypt.
+ * @returns A boolean indicating success. If false, an error status is set.
+ * Retrieve it with @ref mongocrypt_ctx_status
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_setopt_kms_provider_aws (mongocrypt_t *crypt,
+ const char *aws_access_key_id,
+ int32_t aws_access_key_id_len,
+ const char *aws_secret_access_key,
+ int32_t aws_secret_access_key_len);
+
+
+/**
+ * Configure a local KMS provider on the @ref mongocrypt_t object.
+ *
+ * This has been superseded by the more flexible:
+ * @ref mongocrypt_setopt_kms_providers
+ *
+ * @param[in] crypt The @ref mongocrypt_t object.
+ * @param[in] key A 96 byte master key used to encrypt and decrypt key vault
+ * keys. The viewed data is copied. It is valid to destroy @p key with @ref
+ * mongocrypt_binary_destroy immediately after.
+ * @pre @ref mongocrypt_init has not been called on @p crypt.
+ * @returns A boolean indicating success. If false, an error status is set.
+ * Retrieve it with @ref mongocrypt_ctx_status
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_setopt_kms_provider_local (mongocrypt_t *crypt,
+ mongocrypt_binary_t *key);
+
+/**
+ * Configure KMS providers with a BSON document.
+ *
+ * @param[in] crypt The @ref mongocrypt_t object.
+ * @param[in] kms_providers A BSON document mapping the KMS provider names
+ * to credentials.
+ * @pre @ref mongocrypt_init has not been called on @p crypt.
+ * @returns A boolean indicating success. If false, an error status is set.
+ * Retrieve it with @ref mongocrypt_ctx_status
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_setopt_kms_providers (mongocrypt_t *crypt,
+ mongocrypt_binary_t *kms_providers);
+
+/**
+ * Set a local schema map for encryption.
+ *
+ * @param[in] crypt The @ref mongocrypt_t object.
+ * @param[in] schema_map A BSON document representing the schema map supplied by
+ * the user. The keys are collection namespaces and values are JSON schemas. The
+ * viewed data copied. It is valid to destroy @p schema_map with @ref
+ * mongocrypt_binary_destroy immediately after.
+ * @pre @p crypt has not been initialized.
+ * @returns A boolean indicating success. If false, an error status is set.
+ * Retrieve it with @ref mongocrypt_status
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_setopt_schema_map (mongocrypt_t *crypt,
+ mongocrypt_binary_t *schema_map);
+
+
+/**
+ * @brief Append an additional search directory to the search path for loading
+ * the CSFLE dynamic library.
+ *
+ * @param[in] crypt The @ref mongocrypt_t object to update
+ * @param[in] path A null-terminated sequence of bytes for the search path. On
+ * some filesystems, this may be arbitrary bytes. On other filesystems, this may
+ * be required to be a valid UTF-8 code unit sequence. If the leading element of
+ * the path is the literal string "$ORIGIN", that substring will be replaced
+ * with the directory path containing the executable libmongocrypt module. If
+ * the path string is literal "$SYSTEM", then libmongocrypt will defer to the
+ * system's library resolution mechanism to find the CSFLE library.
+ *
+ * @note If no CSFLE dynamic library is found in any of the directories
+ * specified by the search paths loaded here, @ref mongocrypt_init() will still
+ * succeed and continue to operate without CSFLE.
+ *
+ * @note The search paths are searched in the order that they are appended. This
+ * allows one to provide a precedence in how the library will be discovered. For
+ * example, appending known directories before appending "$SYSTEM" will allow
+ * one to supersede the system's installed library, but still fall-back to it if
+ * the library wasn't found otherwise. If one does not ever append "$SYSTEM",
+ * then the system's library-search mechanism will never be consulted.
+ *
+ * @note If an absolute path to the library is specified using
+ * @ref mongocrypt_setopt_set_csfle_lib_path_override, then paths appended here
+ * will have no effect.
+ */
+MONGOCRYPT_EXPORT
+void
+mongocrypt_setopt_append_csfle_search_path (mongocrypt_t *crypt,
+ const char *path);
+
+
+/**
+ * @brief Set a single override path for loading the CSFLE dynamic library.
+ *
+ * @param[in] crypt The @ref mongocrypt_t object to update
+ * @param[in] path A null-terminated sequence of bytes for a path to the CSFLE
+ * dynamic library. On some filesystems, this may be arbitrary bytes. On other
+ * filesystems, this may be required to be a valid UTF-8 code unit sequence. If
+ * the leading element of the path is the literal string `$ORIGIN`, that
+ * substring will be replaced with the directory path containing the executable
+ * libmongocrypt module.
+ *
+ * @note This function will do no IO nor path validation. All validation will
+ * occur during the call to @ref mongocrypt_init.
+ *
+ * @note If a CSFLE library path override is specified here, then no paths given
+ * to @ref mongocrypt_setopt_append_csfle_search_path will be consulted when
+ * opening the CSFLE library.
+ *
+ * @note If a path is provided via this API and @ref mongocrypt_init fails to
+ * initialize a valid CSFLE library instance for the path specified, then
+ * the initialization of mongocrypt_t will fail with an error.
+ */
+MONGOCRYPT_EXPORT
+void
+mongocrypt_setopt_set_csfle_lib_path_override (mongocrypt_t *crypt,
+ const char *path);
+
+
+/**
+ * Initialize new @ref mongocrypt_t object.
+ *
+ * Set options before using @ref mongocrypt_setopt_kms_provider_local, @ref
+ * mongocrypt_setopt_kms_provider_aws, or @ref mongocrypt_setopt_log_handler.
+ *
+ * @param[in] crypt The @ref mongocrypt_t object.
+ *
+ * @returns A boolean indicating success. If false, an error status is set.
+ * Retrieve it with @ref mongocrypt_ctx_status Failure may occur if previously
+ * set
+ * options are invalid.
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_init (mongocrypt_t *crypt);
+
+
+/**
+ * Get the status associated with a @ref mongocrypt_t object.
+ *
+ * @param[in] crypt The @ref mongocrypt_t object.
+ * @param[out] status Receives the status.
+ *
+ * @returns A boolean indicating success. If false, an error status is set.
+ * Retrieve it with @ref mongocrypt_ctx_status
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_status (mongocrypt_t *crypt, mongocrypt_status_t *status);
+
+
+/**
+ * Destroy the @ref mongocrypt_t object.
+ *
+ * @param[in] crypt The @ref mongocrypt_t object to destroy.
+ */
+MONGOCRYPT_EXPORT
+void
+mongocrypt_destroy (mongocrypt_t *crypt);
+
+
+/**
+ * Manages the state machine for encryption or decryption.
+ */
+typedef struct _mongocrypt_ctx_t mongocrypt_ctx_t;
+
+
+/**
+ * Create a new uninitialized @ref mongocrypt_ctx_t.
+ *
+ * Initialize the context with functions like @ref mongocrypt_ctx_encrypt_init.
+ * When done, destroy it with @ref mongocrypt_ctx_destroy.
+ *
+ * @param[in] crypt The @ref mongocrypt_t object.
+ * @returns A new context.
+ */
+MONGOCRYPT_EXPORT
+mongocrypt_ctx_t *
+mongocrypt_ctx_new (mongocrypt_t *crypt);
+
+
+/**
+ * Get the status associated with a @ref mongocrypt_ctx_t object.
+ *
+ * @param[in] ctx The @ref mongocrypt_ctx_t object.
+ * @param[out] status Receives the status.
+ *
+ * @returns True if the output is an ok status, false if it is an error
+ * status.
+ *
+ * @see mongocrypt_status_ok
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_ctx_status (mongocrypt_ctx_t *ctx, mongocrypt_status_t *status);
+
+
+/**
+ * Set the key id to use for explicit encryption.
+ *
+ * It is an error to set both this and the key alt name.
+ *
+ * @param[in] ctx The @ref mongocrypt_ctx_t object.
+ * @param[in] key_id The binary corresponding to the _id (a UUID) of the data
+ * key to use from the key vault collection. Note, the UUID must be encoded with
+ * RFC-4122 byte order. The viewed data is copied. It is valid to destroy
+ * @p key_id with @ref mongocrypt_binary_destroy immediately after.
+ * @pre @p ctx has not been initialized.
+ * @returns A boolean indicating success. If false, an error status is set.
+ * Retrieve it with @ref mongocrypt_ctx_status
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_ctx_setopt_key_id (mongocrypt_ctx_t *ctx,
+ mongocrypt_binary_t *key_id);
+
+/**
+ * Set the keyAltName to use for explicit encryption or
+ * data key creation.
+ *
+ * Pass the binary encoding a BSON document like the following:
+ *
+ * { "keyAltName" : (BSON UTF8 value) }
+ *
+ * For explicit encryption, it is an error to set both the keyAltName
+ * and the key id.
+ *
+ * For creating data keys, call this function repeatedly to set
+ * multiple keyAltNames.
+ *
+ * @param[in] ctx The @ref mongocrypt_ctx_t object.
+ * @param[in] key_alt_name The name to use. The viewed data is copied. It is
+ * valid to destroy @p key_alt_name with @ref mongocrypt_binary_destroy
+ * immediately after.
+ * @pre @p ctx has not been initialized.
+ * @returns A boolean indicating success. If false, an error status is set.
+ * Retrieve it with @ref mongocrypt_ctx_status
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_ctx_setopt_key_alt_name (mongocrypt_ctx_t *ctx,
+ mongocrypt_binary_t *key_alt_name);
+
+/**
+ * Set the keyMaterial to use for encrypting data.
+ *
+ * Pass the binary encoding of a BSON document like the following:
+ *
+ * { "keyMaterial" : (BSON BINARY value) }
+ *
+ * @param[in] ctx The @ref mongocrypt_ctx_t object.
+ * @param[in] key_material The data encryption key to use. The viewed data is
+ * copied. It is valid to destroy @p key_material with @ref
+ * mongocrypt_binary_destroy immediately after.
+ * @pre @p ctx has not been initialized.
+ * @returns A boolean indicating success. If false, an error status is set.
+ * Retrieve it with @ref mongocrypt_ctx_status
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_ctx_setopt_key_material (mongocrypt_ctx_t *ctx,
+ mongocrypt_binary_t *key_material);
+
+/**
+ * Set the algorithm used for encryption to either
+ * deterministic or random encryption. This value
+ * should only be set when using explicit encryption.
+ *
+ * If -1 is passed in for "len", then "algorithm" is
+ * assumed to be a null-terminated string.
+ *
+ * Valid values for algorithm are:
+ * "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic"
+ * "AEAD_AES_256_CBC_HMAC_SHA_512-Random"
+ *
+ * @param[in] ctx The @ref mongocrypt_ctx_t object.
+ * @param[in] algorithm A string specifying the algorithm to
+ * use for encryption.
+ * @param[in] len The length of the algorithm string.
+ * @pre @p ctx has not been initialized.
+ * @returns A boolean indicating success. If false, an error status is set.
+ * Retrieve it with @ref mongocrypt_ctx_status
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_ctx_setopt_algorithm (mongocrypt_ctx_t *ctx,
+ const char *algorithm,
+ int len);
+
+
+/**
+ * Identify the AWS KMS master key to use for creating a data key.
+ *
+ * This has been superseded by the more flexible:
+ * @ref mongocrypt_ctx_setopt_key_encryption_key
+ *
+ * @param[in] ctx The @ref mongocrypt_ctx_t object.
+ * @param[in] region The AWS region.
+ * @param[in] region_len The string length of @p region. Pass -1 to determine
+ * the string length with strlen (must be NULL terminated).
+ * @param[in] cmk The Amazon Resource Name (ARN) of the customer master key
+ * (CMK).
+ * @param[in] cmk_len The string length of @p cmk_len. Pass -1 to determine the
+ * string length with strlen (must be NULL terminated).
+ * @pre @p ctx has not been initialized.
+ * @returns A boolean indicating success. If false, an error status is set.
+ * Retrieve it with @ref mongocrypt_ctx_status
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_ctx_setopt_masterkey_aws (mongocrypt_ctx_t *ctx,
+ const char *region,
+ int32_t region_len,
+ const char *cmk,
+ int32_t cmk_len);
+
+
+/**
+ * Identify a custom AWS endpoint when creating a data key.
+ * This is used internally to construct the correct HTTP request
+ * (with the Host header set to this endpoint). This endpoint
+ * is persisted in the new data key, and will be returned via
+ * @ref mongocrypt_kms_ctx_endpoint.
+ *
+ * This has been superseded by the more flexible:
+ * @ref mongocrypt_ctx_setopt_key_encryption_key
+ *
+ * @param[in] ctx The @ref mongocrypt_ctx_t object.
+ * @param[in] endpoint The endpoint.
+ * @param[in] endpoint_len The string length of @p endpoint. Pass -1 to
+ * determine the string length with strlen (must be NULL terminated).
+ * @returns A boolean indicating success. If false, an error status is set.
+ * Retrieve it with @ref mongocrypt_ctx_status
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_ctx_setopt_masterkey_aws_endpoint (mongocrypt_ctx_t *ctx,
+ const char *endpoint,
+ int32_t endpoint_len);
+
+/**
+ * Set the master key to "local" for creating a data key.
+ * This has been superseded by the more flexible:
+ * @ref mongocrypt_ctx_setopt_key_encryption_key
+ *
+ * @param[in] ctx The @ref mongocrypt_ctx_t object.
+ * @pre @p ctx has not been initialized.
+ * @returns A boolean indicating success. If false, an error status is set.
+ * Retrieve it with @ref mongocrypt_ctx_status
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_ctx_setopt_masterkey_local (mongocrypt_ctx_t *ctx);
+
+/**
+ * Set key encryption key document for creating a data key.
+ *
+ * @param[in] ctx The @ref mongocrypt_ctx_t object.
+ * @param[in] bin BSON representing the key encryption key document with
+ * an additional "provider" field. The following forms are accepted:
+ *
+ * AWS
+ * {
+ * provider: "aws",
+ * region: <string>,
+ * key: <string>,
+ * endpoint: <optional string>
+ * }
+ *
+ * Azure
+ * {
+ * provider: "azure",
+ * keyVaultEndpoint: <string>,
+ * keyName: <string>,
+ * keyVersion: <optional string>
+ * }
+ *
+ * GCP
+ * {
+ * provider: "gcp",
+ * projectId: <string>,
+ * location: <string>,
+ * keyRing: <string>,
+ * keyName: <string>,
+ * keyVersion: <string>,
+ * endpoint: <optional string>
+ * }
+ *
+ * Local
+ * {
+ * provider: "local"
+ * }
+ *
+ * KMIP
+ * {
+ * provider: "kmip",
+ * keyId: <optional string>
+ * endpoint: <string>
+ * }
+ *
+ * @pre @p ctx has not been initialized.
+ * @returns A boolean indicating success. If false, and error status is set.
+ * Retrieve it with @ref mongocrypt_ctx_status.
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_ctx_setopt_key_encryption_key (mongocrypt_ctx_t *ctx,
+ mongocrypt_binary_t *bin);
+
+
+/**
+ * Initialize a context to create a data key.
+ *
+ * Associated options:
+ * - @ref mongocrypt_ctx_setopt_masterkey_aws
+ * - @ref mongocrypt_ctx_setopt_masterkey_aws_endpoint
+ * - @ref mongocrypt_ctx_setopt_masterkey_local
+ *
+ * @param[in] ctx The @ref mongocrypt_ctx_t object.
+ * @returns A boolean indicating success. If false, an error status is set.
+ * Retrieve it with @ref mongocrypt_ctx_status
+ * @pre A master key option has been set, and an associated KMS provider
+ * has been set on the parent @ref mongocrypt_t.
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_ctx_datakey_init (mongocrypt_ctx_t *ctx);
+
+/**
+ * Initialize a context for encryption.
+ *
+ * @param[in] ctx The @ref mongocrypt_ctx_t object.
+ * @param[in] db The database name.
+ * @param[in] db_len The byte length of @p db. Pass -1 to determine the string
+ * length with strlen (must
+ * be NULL terminated).
+ * @param[in] cmd The BSON command to be encrypted. The viewed data is copied.
+ * It is valid to destroy @p cmd with @ref mongocrypt_binary_destroy immediately
+ * after.
+ * @returns A boolean indicating success. If false, an error status is set.
+ * Retrieve it with @ref mongocrypt_ctx_status
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_ctx_encrypt_init (mongocrypt_ctx_t *ctx,
+ const char *db,
+ int32_t db_len,
+ mongocrypt_binary_t *cmd);
+
+/**
+ * Explicit helper method to encrypt a single BSON object. Contexts
+ * created for explicit encryption will not go through mongocryptd.
+ *
+ * To specify a key_id, algorithm, or iv to use, please use the
+ * corresponding mongocrypt_setopt methods before calling this.
+ *
+ * This method expects the passed-in BSON to be of the form:
+ * { "v" : BSON value to encrypt }
+ *
+ * Associated options:
+ * - @ref mongocrypt_ctx_setopt_key_id
+ * - @ref mongocrypt_ctx_setopt_key_alt_name
+ * - @ref mongocrypt_ctx_setopt_algorithm
+ *
+ * @param[in] ctx A @ref mongocrypt_ctx_t.
+ * @param[in] msg A @ref mongocrypt_binary_t the plaintext BSON value. The
+ * viewed data is copied. It is valid to destroy @p msg with @ref
+ * mongocrypt_binary_destroy immediately after.
+ * @returns A boolean indicating success. If false, an error status is set.
+ * Retrieve it with @ref mongocrypt_ctx_status
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_ctx_explicit_encrypt_init (mongocrypt_ctx_t *ctx,
+ mongocrypt_binary_t *msg);
+
+
+/**
+ * Initialize a context for decryption.
+ *
+ * This method expects the passed-in BSON to be of the form:
+ * { "v" : BSON value to encrypt }
+ *
+ * @param[in] ctx The @ref mongocrypt_ctx_t object.
+ * @param[in] doc The document to be decrypted. The viewed data is copied. It is
+ * valid to destroy @p doc with @ref mongocrypt_binary_destroy immediately
+ * after.
+ * @returns A boolean indicating success. If false, an error status is set.
+ * Retrieve it with @ref mongocrypt_ctx_status
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_ctx_decrypt_init (mongocrypt_ctx_t *ctx, mongocrypt_binary_t *doc);
+
+
+/**
+ * Explicit helper method to decrypt a single BSON object.
+ *
+ *
+ * @param[in] ctx A @ref mongocrypt_ctx_t.
+ * @param[in] msg A @ref mongocrypt_binary_t the encrypted BSON. The viewed data
+ * is copied. It is valid to destroy @p msg with @ref mongocrypt_binary_destroy
+ * immediately after.
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_ctx_explicit_decrypt_init (mongocrypt_ctx_t *ctx,
+ mongocrypt_binary_t *msg);
+
+
+/**
+ * Indicates the state of the @ref mongocrypt_ctx_t. Each state requires
+ * different handling. See [the integration
+ * guide](https://github.com/mongodb/libmongocrypt/blob/master/integrating.md#state-machine)
+ * for information on what to do for each state.
+ */
+typedef enum {
+ MONGOCRYPT_CTX_ERROR = 0,
+ MONGOCRYPT_CTX_NEED_MONGO_COLLINFO = 1, /* run on main MongoClient */
+ MONGOCRYPT_CTX_NEED_MONGO_MARKINGS = 2, /* run on mongocryptd. */
+ MONGOCRYPT_CTX_NEED_MONGO_KEYS = 3, /* run on key vault */
+ MONGOCRYPT_CTX_NEED_KMS = 4,
+ MONGOCRYPT_CTX_READY = 5, /* ready for encryption/decryption */
+ MONGOCRYPT_CTX_DONE = 6
+} mongocrypt_ctx_state_t;
+
+
+/**
+ * Get the current state of a context.
+ *
+ * @param[in] ctx The @ref mongocrypt_ctx_t object.
+ * @returns A @ref mongocrypt_ctx_state_t.
+ */
+MONGOCRYPT_EXPORT
+mongocrypt_ctx_state_t
+mongocrypt_ctx_state (mongocrypt_ctx_t *ctx);
+
+
+/**
+ * Get BSON necessary to run the mongo operation when mongocrypt_ctx_t
+ * is in MONGOCRYPT_CTX_NEED_MONGO_* states.
+ *
+ * @p op_bson is a BSON document to be used for the operation.
+ * - For MONGOCRYPT_CTX_NEED_MONGO_COLLINFO it is a listCollections filter.
+ * - For MONGOCRYPT_CTX_NEED_MONGO_KEYS it is a find filter.
+ * - For MONGOCRYPT_CTX_NEED_MONGO_MARKINGS it is a command to send to
+ * mongocryptd.
+ *
+ * The lifetime of @p op_bson is tied to the lifetime of @p ctx. It is valid
+ * until @ref mongocrypt_ctx_destroy is called.
+ *
+ * @param[in] ctx The @ref mongocrypt_ctx_t object.
+ * @param[out] op_bson A BSON document for the MongoDB operation. The data
+ * viewed by @p op_bson is guaranteed to be valid until @p ctx is destroyed with
+ * @ref mongocrypt_ctx_destroy.
+ * @returns A boolean indicating success. If false, an error status is set.
+ * Retrieve it with @ref mongocrypt_ctx_status
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_ctx_mongo_op (mongocrypt_ctx_t *ctx, mongocrypt_binary_t *op_bson);
+
+
+/**
+ * Feed a BSON reply or result when mongocrypt_ctx_t is in
+ * MONGOCRYPT_CTX_NEED_MONGO_* states. This may be called multiple times
+ * depending on the operation.
+ *
+ * reply is a BSON document result being fed back for this operation.
+ * - For MONGOCRYPT_CTX_NEED_MONGO_COLLINFO it is a doc from a listCollections
+ * cursor. (Note, if listCollections returned no result, do not call this
+ * function.)
+ * - For MONGOCRYPT_CTX_NEED_MONGO_KEYS it is a doc from a find cursor.
+ * (Note, if find returned no results, do not call this function. reply must
+ * not
+ * be NULL.)
+ * - For MONGOCRYPT_CTX_NEED_MONGO_MARKINGS it is a reply from mongocryptd.
+ *
+ * @param[in] ctx The @ref mongocrypt_ctx_t object.
+ * @param[in] reply A BSON document for the MongoDB operation. The viewed data
+ * is copied. It is valid to destroy @p reply with @ref
+ * mongocrypt_binary_destroy immediately after.
+ * @returns A boolean indicating success. If false, an error status is set.
+ * Retrieve it with @ref mongocrypt_ctx_status
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_ctx_mongo_feed (mongocrypt_ctx_t *ctx, mongocrypt_binary_t *reply);
+
+
+/**
+ * Call when done feeding the reply (or replies) back to the context.
+ *
+ * @param[in] ctx The @ref mongocrypt_ctx_t object.
+ * @returns A boolean indicating success. If false, an error status is set.
+ * Retrieve it with @ref mongocrypt_ctx_status
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_ctx_mongo_done (mongocrypt_ctx_t *ctx);
+
+
+/**
+ * Manages a single KMS HTTP request/response.
+ */
+typedef struct _mongocrypt_kms_ctx_t mongocrypt_kms_ctx_t;
+
+
+/**
+ * Get the next KMS handle.
+ *
+ * Multiple KMS handles may be retrieved at once. Drivers may do this to fan
+ * out multiple concurrent KMS HTTP requests. Feeding multiple KMS requests
+ * is thread-safe.
+ *
+ * If KMS handles are being handled synchronously, the driver can reuse the same
+ * TLS socket to send HTTP requests and receive responses.
+ *
+ * @param[in] ctx A @ref mongocrypt_ctx_t.
+ * @returns a new @ref mongocrypt_kms_ctx_t or NULL.
+ */
+MONGOCRYPT_EXPORT
+mongocrypt_kms_ctx_t *
+mongocrypt_ctx_next_kms_ctx (mongocrypt_ctx_t *ctx);
+
+
+/**
+ * Get the HTTP request message for a KMS handle.
+ *
+ * The lifetime of @p msg is tied to the lifetime of @p kms. It is valid
+ * until @ref mongocrypt_ctx_kms_done is called.
+ *
+ * @param[in] kms A @ref mongocrypt_kms_ctx_t.
+ * @param[out] msg The HTTP request to send to KMS. The data viewed by @p msg is
+ * guaranteed to be valid until the call of @ref mongocrypt_ctx_kms_done of the
+ * parent @ref mongocrypt_ctx_t.
+ * @returns A boolean indicating success. If false, an error status is set.
+ * Retrieve it with @ref mongocrypt_kms_ctx_status
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_kms_ctx_message (mongocrypt_kms_ctx_t *kms,
+ mongocrypt_binary_t *msg);
+
+
+/**
+ * Get the hostname from which to connect over TLS.
+ *
+ * The storage for @p endpoint is not owned by the caller, but
+ * is valid until calling @ref mongocrypt_ctx_kms_done.
+ *
+ * @param[in] kms A @ref mongocrypt_kms_ctx_t.
+ * @param[out] endpoint The output endpoint as a NULL terminated string.
+ * The endpoint consists of a hostname and port separated by a colon.
+ * E.g. "example.com:123". A port is always present.
+ *
+ * @returns A boolean indicating success. If false, an error status is set.
+ * Retrieve it with @ref mongocrypt_kms_ctx_status
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_kms_ctx_endpoint (mongocrypt_kms_ctx_t *kms, const char **endpoint);
+
+
+/**
+ * Indicates how many bytes to feed into @ref mongocrypt_kms_ctx_feed.
+ *
+ * @param[in] kms The @ref mongocrypt_kms_ctx_t.
+ * @returns The number of requested bytes.
+ */
+MONGOCRYPT_EXPORT
+uint32_t
+mongocrypt_kms_ctx_bytes_needed (mongocrypt_kms_ctx_t *kms);
+
+
+/**
+ * Feed bytes from the HTTP response.
+ *
+ * Feeding more bytes than what has been returned in @ref
+ * mongocrypt_kms_ctx_bytes_needed is an error.
+ *
+ * @param[in] kms The @ref mongocrypt_kms_ctx_t.
+ * @param[in] bytes The bytes to feed. The viewed data is copied. It is valid to
+ * destroy @p bytes with @ref mongocrypt_binary_destroy immediately after.
+ * @returns A boolean indicating success. If false, an error status is set.
+ * Retrieve it with @ref mongocrypt_kms_ctx_status
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_kms_ctx_feed (mongocrypt_kms_ctx_t *kms, mongocrypt_binary_t *bytes);
+
+
+/**
+ * Get the status associated with a @ref mongocrypt_kms_ctx_t object.
+ *
+ * @param[in] kms The @ref mongocrypt_kms_ctx_t object.
+ * @param[out] status Receives the status.
+ *
+ * @returns A boolean indicating success. If false, an error status is set.
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_kms_ctx_status (mongocrypt_kms_ctx_t *kms,
+ mongocrypt_status_t *status);
+
+/**
+ * Get the KMS provider identifier associated with this KMS request.
+ *
+ * This is used to conditionally configure TLS connections based on the KMS
+ * request. It is useful for KMIP, which authenticates with a client
+ * certificate.
+ *
+ * @param[in] kms The @ref mongocrypt_kms_ctx_t object.
+ * @param[out] len Receives the length of the returned string. It may be NULL.
+ * If it is not NULL, it is set to the length of the returned string without
+ * the NULL terminator.
+ *
+ * @returns One of the NULL terminated static strings: "aws", "azure", "gcp", or
+ * "kmip".
+ */
+MONGOCRYPT_EXPORT
+const char *
+mongocrypt_kms_ctx_get_kms_provider (mongocrypt_kms_ctx_t *kms, uint32_t *len);
+
+
+/**
+ * Call when done handling all KMS contexts.
+ *
+ * @param[in] ctx The @ref mongocrypt_ctx_t object.
+ *
+ * @returns A boolean indicating success. If false, an error status is set.
+ * Retrieve it with @ref mongocrypt_ctx_status
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_ctx_kms_done (mongocrypt_ctx_t *ctx);
+
+
+/**
+ * Perform the final encryption or decryption.
+ *
+ * @param[in] ctx A @ref mongocrypt_ctx_t.
+ * @param[out] out The final BSON. The data viewed by @p out is guaranteed
+ * to be valid until @p ctx is destroyed with @ref mongocrypt_ctx_destroy.
+ * The meaning of this BSON depends on the type of @p ctx.
+ *
+ * If @p ctx was initialized with @ref mongocrypt_ctx_encrypt_init, then
+ * this BSON is the (possibly) encrypted command to send to the server.
+ *
+ * If @p ctx was initialized with @ref mongocrypt_ctx_decrypt_init, then
+ * this BSON is the decrypted result to return to the user.
+ *
+ * If @p ctx was initialized with @ref mongocrypt_ctx_explicit_encrypt_init,
+ * then this BSON has the form { "v": (BSON binary) } where the BSON binary
+ * is the resulting encrypted value.
+ *
+ * If @p ctx was initialized with @ref mongocrypt_ctx_explicit_decrypt_init,
+ * then this BSON has the form { "v": (BSON value) } where the BSON value
+ * is the resulting decrypted value.
+ *
+ * If @p ctx was initialized with @ref mongocrypt_ctx_datakey_init, then
+ * this BSON is the document containing the new data key to be inserted into
+ * the key vault collection.
+ *
+ * @returns a bool indicating success. If false, an error status is set.
+ * Retrieve it with @ref mongocrypt_ctx_status
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_ctx_finalize (mongocrypt_ctx_t *ctx, mongocrypt_binary_t *out);
+
+
+/**
+ * Destroy and free all memory associated with a @ref mongocrypt_ctx_t.
+ *
+ * @param[in] ctx A @ref mongocrypt_ctx_t.
+ */
+MONGOCRYPT_EXPORT
+void
+mongocrypt_ctx_destroy (mongocrypt_ctx_t *ctx);
+
+/**
+ * An crypto AES-256-CBC encrypt or decrypt function.
+ *
+ * Note, @p in is already padded. Encrypt with padding disabled.
+ * @param[in] ctx An optional context object that may have been set when hooks
+ * were enabled.
+ * @param[in] key An encryption key (32 bytes for AES_256).
+ * @param[in] iv An initialization vector (16 bytes for AES_256);
+ * @param[in] in The input.
+ * @param[out] out A preallocated byte array for the output. See @ref
+ * mongocrypt_binary_data.
+ * @param[out] bytes_written Set this to the number of bytes written to @p out.
+ * @param[out] status An optional status to pass error messages. See @ref
+ * mongocrypt_status_set.
+ * @returns A boolean indicating success. If returning false, set @p status
+ * with a message indiciating the error using @ref mongocrypt_status_set.
+ */
+typedef bool (*mongocrypt_crypto_fn) (void *ctx,
+ mongocrypt_binary_t *key,
+ mongocrypt_binary_t *iv,
+ mongocrypt_binary_t *in,
+ mongocrypt_binary_t *out,
+ uint32_t *bytes_written,
+ mongocrypt_status_t *status);
+
+/**
+ * A crypto signature or HMAC function.
+ *
+ * Currently used in callbacks for HMAC SHA-512, HMAC SHA-256, and RSA SHA-256
+ * signature.
+ *
+ * @param[in] ctx An optional context object that may have been set when hooks
+ * were enabled.
+ * @param[in] key An encryption key (32 bytes for HMAC_SHA512).
+ * @param[in] in The input.
+ * @param[out] out A preallocated byte array for the output. See @ref
+ * mongocrypt_binary_data.
+ * @param[out] status An optional status to pass error messages. See @ref
+ * mongocrypt_status_set.
+ * @returns A boolean indicating success. If returning false, set @p status
+ * with a message indiciating the error using @ref mongocrypt_status_set.
+ */
+typedef bool (*mongocrypt_hmac_fn) (void *ctx,
+ mongocrypt_binary_t *key,
+ mongocrypt_binary_t *in,
+ mongocrypt_binary_t *out,
+ mongocrypt_status_t *status);
+
+
+/**
+ * A crypto hash (SHA-256) function.
+ *
+ * @param[in] ctx An optional context object that may have been set when hooks
+ * were enabled.
+ * @param[in] in The input.
+ * @param[out] out A preallocated byte array for the output. See @ref
+ * mongocrypt_binary_data.
+ * @param[out] status An optional status to pass error messages. See @ref
+ * mongocrypt_status_set.
+ * @returns A boolean indicating success. If returning false, set @p status
+ * with a message indiciating the error using @ref mongocrypt_status_set.
+ */
+typedef bool (*mongocrypt_hash_fn) (void *ctx,
+ mongocrypt_binary_t *in,
+ mongocrypt_binary_t *out,
+ mongocrypt_status_t *status);
+
+/**
+ * A crypto secure random function.
+ *
+ * @param[in] ctx An optional context object that may have been set when hooks
+ * were enabled.
+ * @param[out] out A preallocated byte array for the output. See @ref
+ * mongocrypt_binary_data.
+ * @param[in] count The number of random bytes requested.
+ * @param[out] status An optional status to pass error messages. See @ref
+ * mongocrypt_status_set.
+ * @returns A boolean indicating success. If returning false, set @p status
+ * with a message indiciating the error using @ref mongocrypt_status_set.
+ */
+typedef bool (*mongocrypt_random_fn) (void *ctx,
+ mongocrypt_binary_t *out,
+ uint32_t count,
+ mongocrypt_status_t *status);
+
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_setopt_crypto_hooks (mongocrypt_t *crypt,
+ mongocrypt_crypto_fn aes_256_cbc_encrypt,
+ mongocrypt_crypto_fn aes_256_cbc_decrypt,
+ mongocrypt_random_fn random,
+ mongocrypt_hmac_fn hmac_sha_512,
+ mongocrypt_hmac_fn hmac_sha_256,
+ mongocrypt_hash_fn sha_256,
+ void *ctx);
+
+/**
+ * Set a crypto hook for the RSASSA-PKCS1-v1_5 algorithm with a SHA-256 hash.
+ *
+ * See: https://tools.ietf.org/html/rfc3447#section-8.2
+ *
+ * Note: this function has the wrong name. It should be:
+ * mongocrypt_setopt_crypto_hook_sign_rsassa_pkcs1_v1_5
+ *
+ * @param[in] crypt The @ref mongocrypt_t object.
+ * @param[in] sign_rsaes_pkcs1_v1_5 The crypto callback function.
+ * @param[in] sign_ctx A context passed as an argument to the crypto callback
+ * every invocation.
+ * @pre @ref mongocrypt_init has not been called on @p crypt.
+ * @returns A boolean indicating success. If false, an error status is set.
+ * Retrieve it with @ref mongocrypt_status
+ *
+ */
+MONGOCRYPT_EXPORT
+bool
+mongocrypt_setopt_crypto_hook_sign_rsaes_pkcs1_v1_5 (
+ mongocrypt_t *crypt,
+ mongocrypt_hmac_fn sign_rsaes_pkcs1_v1_5,
+ void *sign_ctx);
+
+#endif /* MONGOCRYPT_H */
diff --git a/mongodb-1.13.0/src/libmongocrypt/src/os_posix/os_dll.c b/mongodb-1.13.0/src/libmongocrypt/src/os_posix/os_dll.c
new file mode 100644
index 00000000..1c896a96
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongocrypt/src/os_posix/os_dll.c
@@ -0,0 +1,43 @@
+#include "../mongocrypt-dll-private.h"
+
+#ifndef _WIN32
+
+#include <string.h>
+#include <stdio.h>
+
+#include <dlfcn.h>
+
+mcr_dll
+mcr_dll_open (const char *filepath)
+{
+ void *handle = dlopen (filepath, RTLD_LAZY | RTLD_LOCAL);
+ if (handle == NULL) {
+ // Failed to open. Return NULL and copy the error message
+ return (mcr_dll){
+ ._native_handle = NULL,
+ .error_string = mstr_copy_cstr (dlerror ()),
+ };
+ } else {
+ // Okay
+ return (mcr_dll){
+ ._native_handle = handle,
+ .error_string = MSTR_NULL,
+ };
+ }
+}
+
+void
+mcr_dll_close_handle (mcr_dll dll)
+{
+ if (dll._native_handle) {
+ dlclose (dll._native_handle);
+ }
+}
+
+void *
+mcr_dll_sym (mcr_dll dll, const char *sym)
+{
+ return dlsym (dll._native_handle, sym);
+}
+
+#endif
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/os_posix/os_mutex.c b/mongodb-1.13.0/src/libmongocrypt/src/os_posix/os_mutex.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/src/os_posix/os_mutex.c
rename to mongodb-1.13.0/src/libmongocrypt/src/os_posix/os_mutex.c
diff --git a/mongodb-1.13.0/src/libmongocrypt/src/os_win/os_dll.c b/mongodb-1.13.0/src/libmongocrypt/src/os_win/os_dll.c
new file mode 100644
index 00000000..26920d64
--- /dev/null
+++ b/mongodb-1.13.0/src/libmongocrypt/src/os_win/os_dll.c
@@ -0,0 +1,60 @@
+#include "../mongocrypt-dll-private.h"
+
+#ifdef _WIN32
+
+#include <mlib/str.h>
+#include <mlib/path.h>
+#include <mlib/error.h>
+
+#include <string.h>
+#include <stdio.h>
+
+#include <windows.h>
+
+mcr_dll
+mcr_dll_open (const char *filepath_)
+{
+ // Convert all slashes to the native Windows separator
+ mstr filepath =
+ mpath_to_format (MPATH_WIN32, mstrv_view_cstr (filepath_), MPATH_WIN32);
+ // Check if the path is just a filename.
+ bool is_just_filename =
+ mstr_eq (mpath_filename (filepath.view, MPATH_WIN32), filepath.view);
+ if (!is_just_filename) {
+ // If the path is only a filename, we'll allow LoadLibrary() to do a
+ // proper full DLL search. If the path is NOT just a filename, resolve the
+ // given path to a single unambiguous absolute path to suppress
+ // LoadLibrary()'s DLL search behavior.
+ mstr_assign (&filepath, mpath_absolute (filepath.view, MPATH_WIN32));
+ }
+ mstr_widen_result wide = mstr_win32_widen (filepath.view);
+ mstr_free (filepath);
+ if (wide.error) {
+ return (mcr_dll){._native_handle = NULL,
+ .error_string = merror_system_error_string (wide.error)};
+ }
+ HMODULE lib = LoadLibraryW (wide.wstring);
+ if (lib == NULL) {
+ return (mcr_dll){._native_handle = NULL,
+ .error_string =
+ merror_system_error_string (GetLastError ())};
+ }
+ free (wide.wstring);
+ return (mcr_dll){.error_string = NULL, ._native_handle = lib};
+}
+
+void
+mcr_dll_close_handle (mcr_dll dll)
+{
+ if (dll._native_handle) {
+ FreeLibrary (dll._native_handle);
+ }
+}
+
+void *
+mcr_dll_sym (mcr_dll dll, const char *sym)
+{
+ return GetProcAddress (dll._native_handle, sym);
+}
+
+#endif
diff --git a/mongodb-1.12.0/src/libmongocrypt/src/os_win/os_mutex.c b/mongodb-1.13.0/src/libmongocrypt/src/os_win/os_mutex.c
similarity index 100%
rename from mongodb-1.12.0/src/libmongocrypt/src/os_win/os_mutex.c
rename to mongodb-1.13.0/src/libmongocrypt/src/os_win/os_mutex.c
diff --git a/mongodb-1.13.0/src/phongo_apm.c b/mongodb-1.13.0/src/phongo_apm.c
new file mode 100644
index 00000000..36f49546
--- /dev/null
+++ b/mongodb-1.13.0/src/phongo_apm.c
@@ -0,0 +1,636 @@
+/*
+ * Copyright 2021-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bson/bson.h"
+#include "mongoc/mongoc.h"
+
+#include <php.h>
+#include <Zend/zend_exceptions.h>
+#include <Zend/zend_interfaces.h>
+#include <Zend/zend_operators.h>
+
+#include "php_phongo.h"
+#include "phongo_apm.h"
+#include "phongo_error.h"
+
+ZEND_EXTERN_MODULE_GLOBALS(mongodb)
+
+/* Ensures that instances of @subscriber_ce in @from (those registered with a
+ * Manager or globally) are added to the set @to. This is used to build the list
+ * of subscribers notify for an event. */
+static void phongo_apm_add_subscribers_to_notify(zend_class_entry* subscriber_ce, HashTable* from, HashTable* to)
+{
+ zval* subscriber;
+
+ ZEND_HASH_FOREACH_VAL_IND(from, subscriber)
+ {
+ if (Z_TYPE_P(subscriber) != IS_OBJECT || !instanceof_function(Z_OBJCE_P(subscriber), subscriber_ce)) {
+ continue;
+ }
+
+ if (zend_hash_index_exists(to, Z_OBJ_HANDLE_P(subscriber))) {
+ continue;
+ }
+
+ zend_hash_index_update(to, Z_OBJ_HANDLE_P(subscriber), subscriber);
+ Z_ADDREF_P(subscriber);
+ }
+ ZEND_HASH_FOREACH_END();
+}
+
+/* Returns a newly allocated HashTable, which will contain all subscribers of a
+ * certain type that should be notified for an event on the specified client. */
+static HashTable* phongo_apm_get_subscribers_to_notify(zend_class_entry* subscriber_ce, mongoc_client_t* client)
+{
+ HashTable* subscribers = NULL;
+
+ ALLOC_HASHTABLE(subscribers);
+ zend_hash_init(subscribers, 0, NULL, ZVAL_PTR_DTOR, 0);
+
+ if (MONGODB_G(subscribers)) {
+ phongo_apm_add_subscribers_to_notify(subscriber_ce, MONGODB_G(subscribers), subscribers);
+ }
+
+ if (MONGODB_G(managers)) {
+ php_phongo_manager_t* manager;
+
+ ZEND_HASH_FOREACH_PTR(MONGODB_G(managers), manager)
+ {
+ if (manager->client == client && manager->subscribers) {
+ phongo_apm_add_subscribers_to_notify(subscriber_ce, manager->subscribers, subscribers);
+ }
+ }
+ ZEND_HASH_FOREACH_END();
+ }
+
+ return subscribers;
+}
+
+/* Search for a Manager associated with the given client in the request-scoped
+ * registry. If any Manager is found, copy it to @out, increment its ref-count,
+ * and return true; otherwise, set @out to undefined and return false. */
+static bool phongo_apm_copy_manager_for_client(mongoc_client_t* client, zval* out)
+{
+ php_phongo_manager_t* manager;
+
+ ZVAL_UNDEF(out);
+
+ if (!MONGODB_G(managers) || zend_hash_num_elements(MONGODB_G(managers)) == 0) {
+ return false;
+ }
+
+ ZEND_HASH_FOREACH_PTR(MONGODB_G(managers), manager)
+ {
+ if (manager->client == client) {
+ ZVAL_OBJ(out, &manager->std);
+ Z_ADDREF_P(out);
+
+ return true;
+ }
+ }
+ ZEND_HASH_FOREACH_END();
+
+ return false;
+}
+
+/* Dispatch an event to all subscribers in a HashTable. The caller is
+ * responsible for ensuring that subscribers implement the correct interface. */
+static void phongo_apm_dispatch_event(HashTable* subscribers, const char* function_name, zval* event)
+{
+ zval* subscriber;
+
+ ZEND_HASH_FOREACH_VAL_IND(subscribers, subscriber)
+ {
+ if (EG(exception)) {
+ break;
+ }
+
+ /* We can't use the zend_call_method_with_1_params macro here, as it
+ * assumes the function name is a string literal. */
+ zend_call_method(PHONGO_COMPAT_OBJ_P(subscriber), NULL, NULL, function_name, strlen(function_name), NULL, 1, event, NULL);
+ }
+ ZEND_HASH_FOREACH_END();
+}
+
+static void phongo_apm_command_started(const mongoc_apm_command_started_t* event)
+{
+ mongoc_client_t* client;
+ HashTable* subscribers;
+ php_phongo_commandstartedevent_t* p_event;
+ zval z_event;
+
+ client = mongoc_apm_command_started_get_context(event);
+ subscribers = phongo_apm_get_subscribers_to_notify(php_phongo_commandsubscriber_ce, client);
+
+ /* Return early if there are no APM subscribers to notify */
+ if (zend_hash_num_elements(subscribers) == 0) {
+ goto cleanup;
+ }
+
+ object_init_ex(&z_event, php_phongo_commandstartedevent_ce);
+ p_event = Z_COMMANDSTARTEDEVENT_OBJ_P(&z_event);
+
+ p_event->command_name = estrdup(mongoc_apm_command_started_get_command_name(event));
+ p_event->server_id = mongoc_apm_command_started_get_server_id(event);
+ p_event->operation_id = mongoc_apm_command_started_get_operation_id(event);
+ p_event->request_id = mongoc_apm_command_started_get_request_id(event);
+ p_event->command = bson_copy(mongoc_apm_command_started_get_command(event));
+ p_event->database_name = estrdup(mongoc_apm_command_started_get_database_name(event));
+ p_event->has_service_id = mongoc_apm_command_started_get_service_id(event) != NULL;
+
+ if (p_event->has_service_id) {
+ bson_oid_copy(mongoc_apm_command_started_get_service_id(event), &p_event->service_id);
+ }
+
+ if (!phongo_apm_copy_manager_for_client(client, &p_event->manager)) {
+ phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "Found no Manager for client in APM event context");
+ zval_ptr_dtor(&z_event);
+
+ goto cleanup;
+ }
+
+ phongo_apm_dispatch_event(subscribers, "commandStarted", &z_event);
+ zval_ptr_dtor(&z_event);
+
+cleanup:
+ zend_hash_destroy(subscribers);
+ FREE_HASHTABLE(subscribers);
+}
+
+static void phongo_apm_command_succeeded(const mongoc_apm_command_succeeded_t* event)
+{
+ mongoc_client_t* client;
+ HashTable* subscribers;
+ php_phongo_commandsucceededevent_t* p_event;
+ zval z_event;
+
+ client = mongoc_apm_command_succeeded_get_context(event);
+ subscribers = phongo_apm_get_subscribers_to_notify(php_phongo_commandsubscriber_ce, client);
+
+ /* Return early if there are no APM subscribers to notify */
+ if (zend_hash_num_elements(subscribers) == 0) {
+ goto cleanup;
+ }
+
+ object_init_ex(&z_event, php_phongo_commandsucceededevent_ce);
+ p_event = Z_COMMANDSUCCEEDEDEVENT_OBJ_P(&z_event);
+
+ p_event->command_name = estrdup(mongoc_apm_command_succeeded_get_command_name(event));
+ p_event->server_id = mongoc_apm_command_succeeded_get_server_id(event);
+ p_event->operation_id = mongoc_apm_command_succeeded_get_operation_id(event);
+ p_event->request_id = mongoc_apm_command_succeeded_get_request_id(event);
+ p_event->duration_micros = mongoc_apm_command_succeeded_get_duration(event);
+ p_event->reply = bson_copy(mongoc_apm_command_succeeded_get_reply(event));
+ p_event->has_service_id = mongoc_apm_command_succeeded_get_service_id(event) != NULL;
+
+ if (p_event->has_service_id) {
+ bson_oid_copy(mongoc_apm_command_succeeded_get_service_id(event), &p_event->service_id);
+ }
+
+ if (!phongo_apm_copy_manager_for_client(client, &p_event->manager)) {
+ phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "Found no Manager for client in APM event context");
+ zval_ptr_dtor(&z_event);
+
+ goto cleanup;
+ }
+
+ phongo_apm_dispatch_event(subscribers, "commandSucceeded", &z_event);
+ zval_ptr_dtor(&z_event);
+
+cleanup:
+ zend_hash_destroy(subscribers);
+ FREE_HASHTABLE(subscribers);
+}
+
+static void phongo_apm_command_failed(const mongoc_apm_command_failed_t* event)
+{
+ mongoc_client_t* client;
+ HashTable* subscribers;
+ php_phongo_commandfailedevent_t* p_event;
+ zval z_event;
+ bson_error_t tmp_error = { 0 };
+
+ client = mongoc_apm_command_failed_get_context(event);
+ subscribers = phongo_apm_get_subscribers_to_notify(php_phongo_commandsubscriber_ce, client);
+
+ /* Return early if there are no APM subscribers to notify */
+ if (zend_hash_num_elements(subscribers) == 0) {
+ goto cleanup;
+ }
+
+ object_init_ex(&z_event, php_phongo_commandfailedevent_ce);
+ p_event = Z_COMMANDFAILEDEVENT_OBJ_P(&z_event);
+
+ p_event->command_name = estrdup(mongoc_apm_command_failed_get_command_name(event));
+ p_event->server_id = mongoc_apm_command_failed_get_server_id(event);
+ p_event->operation_id = mongoc_apm_command_failed_get_operation_id(event);
+ p_event->request_id = mongoc_apm_command_failed_get_request_id(event);
+ p_event->duration_micros = mongoc_apm_command_failed_get_duration(event);
+ p_event->reply = bson_copy(mongoc_apm_command_failed_get_reply(event));
+ p_event->has_service_id = mongoc_apm_command_failed_get_service_id(event) != NULL;
+
+ if (p_event->has_service_id) {
+ bson_oid_copy(mongoc_apm_command_failed_get_service_id(event), &p_event->service_id);
+ }
+
+ if (!phongo_apm_copy_manager_for_client(client, &p_event->manager)) {
+ phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "Found no Manager for client in APM event context");
+ zval_ptr_dtor(&z_event);
+
+ goto cleanup;
+ }
+
+ /* We need to process and convert the error right here, otherwise
+ * debug_info will turn into a recursive loop, and with the wrong trace
+ * locations */
+ mongoc_apm_command_failed_get_error(event, &tmp_error);
+
+ object_init_ex(&p_event->z_error, phongo_exception_from_mongoc_domain(tmp_error.domain, tmp_error.code));
+ zend_update_property_string(zend_ce_exception, PHONGO_COMPAT_OBJ_P(&p_event->z_error), ZEND_STRL("message"), tmp_error.message);
+ zend_update_property_long(zend_ce_exception, PHONGO_COMPAT_OBJ_P(&p_event->z_error), ZEND_STRL("code"), tmp_error.code);
+
+ phongo_apm_dispatch_event(subscribers, "commandFailed", &z_event);
+ zval_ptr_dtor(&z_event);
+
+cleanup:
+ zend_hash_destroy(subscribers);
+ FREE_HASHTABLE(subscribers);
+}
+
+static void phongo_apm_server_changed(const mongoc_apm_server_changed_t* event)
+{
+ mongoc_client_t* client;
+ HashTable* subscribers;
+ php_phongo_serverchangedevent_t* p_event;
+ zval z_event;
+
+ client = mongoc_apm_server_changed_get_context(event);
+ subscribers = phongo_apm_get_subscribers_to_notify(php_phongo_sdamsubscriber_ce, client);
+
+ /* Return early if there are no APM subscribers to notify */
+ if (zend_hash_num_elements(subscribers) == 0) {
+ goto cleanup;
+ }
+
+ object_init_ex(&z_event, php_phongo_serverchangedevent_ce);
+ p_event = Z_SERVERCHANGEDEVENT_OBJ_P(&z_event);
+
+ memcpy(&p_event->host, mongoc_apm_server_changed_get_host(event), sizeof(mongoc_host_list_t));
+ mongoc_apm_server_changed_get_topology_id(event, &p_event->topology_id);
+ p_event->new_server_description = mongoc_server_description_new_copy(mongoc_apm_server_changed_get_new_description(event));
+ p_event->old_server_description = mongoc_server_description_new_copy(mongoc_apm_server_changed_get_previous_description(event));
+
+ phongo_apm_dispatch_event(subscribers, "serverChanged", &z_event);
+ zval_ptr_dtor(&z_event);
+
+cleanup:
+ zend_hash_destroy(subscribers);
+ FREE_HASHTABLE(subscribers);
+}
+
+static void phongo_apm_server_closed(const mongoc_apm_server_closed_t* event)
+{
+ mongoc_client_t* client;
+ HashTable* subscribers;
+ php_phongo_serverclosedevent_t* p_event;
+ zval z_event;
+
+ client = mongoc_apm_server_closed_get_context(event);
+ subscribers = phongo_apm_get_subscribers_to_notify(php_phongo_sdamsubscriber_ce, client);
+
+ /* Return early if there are no APM subscribers to notify */
+ if (zend_hash_num_elements(subscribers) == 0) {
+ goto cleanup;
+ }
+
+ object_init_ex(&z_event, php_phongo_serverclosedevent_ce);
+ p_event = Z_SERVERCLOSEDEVENT_OBJ_P(&z_event);
+
+ memcpy(&p_event->host, mongoc_apm_server_closed_get_host(event), sizeof(mongoc_host_list_t));
+ mongoc_apm_server_closed_get_topology_id(event, &p_event->topology_id);
+
+ phongo_apm_dispatch_event(subscribers, "serverClosed", &z_event);
+ zval_ptr_dtor(&z_event);
+
+cleanup:
+ zend_hash_destroy(subscribers);
+ FREE_HASHTABLE(subscribers);
+}
+
+static void phongo_apm_server_heartbeat_failed(const mongoc_apm_server_heartbeat_failed_t* event)
+{
+ mongoc_client_t* client;
+ HashTable* subscribers;
+ php_phongo_serverheartbeatfailedevent_t* p_event;
+ zval z_event;
+ bson_error_t tmp_error = { 0 };
+
+ client = mongoc_apm_server_heartbeat_failed_get_context(event);
+ subscribers = phongo_apm_get_subscribers_to_notify(php_phongo_sdamsubscriber_ce, client);
+
+ /* Return early if there are no APM subscribers to notify */
+ if (zend_hash_num_elements(subscribers) == 0) {
+ goto cleanup;
+ }
+
+ object_init_ex(&z_event, php_phongo_serverheartbeatfailedevent_ce);
+ p_event = Z_SERVERHEARTBEATFAILEDEVENT_OBJ_P(&z_event);
+
+ memcpy(&p_event->host, mongoc_apm_server_heartbeat_failed_get_host(event), sizeof(mongoc_host_list_t));
+ p_event->awaited = mongoc_apm_server_heartbeat_failed_get_awaited(event);
+ p_event->duration_micros = mongoc_apm_server_heartbeat_failed_get_duration(event);
+
+ /* We need to process and convert the error right here, otherwise
+ * debug_info will turn into a recursive loop, and with the wrong trace
+ * locations */
+ mongoc_apm_server_heartbeat_failed_get_error(event, &tmp_error);
+
+ object_init_ex(&p_event->z_error, phongo_exception_from_mongoc_domain(tmp_error.domain, tmp_error.code));
+ zend_update_property_string(zend_ce_exception, PHONGO_COMPAT_OBJ_P(&p_event->z_error), ZEND_STRL("message"), tmp_error.message);
+ zend_update_property_long(zend_ce_exception, PHONGO_COMPAT_OBJ_P(&p_event->z_error), ZEND_STRL("code"), tmp_error.code);
+
+ phongo_apm_dispatch_event(subscribers, "serverHeartbeatFailed", &z_event);
+ zval_ptr_dtor(&z_event);
+
+cleanup:
+ zend_hash_destroy(subscribers);
+ FREE_HASHTABLE(subscribers);
+}
+
+static void phongo_apm_server_heartbeat_succeeded(const mongoc_apm_server_heartbeat_succeeded_t* event)
+{
+ mongoc_client_t* client;
+ HashTable* subscribers;
+ php_phongo_serverheartbeatsucceededevent_t* p_event;
+ zval z_event;
+
+ client = mongoc_apm_server_heartbeat_succeeded_get_context(event);
+ subscribers = phongo_apm_get_subscribers_to_notify(php_phongo_sdamsubscriber_ce, client);
+
+ /* Return early if there are no APM subscribers to notify */
+ if (zend_hash_num_elements(subscribers) == 0) {
+ goto cleanup;
+ }
+
+ object_init_ex(&z_event, php_phongo_serverheartbeatsucceededevent_ce);
+ p_event = Z_SERVERHEARTBEATSUCCEEDEDEVENT_OBJ_P(&z_event);
+
+ memcpy(&p_event->host, mongoc_apm_server_heartbeat_succeeded_get_host(event), sizeof(mongoc_host_list_t));
+ p_event->awaited = mongoc_apm_server_heartbeat_succeeded_get_awaited(event);
+ p_event->duration_micros = mongoc_apm_server_heartbeat_succeeded_get_duration(event);
+ p_event->reply = bson_copy(mongoc_apm_server_heartbeat_succeeded_get_reply(event));
+
+ phongo_apm_dispatch_event(subscribers, "serverHeartbeatSucceeded", &z_event);
+ zval_ptr_dtor(&z_event);
+
+cleanup:
+ zend_hash_destroy(subscribers);
+ FREE_HASHTABLE(subscribers);
+}
+
+static void phongo_apm_server_heartbeat_started(const mongoc_apm_server_heartbeat_started_t* event)
+{
+ mongoc_client_t* client;
+ HashTable* subscribers;
+ php_phongo_serverheartbeatstartedevent_t* p_event;
+ zval z_event;
+
+ client = mongoc_apm_server_heartbeat_started_get_context(event);
+ subscribers = phongo_apm_get_subscribers_to_notify(php_phongo_sdamsubscriber_ce, client);
+
+ /* Return early if there are no APM subscribers to notify */
+ if (zend_hash_num_elements(subscribers) == 0) {
+ goto cleanup;
+ }
+
+ object_init_ex(&z_event, php_phongo_serverheartbeatstartedevent_ce);
+ p_event = Z_SERVERHEARTBEATSTARTEDEVENT_OBJ_P(&z_event);
+
+ memcpy(&p_event->host, mongoc_apm_server_heartbeat_started_get_host(event), sizeof(mongoc_host_list_t));
+ p_event->awaited = mongoc_apm_server_heartbeat_started_get_awaited(event);
+
+ phongo_apm_dispatch_event(subscribers, "serverHeartbeatStarted", &z_event);
+ zval_ptr_dtor(&z_event);
+
+cleanup:
+ zend_hash_destroy(subscribers);
+ FREE_HASHTABLE(subscribers);
+}
+
+static void phongo_apm_server_opening(const mongoc_apm_server_opening_t* event)
+{
+ mongoc_client_t* client;
+ HashTable* subscribers;
+ php_phongo_serveropeningevent_t* p_event;
+ zval z_event;
+
+ client = mongoc_apm_server_opening_get_context(event);
+ subscribers = phongo_apm_get_subscribers_to_notify(php_phongo_sdamsubscriber_ce, client);
+
+ /* Return early if there are no APM subscribers to notify */
+ if (zend_hash_num_elements(subscribers) == 0) {
+ goto cleanup;
+ }
+
+ object_init_ex(&z_event, php_phongo_serveropeningevent_ce);
+ p_event = Z_SERVEROPENINGEVENT_OBJ_P(&z_event);
+
+ memcpy(&p_event->host, mongoc_apm_server_opening_get_host(event), sizeof(mongoc_host_list_t));
+ mongoc_apm_server_opening_get_topology_id(event, &p_event->topology_id);
+
+ phongo_apm_dispatch_event(subscribers, "serverOpening", &z_event);
+ zval_ptr_dtor(&z_event);
+
+cleanup:
+ zend_hash_destroy(subscribers);
+ FREE_HASHTABLE(subscribers);
+}
+
+static void phongo_apm_topology_changed(const mongoc_apm_topology_changed_t* event)
+{
+ mongoc_client_t* client;
+ HashTable* subscribers;
+ php_phongo_topologychangedevent_t* p_event;
+ zval z_event;
+
+ client = mongoc_apm_topology_changed_get_context(event);
+ subscribers = phongo_apm_get_subscribers_to_notify(php_phongo_sdamsubscriber_ce, client);
+
+ /* Return early if there are no APM subscribers to notify */
+ if (zend_hash_num_elements(subscribers) == 0) {
+ goto cleanup;
+ }
+
+ object_init_ex(&z_event, php_phongo_topologychangedevent_ce);
+ p_event = Z_TOPOLOGYCHANGEDEVENT_OBJ_P(&z_event);
+
+ mongoc_apm_topology_changed_get_topology_id(event, &p_event->topology_id);
+ p_event->new_topology_description = mongoc_topology_description_new_copy(mongoc_apm_topology_changed_get_new_description(event));
+ p_event->old_topology_description = mongoc_topology_description_new_copy(mongoc_apm_topology_changed_get_previous_description(event));
+
+ phongo_apm_dispatch_event(subscribers, "topologyChanged", &z_event);
+ zval_ptr_dtor(&z_event);
+
+cleanup:
+ zend_hash_destroy(subscribers);
+ FREE_HASHTABLE(subscribers);
+}
+
+static void phongo_apm_topology_closed(const mongoc_apm_topology_closed_t* event)
+{
+ mongoc_client_t* client;
+ HashTable* subscribers;
+ php_phongo_topologyclosedevent_t* p_event;
+ zval z_event;
+
+ client = mongoc_apm_topology_closed_get_context(event);
+ subscribers = phongo_apm_get_subscribers_to_notify(php_phongo_sdamsubscriber_ce, client);
+
+ /* Return early if there are no APM subscribers to notify */
+ if (zend_hash_num_elements(subscribers) == 0) {
+ goto cleanup;
+ }
+
+ object_init_ex(&z_event, php_phongo_topologyclosedevent_ce);
+ p_event = Z_TOPOLOGYCLOSEDEVENT_OBJ_P(&z_event);
+
+ mongoc_apm_topology_closed_get_topology_id(event, &p_event->topology_id);
+
+ phongo_apm_dispatch_event(subscribers, "topologyClosed", &z_event);
+ zval_ptr_dtor(&z_event);
+
+cleanup:
+ zend_hash_destroy(subscribers);
+ FREE_HASHTABLE(subscribers);
+}
+
+static void phongo_apm_topology_opening(const mongoc_apm_topology_opening_t* event)
+{
+ mongoc_client_t* client;
+ HashTable* subscribers;
+ php_phongo_topologyopeningevent_t* p_event;
+ zval z_event;
+
+ client = mongoc_apm_topology_opening_get_context(event);
+ subscribers = phongo_apm_get_subscribers_to_notify(php_phongo_sdamsubscriber_ce, client);
+
+ /* Return early if there are no APM subscribers to notify */
+ if (zend_hash_num_elements(subscribers) == 0) {
+ goto cleanup;
+ }
+
+ object_init_ex(&z_event, php_phongo_topologyopeningevent_ce);
+ p_event = Z_TOPOLOGYOPENINGEVENT_OBJ_P(&z_event);
+
+ mongoc_apm_topology_opening_get_topology_id(event, &p_event->topology_id);
+
+ phongo_apm_dispatch_event(subscribers, "topologyOpening", &z_event);
+ zval_ptr_dtor(&z_event);
+
+cleanup:
+ zend_hash_destroy(subscribers);
+ FREE_HASHTABLE(subscribers);
+}
+
+/* Assigns APM callbacks to a client, which will notify any global or per-client
+ * subscribers. This should be called for all clients created by the driver.
+ * Returns true on success; otherwise, throws an exception and returns false. */
+bool phongo_apm_set_callbacks(mongoc_client_t* client)
+{
+ bool retval;
+
+ mongoc_apm_callbacks_t* callbacks = mongoc_apm_callbacks_new();
+
+ mongoc_apm_set_command_started_cb(callbacks, phongo_apm_command_started);
+ mongoc_apm_set_command_succeeded_cb(callbacks, phongo_apm_command_succeeded);
+ mongoc_apm_set_command_failed_cb(callbacks, phongo_apm_command_failed);
+ mongoc_apm_set_server_changed_cb(callbacks, phongo_apm_server_changed);
+ mongoc_apm_set_server_closed_cb(callbacks, phongo_apm_server_closed);
+ mongoc_apm_set_server_heartbeat_failed_cb(callbacks, phongo_apm_server_heartbeat_failed);
+ mongoc_apm_set_server_heartbeat_succeeded_cb(callbacks, phongo_apm_server_heartbeat_succeeded);
+ mongoc_apm_set_server_heartbeat_started_cb(callbacks, phongo_apm_server_heartbeat_started);
+ mongoc_apm_set_server_opening_cb(callbacks, phongo_apm_server_opening);
+ mongoc_apm_set_topology_changed_cb(callbacks, phongo_apm_topology_changed);
+ mongoc_apm_set_topology_closed_cb(callbacks, phongo_apm_topology_closed);
+ mongoc_apm_set_topology_opening_cb(callbacks, phongo_apm_topology_opening);
+
+ retval = mongoc_client_set_apm_callbacks(client, callbacks, client);
+
+ if (!retval) {
+ phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "Failed to set APM callbacks");
+ }
+
+ mongoc_apm_callbacks_destroy(callbacks);
+
+ return retval;
+}
+
+/* Checks args for adding/removing a subscriber. Returns true on success;
+ * otherwise, throws an exception and returns false. */
+static bool phongo_apm_check_args_for_add_and_remove(HashTable* subscribers, zval* subscriber)
+{
+ if (!subscribers) {
+ phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "Subscriber HashTable is not initialized");
+ return false;
+ }
+
+ if (!subscriber || Z_TYPE_P(subscriber) != IS_OBJECT || !instanceof_function(Z_OBJCE_P(subscriber), php_phongo_subscriber_ce)) {
+ phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "Subscriber is not an instance of %s", ZSTR_VAL(php_phongo_subscriber_ce->name));
+ return false;
+ }
+
+ return true;
+}
+
+/* Adds a subscriber to the HashTable (global or Manager). Returns true on
+ * success (including NOP if already registered); otherwise, throws an exception
+ * and returns false. */
+bool phongo_apm_add_subscriber(HashTable* subscribers, zval* subscriber)
+{
+ if (!phongo_apm_check_args_for_add_and_remove(subscribers, subscriber)) {
+ /* Exception should already have been thrown */
+ return false;
+ }
+
+ /* NOP if the subscriber was already registered */
+ if (zend_hash_index_exists(subscribers, Z_OBJ_HANDLE_P(subscriber))) {
+ return true;
+ }
+
+ zend_hash_index_update(subscribers, Z_OBJ_HANDLE_P(subscriber), subscriber);
+ Z_ADDREF_P(subscriber);
+
+ return true;
+}
+
+/* Removes a subscriber from the HashTable (global or Manager). Returns true on
+ * success (including NOP if never registered); otherwise, throws an exception
+ * and returns false. */
+bool phongo_apm_remove_subscriber(HashTable* subscribers, zval* subscriber)
+{
+ if (!phongo_apm_check_args_for_add_and_remove(subscribers, subscriber)) {
+ /* Exception should already have been thrown */
+ return false;
+ }
+
+ /* Note: HashTables should specify ZVAL_PTR_DTOR as their element destructor
+ * so there is no need to decrement the subscriber's reference count here.
+ * We also don't care about whether zend_hash_index_del returns SUCCESS or
+ * FAILURE, as removing an unregistered subscriber is a NOP. */
+ zend_hash_index_del(subscribers, Z_OBJ_HANDLE_P(subscriber));
+
+ return true;
+}
diff --git a/mongodb-1.13.0/src/phongo_apm.h b/mongodb-1.13.0/src/phongo_apm.h
new file mode 100644
index 00000000..5b5f92d6
--- /dev/null
+++ b/mongodb-1.13.0/src/phongo_apm.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2021-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PHONGO_APM_H
+#define PHONGO_APM_H
+
+#include "mongoc/mongoc.h"
+
+#include <php.h>
+
+bool phongo_apm_set_callbacks(mongoc_client_t* client);
+bool phongo_apm_add_subscriber(HashTable* subscribers, zval* subscriber);
+bool phongo_apm_remove_subscriber(HashTable* subscribers, zval* subscriber);
+
+#endif /* PHONGO_APM_H */
diff --git a/mongodb-1.13.0/src/phongo_bson.c b/mongodb-1.13.0/src/phongo_bson.c
new file mode 100644
index 00000000..aa704a47
--- /dev/null
+++ b/mongodb-1.13.0/src/phongo_bson.c
@@ -0,0 +1,1321 @@
+/*
+ * Copyright 2014-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bson/bson.h"
+
+#include <php.h>
+#include <Zend/zend_interfaces.h>
+
+#include "php_array_api.h"
+
+#include "php_phongo.h"
+#include "phongo_bson.h"
+#include "phongo_error.h"
+
+#undef MONGOC_LOG_DOMAIN
+#define MONGOC_LOG_DOMAIN "PHONGO-BSON"
+
+#define PHONGO_IS_CLASS_INSTANTIATABLE(ce) \
+ (!(ce->ce_flags & (ZEND_ACC_INTERFACE | ZEND_ACC_IMPLICIT_ABSTRACT_CLASS | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)))
+
+#define PHONGO_BSON_STATE_ZCHILD(state) (&((php_phongo_bson_state*) (state))->zchild)
+
+#define PHONGO_FIELD_PATH_EXPANSION 8
+
+/* Forward declarations */
+static bool php_phongo_bson_visit_document(const bson_iter_t* iter ARG_UNUSED, const char* key, const bson_t* v_document, void* data);
+static bool php_phongo_bson_visit_array(const bson_iter_t* iter ARG_UNUSED, const char* key, const bson_t* v_document, void* data);
+
+/* Path builder */
+char* php_phongo_field_path_as_string(php_phongo_field_path* field_path)
+{
+ size_t length = 1; /* NULL character */
+ size_t i;
+ char* path;
+ char* ptr;
+
+ if (!field_path) {
+ return estrdup("");
+ }
+ if (!field_path->elements) {
+ return estrdup("");
+ }
+
+ for (i = 0; i <= field_path->size; i++) {
+ if (!field_path->elements[i]) {
+ continue;
+ }
+ length += (1 + strlen(field_path->elements[i]));
+ }
+
+ path = emalloc(length);
+ ptr = path;
+
+ for (i = 0; i <= field_path->size; i++) {
+ if (!field_path->elements[i]) {
+ continue;
+ }
+ strcpy(ptr, field_path->elements[i]);
+ ptr += strlen(field_path->elements[i]);
+ ptr[0] = '.';
+ ptr++;
+ }
+ ptr[-1] = '\0';
+
+ return path;
+}
+
+php_phongo_field_path* php_phongo_field_path_alloc(bool owns_elements)
+{
+ php_phongo_field_path* tmp = ecalloc(1, sizeof(php_phongo_field_path));
+ tmp->ref_count = 1;
+ tmp->owns_elements = owns_elements;
+
+ return tmp;
+}
+
+void php_phongo_field_path_free(php_phongo_field_path* field_path)
+{
+ if (field_path->owns_elements) {
+ size_t i;
+
+ for (i = 0; i < field_path->size; i++) {
+ efree(field_path->elements[i]);
+ }
+ }
+ if (field_path->elements) {
+ efree(field_path->elements);
+ }
+ if (field_path->element_types) {
+ efree(field_path->element_types);
+ }
+ efree(field_path);
+}
+
+static void php_phongo_field_path_ensure_allocation(php_phongo_field_path* field_path, size_t level)
+{
+ if (level >= field_path->allocated_size) {
+ size_t i;
+
+ field_path->allocated_size = field_path->size + PHONGO_FIELD_PATH_EXPANSION;
+ field_path->elements = erealloc(field_path->elements, sizeof(char*) * field_path->allocated_size);
+ field_path->element_types = erealloc(field_path->element_types, sizeof(php_phongo_bson_field_path_item_types) * field_path->allocated_size);
+
+ for (i = level; i < field_path->allocated_size; i++) {
+ field_path->elements[i] = NULL;
+ field_path->element_types[i] = PHONGO_FIELD_PATH_ITEM_NONE;
+ }
+ }
+}
+
+void php_phongo_field_path_write_item_at_current_level(php_phongo_field_path* field_path, const char* element)
+{
+ php_phongo_field_path_ensure_allocation(field_path, field_path->size);
+
+ if (field_path->owns_elements) {
+ field_path->elements[field_path->size] = estrdup(element);
+ } else {
+ field_path->elements[field_path->size] = (char*) element;
+ }
+}
+
+void php_phongo_field_path_write_type_at_current_level(php_phongo_field_path* field_path, php_phongo_bson_field_path_item_types element_type)
+{
+ php_phongo_field_path_ensure_allocation(field_path, field_path->size);
+
+ field_path->element_types[field_path->size] = element_type;
+}
+
+bool php_phongo_field_path_push(php_phongo_field_path* field_path, const char* element, php_phongo_bson_field_path_item_types element_type)
+{
+ php_phongo_field_path_write_item_at_current_level(field_path, element);
+ php_phongo_field_path_write_type_at_current_level(field_path, element_type);
+
+ field_path->size++;
+
+ return true;
+}
+
+bool php_phongo_field_path_pop(php_phongo_field_path* field_path)
+{
+ php_phongo_field_path_ensure_allocation(field_path, field_path->size);
+
+ field_path->elements[field_path->size] = NULL;
+ field_path->element_types[field_path->size] = PHONGO_FIELD_PATH_ITEM_NONE;
+
+ field_path->size--;
+
+ field_path->elements[field_path->size] = NULL;
+ field_path->element_types[field_path->size] = PHONGO_FIELD_PATH_ITEM_NONE;
+
+ return true;
+}
+
+inline static bool php_phongo_bson_state_is_initialized(php_phongo_bson_state* state)
+{
+ return state->field_path != NULL;
+}
+
+static void php_phongo_bson_state_ctor(php_phongo_bson_state* state)
+{
+ state->field_path = php_phongo_field_path_alloc(false);
+}
+
+static void php_phongo_bson_state_copy_ctor(php_phongo_bson_state* dst, php_phongo_bson_state* src)
+{
+ dst->map = src->map;
+ if (src->field_path) {
+ src->field_path->ref_count++;
+ }
+ dst->field_path = src->field_path;
+}
+
+static void php_phongo_bson_state_dtor(php_phongo_bson_state* state)
+{
+ if (state->field_path) {
+ state->field_path->ref_count--;
+
+ if (state->field_path->ref_count < 1) {
+ php_phongo_field_path_free(state->field_path);
+ }
+ state->field_path = NULL;
+ }
+} /* }}} */
+
+static void php_phongo_bson_visit_corrupt(const bson_iter_t* iter ARG_UNUSED, void* data ARG_UNUSED) /* {{{ */
+{
+ mongoc_log(MONGOC_LOG_LEVEL_WARNING, MONGOC_LOG_DOMAIN, "Corrupt BSON data detected!");
+} /* }}} */
+
+static void php_phongo_bson_visit_unsupported_type(const bson_iter_t* iter ARG_UNUSED, const char* key, uint32_t v_type_code, void* data ARG_UNUSED) /* {{{ */
+{
+ php_phongo_bson_state* state = (php_phongo_bson_state*) data;
+ char* path_string;
+
+ php_phongo_field_path_write_item_at_current_level(state->field_path, key);
+ path_string = php_phongo_field_path_as_string(state->field_path);
+
+ phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "Detected unknown BSON type 0x%02hhx for field path \"%s\". Are you using the latest driver?", (unsigned char) v_type_code, path_string);
+
+ efree(path_string);
+} /* }}} */
+
+static bool php_phongo_bson_visit_double(const bson_iter_t* iter ARG_UNUSED, const char* key, double v_double, void* data) /* {{{ */
+{
+ zval* retval = PHONGO_BSON_STATE_ZCHILD(data);
+ php_phongo_bson_state* state = (php_phongo_bson_state*) data;
+
+ if (state->is_visiting_array) {
+ add_next_index_double(retval, v_double);
+ } else {
+ add_assoc_double(retval, key, v_double);
+ }
+
+ php_phongo_field_path_write_item_at_current_level(state->field_path, key);
+
+ return false;
+} /* }}} */
+
+static bool php_phongo_bson_visit_utf8(const bson_iter_t* iter ARG_UNUSED, const char* key, size_t v_utf8_len, const char* v_utf8, void* data) /* {{{ */
+{
+ zval* retval = PHONGO_BSON_STATE_ZCHILD(data);
+ php_phongo_bson_state* state = (php_phongo_bson_state*) data;
+
+ if (state->is_visiting_array) {
+ ADD_NEXT_INDEX_STRINGL(retval, v_utf8, v_utf8_len);
+ } else {
+ ADD_ASSOC_STRING_EX(retval, key, strlen(key), v_utf8, v_utf8_len);
+ }
+
+ php_phongo_field_path_write_item_at_current_level(state->field_path, key);
+
+ return false;
+} /* }}} */
+
+static void php_phongo_bson_new_binary_from_binary_and_type(zval* object, const char* data, size_t data_len, bson_subtype_t type) /* {{{ */
+{
+ php_phongo_binary_t* intern;
+
+ object_init_ex(object, php_phongo_binary_ce);
+
+ intern = Z_BINARY_OBJ_P(object);
+ intern->data = estrndup(data, data_len);
+ intern->data_len = data_len;
+ intern->type = (uint8_t) type;
+} /* }}} */
+
+static bool php_phongo_bson_visit_binary(const bson_iter_t* iter ARG_UNUSED, const char* key, bson_subtype_t v_subtype, size_t v_binary_len, const uint8_t* v_binary, void* data) /* {{{ */
+{
+ zval* retval = PHONGO_BSON_STATE_ZCHILD(data);
+ php_phongo_bson_state* state = (php_phongo_bson_state*) data;
+
+ if (v_subtype == 0x80 && strcmp(key, PHONGO_ODM_FIELD_NAME) == 0) {
+ zend_string* zs_classname = zend_string_init((const char*) v_binary, v_binary_len, 0);
+ zend_class_entry* found_ce = zend_fetch_class(zs_classname, ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_SILENT);
+ zend_string_release(zs_classname);
+
+ if (found_ce && PHONGO_IS_CLASS_INSTANTIATABLE(found_ce) && instanceof_function(found_ce, php_phongo_persistable_ce)) {
+ ((php_phongo_bson_state*) data)->odm = found_ce;
+ }
+ }
+
+ {
+ zval zchild;
+
+ php_phongo_bson_new_binary_from_binary_and_type(&zchild, (const char*) v_binary, v_binary_len, v_subtype);
+
+ if (state->is_visiting_array) {
+ add_next_index_zval(retval, &zchild);
+ } else {
+ ADD_ASSOC_ZVAL(retval, key, &zchild);
+ }
+ }
+
+ php_phongo_field_path_write_item_at_current_level(state->field_path, key);
+
+ return false;
+} /* }}} */
+
+static bool php_phongo_bson_visit_undefined(const bson_iter_t* iter, const char* key, void* data) /* {{{ */
+{
+ zval* retval = PHONGO_BSON_STATE_ZCHILD(data);
+ php_phongo_bson_state* state = (php_phongo_bson_state*) data;
+ zval zchild;
+
+ object_init_ex(&zchild, php_phongo_undefined_ce);
+
+ if (state->is_visiting_array) {
+ add_next_index_zval(retval, &zchild);
+ } else {
+ ADD_ASSOC_ZVAL(retval, key, &zchild);
+ }
+
+ php_phongo_field_path_write_item_at_current_level(state->field_path, key);
+
+ return false;
+} /* }}} */
+
+static void php_phongo_objectid_new_from_oid(zval* object, const bson_oid_t* oid) /* {{{ */
+{
+ php_phongo_objectid_t* intern;
+
+ object_init_ex(object, php_phongo_objectid_ce);
+
+ intern = Z_OBJECTID_OBJ_P(object);
+ bson_oid_to_string(oid, intern->oid);
+ intern->initialized = true;
+} /* }}} */
+
+static bool php_phongo_bson_visit_oid(const bson_iter_t* iter ARG_UNUSED, const char* key, const bson_oid_t* v_oid, void* data) /* {{{ */
+{
+ zval* retval = PHONGO_BSON_STATE_ZCHILD(data);
+ php_phongo_bson_state* state = (php_phongo_bson_state*) data;
+ zval zchild;
+
+ php_phongo_objectid_new_from_oid(&zchild, v_oid);
+
+ if (state->is_visiting_array) {
+ add_next_index_zval(retval, &zchild);
+ } else {
+ ADD_ASSOC_ZVAL(retval, key, &zchild);
+ }
+
+ php_phongo_field_path_write_item_at_current_level(state->field_path, key);
+
+ return false;
+} /* }}} */
+
+static bool php_phongo_bson_visit_bool(const bson_iter_t* iter ARG_UNUSED, const char* key, bool v_bool, void* data) /* {{{ */
+{
+ zval* retval = PHONGO_BSON_STATE_ZCHILD(data);
+ php_phongo_bson_state* state = (php_phongo_bson_state*) data;
+
+ if (state->is_visiting_array) {
+ add_next_index_bool(retval, v_bool);
+ } else {
+ add_assoc_bool(retval, key, v_bool);
+ }
+
+ php_phongo_field_path_write_item_at_current_level(state->field_path, key);
+
+ return false;
+} /* }}} */
+
+static void php_phongo_bson_new_utcdatetime_from_epoch(zval* object, int64_t msec_since_epoch) /* {{{ */
+{
+ php_phongo_utcdatetime_t* intern;
+
+ object_init_ex(object, php_phongo_utcdatetime_ce);
+
+ intern = Z_UTCDATETIME_OBJ_P(object);
+ intern->milliseconds = msec_since_epoch;
+ intern->initialized = true;
+} /* }}} */
+
+static bool php_phongo_bson_visit_date_time(const bson_iter_t* iter ARG_UNUSED, const char* key, int64_t msec_since_epoch, void* data) /* {{{ */
+{
+ zval* retval = PHONGO_BSON_STATE_ZCHILD(data);
+ php_phongo_bson_state* state = (php_phongo_bson_state*) data;
+ zval zchild;
+
+ php_phongo_bson_new_utcdatetime_from_epoch(&zchild, msec_since_epoch);
+
+ if (state->is_visiting_array) {
+ add_next_index_zval(retval, &zchild);
+ } else {
+ ADD_ASSOC_ZVAL(retval, key, &zchild);
+ }
+
+ php_phongo_field_path_write_item_at_current_level(state->field_path, key);
+
+ return false;
+} /* }}} */
+
+static void php_phongo_bson_new_decimal128(zval* object, const bson_decimal128_t* decimal) /* {{{ */
+{
+ php_phongo_decimal128_t* intern;
+
+ object_init_ex(object, php_phongo_decimal128_ce);
+
+ intern = Z_DECIMAL128_OBJ_P(object);
+ memcpy(&intern->decimal, decimal, sizeof(bson_decimal128_t));
+ intern->initialized = true;
+} /* }}} */
+
+static bool php_phongo_bson_visit_decimal128(const bson_iter_t* iter ARG_UNUSED, const char* key, const bson_decimal128_t* decimal, void* data) /* {{{ */
+{
+ zval* retval = PHONGO_BSON_STATE_ZCHILD(data);
+ php_phongo_bson_state* state = (php_phongo_bson_state*) data;
+ zval zchild;
+
+ php_phongo_bson_new_decimal128(&zchild, decimal);
+
+ if (state->is_visiting_array) {
+ add_next_index_zval(retval, &zchild);
+ } else {
+ ADD_ASSOC_ZVAL(retval, key, &zchild);
+ }
+
+ php_phongo_field_path_write_item_at_current_level(state->field_path, key);
+
+ return false;
+} /* }}} */
+
+static bool php_phongo_bson_visit_null(const bson_iter_t* iter ARG_UNUSED, const char* key, void* data) /* {{{ */
+{
+ zval* retval = PHONGO_BSON_STATE_ZCHILD(data);
+ php_phongo_bson_state* state = (php_phongo_bson_state*) data;
+
+ if (state->is_visiting_array) {
+ add_next_index_null(retval);
+ } else {
+ add_assoc_null(retval, key);
+ }
+
+ php_phongo_field_path_write_item_at_current_level(state->field_path, key);
+
+ return false;
+} /* }}} */
+
+static void php_phongo_bson_new_regex_from_regex_and_options(zval* object, const char* pattern, const char* flags) /* {{{ */
+{
+ php_phongo_regex_t* intern;
+
+ object_init_ex(object, php_phongo_regex_ce);
+
+ intern = Z_REGEX_OBJ_P(object);
+ intern->pattern_len = strlen(pattern);
+ intern->pattern = estrndup(pattern, intern->pattern_len);
+ intern->flags_len = strlen(flags);
+ intern->flags = estrndup(flags, intern->flags_len);
+} /* }}} */
+
+static bool php_phongo_bson_visit_regex(const bson_iter_t* iter ARG_UNUSED, const char* key, const char* v_regex, const char* v_options, void* data) /* {{{ */
+{
+ zval* retval = PHONGO_BSON_STATE_ZCHILD(data);
+ php_phongo_bson_state* state = (php_phongo_bson_state*) data;
+ zval zchild;
+
+ php_phongo_bson_new_regex_from_regex_and_options(&zchild, v_regex, v_options);
+
+ if (state->is_visiting_array) {
+ add_next_index_zval(retval, &zchild);
+ } else {
+ ADD_ASSOC_ZVAL(retval, key, &zchild);
+ }
+
+ php_phongo_field_path_write_item_at_current_level(state->field_path, key);
+
+ return false;
+} /* }}} */
+
+static void php_phongo_bson_new_symbol(zval* object, const char* symbol, size_t symbol_len) /* {{{ */
+{
+ php_phongo_symbol_t* intern;
+
+ object_init_ex(object, php_phongo_symbol_ce);
+
+ intern = Z_SYMBOL_OBJ_P(object);
+ intern->symbol = estrndup(symbol, symbol_len);
+ intern->symbol_len = symbol_len;
+} /* }}} */
+
+static bool php_phongo_bson_visit_symbol(const bson_iter_t* iter, const char* key, size_t v_symbol_len, const char* v_symbol, void* data) /* {{{ */
+{
+ zval* retval = PHONGO_BSON_STATE_ZCHILD(data);
+ php_phongo_bson_state* state = (php_phongo_bson_state*) data;
+ zval zchild;
+
+ php_phongo_bson_new_symbol(&zchild, v_symbol, v_symbol_len);
+
+ if (state->is_visiting_array) {
+ add_next_index_zval(retval, &zchild);
+ } else {
+ ADD_ASSOC_ZVAL(retval, key, &zchild);
+ }
+
+ php_phongo_field_path_write_item_at_current_level(state->field_path, key);
+
+ return false;
+} /* }}} */
+
+static bool php_phongo_bson_new_javascript_from_javascript_and_scope(zval* object, const char* code, size_t code_len, const bson_t* scope) /* {{{ */
+{
+ php_phongo_javascript_t* intern;
+
+ if (scope) {
+ php_phongo_bson_state state;
+ bool valid_scope;
+
+ PHONGO_BSON_INIT_STATE(state);
+
+ valid_scope = php_phongo_bson_to_zval_ex(bson_get_data(scope), scope->len, &state);
+ zval_ptr_dtor(&state.zchild);
+
+ if (!valid_scope) {
+ return false;
+ }
+ }
+
+ object_init_ex(object, php_phongo_javascript_ce);
+
+ intern = Z_JAVASCRIPT_OBJ_P(object);
+ intern->code = estrndup(code, code_len);
+ intern->code_len = code_len;
+ intern->scope = scope ? bson_copy(scope) : NULL;
+
+ return true;
+} /* }}} */
+
+static bool php_phongo_bson_new_javascript_from_javascript(zval* object, const char* code, size_t code_len) /* {{{ */
+{
+ return php_phongo_bson_new_javascript_from_javascript_and_scope(object, code, code_len, NULL);
+} /* }}} */
+
+static bool php_phongo_bson_visit_code(const bson_iter_t* iter ARG_UNUSED, const char* key, size_t v_code_len, const char* v_code, void* data) /* {{{ */
+{
+ zval* retval = PHONGO_BSON_STATE_ZCHILD(data);
+ php_phongo_bson_state* state = (php_phongo_bson_state*) data;
+ zval zchild;
+
+ if (!php_phongo_bson_new_javascript_from_javascript(&zchild, v_code, v_code_len)) {
+ return true;
+ }
+
+ if (state->is_visiting_array) {
+ add_next_index_zval(retval, &zchild);
+ } else {
+ ADD_ASSOC_ZVAL(retval, key, &zchild);
+ }
+
+ php_phongo_field_path_write_item_at_current_level(state->field_path, key);
+
+ return false;
+} /* }}} */
+
+static void php_phongo_bson_new_dbpointer(zval* object, const char* ref, size_t ref_len, const bson_oid_t* oid) /* {{{ */
+{
+ php_phongo_dbpointer_t* intern;
+
+ object_init_ex(object, php_phongo_dbpointer_ce);
+
+ intern = Z_DBPOINTER_OBJ_P(object);
+ intern->ref = estrndup(ref, ref_len);
+ intern->ref_len = ref_len;
+ bson_oid_to_string(oid, intern->id);
+} /* }}} */
+
+static bool php_phongo_bson_visit_dbpointer(const bson_iter_t* iter, const char* key, size_t namespace_len, const char* namespace, const bson_oid_t* oid, void* data) /* {{{ */
+{
+ zval* retval = PHONGO_BSON_STATE_ZCHILD(data);
+ php_phongo_bson_state* state = (php_phongo_bson_state*) data;
+ zval zchild;
+
+ php_phongo_bson_new_dbpointer(&zchild, namespace, namespace_len, oid);
+
+ if (state->is_visiting_array) {
+ add_next_index_zval(retval, &zchild);
+ } else {
+ ADD_ASSOC_ZVAL(retval, key, &zchild);
+ }
+
+ php_phongo_field_path_write_item_at_current_level(state->field_path, key);
+
+ return false;
+} /* }}} */
+
+static bool php_phongo_bson_visit_codewscope(const bson_iter_t* iter ARG_UNUSED, const char* key, size_t v_code_len, const char* v_code, const bson_t* v_scope, void* data) /* {{{ */
+{
+ zval* retval = PHONGO_BSON_STATE_ZCHILD(data);
+ php_phongo_bson_state* state = (php_phongo_bson_state*) data;
+ zval zchild;
+
+ if (!php_phongo_bson_new_javascript_from_javascript_and_scope(&zchild, v_code, v_code_len, v_scope)) {
+ return true;
+ }
+
+ if (state->is_visiting_array) {
+ add_next_index_zval(retval, &zchild);
+ } else {
+ ADD_ASSOC_ZVAL(retval, key, &zchild);
+ }
+
+ php_phongo_field_path_write_item_at_current_level(state->field_path, key);
+
+ return false;
+} /* }}} */
+
+static bool php_phongo_bson_visit_int32(const bson_iter_t* iter ARG_UNUSED, const char* key, int32_t v_int32, void* data) /* {{{ */
+{
+ zval* retval = PHONGO_BSON_STATE_ZCHILD(data);
+ php_phongo_bson_state* state = (php_phongo_bson_state*) data;
+
+ if (state->is_visiting_array) {
+ add_next_index_long(retval, v_int32);
+ } else {
+ add_assoc_long(retval, key, v_int32);
+ }
+
+ php_phongo_field_path_write_item_at_current_level(state->field_path, key);
+
+ return false;
+} /* }}} */
+
+static bool php_phongo_bson_visit_timestamp(const bson_iter_t* iter ARG_UNUSED, const char* key, uint32_t v_timestamp, uint32_t v_increment, void* data) /* {{{ */
+{
+ zval* retval = PHONGO_BSON_STATE_ZCHILD(data);
+ php_phongo_bson_state* state = (php_phongo_bson_state*) data;
+ zval zchild;
+
+ php_phongo_bson_new_timestamp_from_increment_and_timestamp(&zchild, v_increment, v_timestamp);
+
+ if (state->is_visiting_array) {
+ add_next_index_zval(retval, &zchild);
+ } else {
+ ADD_ASSOC_ZVAL(retval, key, &zchild);
+ }
+
+ php_phongo_field_path_write_item_at_current_level(state->field_path, key);
+
+ return false;
+} /* }}} */
+
+static bool php_phongo_bson_visit_int64(const bson_iter_t* iter ARG_UNUSED, const char* key, int64_t v_int64, void* data) /* {{{ */
+{
+ zval* retval = PHONGO_BSON_STATE_ZCHILD(data);
+ php_phongo_bson_state* state = (php_phongo_bson_state*) data;
+
+ php_phongo_field_path_write_item_at_current_level(state->field_path, key);
+
+ if (state->is_visiting_array) {
+ ADD_NEXT_INDEX_INT64(retval, v_int64);
+ } else {
+ ADD_ASSOC_INT64(retval, key, v_int64);
+ }
+
+ return false;
+} /* }}} */
+
+static bool php_phongo_bson_visit_maxkey(const bson_iter_t* iter ARG_UNUSED, const char* key, void* data) /* {{{ */
+{
+ zval* retval = PHONGO_BSON_STATE_ZCHILD(data);
+ php_phongo_bson_state* state = (php_phongo_bson_state*) data;
+ zval zchild;
+
+ object_init_ex(&zchild, php_phongo_maxkey_ce);
+
+ if (state->is_visiting_array) {
+ add_next_index_zval(retval, &zchild);
+ } else {
+ ADD_ASSOC_ZVAL(retval, key, &zchild);
+ }
+
+ php_phongo_field_path_write_item_at_current_level(state->field_path, key);
+
+ return false;
+} /* }}} */
+
+static bool php_phongo_bson_visit_minkey(const bson_iter_t* iter ARG_UNUSED, const char* key, void* data) /* {{{ */
+{
+ zval* retval = PHONGO_BSON_STATE_ZCHILD(data);
+ php_phongo_bson_state* state = (php_phongo_bson_state*) data;
+ zval zchild;
+
+ object_init_ex(&zchild, php_phongo_minkey_ce);
+
+ if (state->is_visiting_array) {
+ add_next_index_zval(retval, &zchild);
+ } else {
+ ADD_ASSOC_ZVAL(retval, key, &zchild);
+ }
+
+ php_phongo_field_path_write_item_at_current_level(state->field_path, key);
+
+ return false;
+} /* }}} */
+
+static const bson_visitor_t php_bson_visitors = {
+ NULL /* php_phongo_bson_visit_before*/,
+ NULL /*php_phongo_bson_visit_after*/,
+ php_phongo_bson_visit_corrupt,
+ php_phongo_bson_visit_double,
+ php_phongo_bson_visit_utf8,
+ php_phongo_bson_visit_document,
+ php_phongo_bson_visit_array,
+ php_phongo_bson_visit_binary,
+ php_phongo_bson_visit_undefined,
+ php_phongo_bson_visit_oid,
+ php_phongo_bson_visit_bool,
+ php_phongo_bson_visit_date_time,
+ php_phongo_bson_visit_null,
+ php_phongo_bson_visit_regex,
+ php_phongo_bson_visit_dbpointer,
+ php_phongo_bson_visit_code,
+ php_phongo_bson_visit_symbol,
+ php_phongo_bson_visit_codewscope,
+ php_phongo_bson_visit_int32,
+ php_phongo_bson_visit_timestamp,
+ php_phongo_bson_visit_int64,
+ php_phongo_bson_visit_maxkey,
+ php_phongo_bson_visit_minkey,
+ php_phongo_bson_visit_unsupported_type,
+ php_phongo_bson_visit_decimal128,
+ { NULL }
+};
+
+static inline bool map_element_matches_field_path(php_phongo_field_path_map_element* map_element, php_phongo_field_path* current)
+{
+ size_t i;
+
+ if (map_element->entry->size != current->size) {
+ return false;
+ }
+ for (i = 0; i < current->size; i++) {
+ if (strcmp(map_element->entry->elements[i], "$") == 0) {
+ continue;
+ }
+ if (strcmp(map_element->entry->elements[i], current->elements[i]) != 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+static php_phongo_field_path_map_element* map_find_field_path_entry(php_phongo_bson_state* state)
+{
+ size_t i;
+
+ /* Loop over all field path mappings, and for each, try to see whether it matches the current path */
+ for (i = 0; i < state->map.field_paths.size; i++) {
+ if (map_element_matches_field_path(state->map.field_paths.map[i], state->field_path)) {
+ return state->map.field_paths.map[i];
+ }
+ }
+ return NULL;
+}
+
+static void php_phongo_handle_field_path_entry_for_compound_type(php_phongo_bson_state* state, php_phongo_bson_typemap_types* type, zend_class_entry** ce)
+{
+ php_phongo_field_path_map_element* entry = map_find_field_path_entry(state);
+
+ if (entry) {
+ switch (entry->node_type) {
+ case PHONGO_TYPEMAP_NATIVE_ARRAY:
+ case PHONGO_TYPEMAP_NATIVE_OBJECT:
+ *type = entry->node_type;
+ break;
+ case PHONGO_TYPEMAP_CLASS:
+ *type = entry->node_type;
+ *ce = entry->node_ce;
+ break;
+ default:
+ /* Do nothing - pacify compiler */
+ break;
+ }
+ }
+}
+
+static bool php_phongo_bson_visit_document(const bson_iter_t* iter ARG_UNUSED, const char* key, const bson_t* v_document, void* data) /* {{{ */
+{
+ zval* retval = PHONGO_BSON_STATE_ZCHILD(data);
+ bson_iter_t child;
+ php_phongo_bson_state* parent_state = (php_phongo_bson_state*) data;
+
+ php_phongo_field_path_push(parent_state->field_path, key, PHONGO_FIELD_PATH_ITEM_DOCUMENT);
+
+ if (bson_iter_init(&child, v_document)) {
+ php_phongo_bson_state state;
+
+ PHONGO_BSON_INIT_STATE(state);
+ php_phongo_bson_state_copy_ctor(&state, parent_state);
+
+ array_init(&state.zchild);
+
+ if (!bson_iter_visit_all(&child, &php_bson_visitors, &state) && !child.err_off) {
+ /* Check for entries in the fieldPath type map key, and use them to
+ * override the default ones for this type */
+ php_phongo_handle_field_path_entry_for_compound_type(&state, &state.map.document_type, &state.map.document);
+
+ /* If php_phongo_bson_visit_binary() finds an ODM class, it should
+ * supersede a default type map and named document class. */
+ if (state.odm && state.map.document_type == PHONGO_TYPEMAP_NONE) {
+ state.map.document_type = PHONGO_TYPEMAP_CLASS;
+ }
+
+ switch (state.map.document_type) {
+ case PHONGO_TYPEMAP_NATIVE_ARRAY:
+ if (((php_phongo_bson_state*) data)->is_visiting_array) {
+ add_next_index_zval(retval, &state.zchild);
+ } else {
+ ADD_ASSOC_ZVAL(retval, key, &state.zchild);
+ }
+ break;
+
+ case PHONGO_TYPEMAP_CLASS: {
+ zval obj;
+
+ object_init_ex(&obj, state.odm ? state.odm : state.map.document);
+ zend_call_method_with_1_params(PHONGO_COMPAT_OBJ_P(&obj), NULL, NULL, BSON_UNSERIALIZE_FUNC_NAME, NULL, &state.zchild);
+ if (((php_phongo_bson_state*) data)->is_visiting_array) {
+ add_next_index_zval(retval, &obj);
+ } else {
+ ADD_ASSOC_ZVAL(retval, key, &obj);
+ }
+ zval_ptr_dtor(&state.zchild);
+ break;
+ }
+
+ case PHONGO_TYPEMAP_NATIVE_OBJECT:
+ default:
+ convert_to_object(&state.zchild);
+ if (((php_phongo_bson_state*) data)->is_visiting_array) {
+ add_next_index_zval(retval, &state.zchild);
+ } else {
+ ADD_ASSOC_ZVAL(retval, key, &state.zchild);
+ }
+ }
+ } else {
+ /* Iteration stopped prematurely due to corruption or a failed
+ * visitor. Free state.zchild, which we just initialized, and return
+ * true to stop iteration for our parent context. */
+ zval_ptr_dtor(&state.zchild);
+ php_phongo_bson_state_dtor(&state);
+ return true;
+ }
+
+ php_phongo_bson_state_dtor(&state);
+ php_phongo_field_path_pop(parent_state->field_path);
+ }
+
+ return false;
+} /* }}} */
+
+static bool php_phongo_bson_visit_array(const bson_iter_t* iter ARG_UNUSED, const char* key, const bson_t* v_array, void* data) /* {{{ */
+{
+ zval* retval = PHONGO_BSON_STATE_ZCHILD(data);
+ bson_iter_t child;
+ php_phongo_bson_state* parent_state = (php_phongo_bson_state*) data;
+
+ php_phongo_field_path_push(parent_state->field_path, key, PHONGO_FIELD_PATH_ITEM_ARRAY);
+
+ if (bson_iter_init(&child, v_array)) {
+ php_phongo_bson_state state;
+
+ PHONGO_BSON_INIT_STATE(state);
+ php_phongo_bson_state_copy_ctor(&state, parent_state);
+
+ /* Note that we are visiting an array, so element visitors know to use
+ * add_next_index() (i.e. disregard BSON keys) instead of add_assoc()
+ * when building the PHP array.
+ */
+ state.is_visiting_array = true;
+
+ array_init(&state.zchild);
+
+ if (!bson_iter_visit_all(&child, &php_bson_visitors, &state) && !child.err_off) {
+ /* Check for entries in the fieldPath type map key, and use them to
+ * override the default ones for this type */
+ php_phongo_handle_field_path_entry_for_compound_type(&state, &state.map.array_type, &state.map.array);
+
+ switch (state.map.array_type) {
+ case PHONGO_TYPEMAP_CLASS: {
+ zval obj;
+
+ object_init_ex(&obj, state.map.array);
+ zend_call_method_with_1_params(PHONGO_COMPAT_OBJ_P(&obj), NULL, NULL, BSON_UNSERIALIZE_FUNC_NAME, NULL, &state.zchild);
+ if (((php_phongo_bson_state*) data)->is_visiting_array) {
+ add_next_index_zval(retval, &obj);
+ } else {
+ ADD_ASSOC_ZVAL(retval, key, &obj);
+ }
+ zval_ptr_dtor(&state.zchild);
+ break;
+ }
+
+ case PHONGO_TYPEMAP_NATIVE_OBJECT:
+ convert_to_object(&state.zchild);
+ if (((php_phongo_bson_state*) data)->is_visiting_array) {
+ add_next_index_zval(retval, &state.zchild);
+ } else {
+ ADD_ASSOC_ZVAL(retval, key, &state.zchild);
+ }
+ break;
+
+ case PHONGO_TYPEMAP_NATIVE_ARRAY:
+ default:
+ if (((php_phongo_bson_state*) data)->is_visiting_array) {
+ add_next_index_zval(retval, &state.zchild);
+ } else {
+ ADD_ASSOC_ZVAL(retval, key, &state.zchild);
+ }
+ break;
+ }
+ } else {
+ /* Iteration stopped prematurely due to corruption or a failed
+ * visitor. Free state.zchild, which we just initialized, and return
+ * true to stop iteration for our parent context. */
+ zval_ptr_dtor(&state.zchild);
+ php_phongo_bson_state_dtor(&state);
+ return true;
+ }
+
+ php_phongo_bson_state_dtor(&state);
+ php_phongo_field_path_pop(parent_state->field_path);
+ }
+
+ return false;
+} /* }}} */
+
+/* Converts a BSON document to a PHP value using the default typemap. */
+bool php_phongo_bson_to_zval(const unsigned char* data, int data_len, zval* zv) /* {{{ */
+{
+ bool retval;
+ php_phongo_bson_state state;
+
+ PHONGO_BSON_INIT_STATE(state);
+
+ retval = php_phongo_bson_to_zval_ex(data, data_len, &state);
+ ZVAL_ZVAL(zv, &state.zchild, 1, 1);
+
+ return retval;
+} /* }}} */
+
+/* Converts a BSON value to a ZVAL. */
+bool php_phongo_bson_value_to_zval(const bson_value_t* value, zval* zv) /* {{{ */
+{
+ bson_t bson = BSON_INITIALIZER;
+ php_phongo_bson_state state;
+ zval* return_value;
+ bool retval = false;
+
+ PHONGO_BSON_INIT_STATE(state);
+ state.map.root_type = PHONGO_TYPEMAP_NATIVE_ARRAY;
+
+ bson_append_value(&bson, "data", 4, value);
+ if (!php_phongo_bson_to_zval_ex(bson_get_data(&bson), bson.len, &state)) {
+ /* Exception already thrown */
+ goto cleanup;
+ }
+
+ retval = true;
+
+ return_value = php_array_fetchc(&state.zchild, "data");
+
+ if (return_value) {
+ ZVAL_ZVAL(zv, return_value, 1, 0);
+ }
+
+cleanup:
+ zval_ptr_dtor(&state.zchild);
+ return retval;
+} /* }}} */
+
+/* Converts a BSON document to a PHP value according to the typemap specified in
+ * the state argument.
+ *
+ * On success, the result will be set on the state argument and true will be
+ * returned. On error, an exception will have been thrown and false will be
+ * returned.
+ *
+ * Note: the result zval in the state argument will always be initialized for
+ * PHP 5.x so that the caller may always zval_ptr_dtor() it. The zval is left
+ * as-is on PHP 7; however, it should have the type undefined if the state
+ * was initialized to zero.
+ */
+bool php_phongo_bson_to_zval_ex(const unsigned char* data, int data_len, php_phongo_bson_state* state) /* {{{ */
+{
+ bson_reader_t* reader = NULL;
+ bson_iter_t iter;
+ const bson_t* b;
+ bool eof = false;
+ bool retval = false;
+ bool must_dtor_state = false;
+
+ if (!php_phongo_bson_state_is_initialized(state)) {
+ php_phongo_bson_state_ctor(state);
+ must_dtor_state = true;
+ }
+
+ reader = bson_reader_new_from_data(data, data_len);
+
+ if (!(b = bson_reader_read(reader, NULL))) {
+ phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "Could not read document from BSON reader");
+
+ goto cleanup;
+ }
+
+ if (!bson_iter_init(&iter, b)) {
+ phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "Could not initialize BSON iterator");
+
+ goto cleanup;
+ }
+
+ /* We initialize an array because it will either be returned as-is (native
+ * array in type map), passed to bsonUnserialize() (ODM class), or used to
+ * initialize a stdClass object (native object in type map). */
+ array_init(&state->zchild);
+
+ if (bson_iter_visit_all(&iter, &php_bson_visitors, state) || iter.err_off) {
+ /* Iteration stopped prematurely due to corruption or a failed visitor.
+ * While we free the reader, state->zchild should be left as-is, since
+ * the calling code may want to zval_ptr_dtor() it. If an exception has
+ * been thrown already (due to an unsupported BSON type for example,
+ * don't overwrite with a generic exception message. */
+ if (!EG(exception)) {
+ char* path = php_phongo_field_path_as_string(state->field_path);
+ phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "Detected corrupt BSON data for field path '%s' at offset %d", path, iter.err_off);
+ efree(path);
+ }
+
+ goto cleanup;
+ }
+
+ /* If php_phongo_bson_visit_binary() finds an ODM class, it should supersede
+ * a default type map and named root class. */
+ if (state->odm && state->map.root_type == PHONGO_TYPEMAP_NONE) {
+ state->map.root_type = PHONGO_TYPEMAP_CLASS;
+ }
+
+ switch (state->map.root_type) {
+ case PHONGO_TYPEMAP_NATIVE_ARRAY:
+ /* Nothing to do here */
+ break;
+
+ case PHONGO_TYPEMAP_CLASS: {
+ zval obj;
+
+ object_init_ex(&obj, state->odm ? state->odm : state->map.root);
+ zend_call_method_with_1_params(PHONGO_COMPAT_OBJ_P(&obj), NULL, NULL, BSON_UNSERIALIZE_FUNC_NAME, NULL, &state->zchild);
+ zval_ptr_dtor(&state->zchild);
+ ZVAL_COPY_VALUE(&state->zchild, &obj);
+
+ break;
+ }
+
+ case PHONGO_TYPEMAP_NATIVE_OBJECT:
+ default:
+ convert_to_object(&state->zchild);
+ }
+
+ if (bson_reader_read(reader, &eof) || !eof) {
+ phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "Reading document did not exhaust input buffer");
+
+ goto cleanup;
+ }
+
+ retval = true;
+
+cleanup:
+ if (reader) {
+ bson_reader_destroy(reader);
+ }
+ if (must_dtor_state) {
+ php_phongo_bson_state_dtor(state);
+ }
+
+ return retval;
+} /* }}} */
+
+/* Fetches a zend_class_entry for the given class name and checks that it is
+ * also instantiatable and implements a specified interface. Returns the class
+ * on success; otherwise, NULL is returned and an exception is thrown. */
+static zend_class_entry* php_phongo_bson_state_fetch_class(const char* classname, int classname_len, zend_class_entry* interface_ce) /* {{{ */
+{
+ zend_string* zs_classname = zend_string_init(classname, classname_len, 0);
+ zend_class_entry* found_ce = zend_fetch_class(zs_classname, ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_SILENT);
+ zend_string_release(zs_classname);
+
+ if (!found_ce) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Class %s does not exist", classname);
+ } else if (!PHONGO_IS_CLASS_INSTANTIATABLE(found_ce)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Class %s is not instantiatable", classname);
+ } else if (!instanceof_function(found_ce, interface_ce)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Class %s does not implement %s", classname, ZSTR_VAL(interface_ce->name));
+ } else {
+ return found_ce;
+ }
+
+ return NULL;
+} /* }}} */
+
+/* Parses a BSON type (i.e. array, document, or root). On success, the type and
+ * type_ce output arguments will be assigned and true will be returned;
+ * otherwise, false is returned and an exception is thrown. */
+static bool php_phongo_bson_state_parse_type(zval* options, const char* name, php_phongo_bson_typemap_types* type, zend_class_entry** type_ce) /* {{{ */
+{
+ char* classname;
+ int classname_len;
+ zend_bool classname_free = 0;
+ bool retval = true;
+
+ classname = php_array_fetch_string(options, name, &classname_len, &classname_free);
+
+ if (!classname_len) {
+ goto cleanup;
+ }
+
+ if (!strcasecmp(classname, "array")) {
+ *type = PHONGO_TYPEMAP_NATIVE_ARRAY;
+ *type_ce = NULL;
+ } else if (!strcasecmp(classname, "stdclass") || !strcasecmp(classname, "object")) {
+ *type = PHONGO_TYPEMAP_NATIVE_OBJECT;
+ *type_ce = NULL;
+ } else {
+ if ((*type_ce = php_phongo_bson_state_fetch_class(classname, classname_len, php_phongo_unserializable_ce))) {
+ *type = PHONGO_TYPEMAP_CLASS;
+ } else {
+ retval = false;
+ }
+ }
+
+cleanup:
+ if (classname_free) {
+ efree(classname);
+ }
+
+ return retval;
+} /* }}} */
+
+static void field_path_map_element_set_info(php_phongo_field_path_map_element* element, php_phongo_bson_typemap_types type, zend_class_entry* ce)
+{
+ element->node_type = type;
+ element->node_ce = ce;
+}
+
+static void map_add_field_path_element(php_phongo_bson_typemap* map, php_phongo_field_path_map_element* element)
+{
+ /* Make sure we have allocated enough */
+ if (map->field_paths.allocated_size < map->field_paths.size + 1) {
+ map->field_paths.allocated_size += PHONGO_FIELD_PATH_EXPANSION;
+ map->field_paths.map = erealloc(map->field_paths.map, sizeof(php_phongo_field_path_map_element) * map->field_paths.allocated_size);
+ }
+
+ map->field_paths.map[map->field_paths.size] = element;
+ map->field_paths.size++;
+}
+
+static php_phongo_field_path_map_element* field_path_map_element_alloc(void)
+{
+ php_phongo_field_path_map_element* tmp = ecalloc(1, sizeof(php_phongo_field_path_map_element));
+
+ tmp->entry = php_phongo_field_path_alloc(true);
+
+ return tmp;
+}
+
+static void field_path_map_element_dtor(php_phongo_field_path_map_element* element)
+{
+ php_phongo_field_path_free(element->entry);
+ efree(element);
+}
+
+static bool php_phongo_bson_state_add_field_path(php_phongo_bson_typemap* map, char* field_path_original, php_phongo_bson_typemap_types type, zend_class_entry* ce)
+{
+ char* ptr = NULL;
+ char* segment_end = NULL;
+ php_phongo_field_path_map_element* field_path_map_element;
+
+ if (field_path_original[0] == '.') {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "A 'fieldPaths' key may not start with a '.'");
+ return false;
+ }
+
+ if (field_path_original[strlen(field_path_original) - 1] == '.') {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "A 'fieldPaths' key may not end with a '.'");
+ return false;
+ }
+
+ field_path_map_element = field_path_map_element_alloc();
+ ptr = field_path_original;
+
+ /* Loop over all the segments. A segment is delimited by a "." */
+ while ((segment_end = strchr(ptr, '.')) != NULL) {
+ char* tmp = NULL;
+
+ /* Bail out if we have an empty segment */
+ if (ptr == segment_end) {
+ field_path_map_element_dtor(field_path_map_element);
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "A 'fieldPaths' key may not have an empty segment");
+ return false;
+ }
+
+ tmp = calloc(1, segment_end - ptr + 1);
+ memcpy(tmp, ptr, segment_end - ptr);
+ php_phongo_field_path_push(field_path_map_element->entry, tmp, PHONGO_FIELD_PATH_ITEM_NONE);
+ free(tmp);
+
+ ptr = segment_end + 1;
+ }
+
+ /* Add the last (or single) element */
+ php_phongo_field_path_push(field_path_map_element->entry, ptr, PHONGO_FIELD_PATH_ITEM_NONE);
+
+ field_path_map_element_set_info(field_path_map_element, type, ce);
+ map_add_field_path_element(map, field_path_map_element);
+
+ return true;
+}
+
+void php_phongo_bson_typemap_dtor(php_phongo_bson_typemap* map)
+{
+ size_t i;
+
+ if (map->field_paths.map) {
+ for (i = 0; i < map->field_paths.size; i++) {
+ field_path_map_element_dtor(map->field_paths.map[i]);
+ }
+ efree(map->field_paths.map);
+ }
+
+ map->field_paths.map = NULL;
+}
+
+/* Loops over each element in the fieldPaths array (if exists, and is an
+ * array), and then checks whether each element is a valid type mapping */
+static bool php_phongo_bson_state_parse_fieldpaths(zval* typemap, php_phongo_bson_typemap* map) /* {{{ */
+{
+ zval* fieldpaths = NULL;
+ HashTable* ht_data;
+
+ if (!php_array_existsc(typemap, "fieldPaths")) {
+ return true;
+ }
+
+ fieldpaths = php_array_fetchc_array(typemap, "fieldPaths");
+
+ if (!fieldpaths) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "The 'fieldPaths' element is not an array");
+ return false;
+ }
+
+ ht_data = HASH_OF(fieldpaths);
+
+ {
+ zend_string* string_key = NULL;
+ zend_ulong num_key = 0;
+ zval* property;
+
+ ZEND_HASH_FOREACH_KEY_VAL(ht_data, num_key, string_key, property)
+ {
+ zend_class_entry* map_ce = NULL;
+ php_phongo_bson_typemap_types map_type;
+
+ if (!string_key) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "The 'fieldPaths' element is not an associative array");
+ return false;
+ }
+
+ if (strcmp(ZSTR_VAL(string_key), "") == 0) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "The 'fieldPaths' element may not be an empty string");
+ return false;
+ }
+
+ if (!php_phongo_bson_state_parse_type(fieldpaths, ZSTR_VAL(string_key), &map_type, &map_ce)) {
+ return false;
+ }
+
+ if (!php_phongo_bson_state_add_field_path(map, ZSTR_VAL(string_key), map_type, map_ce)) {
+ return false;
+ }
+ }
+ ZEND_HASH_FOREACH_END();
+ }
+
+ return true;
+} /* }}} */
+
+/* Applies the array argument to a typemap struct. Returns true on success;
+ * otherwise, false is returned an an exception is thrown. */
+bool php_phongo_bson_typemap_to_state(zval* typemap, php_phongo_bson_typemap* map) /* {{{ */
+{
+ if (!typemap) {
+ return true;
+ }
+
+ if (!php_phongo_bson_state_parse_type(typemap, "array", &map->array_type, &map->array) ||
+ !php_phongo_bson_state_parse_type(typemap, "document", &map->document_type, &map->document) ||
+ !php_phongo_bson_state_parse_type(typemap, "root", &map->root_type, &map->root) ||
+ !php_phongo_bson_state_parse_fieldpaths(typemap, map)) {
+
+ /* Exception should already have been thrown */
+ return false;
+ }
+
+ return true;
+} /* }}} */
+
+void php_phongo_bson_new_timestamp_from_increment_and_timestamp(zval* object, uint32_t increment, uint32_t timestamp) /* {{{ */
+{
+ php_phongo_timestamp_t* intern;
+
+ object_init_ex(object, php_phongo_timestamp_ce);
+
+ intern = Z_TIMESTAMP_OBJ_P(object);
+ intern->increment = increment;
+ intern->timestamp = timestamp;
+ intern->initialized = true;
+} /* }}} */
+
+void php_phongo_bson_new_int64(zval* object, int64_t integer) /* {{{ */
+{
+ php_phongo_int64_t* intern;
+
+ object_init_ex(object, php_phongo_int64_ce);
+
+ intern = Z_INT64_OBJ_P(object);
+ intern->integer = integer;
+ intern->initialized = true;
+} /* }}} */
diff --git a/mongodb-1.13.0/src/phongo_bson.h b/mongodb-1.13.0/src/phongo_bson.h
new file mode 100644
index 00000000..7732979a
--- /dev/null
+++ b/mongodb-1.13.0/src/phongo_bson.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2022-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PHONGO_BSON_H
+#define PHONGO_BSON_H
+
+#include "bson/bson.h"
+
+#include <php.h>
+
+#define BSON_UNSERIALIZE_FUNC_NAME "bsonUnserialize"
+#define BSON_SERIALIZE_FUNC_NAME "bsonSerialize"
+#define PHONGO_ODM_FIELD_NAME "__pclass"
+
+typedef enum {
+ PHONGO_FIELD_PATH_ITEM_NONE,
+ PHONGO_FIELD_PATH_ITEM_ARRAY,
+ PHONGO_FIELD_PATH_ITEM_DOCUMENT
+} php_phongo_bson_field_path_item_types;
+
+typedef struct {
+ char** elements;
+ php_phongo_bson_field_path_item_types* element_types;
+ size_t allocated_size;
+ size_t size;
+ size_t ref_count;
+ bool owns_elements;
+} php_phongo_field_path;
+
+typedef enum {
+ PHONGO_TYPEMAP_NONE,
+ PHONGO_TYPEMAP_NATIVE_ARRAY,
+ PHONGO_TYPEMAP_NATIVE_OBJECT,
+ PHONGO_TYPEMAP_CLASS
+} php_phongo_bson_typemap_types;
+
+typedef struct {
+ php_phongo_field_path* entry;
+ php_phongo_bson_typemap_types node_type;
+ zend_class_entry* node_ce;
+} php_phongo_field_path_map_element;
+
+typedef struct {
+ php_phongo_bson_typemap_types document_type;
+ zend_class_entry* document;
+ php_phongo_bson_typemap_types array_type;
+ zend_class_entry* array;
+ php_phongo_bson_typemap_types root_type;
+ zend_class_entry* root;
+ struct {
+ php_phongo_field_path_map_element** map;
+ size_t allocated_size;
+ size_t size;
+ } field_paths;
+} php_phongo_bson_typemap;
+
+typedef struct {
+ zval zchild;
+ php_phongo_bson_typemap map;
+ zend_class_entry* odm;
+ bool is_visiting_array;
+ php_phongo_field_path* field_path;
+} php_phongo_bson_state;
+
+#define PHONGO_BSON_INIT_STATE(s) \
+ do { \
+ memset(&(s), 0, sizeof(php_phongo_bson_state)); \
+ } while (0)
+
+#define PHONGO_BSON_INIT_DEBUG_STATE(s) \
+ do { \
+ memset(&(s), 0, sizeof(php_phongo_bson_state)); \
+ s.map.root_type = PHONGO_TYPEMAP_NATIVE_ARRAY; \
+ s.map.document_type = PHONGO_TYPEMAP_NATIVE_ARRAY; \
+ } while (0)
+
+char* php_phongo_field_path_as_string(php_phongo_field_path* field_path);
+php_phongo_field_path* php_phongo_field_path_alloc(bool owns_elements);
+void php_phongo_field_path_free(php_phongo_field_path* field_path);
+void php_phongo_field_path_write_item_at_current_level(php_phongo_field_path* field_path, const char* element);
+void php_phongo_field_path_write_type_at_current_level(php_phongo_field_path* field_path, php_phongo_bson_field_path_item_types element_type);
+bool php_phongo_field_path_push(php_phongo_field_path* field_path, const char* element, php_phongo_bson_field_path_item_types element_type);
+bool php_phongo_field_path_pop(php_phongo_field_path* field_path);
+
+bool php_phongo_bson_to_zval(const unsigned char* data, int data_len, zval* out);
+bool php_phongo_bson_to_zval_ex(const unsigned char* data, int data_len, php_phongo_bson_state* state);
+
+bool php_phongo_bson_value_to_zval(const bson_value_t* value, zval* zv);
+
+bool php_phongo_bson_typemap_to_state(zval* typemap, php_phongo_bson_typemap* map);
+void php_phongo_bson_typemap_dtor(php_phongo_bson_typemap* map);
+
+void php_phongo_bson_new_timestamp_from_increment_and_timestamp(zval* object, uint32_t increment, uint32_t timestamp);
+void php_phongo_bson_new_int64(zval* object, int64_t integer);
+
+#endif /* PHONGO_BSON_H */
diff --git a/mongodb-1.13.0/src/phongo_bson_encode.c b/mongodb-1.13.0/src/phongo_bson_encode.c
new file mode 100644
index 00000000..dd4209f6
--- /dev/null
+++ b/mongodb-1.13.0/src/phongo_bson_encode.c
@@ -0,0 +1,518 @@
+/*
+ * Copyright 2014-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bson/bson.h"
+
+#include <php.h>
+#include <Zend/zend_interfaces.h>
+
+#include "php_phongo.h"
+#include "phongo_bson.h"
+#include "phongo_bson_encode.h"
+#include "phongo_compat.h"
+#include "phongo_error.h"
+
+#undef MONGOC_LOG_DOMAIN
+#define MONGOC_LOG_DOMAIN "PHONGO-BSON"
+
+#if SIZEOF_ZEND_LONG == 8
+#define BSON_APPEND_INT(b, key, keylen, val) \
+ if (val > INT32_MAX || val < INT32_MIN) { \
+ bson_append_int64(b, key, keylen, val); \
+ } else { \
+ bson_append_int32(b, key, keylen, val); \
+ }
+#elif SIZEOF_ZEND_LONG == 4
+#define BSON_APPEND_INT(b, key, keylen, val) \
+ bson_append_int32(b, key, keylen, val)
+#else
+#error Unsupported architecture (integers are neither 32-bit nor 64-bit)
+#endif
+
+/* Forwards declarations */
+static void php_phongo_zval_to_bson_internal(zval* data, php_phongo_field_path* field_path, php_phongo_bson_flags_t flags, bson_t* bson, bson_t** bson_out);
+
+/* Determines whether the argument should be serialized as a BSON array or
+ * document. IS_ARRAY is returned if the argument's keys are a sequence of
+ * integers starting at zero; otherwise, IS_OBJECT is returned. */
+static int php_phongo_is_array_or_document(zval* val) /* {{{ */
+{
+ HashTable* ht_data = HASH_OF(val);
+ int count;
+
+ if (Z_TYPE_P(val) != IS_ARRAY) {
+ return IS_OBJECT;
+ }
+
+ count = ht_data ? zend_hash_num_elements(ht_data) : 0;
+ if (count > 0) {
+ zend_string* key;
+ zend_ulong index, idx;
+
+ idx = 0;
+ ZEND_HASH_FOREACH_KEY(ht_data, index, key)
+ {
+ if (key) {
+ return IS_OBJECT;
+ } else {
+ if (index != idx) {
+ return IS_OBJECT;
+ }
+ }
+ idx++;
+ }
+ ZEND_HASH_FOREACH_END();
+ } else {
+ return Z_TYPE_P(val);
+ }
+
+ return IS_ARRAY;
+} /* }}} */
+
+/* Appends the array or object argument to the BSON document. If the object is
+ * an instance of MongoDB\BSON\Serializable, the return value of bsonSerialize()
+ * will be appended as an embedded document. Other MongoDB\BSON\Type instances
+ * will be appended as the appropriate BSON type. Other array or object values
+ * will be appended as an embedded document. */
+static void php_phongo_bson_append_object(bson_t* bson, php_phongo_field_path* field_path, php_phongo_bson_flags_t flags, const char* key, long key_len, zval* object) /* {{{ */
+{
+ if (Z_TYPE_P(object) == IS_OBJECT && instanceof_function(Z_OBJCE_P(object), php_phongo_cursorid_ce)) {
+ bson_append_int64(bson, key, key_len, Z_CURSORID_OBJ_P(object)->id);
+ return;
+ }
+
+ if (Z_TYPE_P(object) == IS_OBJECT && instanceof_function(Z_OBJCE_P(object), php_phongo_type_ce)) {
+ if (instanceof_function(Z_OBJCE_P(object), php_phongo_serializable_ce)) {
+ zval obj_data;
+ bson_t child;
+
+ zend_call_method_with_0_params(PHONGO_COMPAT_OBJ_P(object), NULL, NULL, BSON_SERIALIZE_FUNC_NAME, &obj_data);
+
+ if (Z_ISUNDEF(obj_data)) {
+ /* zend_call_method() failed or bsonSerialize() threw an
+ * exception. Either way, there is nothing else to do. */
+ return;
+ }
+
+ if (Z_TYPE(obj_data) != IS_ARRAY && !(Z_TYPE(obj_data) == IS_OBJECT && instanceof_function(Z_OBJCE(obj_data), zend_standard_class_def))) {
+ phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE,
+ "Expected %s::%s() to return an array or stdClass, %s given",
+ ZSTR_VAL(Z_OBJCE_P(object)->name),
+ BSON_SERIALIZE_FUNC_NAME,
+ PHONGO_ZVAL_CLASS_OR_TYPE_NAME(obj_data));
+ zval_ptr_dtor(&obj_data);
+
+ return;
+ }
+
+ /* Persistable objects must always be serialized as BSON documents;
+ * otherwise, infer based on bsonSerialize()'s return value. */
+ if (instanceof_function(Z_OBJCE_P(object), php_phongo_persistable_ce) || php_phongo_is_array_or_document(&obj_data) == IS_OBJECT) {
+ bson_append_document_begin(bson, key, key_len, &child);
+ if (instanceof_function(Z_OBJCE_P(object), php_phongo_persistable_ce)) {
+ bson_append_binary(&child, PHONGO_ODM_FIELD_NAME, -1, 0x80, (const uint8_t*) Z_OBJCE_P(object)->name->val, Z_OBJCE_P(object)->name->len);
+ }
+ php_phongo_zval_to_bson_internal(&obj_data, field_path, flags, &child, NULL);
+ bson_append_document_end(bson, &child);
+ } else {
+ bson_append_array_begin(bson, key, key_len, &child);
+ php_phongo_zval_to_bson_internal(&obj_data, field_path, flags, &child, NULL);
+ bson_append_array_end(bson, &child);
+ }
+
+ zval_ptr_dtor(&obj_data);
+ return;
+ }
+
+ if (instanceof_function(Z_OBJCE_P(object), php_phongo_objectid_ce)) {
+ bson_oid_t oid;
+ php_phongo_objectid_t* intern = Z_OBJECTID_OBJ_P(object);
+
+ mongoc_log(MONGOC_LOG_LEVEL_TRACE, MONGOC_LOG_DOMAIN, "encoding ObjectId");
+ bson_oid_init_from_string(&oid, intern->oid);
+ bson_append_oid(bson, key, key_len, &oid);
+ return;
+ }
+ if (instanceof_function(Z_OBJCE_P(object), php_phongo_utcdatetime_ce)) {
+ php_phongo_utcdatetime_t* intern = Z_UTCDATETIME_OBJ_P(object);
+
+ mongoc_log(MONGOC_LOG_LEVEL_TRACE, MONGOC_LOG_DOMAIN, "encoding UTCDateTime");
+ bson_append_date_time(bson, key, key_len, intern->milliseconds);
+ return;
+ }
+ if (instanceof_function(Z_OBJCE_P(object), php_phongo_binary_ce)) {
+ php_phongo_binary_t* intern = Z_BINARY_OBJ_P(object);
+
+ mongoc_log(MONGOC_LOG_LEVEL_TRACE, MONGOC_LOG_DOMAIN, "encoding Binary");
+ bson_append_binary(bson, key, key_len, intern->type, (const uint8_t*) intern->data, (uint32_t) intern->data_len);
+ return;
+ }
+ if (instanceof_function(Z_OBJCE_P(object), php_phongo_decimal128_ce)) {
+ php_phongo_decimal128_t* intern = Z_DECIMAL128_OBJ_P(object);
+
+ mongoc_log(MONGOC_LOG_LEVEL_TRACE, MONGOC_LOG_DOMAIN, "encoding Decimal128");
+ bson_append_decimal128(bson, key, key_len, &intern->decimal);
+ return;
+ }
+ if (instanceof_function(Z_OBJCE_P(object), php_phongo_int64_ce)) {
+ php_phongo_int64_t* intern = Z_INT64_OBJ_P(object);
+
+ mongoc_log(MONGOC_LOG_LEVEL_TRACE, MONGOC_LOG_DOMAIN, "encoding Int64");
+ bson_append_int64(bson, key, key_len, intern->integer);
+ return;
+ }
+ if (instanceof_function(Z_OBJCE_P(object), php_phongo_regex_ce)) {
+ php_phongo_regex_t* intern = Z_REGEX_OBJ_P(object);
+
+ mongoc_log(MONGOC_LOG_LEVEL_TRACE, MONGOC_LOG_DOMAIN, "encoding Regex");
+ bson_append_regex(bson, key, key_len, intern->pattern, intern->flags);
+ return;
+ }
+ if (instanceof_function(Z_OBJCE_P(object), php_phongo_javascript_ce)) {
+ php_phongo_javascript_t* intern = Z_JAVASCRIPT_OBJ_P(object);
+
+ if (intern->scope) {
+ mongoc_log(MONGOC_LOG_LEVEL_TRACE, MONGOC_LOG_DOMAIN, "encoding Javascript with scope");
+ bson_append_code_with_scope(bson, key, key_len, intern->code, intern->scope);
+ } else {
+ mongoc_log(MONGOC_LOG_LEVEL_TRACE, MONGOC_LOG_DOMAIN, "encoding Javascript without scope");
+ bson_append_code(bson, key, key_len, intern->code);
+ }
+ return;
+ }
+ if (instanceof_function(Z_OBJCE_P(object), php_phongo_timestamp_ce)) {
+ php_phongo_timestamp_t* intern = Z_TIMESTAMP_OBJ_P(object);
+
+ mongoc_log(MONGOC_LOG_LEVEL_TRACE, MONGOC_LOG_DOMAIN, "encoding Timestamp");
+ bson_append_timestamp(bson, key, key_len, intern->timestamp, intern->increment);
+ return;
+ }
+ if (instanceof_function(Z_OBJCE_P(object), php_phongo_maxkey_ce)) {
+ mongoc_log(MONGOC_LOG_LEVEL_TRACE, MONGOC_LOG_DOMAIN, "encoding MaxKey");
+ bson_append_maxkey(bson, key, key_len);
+ return;
+ }
+ if (instanceof_function(Z_OBJCE_P(object), php_phongo_minkey_ce)) {
+ mongoc_log(MONGOC_LOG_LEVEL_TRACE, MONGOC_LOG_DOMAIN, "encoding MinKey");
+ bson_append_minkey(bson, key, key_len);
+ return;
+ }
+
+ /* Deprecated types */
+ if (instanceof_function(Z_OBJCE_P(object), php_phongo_dbpointer_ce)) {
+ bson_oid_t oid;
+ php_phongo_dbpointer_t* intern = Z_DBPOINTER_OBJ_P(object);
+
+ mongoc_log(MONGOC_LOG_LEVEL_TRACE, MONGOC_LOG_DOMAIN, "encoding DBPointer");
+ bson_oid_init_from_string(&oid, intern->id);
+ bson_append_dbpointer(bson, key, key_len, intern->ref, &oid);
+ return;
+ }
+ if (instanceof_function(Z_OBJCE_P(object), php_phongo_symbol_ce)) {
+ php_phongo_symbol_t* intern = Z_SYMBOL_OBJ_P(object);
+
+ mongoc_log(MONGOC_LOG_LEVEL_TRACE, MONGOC_LOG_DOMAIN, "encoding Symbol");
+ bson_append_symbol(bson, key, key_len, intern->symbol, intern->symbol_len);
+ return;
+ }
+ if (instanceof_function(Z_OBJCE_P(object), php_phongo_undefined_ce)) {
+ mongoc_log(MONGOC_LOG_LEVEL_TRACE, MONGOC_LOG_DOMAIN, "encoding Undefined");
+ bson_append_undefined(bson, key, key_len);
+ return;
+ }
+
+ phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "Unexpected %s instance: %s", ZSTR_VAL(php_phongo_type_ce->name), ZSTR_VAL(Z_OBJCE_P(object)->name));
+ return;
+ } else {
+ bson_t child;
+
+ mongoc_log(MONGOC_LOG_LEVEL_TRACE, MONGOC_LOG_DOMAIN, "encoding document");
+ bson_append_document_begin(bson, key, key_len, &child);
+ php_phongo_zval_to_bson_internal(object, field_path, flags, &child, NULL);
+ bson_append_document_end(bson, &child);
+ }
+} /* }}} */
+
+/* Appends the zval argument to the BSON document. If the argument is an object,
+ * or an array that should be serialized as an embedded document, this function
+ * will defer to php_phongo_bson_append_object(). */
+static void php_phongo_bson_append(bson_t* bson, php_phongo_field_path* field_path, php_phongo_bson_flags_t flags, const char* key, long key_len, zval* entry) /* {{{ */
+{
+ php_phongo_field_path_write_item_at_current_level(field_path, key);
+
+try_again:
+ switch (Z_TYPE_P(entry)) {
+ case IS_NULL:
+ bson_append_null(bson, key, key_len);
+ break;
+ case IS_TRUE:
+ bson_append_bool(bson, key, key_len, true);
+ break;
+
+ case IS_FALSE:
+ bson_append_bool(bson, key, key_len, false);
+ break;
+
+ case IS_LONG:
+ BSON_APPEND_INT(bson, key, key_len, Z_LVAL_P(entry));
+ break;
+
+ case IS_DOUBLE:
+ bson_append_double(bson, key, key_len, Z_DVAL_P(entry));
+ break;
+
+ case IS_STRING:
+ if (bson_utf8_validate(Z_STRVAL_P(entry), Z_STRLEN_P(entry), true)) {
+ bson_append_utf8(bson, key, key_len, Z_STRVAL_P(entry), Z_STRLEN_P(entry));
+ } else {
+ char* path_string = php_phongo_field_path_as_string(field_path);
+ phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "Detected invalid UTF-8 for field path \"%s\": %s", path_string, Z_STRVAL_P(entry));
+ efree(path_string);
+ }
+ break;
+
+ case IS_ARRAY:
+ if (php_phongo_is_array_or_document(entry) == IS_ARRAY) {
+ bson_t child;
+ HashTable* tmp_ht = HASH_OF(entry);
+
+ if (!php_phongo_zend_hash_apply_protection_begin(tmp_ht)) {
+ char* path_string = php_phongo_field_path_as_string(field_path);
+ phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "Detected recursion for field path \"%s\"", path_string);
+ efree(path_string);
+ break;
+ }
+
+ bson_append_array_begin(bson, key, key_len, &child);
+ php_phongo_field_path_write_type_at_current_level(field_path, PHONGO_FIELD_PATH_ITEM_ARRAY);
+ field_path->size++;
+ php_phongo_zval_to_bson_internal(entry, field_path, flags, &child, NULL);
+ field_path->size--;
+ bson_append_array_end(bson, &child);
+
+ php_phongo_zend_hash_apply_protection_end(tmp_ht);
+ break;
+ }
+ PHONGO_BREAK_INTENTIONALLY_MISSING
+
+ case IS_OBJECT: {
+ HashTable* tmp_ht = HASH_OF(entry);
+
+ if (!php_phongo_zend_hash_apply_protection_begin(tmp_ht)) {
+ char* path_string = php_phongo_field_path_as_string(field_path);
+ phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "Detected recursion for field path \"%s\"", path_string);
+ efree(path_string);
+ break;
+ }
+
+ php_phongo_field_path_write_type_at_current_level(field_path, PHONGO_FIELD_PATH_ITEM_DOCUMENT);
+ field_path->size++;
+ php_phongo_bson_append_object(bson, field_path, flags, key, key_len, entry);
+ field_path->size--;
+
+ php_phongo_zend_hash_apply_protection_end(tmp_ht);
+ break;
+ }
+
+ case IS_REFERENCE:
+ ZVAL_DEREF(entry);
+ goto try_again;
+
+ default: {
+ char* path_string = php_phongo_field_path_as_string(field_path);
+ phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "Detected unsupported PHP type for field path \"%s\": %d (%s)", path_string, Z_TYPE_P(entry), zend_get_type_by_const(Z_TYPE_P(entry)));
+ efree(path_string);
+ }
+ }
+} /* }}} */
+
+static void php_phongo_zval_to_bson_internal(zval* data, php_phongo_field_path* field_path, php_phongo_bson_flags_t flags, bson_t* bson, bson_t** bson_out) /* {{{ */
+{
+ HashTable* ht_data = NULL;
+ zval obj_data;
+
+ /* If we will be encoding a class that may contain protected and private
+ * properties, we'll need to filter them out later. */
+ bool ht_data_from_properties = false;
+
+ /* If the object is an instance of MongoDB\BSON\Persistable, we will need to
+ * inject the PHP class name as a BSON key and ignore any existing key in
+ * the return value of bsonSerialize(). */
+ bool skip_odm_field = false;
+
+ ZVAL_UNDEF(&obj_data);
+
+ switch (Z_TYPE_P(data)) {
+ case IS_OBJECT:
+ if (instanceof_function(Z_OBJCE_P(data), php_phongo_serializable_ce)) {
+ zend_call_method_with_0_params(PHONGO_COMPAT_OBJ_P(data), NULL, NULL, BSON_SERIALIZE_FUNC_NAME, &obj_data);
+
+ if (Z_ISUNDEF(obj_data)) {
+ /* zend_call_method() failed or bsonSerialize() threw an
+ * exception. Either way, there is nothing else to do. */
+ return;
+ }
+
+ if (Z_TYPE(obj_data) != IS_ARRAY && !(Z_TYPE(obj_data) == IS_OBJECT && instanceof_function(Z_OBJCE(obj_data), zend_standard_class_def))) {
+ phongo_throw_exception(
+ PHONGO_ERROR_UNEXPECTED_VALUE,
+ "Expected %s::%s() to return an array or stdClass, %s given",
+ ZSTR_VAL(Z_OBJCE_P(data)->name),
+ BSON_SERIALIZE_FUNC_NAME,
+ PHONGO_ZVAL_CLASS_OR_TYPE_NAME(obj_data));
+
+ goto cleanup;
+ }
+
+ ht_data = HASH_OF(&obj_data);
+
+ if (instanceof_function(Z_OBJCE_P(data), php_phongo_persistable_ce)) {
+ bson_append_binary(bson, PHONGO_ODM_FIELD_NAME, -1, 0x80, (const uint8_t*) Z_OBJCE_P(data)->name->val, Z_OBJCE_P(data)->name->len);
+ /* Ensure that we ignore an existing key with the same name
+ * if one exists in the bsonSerialize() return value. */
+ skip_odm_field = true;
+ }
+
+ break;
+ }
+
+ if (instanceof_function(Z_OBJCE_P(data), php_phongo_type_ce)) {
+ phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "%s instance %s cannot be serialized as a root element", ZSTR_VAL(php_phongo_type_ce->name), ZSTR_VAL(Z_OBJCE_P(data)->name));
+ return;
+ }
+
+ ht_data = Z_OBJ_HT_P(data)->get_properties(PHONGO_COMPAT_OBJ_P(data));
+ ht_data_from_properties = true;
+ break;
+
+ case IS_ARRAY:
+ ht_data = HASH_OF(data);
+ break;
+
+ default:
+ return;
+ }
+
+ {
+ zend_string* string_key = NULL;
+ zend_ulong num_key = 0;
+ zval* value;
+
+ ZEND_HASH_FOREACH_KEY_VAL_IND(ht_data, num_key, string_key, value)
+ {
+ if (string_key) {
+ if (ht_data_from_properties) {
+ /* Skip protected and private properties */
+ if (ZSTR_VAL(string_key)[0] == '\0' && ZSTR_LEN(string_key) > 0) {
+ continue;
+ }
+ }
+
+ if (strlen(ZSTR_VAL(string_key)) != ZSTR_LEN(string_key)) {
+ phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "BSON keys cannot contain null bytes. Unexpected null byte after \"%s\".", ZSTR_VAL(string_key));
+
+ goto cleanup;
+ }
+
+ if (skip_odm_field && !strcmp(ZSTR_VAL(string_key), PHONGO_ODM_FIELD_NAME)) {
+ continue;
+ }
+
+ if (flags & PHONGO_BSON_ADD_ID) {
+ if (!strcmp(ZSTR_VAL(string_key), "_id")) {
+ flags &= ~PHONGO_BSON_ADD_ID;
+ }
+ }
+ }
+
+ /* Ensure we're working with a string key */
+ if (!string_key) {
+ string_key = zend_long_to_str(num_key);
+ } else {
+ zend_string_addref(string_key);
+ }
+
+ php_phongo_bson_append(bson, field_path, flags & ~PHONGO_BSON_ADD_ID, ZSTR_VAL(string_key), strlen(ZSTR_VAL(string_key)), value);
+
+ zend_string_release(string_key);
+ }
+ ZEND_HASH_FOREACH_END();
+ }
+
+ if (flags & PHONGO_BSON_ADD_ID) {
+ bson_oid_t oid;
+
+ bson_oid_init(&oid, NULL);
+ bson_append_oid(bson, "_id", strlen("_id"), &oid);
+ mongoc_log(MONGOC_LOG_LEVEL_TRACE, MONGOC_LOG_DOMAIN, "Added new _id");
+ }
+
+ if (flags & PHONGO_BSON_RETURN_ID && bson_out) {
+ bson_iter_t iter;
+
+ *bson_out = bson_new();
+
+ if (bson_iter_init_find(&iter, bson, "_id") && !bson_append_iter(*bson_out, NULL, 0, &iter)) {
+ /* This should not be able to happen since we are copying from
+ * within a valid bson_t. */
+ phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "Error copying \"_id\" field from encoded document");
+
+ goto cleanup;
+ }
+ }
+
+cleanup:
+ if (!Z_ISUNDEF(obj_data)) {
+ zval_ptr_dtor(&obj_data);
+ }
+} /* }}} */
+
+/* Converts the array or object argument to a BSON document. If the object is an
+ * instance of MongoDB\BSON\Serializable, the return value of bsonSerialize()
+ * will be used. */
+void php_phongo_zval_to_bson(zval* data, php_phongo_bson_flags_t flags, bson_t* bson, bson_t** bson_out) /* {{{ */
+{
+ php_phongo_field_path* field_path = php_phongo_field_path_alloc(false);
+
+ php_phongo_zval_to_bson_internal(data, field_path, flags, bson, bson_out);
+
+ php_phongo_field_path_free(field_path);
+} /* }}} */
+
+/* Converts the argument to a bson_value_t. If the object is an instance of
+ * MongoDB\BSON\Serializable, the return value of bsonSerialize() will be
+ * used. */
+void php_phongo_zval_to_bson_value(zval* data, php_phongo_bson_flags_t flags, bson_value_t* value) /* {{{ */
+{
+ bson_iter_t iter;
+ bson_t bson = BSON_INITIALIZER;
+
+ zval* data_object = ecalloc(1, sizeof(zval));
+
+ array_init_size(data_object, 1);
+ add_assoc_zval(data_object, "data", data);
+
+ Z_TRY_ADDREF_P(data);
+
+ php_phongo_zval_to_bson(data_object, flags, &bson, NULL);
+
+ if (bson_iter_init_find(&iter, &bson, "data")) {
+ bson_value_copy(bson_iter_value(&iter), value);
+ }
+
+ zval_ptr_dtor(data_object);
+ efree(data_object);
+} /* }}} */
diff --git a/mongodb-1.13.0/src/phongo_bson_encode.h b/mongodb-1.13.0/src/phongo_bson_encode.h
new file mode 100644
index 00000000..d8f7934d
--- /dev/null
+++ b/mongodb-1.13.0/src/phongo_bson_encode.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2022-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PHONGO_BSON_ENCODE_H
+#define PHONGO_BSON_ENCODE_H
+
+#include "bson/bson.h"
+
+#include <php.h>
+
+typedef enum {
+ PHONGO_BSON_NONE = 0x00,
+ PHONGO_BSON_ADD_ID = 0x01,
+ PHONGO_BSON_RETURN_ID = 0x02
+} php_phongo_bson_flags_t;
+
+void php_phongo_zval_to_bson(zval* data, php_phongo_bson_flags_t flags, bson_t* bson, bson_t** bson_out);
+void php_phongo_zval_to_bson_value(zval* data, php_phongo_bson_flags_t flags, bson_value_t* value);
+
+#endif /* PHONGO_BSON_ENCODE_H */
diff --git a/mongodb-1.13.0/src/phongo_classes.h b/mongodb-1.13.0/src/phongo_classes.h
new file mode 100644
index 00000000..b304a669
--- /dev/null
+++ b/mongodb-1.13.0/src/phongo_classes.h
@@ -0,0 +1,449 @@
+/*
+ * Copyright 2014-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PHONGO_CLASSES_H
+#define PHONGO_CLASSES_H
+
+#include "phongo_structs.h"
+
+/* Export zend_class_entry dependencies, which are initialized in MINIT */
+extern zend_class_entry* php_phongo_date_immutable_ce;
+extern zend_class_entry* php_phongo_json_serializable_ce;
+
+static inline php_phongo_bulkwrite_t* php_bulkwrite_fetch_object(zend_object* obj)
+{
+ return (php_phongo_bulkwrite_t*) ((char*) obj - XtOffsetOf(php_phongo_bulkwrite_t, std));
+}
+static inline php_phongo_clientencryption_t* php_clientencryption_fetch_object(zend_object* obj)
+{
+ return (php_phongo_clientencryption_t*) ((char*) obj - XtOffsetOf(php_phongo_clientencryption_t, std));
+}
+static inline php_phongo_command_t* php_command_fetch_object(zend_object* obj)
+{
+ return (php_phongo_command_t*) ((char*) obj - XtOffsetOf(php_phongo_command_t, std));
+}
+static inline php_phongo_cursor_t* php_cursor_fetch_object(zend_object* obj)
+{
+ return (php_phongo_cursor_t*) ((char*) obj - XtOffsetOf(php_phongo_cursor_t, std));
+}
+static inline php_phongo_cursorid_t* php_cursorid_fetch_object(zend_object* obj)
+{
+ return (php_phongo_cursorid_t*) ((char*) obj - XtOffsetOf(php_phongo_cursorid_t, std));
+}
+static inline php_phongo_manager_t* php_manager_fetch_object(zend_object* obj)
+{
+ return (php_phongo_manager_t*) ((char*) obj - XtOffsetOf(php_phongo_manager_t, std));
+}
+static inline php_phongo_query_t* php_query_fetch_object(zend_object* obj)
+{
+ return (php_phongo_query_t*) ((char*) obj - XtOffsetOf(php_phongo_query_t, std));
+}
+static inline php_phongo_readconcern_t* php_readconcern_fetch_object(zend_object* obj)
+{
+ return (php_phongo_readconcern_t*) ((char*) obj - XtOffsetOf(php_phongo_readconcern_t, std));
+}
+static inline php_phongo_readpreference_t* php_readpreference_fetch_object(zend_object* obj)
+{
+ return (php_phongo_readpreference_t*) ((char*) obj - XtOffsetOf(php_phongo_readpreference_t, std));
+}
+static inline php_phongo_server_t* php_server_fetch_object(zend_object* obj)
+{
+ return (php_phongo_server_t*) ((char*) obj - XtOffsetOf(php_phongo_server_t, std));
+}
+static inline php_phongo_serverdescription_t* php_serverdescription_fetch_object(zend_object* obj)
+{
+ return (php_phongo_serverdescription_t*) ((char*) obj - XtOffsetOf(php_phongo_serverdescription_t, std));
+}
+static inline php_phongo_topologydescription_t* php_topologydescription_fetch_object(zend_object* obj)
+{
+ return (php_phongo_topologydescription_t*) ((char*) obj - XtOffsetOf(php_phongo_topologydescription_t, std));
+}
+static inline php_phongo_serverapi_t* php_serverapi_fetch_object(zend_object* obj)
+{
+ return (php_phongo_serverapi_t*) ((char*) obj - XtOffsetOf(php_phongo_serverapi_t, std));
+}
+static inline php_phongo_session_t* php_session_fetch_object(zend_object* obj)
+{
+ return (php_phongo_session_t*) ((char*) obj - XtOffsetOf(php_phongo_session_t, std));
+}
+static inline php_phongo_writeconcern_t* php_writeconcern_fetch_object(zend_object* obj)
+{
+ return (php_phongo_writeconcern_t*) ((char*) obj - XtOffsetOf(php_phongo_writeconcern_t, std));
+}
+static inline php_phongo_writeconcernerror_t* php_writeconcernerror_fetch_object(zend_object* obj)
+{
+ return (php_phongo_writeconcernerror_t*) ((char*) obj - XtOffsetOf(php_phongo_writeconcernerror_t, std));
+}
+static inline php_phongo_writeerror_t* php_writeerror_fetch_object(zend_object* obj)
+{
+ return (php_phongo_writeerror_t*) ((char*) obj - XtOffsetOf(php_phongo_writeerror_t, std));
+}
+static inline php_phongo_writeresult_t* php_writeresult_fetch_object(zend_object* obj)
+{
+ return (php_phongo_writeresult_t*) ((char*) obj - XtOffsetOf(php_phongo_writeresult_t, std));
+}
+static inline php_phongo_binary_t* php_binary_fetch_object(zend_object* obj)
+{
+ return (php_phongo_binary_t*) ((char*) obj - XtOffsetOf(php_phongo_binary_t, std));
+}
+static inline php_phongo_dbpointer_t* php_dbpointer_fetch_object(zend_object* obj)
+{
+ return (php_phongo_dbpointer_t*) ((char*) obj - XtOffsetOf(php_phongo_dbpointer_t, std));
+}
+static inline php_phongo_decimal128_t* php_decimal128_fetch_object(zend_object* obj)
+{
+ return (php_phongo_decimal128_t*) ((char*) obj - XtOffsetOf(php_phongo_decimal128_t, std));
+}
+static inline php_phongo_int64_t* php_int64_fetch_object(zend_object* obj)
+{
+ return (php_phongo_int64_t*) ((char*) obj - XtOffsetOf(php_phongo_int64_t, std));
+}
+static inline php_phongo_javascript_t* php_javascript_fetch_object(zend_object* obj)
+{
+ return (php_phongo_javascript_t*) ((char*) obj - XtOffsetOf(php_phongo_javascript_t, std));
+}
+static inline php_phongo_maxkey_t* php_maxkey_fetch_object(zend_object* obj)
+{
+ return (php_phongo_maxkey_t*) ((char*) obj - XtOffsetOf(php_phongo_maxkey_t, std));
+}
+static inline php_phongo_minkey_t* php_minkey_fetch_object(zend_object* obj)
+{
+ return (php_phongo_minkey_t*) ((char*) obj - XtOffsetOf(php_phongo_minkey_t, std));
+}
+static inline php_phongo_objectid_t* php_objectid_fetch_object(zend_object* obj)
+{
+ return (php_phongo_objectid_t*) ((char*) obj - XtOffsetOf(php_phongo_objectid_t, std));
+}
+static inline php_phongo_regex_t* php_regex_fetch_object(zend_object* obj)
+{
+ return (php_phongo_regex_t*) ((char*) obj - XtOffsetOf(php_phongo_regex_t, std));
+}
+static inline php_phongo_symbol_t* php_symbol_fetch_object(zend_object* obj)
+{
+ return (php_phongo_symbol_t*) ((char*) obj - XtOffsetOf(php_phongo_symbol_t, std));
+}
+static inline php_phongo_timestamp_t* php_timestamp_fetch_object(zend_object* obj)
+{
+ return (php_phongo_timestamp_t*) ((char*) obj - XtOffsetOf(php_phongo_timestamp_t, std));
+}
+static inline php_phongo_undefined_t* php_undefined_fetch_object(zend_object* obj)
+{
+ return (php_phongo_undefined_t*) ((char*) obj - XtOffsetOf(php_phongo_undefined_t, std));
+}
+static inline php_phongo_utcdatetime_t* php_utcdatetime_fetch_object(zend_object* obj)
+{
+ return (php_phongo_utcdatetime_t*) ((char*) obj - XtOffsetOf(php_phongo_utcdatetime_t, std));
+}
+static inline php_phongo_commandfailedevent_t* php_commandfailedevent_fetch_object(zend_object* obj)
+{
+ return (php_phongo_commandfailedevent_t*) ((char*) obj - XtOffsetOf(php_phongo_commandfailedevent_t, std));
+}
+static inline php_phongo_commandstartedevent_t* php_commandstartedevent_fetch_object(zend_object* obj)
+{
+ return (php_phongo_commandstartedevent_t*) ((char*) obj - XtOffsetOf(php_phongo_commandstartedevent_t, std));
+}
+static inline php_phongo_commandsucceededevent_t* php_commandsucceededevent_fetch_object(zend_object* obj)
+{
+ return (php_phongo_commandsucceededevent_t*) ((char*) obj - XtOffsetOf(php_phongo_commandsucceededevent_t, std));
+}
+static inline php_phongo_serverchangedevent_t* php_serverchangedevent_fetch_object(zend_object* obj)
+{
+ return (php_phongo_serverchangedevent_t*) ((char*) obj - XtOffsetOf(php_phongo_serverchangedevent_t, std));
+}
+static inline php_phongo_serverclosedevent_t* php_serverclosedevent_fetch_object(zend_object* obj)
+{
+ return (php_phongo_serverclosedevent_t*) ((char*) obj - XtOffsetOf(php_phongo_serverclosedevent_t, std));
+}
+static inline php_phongo_serverheartbeatfailedevent_t* php_serverheartbeatfailedevent_fetch_object(zend_object* obj)
+{
+ return (php_phongo_serverheartbeatfailedevent_t*) ((char*) obj - XtOffsetOf(php_phongo_serverheartbeatfailedevent_t, std));
+}
+static inline php_phongo_serverheartbeatstartedevent_t* php_serverheartbeatstartedevent_fetch_object(zend_object* obj)
+{
+ return (php_phongo_serverheartbeatstartedevent_t*) ((char*) obj - XtOffsetOf(php_phongo_serverheartbeatstartedevent_t, std));
+}
+static inline php_phongo_serverheartbeatsucceededevent_t* php_serverheartbeatsucceededevent_fetch_object(zend_object* obj)
+{
+ return (php_phongo_serverheartbeatsucceededevent_t*) ((char*) obj - XtOffsetOf(php_phongo_serverheartbeatsucceededevent_t, std));
+}
+static inline php_phongo_serveropeningevent_t* php_serveropeningevent_fetch_object(zend_object* obj)
+{
+ return (php_phongo_serveropeningevent_t*) ((char*) obj - XtOffsetOf(php_phongo_serveropeningevent_t, std));
+}
+static inline php_phongo_topologychangedevent_t* php_topologychangedevent_fetch_object(zend_object* obj)
+{
+ return (php_phongo_topologychangedevent_t*) ((char*) obj - XtOffsetOf(php_phongo_topologychangedevent_t, std));
+}
+static inline php_phongo_topologyclosedevent_t* php_topologyclosedevent_fetch_object(zend_object* obj)
+{
+ return (php_phongo_topologyclosedevent_t*) ((char*) obj - XtOffsetOf(php_phongo_topologyclosedevent_t, std));
+}
+static inline php_phongo_topologyopeningevent_t* php_topologyopeningevent_fetch_object(zend_object* obj)
+{
+ return (php_phongo_topologyopeningevent_t*) ((char*) obj - XtOffsetOf(php_phongo_topologyopeningevent_t, std));
+}
+
+#define Z_CLIENTENCRYPTION_OBJ_P(zv) (php_clientencryption_fetch_object(Z_OBJ_P(zv)))
+#define Z_COMMAND_OBJ_P(zv) (php_command_fetch_object(Z_OBJ_P(zv)))
+#define Z_CURSOR_OBJ_P(zv) (php_cursor_fetch_object(Z_OBJ_P(zv)))
+#define Z_CURSORID_OBJ_P(zv) (php_cursorid_fetch_object(Z_OBJ_P(zv)))
+#define Z_MANAGER_OBJ_P(zv) (php_manager_fetch_object(Z_OBJ_P(zv)))
+#define Z_QUERY_OBJ_P(zv) (php_query_fetch_object(Z_OBJ_P(zv)))
+#define Z_READCONCERN_OBJ_P(zv) (php_readconcern_fetch_object(Z_OBJ_P(zv)))
+#define Z_READPREFERENCE_OBJ_P(zv) (php_readpreference_fetch_object(Z_OBJ_P(zv)))
+#define Z_SERVER_OBJ_P(zv) (php_server_fetch_object(Z_OBJ_P(zv)))
+#define Z_SERVERAPI_OBJ_P(zv) (php_serverapi_fetch_object(Z_OBJ_P(zv)))
+#define Z_SERVERDESCRIPTION_OBJ_P(zv) (php_serverdescription_fetch_object(Z_OBJ_P(zv)))
+#define Z_SESSION_OBJ_P(zv) (php_session_fetch_object(Z_OBJ_P(zv)))
+#define Z_TOPOLOGYDESCRIPTION_OBJ_P(zv) (php_topologydescription_fetch_object(Z_OBJ_P(zv)))
+#define Z_BULKWRITE_OBJ_P(zv) (php_bulkwrite_fetch_object(Z_OBJ_P(zv)))
+#define Z_WRITECONCERN_OBJ_P(zv) (php_writeconcern_fetch_object(Z_OBJ_P(zv)))
+#define Z_WRITECONCERNERROR_OBJ_P(zv) (php_writeconcernerror_fetch_object(Z_OBJ_P(zv)))
+#define Z_WRITEERROR_OBJ_P(zv) (php_writeerror_fetch_object(Z_OBJ_P(zv)))
+#define Z_WRITERESULT_OBJ_P(zv) (php_writeresult_fetch_object(Z_OBJ_P(zv)))
+#define Z_BINARY_OBJ_P(zv) (php_binary_fetch_object(Z_OBJ_P(zv)))
+#define Z_DBPOINTER_OBJ_P(zv) (php_dbpointer_fetch_object(Z_OBJ_P(zv)))
+#define Z_DECIMAL128_OBJ_P(zv) (php_decimal128_fetch_object(Z_OBJ_P(zv)))
+#define Z_INT64_OBJ_P(zv) (php_int64_fetch_object(Z_OBJ_P(zv)))
+#define Z_JAVASCRIPT_OBJ_P(zv) (php_javascript_fetch_object(Z_OBJ_P(zv)))
+#define Z_MAXKEY_OBJ_P(zv) (php_maxkey_fetch_object(Z_OBJ_P(zv)))
+#define Z_MINKEY_OBJ_P(zv) (php_minkey_fetch_object(Z_OBJ_P(zv)))
+#define Z_OBJECTID_OBJ_P(zv) (php_objectid_fetch_object(Z_OBJ_P(zv)))
+#define Z_REGEX_OBJ_P(zv) (php_regex_fetch_object(Z_OBJ_P(zv)))
+#define Z_SYMBOL_OBJ_P(zv) (php_symbol_fetch_object(Z_OBJ_P(zv)))
+#define Z_TIMESTAMP_OBJ_P(zv) (php_timestamp_fetch_object(Z_OBJ_P(zv)))
+#define Z_UNDEFINED_OBJ_P(zv) (php_undefined_fetch_object(Z_OBJ_P(zv)))
+#define Z_UTCDATETIME_OBJ_P(zv) (php_utcdatetime_fetch_object(Z_OBJ_P(zv)))
+#define Z_COMMANDFAILEDEVENT_OBJ_P(zv) (php_commandfailedevent_fetch_object(Z_OBJ_P(zv)))
+#define Z_COMMANDSTARTEDEVENT_OBJ_P(zv) (php_commandstartedevent_fetch_object(Z_OBJ_P(zv)))
+#define Z_COMMANDSUCCEEDEDEVENT_OBJ_P(zv) (php_commandsucceededevent_fetch_object(Z_OBJ_P(zv)))
+#define Z_SERVERCHANGEDEVENT_OBJ_P(zv) (php_serverchangedevent_fetch_object(Z_OBJ_P(zv)))
+#define Z_SERVERCLOSEDEVENT_OBJ_P(zv) (php_serverclosedevent_fetch_object(Z_OBJ_P(zv)))
+#define Z_SERVERHEARTBEATFAILEDEVENT_OBJ_P(zv) (php_serverheartbeatfailedevent_fetch_object(Z_OBJ_P(zv)))
+#define Z_SERVERHEARTBEATSTARTEDEVENT_OBJ_P(zv) (php_serverheartbeatstartedevent_fetch_object(Z_OBJ_P(zv)))
+#define Z_SERVERHEARTBEATSUCCEEDEDEVENT_OBJ_P(zv) (php_serverheartbeatsucceededevent_fetch_object(Z_OBJ_P(zv)))
+#define Z_SERVEROPENINGEVENT_OBJ_P(zv) (php_serveropeningevent_fetch_object(Z_OBJ_P(zv)))
+#define Z_TOPOLOGYCHANGEDEVENT_OBJ_P(zv) (php_topologychangedevent_fetch_object(Z_OBJ_P(zv)))
+#define Z_TOPOLOGYCLOSEDEVENT_OBJ_P(zv) (php_topologyclosedevent_fetch_object(Z_OBJ_P(zv)))
+#define Z_TOPOLOGYOPENINGEVENT_OBJ_P(zv) (php_topologyopeningevent_fetch_object(Z_OBJ_P(zv)))
+
+#define Z_OBJ_CLIENTENCRYPTION(zo) (php_clientencryption_fetch_object(zo))
+#define Z_OBJ_COMMAND(zo) (php_command_fetch_object(zo))
+#define Z_OBJ_CURSOR(zo) (php_cursor_fetch_object(zo))
+#define Z_OBJ_CURSORID(zo) (php_cursorid_fetch_object(zo))
+#define Z_OBJ_MANAGER(zo) (php_manager_fetch_object(zo))
+#define Z_OBJ_QUERY(zo) (php_query_fetch_object(zo))
+#define Z_OBJ_READCONCERN(zo) (php_readconcern_fetch_object(zo))
+#define Z_OBJ_READPREFERENCE(zo) (php_readpreference_fetch_object(zo))
+#define Z_OBJ_SERVER(zo) (php_server_fetch_object(zo))
+#define Z_OBJ_SERVERAPI(zo) (php_serverapi_fetch_object(zo))
+#define Z_OBJ_SERVERDESCRIPTION(zo) (php_serverdescription_fetch_object(zo))
+#define Z_OBJ_SESSION(zo) (php_session_fetch_object(zo))
+#define Z_OBJ_TOPOLOGYDESCRIPTION(zo) (php_topologydescription_fetch_object(zo))
+#define Z_OBJ_BULKWRITE(zo) (php_bulkwrite_fetch_object(zo))
+#define Z_OBJ_WRITECONCERN(zo) (php_writeconcern_fetch_object(zo))
+#define Z_OBJ_WRITECONCERNERROR(zo) (php_writeconcernerror_fetch_object(zo))
+#define Z_OBJ_WRITEERROR(zo) (php_writeerror_fetch_object(zo))
+#define Z_OBJ_WRITERESULT(zo) (php_writeresult_fetch_object(zo))
+#define Z_OBJ_BINARY(zo) (php_binary_fetch_object(zo))
+#define Z_OBJ_DBPOINTER(zo) (php_dbpointer_fetch_object(zo))
+#define Z_OBJ_DECIMAL128(zo) (php_decimal128_fetch_object(zo))
+#define Z_OBJ_INT64(zo) (php_int64_fetch_object(zo))
+#define Z_OBJ_JAVASCRIPT(zo) (php_javascript_fetch_object(zo))
+#define Z_OBJ_MAXKEY(zo) (php_maxkey_fetch_object(zo))
+#define Z_OBJ_MINKEY(zo) (php_minkey_fetch_object(zo))
+#define Z_OBJ_OBJECTID(zo) (php_objectid_fetch_object(zo))
+#define Z_OBJ_REGEX(zo) (php_regex_fetch_object(zo))
+#define Z_OBJ_SYMBOL(zo) (php_symbol_fetch_object(zo))
+#define Z_OBJ_TIMESTAMP(zo) (php_timestamp_fetch_object(zo))
+#define Z_OBJ_UNDEFINED(zo) (php_undefined_fetch_object(zo))
+#define Z_OBJ_UTCDATETIME(zo) (php_utcdatetime_fetch_object(zo))
+#define Z_OBJ_COMMANDFAILEDEVENT(zo) (php_commandfailedevent_fetch_object(zo))
+#define Z_OBJ_COMMANDSTARTEDEVENT(zo) (php_commandstartedevent_fetch_object(zo))
+#define Z_OBJ_COMMANDSUCCEEDEDEVENT(zo) (php_commandsucceededevent_fetch_object(zo))
+#define Z_OBJ_SERVERCHANGEDEVENT(zo) (php_serverchangedevent_fetch_object(zo))
+#define Z_OBJ_SERVERCLOSEDEVENT(zo) (php_serverclosedevent_fetch_object(zo))
+#define Z_OBJ_SERVERHEARTBEATFAILEDEVENT(zo) (php_serverheartbeatfailedevent_fetch_object(zo))
+#define Z_OBJ_SERVERHEARTBEATSTARTEDEVENT(zo) (php_serverheartbeatstartedevent_fetch_object(zo))
+#define Z_OBJ_SERVERHEARTBEATSUCCEEDEDEVENT(zo) (php_serverheartbeatsucceededevent_fetch_object(zo))
+#define Z_OBJ_SERVEROPENINGEVENT(zo) (php_serveropeningevent_fetch_object(zo))
+#define Z_OBJ_TOPOLOGYCHANGEDEVENT(zo) (php_topologychangedevent_fetch_object(zo))
+#define Z_OBJ_TOPOLOGYCLOSEDEVENT(zo) (php_topologyclosedevent_fetch_object(zo))
+#define Z_OBJ_TOPOLOGYOPENINGEVENT(zo) (php_topologyopeningevent_fetch_object(zo))
+
+extern zend_class_entry* php_phongo_clientencryption_ce;
+extern zend_class_entry* php_phongo_command_ce;
+extern zend_class_entry* php_phongo_cursor_ce;
+extern zend_class_entry* php_phongo_cursorid_ce;
+extern zend_class_entry* php_phongo_manager_ce;
+extern zend_class_entry* php_phongo_query_ce;
+extern zend_class_entry* php_phongo_readconcern_ce;
+extern zend_class_entry* php_phongo_readpreference_ce;
+extern zend_class_entry* php_phongo_server_ce;
+extern zend_class_entry* php_phongo_serverapi_ce;
+extern zend_class_entry* php_phongo_serverdescription_ce;
+extern zend_class_entry* php_phongo_session_ce;
+extern zend_class_entry* php_phongo_topologydescription_ce;
+extern zend_class_entry* php_phongo_bulkwrite_ce;
+extern zend_class_entry* php_phongo_writeconcern_ce;
+extern zend_class_entry* php_phongo_writeconcernerror_ce;
+extern zend_class_entry* php_phongo_writeerror_ce;
+extern zend_class_entry* php_phongo_writeresult_ce;
+
+extern zend_class_entry* php_phongo_cursor_interface_ce;
+
+extern zend_class_entry* php_phongo_exception_ce;
+extern zend_class_entry* php_phongo_logicexception_ce;
+extern zend_class_entry* php_phongo_runtimeexception_ce;
+extern zend_class_entry* php_phongo_serverexception_ce;
+extern zend_class_entry* php_phongo_commandexception_ce;
+extern zend_class_entry* php_phongo_unexpectedvalueexception_ce;
+extern zend_class_entry* php_phongo_invalidargumentexception_ce;
+extern zend_class_entry* php_phongo_connectionexception_ce;
+extern zend_class_entry* php_phongo_authenticationexception_ce;
+extern zend_class_entry* php_phongo_sslconnectionexception_ce;
+extern zend_class_entry* php_phongo_encryptionexception_ce;
+extern zend_class_entry* php_phongo_executiontimeoutexception_ce;
+extern zend_class_entry* php_phongo_connectiontimeoutexception_ce;
+extern zend_class_entry* php_phongo_writeexception_ce;
+extern zend_class_entry* php_phongo_bulkwriteexception_ce;
+
+extern zend_class_entry* php_phongo_type_ce;
+extern zend_class_entry* php_phongo_persistable_ce;
+extern zend_class_entry* php_phongo_unserializable_ce;
+extern zend_class_entry* php_phongo_serializable_ce;
+extern zend_class_entry* php_phongo_binary_ce;
+extern zend_class_entry* php_phongo_dbpointer_ce;
+extern zend_class_entry* php_phongo_decimal128_ce;
+extern zend_class_entry* php_phongo_int64_ce;
+extern zend_class_entry* php_phongo_javascript_ce;
+extern zend_class_entry* php_phongo_maxkey_ce;
+extern zend_class_entry* php_phongo_minkey_ce;
+extern zend_class_entry* php_phongo_objectid_ce;
+extern zend_class_entry* php_phongo_regex_ce;
+extern zend_class_entry* php_phongo_symbol_ce;
+extern zend_class_entry* php_phongo_timestamp_ce;
+extern zend_class_entry* php_phongo_undefined_ce;
+extern zend_class_entry* php_phongo_utcdatetime_ce;
+
+extern zend_class_entry* php_phongo_binary_interface_ce;
+extern zend_class_entry* php_phongo_decimal128_interface_ce;
+extern zend_class_entry* php_phongo_javascript_interface_ce;
+extern zend_class_entry* php_phongo_maxkey_interface_ce;
+extern zend_class_entry* php_phongo_minkey_interface_ce;
+extern zend_class_entry* php_phongo_objectid_interface_ce;
+extern zend_class_entry* php_phongo_regex_interface_ce;
+extern zend_class_entry* php_phongo_timestamp_interface_ce;
+extern zend_class_entry* php_phongo_utcdatetime_interface_ce;
+
+extern zend_class_entry* php_phongo_commandfailedevent_ce;
+extern zend_class_entry* php_phongo_commandstartedevent_ce;
+extern zend_class_entry* php_phongo_commandsubscriber_ce;
+extern zend_class_entry* php_phongo_commandsucceededevent_ce;
+extern zend_class_entry* php_phongo_sdamsubscriber_ce;
+extern zend_class_entry* php_phongo_subscriber_ce;
+extern zend_class_entry* php_phongo_serverchangedevent_ce;
+extern zend_class_entry* php_phongo_serverclosedevent_ce;
+extern zend_class_entry* php_phongo_serverheartbeatfailedevent_ce;
+extern zend_class_entry* php_phongo_serverheartbeatstartedevent_ce;
+extern zend_class_entry* php_phongo_serverheartbeatsucceededevent_ce;
+extern zend_class_entry* php_phongo_serveropeningevent_ce;
+extern zend_class_entry* php_phongo_topologychangedevent_ce;
+extern zend_class_entry* php_phongo_topologyclosedevent_ce;
+extern zend_class_entry* php_phongo_topologyopeningevent_ce;
+
+extern void php_phongo_binary_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_dbpointer_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_decimal128_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_int64_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_javascript_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_maxkey_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_minkey_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_objectid_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_persistable_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_regex_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_serializable_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_symbol_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_timestamp_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_type_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_undefined_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_unserializable_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_utcdatetime_init_ce(INIT_FUNC_ARGS);
+
+extern void php_phongo_binary_interface_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_decimal128_interface_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_javascript_interface_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_maxkey_interface_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_minkey_interface_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_objectid_interface_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_regex_interface_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_timestamp_interface_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_utcdatetime_interface_init_ce(INIT_FUNC_ARGS);
+
+extern void php_phongo_bulkwrite_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_clientencryption_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_command_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_cursor_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_cursorid_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_manager_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_query_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_readconcern_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_readpreference_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_server_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_serverapi_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_serverdescription_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_session_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_topologydescription_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_writeconcern_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_writeconcernerror_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_writeerror_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_writeresult_init_ce(INIT_FUNC_ARGS);
+
+extern void php_phongo_cursor_interface_init_ce(INIT_FUNC_ARGS);
+
+extern void php_phongo_authenticationexception_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_bulkwriteexception_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_commandexception_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_connectionexception_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_connectiontimeoutexception_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_encryptionexception_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_exception_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_executiontimeoutexception_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_invalidargumentexception_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_logicexception_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_runtimeexception_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_serverexception_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_sslconnectionexception_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_unexpectedvalueexception_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_writeexception_init_ce(INIT_FUNC_ARGS);
+
+extern void php_phongo_commandfailedevent_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_commandstartedevent_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_commandsubscriber_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_commandsucceededevent_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_sdamsubscriber_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_subscriber_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_serverchangedevent_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_serverclosedevent_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_serverheartbeatfailedevent_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_serverheartbeatstartedevent_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_serverheartbeatsucceededevent_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_serveropeningevent_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_topologychangedevent_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_topologyclosedevent_init_ce(INIT_FUNC_ARGS);
+extern void php_phongo_topologyopeningevent_init_ce(INIT_FUNC_ARGS);
+
+#endif /* PHONGO_CLASSES_H */
diff --git a/mongodb-1.13.0/src/phongo_client.c b/mongodb-1.13.0/src/phongo_client.c
new file mode 100644
index 00000000..58eb2126
--- /dev/null
+++ b/mongodb-1.13.0/src/phongo_client.c
@@ -0,0 +1,1688 @@
+/*
+ * Copyright 2022-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bson/bson.h"
+#include "mongoc/mongoc.h"
+
+#include <php.h>
+#include <ext/standard/php_var.h>
+#include <Zend/zend_smart_str.h>
+
+#include "php_array_api.h"
+
+#include "php_phongo.h"
+#include "phongo_apm.h"
+#include "phongo_bson_encode.h"
+#include "phongo_client.h"
+#include "phongo_error.h"
+#include "phongo_util.h"
+
+#include "MongoDB/ReadPreference.h"
+#include "MongoDB/WriteConcern.h"
+
+ZEND_EXTERN_MODULE_GLOBALS(mongodb)
+
+#define PHONGO_METADATA_SEPARATOR " / "
+#define PHONGO_METADATA_SEPARATOR_LEN (sizeof(PHONGO_METADATA_SEPARATOR) - 1)
+#define PHONGO_METADATA_PHP_VERSION_PREFIX "PHP "
+#define PHONGO_METADATA_PHP_VERSION_PREFIX_LEN (sizeof(PHONGO_METADATA_PHP_VERSION_PREFIX) - 1)
+
+/* Structure for tracking libmongoc clients (both persisted and non-persisted).
+ * The PID is included to ensure that processes do not destroy clients created
+ * by other processes (relevant for forking). We avoid using pid_t for Windows
+ * compatibility. */
+typedef struct {
+ mongoc_client_t* client;
+ int created_by_pid;
+ int last_reset_by_pid;
+ bool is_persistent;
+} php_phongo_pclient_t;
+
+static mongoc_uri_t* php_phongo_make_uri(const char* uri_string) /* {{{ */
+{
+ mongoc_uri_t* uri;
+ bson_error_t error = { 0 };
+
+ uri = mongoc_uri_new_with_error(uri_string, &error);
+ MONGOC_DEBUG("Connection string: '%s'", uri_string);
+
+ if (!uri) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Failed to parse MongoDB URI: '%s'. %s.", uri_string, error.message);
+ return NULL;
+ }
+
+ return uri;
+} /* }}} */
+
+static const char* php_phongo_bson_type_to_string(bson_type_t type) /* {{{ */
+{
+ switch (type) {
+ case BSON_TYPE_EOD:
+ return "EOD";
+ case BSON_TYPE_DOUBLE:
+ return "double";
+ case BSON_TYPE_UTF8:
+ return "string";
+ case BSON_TYPE_DOCUMENT:
+ return "document";
+ case BSON_TYPE_ARRAY:
+ return "array";
+ case BSON_TYPE_BINARY:
+ return "Binary";
+ case BSON_TYPE_UNDEFINED:
+ return "undefined";
+ case BSON_TYPE_OID:
+ return "ObjectId";
+ case BSON_TYPE_BOOL:
+ return "boolean";
+ case BSON_TYPE_DATE_TIME:
+ return "UTCDateTime";
+ case BSON_TYPE_NULL:
+ return "null";
+ case BSON_TYPE_REGEX:
+ return "Regex";
+ case BSON_TYPE_DBPOINTER:
+ return "DBPointer";
+ case BSON_TYPE_CODE:
+ return "Javascript";
+ case BSON_TYPE_SYMBOL:
+ return "symbol";
+ case BSON_TYPE_CODEWSCOPE:
+ return "Javascript with scope";
+ case BSON_TYPE_INT32:
+ return "32-bit integer";
+ case BSON_TYPE_TIMESTAMP:
+ return "Timestamp";
+ case BSON_TYPE_INT64:
+ return "64-bit integer";
+ case BSON_TYPE_DECIMAL128:
+ return "Decimal128";
+ case BSON_TYPE_MAXKEY:
+ return "MaxKey";
+ case BSON_TYPE_MINKEY:
+ return "MinKey";
+ default:
+ return "unknown";
+ }
+} /* }}} */
+
+#define PHONGO_URI_INVALID_TYPE(iter, expected) \
+ phongo_throw_exception( \
+ PHONGO_ERROR_INVALID_ARGUMENT, \
+ "Expected %s for \"%s\" URI option, %s given", \
+ (expected), \
+ bson_iter_key(&(iter)), \
+ php_phongo_bson_type_to_string(bson_iter_type(&(iter))))
+
+static bool php_phongo_apply_options_to_uri(mongoc_uri_t* uri, bson_t* options) /* {{{ */
+{
+ bson_iter_t iter;
+
+ /* Return early if there are no options to apply */
+ if (bson_empty0(options) || !bson_iter_init(&iter, options)) {
+ return true;
+ }
+
+ while (bson_iter_next(&iter)) {
+ const char* key = bson_iter_key(&iter);
+
+ /* Skip read preference, read concern, and write concern options, as
+ * those will be processed by other functions. */
+ if (!strcasecmp(key, MONGOC_URI_JOURNAL) ||
+ !strcasecmp(key, MONGOC_URI_MAXSTALENESSSECONDS) ||
+ !strcasecmp(key, MONGOC_URI_READCONCERNLEVEL) ||
+ !strcasecmp(key, MONGOC_URI_READPREFERENCE) ||
+ !strcasecmp(key, MONGOC_URI_READPREFERENCETAGS) ||
+ !strcasecmp(key, MONGOC_URI_SAFE) ||
+ !strcasecmp(key, MONGOC_URI_W) ||
+ !strcasecmp(key, MONGOC_URI_WTIMEOUTMS)) {
+
+ continue;
+ }
+
+ if (mongoc_uri_option_is_bool(key)) {
+ /* The option's type is not validated because bson_iter_as_bool() is
+ * used to cast the value to a boolean. Validation may be introduced
+ * in PHPC-990. */
+ if (!mongoc_uri_set_option_as_bool(uri, key, bson_iter_as_bool(&iter))) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Failed to parse \"%s\" URI option", key);
+ return false;
+ }
+
+ continue;
+ }
+
+ if (mongoc_uri_option_is_int32(key)) {
+ if (!BSON_ITER_HOLDS_INT32(&iter)) {
+ PHONGO_URI_INVALID_TYPE(iter, "32-bit integer");
+ return false;
+ }
+
+ if (!mongoc_uri_set_option_as_int32(uri, key, bson_iter_int32(&iter))) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Failed to parse \"%s\" URI option", key);
+ return false;
+ }
+
+ continue;
+ }
+
+ if (mongoc_uri_option_is_utf8(key)) {
+ if (!BSON_ITER_HOLDS_UTF8(&iter)) {
+ PHONGO_URI_INVALID_TYPE(iter, "string");
+ return false;
+ }
+
+ if (!strcasecmp(key, MONGOC_URI_REPLICASET) && !strcmp("", bson_iter_utf8(&iter, NULL))) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Value for URI option \"%s\" cannot be empty string.", key);
+ return false;
+ }
+
+ if (!mongoc_uri_set_option_as_utf8(uri, key, bson_iter_utf8(&iter, NULL))) {
+ /* Assignment uses mongoc_uri_set_appname() for the "appname"
+ * option, which validates length in addition to UTF-8 encoding.
+ * For BC, we report the invalid string to the user. */
+ if (!strcasecmp(key, MONGOC_URI_APPNAME)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Invalid appname value: '%s'", bson_iter_utf8(&iter, NULL));
+ } else {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Failed to parse \"%s\" URI option", key);
+ }
+ return false;
+ }
+
+ continue;
+ }
+
+ if (!strcasecmp(key, "username")) {
+ if (!BSON_ITER_HOLDS_UTF8(&iter)) {
+ PHONGO_URI_INVALID_TYPE(iter, "string");
+ return false;
+ }
+
+ if (!mongoc_uri_set_username(uri, bson_iter_utf8(&iter, NULL))) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Failed to parse \"%s\" URI option", key);
+ return false;
+ }
+
+ continue;
+ }
+
+ if (!strcasecmp(key, "password")) {
+ if (!BSON_ITER_HOLDS_UTF8(&iter)) {
+ PHONGO_URI_INVALID_TYPE(iter, "string");
+ return false;
+ }
+
+ if (!mongoc_uri_set_password(uri, bson_iter_utf8(&iter, NULL))) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Failed to parse \"%s\" URI option", key);
+ return false;
+ }
+
+ continue;
+ }
+
+ if (!strcasecmp(key, MONGOC_URI_AUTHMECHANISM)) {
+ if (!BSON_ITER_HOLDS_UTF8(&iter)) {
+ PHONGO_URI_INVALID_TYPE(iter, "string");
+ return false;
+ }
+
+ if (!mongoc_uri_set_auth_mechanism(uri, bson_iter_utf8(&iter, NULL))) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Failed to parse \"%s\" URI option", key);
+ return false;
+ }
+
+ continue;
+ }
+
+ if (!strcasecmp(key, MONGOC_URI_AUTHSOURCE)) {
+ if (!BSON_ITER_HOLDS_UTF8(&iter)) {
+ PHONGO_URI_INVALID_TYPE(iter, "string");
+ return false;
+ }
+
+ if (!mongoc_uri_set_auth_source(uri, bson_iter_utf8(&iter, NULL))) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Failed to parse \"%s\" URI option", key);
+ return false;
+ }
+
+ continue;
+ }
+
+ if (!strcasecmp(key, MONGOC_URI_AUTHMECHANISMPROPERTIES)) {
+ bson_t properties;
+ uint32_t len;
+ const uint8_t* data;
+
+ if (!BSON_ITER_HOLDS_DOCUMENT(&iter)) {
+ PHONGO_URI_INVALID_TYPE(iter, "array or object");
+ return false;
+ }
+
+ bson_iter_document(&iter, &len, &data);
+
+ if (!bson_init_static(&properties, data, len)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Could not initialize BSON structure for auth mechanism properties");
+ return false;
+ }
+
+ if (!mongoc_uri_set_mechanism_properties(uri, &properties)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Failed to parse \"%s\" URI option", key);
+ return false;
+ }
+
+ continue;
+ }
+
+ if (!strcasecmp(key, MONGOC_URI_GSSAPISERVICENAME)) {
+ bson_t unused, properties = BSON_INITIALIZER;
+
+ if (mongoc_uri_get_mechanism_properties(uri, &unused)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "authMechanismProperties SERVICE_NAME already set, ignoring \"%s\"", key);
+ return false;
+ }
+
+ if (!BSON_ITER_HOLDS_UTF8(&iter)) {
+ PHONGO_URI_INVALID_TYPE(iter, "string");
+ return false;
+ }
+
+ bson_append_utf8(&properties, "SERVICE_NAME", -1, bson_iter_utf8(&iter, NULL), -1);
+
+ if (!mongoc_uri_set_mechanism_properties(uri, &properties)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Failed to parse \"%s\" URI option", key);
+ bson_destroy(&properties);
+ return false;
+ }
+
+ bson_destroy(&properties);
+
+ continue;
+ }
+
+ if (!strcasecmp(key, MONGOC_URI_COMPRESSORS)) {
+ if (!BSON_ITER_HOLDS_UTF8(&iter)) {
+ PHONGO_URI_INVALID_TYPE(iter, "string");
+ return false;
+ }
+
+ if (!mongoc_uri_set_compressors(uri, bson_iter_utf8(&iter, NULL))) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Failed to parse \"%s\" URI option", key);
+ return false;
+ }
+
+ continue;
+ }
+ }
+
+ return true;
+} /* }}} */
+
+static bool php_phongo_apply_rc_options_to_uri(mongoc_uri_t* uri, bson_t* options) /* {{{ */
+{
+ bson_iter_t iter;
+ mongoc_read_concern_t* new_rc;
+ const mongoc_read_concern_t* old_rc;
+
+ if (!(old_rc = mongoc_uri_get_read_concern(uri))) {
+ phongo_throw_exception(PHONGO_ERROR_MONGOC_FAILED, "mongoc_uri_t does not have a read concern");
+
+ return false;
+ }
+
+ /* Return early if there are no options to apply */
+ if (bson_empty0(options) || !bson_iter_init(&iter, options)) {
+ return true;
+ }
+
+ new_rc = mongoc_read_concern_copy(old_rc);
+
+ while (bson_iter_next(&iter)) {
+ const char* key = bson_iter_key(&iter);
+
+ if (!strcasecmp(key, MONGOC_URI_READCONCERNLEVEL)) {
+ if (!BSON_ITER_HOLDS_UTF8(&iter)) {
+ PHONGO_URI_INVALID_TYPE(iter, "string");
+ mongoc_read_concern_destroy(new_rc);
+
+ return false;
+ }
+
+ mongoc_read_concern_set_level(new_rc, bson_iter_utf8(&iter, NULL));
+ }
+ }
+
+ mongoc_uri_set_read_concern(uri, new_rc);
+ mongoc_read_concern_destroy(new_rc);
+
+ return true;
+} /* }}} */
+
+static bool php_phongo_apply_rp_options_to_uri(mongoc_uri_t* uri, bson_t* options) /* {{{ */
+{
+ bson_iter_t iter;
+ mongoc_read_prefs_t* new_rp;
+ const mongoc_read_prefs_t* old_rp;
+
+ if (!(old_rp = mongoc_uri_get_read_prefs_t(uri))) {
+ phongo_throw_exception(PHONGO_ERROR_MONGOC_FAILED, "mongoc_uri_t does not have a read preference");
+
+ return false;
+ }
+
+ /* Return early if there are no options to apply */
+ if (bson_empty0(options) || !bson_iter_init(&iter, options)) {
+ return true;
+ }
+
+ new_rp = mongoc_read_prefs_copy(old_rp);
+
+ while (bson_iter_next(&iter)) {
+ const char* key = bson_iter_key(&iter);
+
+ if (!strcasecmp(key, MONGOC_URI_READPREFERENCE)) {
+ const char* str;
+
+ if (!BSON_ITER_HOLDS_UTF8(&iter)) {
+ PHONGO_URI_INVALID_TYPE(iter, "string");
+ mongoc_read_prefs_destroy(new_rp);
+
+ return false;
+ }
+
+ str = bson_iter_utf8(&iter, NULL);
+
+ if (0 == strcasecmp("primary", str)) {
+ mongoc_read_prefs_set_mode(new_rp, MONGOC_READ_PRIMARY);
+ } else if (0 == strcasecmp("primarypreferred", str)) {
+ mongoc_read_prefs_set_mode(new_rp, MONGOC_READ_PRIMARY_PREFERRED);
+ } else if (0 == strcasecmp("secondary", str)) {
+ mongoc_read_prefs_set_mode(new_rp, MONGOC_READ_SECONDARY);
+ } else if (0 == strcasecmp("secondarypreferred", str)) {
+ mongoc_read_prefs_set_mode(new_rp, MONGOC_READ_SECONDARY_PREFERRED);
+ } else if (0 == strcasecmp("nearest", str)) {
+ mongoc_read_prefs_set_mode(new_rp, MONGOC_READ_NEAREST);
+ } else {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Unsupported %s value: '%s'", bson_iter_key(&iter), str);
+ mongoc_read_prefs_destroy(new_rp);
+
+ return false;
+ }
+ }
+
+ if (!strcasecmp(key, MONGOC_URI_READPREFERENCETAGS)) {
+ bson_t tags;
+ uint32_t len;
+ const uint8_t* data;
+
+ if (!BSON_ITER_HOLDS_ARRAY(&iter)) {
+ PHONGO_URI_INVALID_TYPE(iter, "array");
+ mongoc_read_prefs_destroy(new_rp);
+
+ return false;
+ }
+
+ bson_iter_array(&iter, &len, &data);
+
+ if (!bson_init_static(&tags, data, len)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Could not initialize BSON structure for read preference tags");
+ mongoc_read_prefs_destroy(new_rp);
+
+ return false;
+ }
+
+ if (!php_phongo_read_preference_tags_are_valid(&tags)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Read preference tags must be an array of zero or more documents");
+ mongoc_read_prefs_destroy(new_rp);
+
+ return false;
+ }
+
+ mongoc_read_prefs_set_tags(new_rp, &tags);
+ }
+
+ if (!strcasecmp(key, MONGOC_URI_MAXSTALENESSSECONDS)) {
+ int64_t max_staleness_seconds;
+
+ if (!BSON_ITER_HOLDS_INT(&iter)) {
+ PHONGO_URI_INVALID_TYPE(iter, "integer");
+ mongoc_read_prefs_destroy(new_rp);
+
+ return false;
+ }
+
+ max_staleness_seconds = bson_iter_as_int64(&iter);
+
+ if (max_staleness_seconds != MONGOC_NO_MAX_STALENESS) {
+
+ if (max_staleness_seconds < MONGOC_SMALLEST_MAX_STALENESS_SECONDS) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected maxStalenessSeconds to be >= %d, %" PRId64 " given", MONGOC_SMALLEST_MAX_STALENESS_SECONDS, max_staleness_seconds);
+ mongoc_read_prefs_destroy(new_rp);
+
+ return false;
+ }
+
+ if (max_staleness_seconds > INT32_MAX) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected maxStalenessSeconds to be <= %d, %" PRId64 " given", INT32_MAX, max_staleness_seconds);
+ mongoc_read_prefs_destroy(new_rp);
+
+ return false;
+ }
+
+ if (mongoc_read_prefs_get_mode(new_rp) == MONGOC_READ_PRIMARY) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Primary read preference mode conflicts with maxStalenessSeconds");
+ mongoc_read_prefs_destroy(new_rp);
+
+ return false;
+ }
+ }
+
+ mongoc_read_prefs_set_max_staleness_seconds(new_rp, max_staleness_seconds);
+ }
+ }
+
+ if (mongoc_read_prefs_get_mode(new_rp) == MONGOC_READ_PRIMARY &&
+ !bson_empty(mongoc_read_prefs_get_tags(new_rp))) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Primary read preference mode conflicts with tags");
+ mongoc_read_prefs_destroy(new_rp);
+
+ return false;
+ }
+
+ /* Make sure maxStalenessSeconds is not combined with primary readPreference */
+ if (mongoc_read_prefs_get_mode(new_rp) == MONGOC_READ_PRIMARY &&
+ mongoc_read_prefs_get_max_staleness_seconds(new_rp) != MONGOC_NO_MAX_STALENESS) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Primary read preference mode conflicts with maxStalenessSeconds");
+ mongoc_read_prefs_destroy(new_rp);
+
+ return false;
+ }
+
+ /* This may be redundant in light of the previous checks (primary with tags
+ * or maxStalenessSeconds), but we'll check anyway in case additional
+ * validation is implemented. */
+ if (!mongoc_read_prefs_is_valid(new_rp)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Read preference is not valid");
+ mongoc_read_prefs_destroy(new_rp);
+
+ return false;
+ }
+
+ mongoc_uri_set_read_prefs_t(uri, new_rp);
+ mongoc_read_prefs_destroy(new_rp);
+
+ return true;
+} /* }}} */
+
+static bool php_phongo_apply_wc_options_to_uri(mongoc_uri_t* uri, bson_t* options) /* {{{ */
+{
+ bson_iter_t iter;
+ mongoc_write_concern_t* new_wc;
+ const mongoc_write_concern_t* old_wc;
+ bool ignore_safe = false;
+
+ if (!(old_wc = mongoc_uri_get_write_concern(uri))) {
+ phongo_throw_exception(PHONGO_ERROR_MONGOC_FAILED, "mongoc_uri_t does not have a write concern");
+
+ return false;
+ }
+
+ /* Return early if there are no options to apply */
+ if (bson_empty0(options) || !bson_iter_init(&iter, options)) {
+ return true;
+ }
+
+ new_wc = mongoc_write_concern_copy(old_wc);
+
+ while (bson_iter_next(&iter)) {
+ const char* key = bson_iter_key(&iter);
+
+ if (!ignore_safe && !strcasecmp(key, MONGOC_URI_SAFE)) {
+ if (!BSON_ITER_HOLDS_BOOL(&iter)) {
+ PHONGO_URI_INVALID_TYPE(iter, "boolean");
+ mongoc_write_concern_destroy(new_wc);
+
+ return false;
+ }
+
+ mongoc_write_concern_set_w(new_wc, bson_iter_bool(&iter) ? 1 : MONGOC_WRITE_CONCERN_W_UNACKNOWLEDGED);
+ }
+
+ if (!strcasecmp(key, MONGOC_URI_WTIMEOUTMS)) {
+ int64_t wtimeout;
+
+ if (!BSON_ITER_HOLDS_INT(&iter)) {
+ PHONGO_URI_INVALID_TYPE(iter, "integer");
+ mongoc_write_concern_destroy(new_wc);
+
+ return false;
+ }
+
+ wtimeout = bson_iter_as_int64(&iter);
+
+ if (wtimeout < 0) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected wtimeoutMS to be >= 0, %" PRId64 " given", wtimeout);
+ mongoc_write_concern_destroy(new_wc);
+
+ return false;
+ }
+
+ mongoc_write_concern_set_wtimeout_int64(new_wc, wtimeout);
+ }
+
+ if (!strcasecmp(key, MONGOC_URI_JOURNAL)) {
+ if (!BSON_ITER_HOLDS_BOOL(&iter)) {
+ PHONGO_URI_INVALID_TYPE(iter, "boolean");
+ mongoc_write_concern_destroy(new_wc);
+
+ return false;
+ }
+
+ mongoc_write_concern_set_journal(new_wc, bson_iter_bool(&iter));
+ }
+
+ if (!strcasecmp(key, MONGOC_URI_W)) {
+ if (BSON_ITER_HOLDS_INT32(&iter)) {
+ int32_t value = bson_iter_int32(&iter);
+
+ switch (value) {
+ case MONGOC_WRITE_CONCERN_W_ERRORS_IGNORED:
+ case MONGOC_WRITE_CONCERN_W_UNACKNOWLEDGED:
+ mongoc_write_concern_set_w(new_wc, value);
+ break;
+
+ default:
+ if (value > 0) {
+ mongoc_write_concern_set_w(new_wc, value);
+ break;
+ }
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Unsupported w value: %d", value);
+ mongoc_write_concern_destroy(new_wc);
+
+ return false;
+ }
+ } else if (BSON_ITER_HOLDS_UTF8(&iter)) {
+ const char* str = bson_iter_utf8(&iter, NULL);
+
+ if (0 == strcasecmp(PHONGO_WRITE_CONCERN_W_MAJORITY, str)) {
+ mongoc_write_concern_set_w(new_wc, MONGOC_WRITE_CONCERN_W_MAJORITY);
+ } else {
+ mongoc_write_concern_set_wtag(new_wc, str);
+ }
+ } else {
+ PHONGO_URI_INVALID_TYPE(iter, "32-bit integer or string");
+ mongoc_write_concern_destroy(new_wc);
+
+ return false;
+ }
+
+ ignore_safe = true;
+ }
+ }
+
+ if (mongoc_write_concern_get_journal(new_wc)) {
+ int32_t w = mongoc_write_concern_get_w(new_wc);
+
+ if (w == MONGOC_WRITE_CONCERN_W_UNACKNOWLEDGED || w == MONGOC_WRITE_CONCERN_W_ERRORS_IGNORED) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Journal conflicts with w value: %d", w);
+ mongoc_write_concern_destroy(new_wc);
+
+ return false;
+ }
+ }
+
+ /* This may be redundant in light of the last check (unacknowledged w with
+ journal), but we'll check anyway in case additional validation is
+ implemented. */
+ if (!mongoc_write_concern_is_valid(new_wc)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Write concern is not valid");
+ mongoc_write_concern_destroy(new_wc);
+
+ return false;
+ }
+
+ mongoc_uri_set_write_concern(uri, new_wc);
+ mongoc_write_concern_destroy(new_wc);
+
+ return true;
+} /* }}} */
+
+#ifdef MONGOC_ENABLE_SSL
+static void php_phongo_mongoc_ssl_opts_from_uri(mongoc_ssl_opt_t* ssl_opt, mongoc_uri_t* uri, bool* any_ssl_option_set)
+{
+ bool insecure = mongoc_uri_get_option_as_bool(uri, MONGOC_URI_TLSINSECURE, false);
+ const char* pem_file = mongoc_uri_get_option_as_utf8(uri, MONGOC_URI_TLSCERTIFICATEKEYFILE, NULL);
+ const char* pem_pwd = mongoc_uri_get_option_as_utf8(uri, MONGOC_URI_TLSCERTIFICATEKEYFILEPASSWORD, NULL);
+ const char* ca_file = mongoc_uri_get_option_as_utf8(uri, MONGOC_URI_TLSCAFILE, NULL);
+
+ ssl_opt->pem_file = pem_file ? estrdup(pem_file) : NULL;
+ ssl_opt->pem_pwd = pem_pwd ? estrdup(pem_pwd) : NULL;
+ ssl_opt->ca_file = ca_file ? estrdup(ca_file) : NULL;
+ ssl_opt->weak_cert_validation = mongoc_uri_get_option_as_bool(uri, MONGOC_URI_TLSALLOWINVALIDCERTIFICATES, insecure);
+ ssl_opt->allow_invalid_hostname = mongoc_uri_get_option_as_bool(uri, MONGOC_URI_TLSALLOWINVALIDHOSTNAMES, insecure);
+
+ /* Boolean options default to false, so we cannot consider them for
+ * any_ssl_option_set. This isn't actually a problem as libmongoc will
+ * already have assigned them when creating the client, enabling SSL, and
+ * assigning SSL options. Therefore, we only need to check for non-defaults
+ * (i.e. non-NULL strings, true booleans). */
+ if (pem_file || pem_pwd || ca_file || ssl_opt->weak_cert_validation || ssl_opt->allow_invalid_hostname) {
+ *any_ssl_option_set = true;
+ }
+}
+
+static inline char* php_phongo_fetch_ssl_opt_string(zval* zoptions, const char* key)
+{
+ int plen;
+ zend_bool pfree;
+ char* pval;
+ char* value;
+
+ pval = php_array_fetch_string(zoptions, key, &plen, &pfree);
+ value = pfree ? pval : estrndup(pval, plen);
+
+ return value;
+}
+
+static mongoc_ssl_opt_t* php_phongo_make_ssl_opt(mongoc_uri_t* uri, zval* zoptions)
+{
+ mongoc_ssl_opt_t* ssl_opt;
+ bool any_ssl_option_set = false;
+
+ if (!zoptions) {
+ return NULL;
+ }
+
+#if defined(MONGOC_ENABLE_SSL_SECURE_CHANNEL) || defined(MONGOC_ENABLE_SSL_SECURE_TRANSPORT)
+ if (php_array_existsc(zoptions, "ca_dir")) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "\"ca_dir\" option is not supported by Secure Channel and Secure Transport");
+ return NULL;
+ }
+
+ if (php_array_existsc(zoptions, "capath")) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "\"capath\" option is not supported by Secure Channel and Secure Transport");
+ return NULL;
+ }
+#endif
+
+#if defined(MONGOC_ENABLE_SSL_LIBRESSL) || defined(MONGOC_ENABLE_SSL_SECURE_TRANSPORT)
+ if (php_array_existsc(zoptions, "crl_file")) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "\"crl_file\" option is not supported by LibreSSL and Secure Transport");
+ return NULL;
+ }
+#endif
+
+ ssl_opt = ecalloc(1, sizeof(mongoc_ssl_opt_t));
+
+ /* If SSL options are set in the URL, we need to read them and set them on
+ * the options struct so we can merge potential options from passed in
+ * driverOptions (zoptions) */
+ if (mongoc_uri_get_tls(uri)) {
+ php_phongo_mongoc_ssl_opts_from_uri(ssl_opt, uri, &any_ssl_option_set);
+ }
+
+#define PHONGO_SSL_OPTION_SWAP_STRING(o, n) \
+ if ((o)) { \
+ efree((char*) (o)); \
+ } \
+ (o) = php_phongo_fetch_ssl_opt_string(zoptions, n);
+
+ /* Apply driver options that don't have a corresponding URI option. These
+ * are set directly on the SSL options struct. */
+ if (php_array_existsc(zoptions, "ca_dir")) {
+ PHONGO_SSL_OPTION_SWAP_STRING(ssl_opt->ca_dir, "ca_dir");
+ any_ssl_option_set = true;
+ } else if (php_array_existsc(zoptions, "capath")) {
+ PHONGO_SSL_OPTION_SWAP_STRING(ssl_opt->ca_dir, "capath");
+ any_ssl_option_set = true;
+
+ php_error_docref(NULL, E_DEPRECATED, "The \"capath\" context driver option is deprecated. Please use the \"ca_dir\" driver option instead.");
+ }
+
+ if (php_array_existsc(zoptions, "crl_file")) {
+ PHONGO_SSL_OPTION_SWAP_STRING(ssl_opt->crl_file, "crl_file");
+ any_ssl_option_set = true;
+ }
+
+#undef PHONGO_SSL_OPTION_SWAP_STRING
+
+ if (!any_ssl_option_set) {
+ efree(ssl_opt);
+ return NULL;
+ }
+
+ return ssl_opt;
+}
+
+static void php_phongo_free_ssl_opt(mongoc_ssl_opt_t* ssl_opt)
+{
+ if (ssl_opt->pem_file) {
+ efree((char*) ssl_opt->pem_file);
+ }
+
+ if (ssl_opt->pem_pwd) {
+ efree((char*) ssl_opt->pem_pwd);
+ }
+
+ if (ssl_opt->ca_file) {
+ efree((char*) ssl_opt->ca_file);
+ }
+
+ if (ssl_opt->ca_dir) {
+ efree((char*) ssl_opt->ca_dir);
+ }
+
+ if (ssl_opt->crl_file) {
+ efree((char*) ssl_opt->crl_file);
+ }
+
+ efree(ssl_opt);
+}
+
+static inline bool php_phongo_apply_driver_option_to_uri(mongoc_uri_t* uri, zval* zoptions, const char* driverOptionKey, const char* optionKey)
+{
+ bool ret;
+ char* value;
+
+ value = php_phongo_fetch_ssl_opt_string(zoptions, driverOptionKey);
+ ret = mongoc_uri_set_option_as_utf8(uri, optionKey, value);
+ efree(value);
+
+ return ret;
+}
+
+static bool php_phongo_apply_driver_options_to_uri(mongoc_uri_t* uri, zval* zoptions)
+{
+ if (!zoptions) {
+ return true;
+ }
+
+ /* Map TLS driver options to the canonical tls options in the URI. */
+ if (php_array_existsc(zoptions, "allow_invalid_hostname")) {
+ if (!mongoc_uri_set_option_as_bool(uri, MONGOC_URI_TLSALLOWINVALIDHOSTNAMES, php_array_fetchc_bool(zoptions, "allow_invalid_hostname"))) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Failed to parse \"%s\" driver option", "allow_invalid_hostname");
+
+ return false;
+ }
+
+ php_error_docref(NULL, E_DEPRECATED, "The \"allow_invalid_hostname\" driver option is deprecated. Please use the \"tlsAllowInvalidHostnames\" URI option instead.");
+ }
+
+ if (php_array_existsc(zoptions, "weak_cert_validation")) {
+ if (!mongoc_uri_set_option_as_bool(uri, MONGOC_URI_TLSALLOWINVALIDCERTIFICATES, php_array_fetchc_bool(zoptions, "weak_cert_validation"))) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Failed to parse \"%s\" driver option", "weak_cert_validation");
+
+ return false;
+ }
+
+ php_error_docref(NULL, E_DEPRECATED, "The \"weak_cert_validation\" driver option is deprecated. Please use the \"tlsAllowInvalidCertificates\" URI option instead.");
+ } else if (php_array_existsc(zoptions, "allow_self_signed")) {
+ if (!mongoc_uri_set_option_as_bool(uri, MONGOC_URI_TLSALLOWINVALIDCERTIFICATES, php_array_fetchc_bool(zoptions, "allow_self_signed"))) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Failed to parse \"%s\" driver option", "allow_self_signed");
+
+ return false;
+ }
+
+ php_error_docref(NULL, E_DEPRECATED, "The \"allow_self_signed\" context driver option is deprecated. Please use the \"tlsAllowInvalidCertificates\" URI option instead.");
+ }
+
+ if (php_array_existsc(zoptions, "pem_file")) {
+ if (!php_phongo_apply_driver_option_to_uri(uri, zoptions, "pem_file", MONGOC_URI_TLSCERTIFICATEKEYFILE)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Failed to parse \"%s\" driver option", "pem_file");
+
+ return false;
+ }
+
+ php_error_docref(NULL, E_DEPRECATED, "The \"pem_file\" driver option is deprecated. Please use the \"tlsCertificateKeyFile\" URI option instead.");
+ } else if (php_array_existsc(zoptions, "local_cert")) {
+ if (!php_phongo_apply_driver_option_to_uri(uri, zoptions, "local_cert", MONGOC_URI_TLSCERTIFICATEKEYFILE)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Failed to parse \"%s\" driver option", "local_cert");
+
+ return false;
+ }
+
+ php_error_docref(NULL, E_DEPRECATED, "The \"local_cert\" context driver option is deprecated. Please use the \"tlsCertificateKeyFile\" URI option instead.");
+ }
+
+ if (php_array_existsc(zoptions, "pem_pwd")) {
+ if (!php_phongo_apply_driver_option_to_uri(uri, zoptions, "pem_pwd", MONGOC_URI_TLSCERTIFICATEKEYFILEPASSWORD)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Failed to parse \"%s\" driver option", "pem_pwd");
+
+ return false;
+ }
+
+ php_error_docref(NULL, E_DEPRECATED, "The \"pem_pwd\" driver option is deprecated. Please use the \"tlsCertificateKeyFilePassword\" URI option instead.");
+ } else if (php_array_existsc(zoptions, "passphrase")) {
+ if (!php_phongo_apply_driver_option_to_uri(uri, zoptions, "passphrase", MONGOC_URI_TLSCERTIFICATEKEYFILEPASSWORD)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Failed to parse \"%s\" driver option", "passphrase");
+
+ return false;
+ }
+
+ php_error_docref(NULL, E_DEPRECATED, "The \"passphrase\" context driver option is deprecated. Please use the \"tlsCertificateKeyFilePassword\" URI option instead.");
+ }
+
+ if (php_array_existsc(zoptions, "ca_file")) {
+ if (!php_phongo_apply_driver_option_to_uri(uri, zoptions, "ca_file", MONGOC_URI_TLSCAFILE)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Failed to parse \"%s\" driver option", "ca_file");
+
+ return false;
+ }
+
+ php_error_docref(NULL, E_DEPRECATED, "The \"ca_file\" driver option is deprecated. Please use the \"tlsCAFile\" URI option instead.");
+ } else if (php_array_existsc(zoptions, "cafile")) {
+ if (!php_phongo_apply_driver_option_to_uri(uri, zoptions, "cafile", MONGOC_URI_TLSCAFILE)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Failed to parse \"%s\" driver option", "cafile");
+
+ return false;
+ }
+
+ php_error_docref(NULL, E_DEPRECATED, "The \"cafile\" context driver option is deprecated. Please use the \"tlsCAFile\" URI option instead.");
+ }
+
+ return true;
+}
+#endif /* MONGOC_ENABLE_SSL */
+
+static zval* php_phongo_manager_prepare_manager_for_hash(zval* driverOptions, bool* free)
+{
+ php_phongo_manager_t* manager;
+ zval* autoEncryptionOpts = NULL;
+ zval* keyVaultClient = NULL;
+ zval* driverOptionsClone = NULL;
+ zval* autoEncryptionOptsClone = NULL;
+ zval stackAutoEncryptionOptsClone;
+
+ *free = false;
+
+ if (!driverOptions) {
+ return NULL;
+ }
+
+ if (!php_array_existsc(driverOptions, "autoEncryption")) {
+ goto ref;
+ }
+
+ autoEncryptionOpts = php_array_fetchc(driverOptions, "autoEncryption");
+ if (Z_TYPE_P(autoEncryptionOpts) != IS_ARRAY) {
+ goto ref;
+ }
+
+ if (!php_array_existsc(autoEncryptionOpts, "keyVaultClient")) {
+ goto ref;
+ }
+
+ keyVaultClient = php_array_fetchc(autoEncryptionOpts, "keyVaultClient");
+ if (Z_TYPE_P(keyVaultClient) != IS_OBJECT || !instanceof_function(Z_OBJCE_P(keyVaultClient), php_phongo_manager_ce)) {
+ goto ref;
+ }
+
+ *free = true;
+
+ manager = Z_MANAGER_OBJ_P(keyVaultClient);
+
+ driverOptionsClone = ecalloc(1, sizeof(zval));
+ autoEncryptionOptsClone = &stackAutoEncryptionOptsClone;
+
+ ZVAL_DUP(autoEncryptionOptsClone, autoEncryptionOpts);
+ ADD_ASSOC_STRINGL(autoEncryptionOptsClone, "keyVaultClient", manager->client_hash, manager->client_hash_len);
+
+ ZVAL_DUP(driverOptionsClone, driverOptions);
+ ADD_ASSOC_ZVAL_EX(driverOptionsClone, "autoEncryption", autoEncryptionOptsClone);
+
+ return driverOptionsClone;
+
+ref:
+ Z_ADDREF_P(driverOptions);
+ return driverOptions;
+}
+
+/* Creates a hash for a client by concatenating the URI string with serialized
+ * options arrays. On success, a persistent string is returned (i.e. pefree()
+ * should be used to free it) and hash_len will be set to the string's length.
+ * On error, an exception will have been thrown and NULL will be returned. */
+static char* php_phongo_manager_make_client_hash(const char* uri_string, zval* options, zval* driverOptions, size_t* hash_len)
+{
+ char* hash = NULL;
+ smart_str var_buf = { 0 };
+ php_serialize_data_t var_hash;
+ zval* serializable_driver_options = NULL;
+ bool free_driver_options = false;
+
+ zval args;
+
+ array_init_size(&args, 4);
+ ADD_ASSOC_LONG_EX(&args, "pid", getpid());
+ ADD_ASSOC_STRING(&args, "uri", uri_string);
+
+ if (options) {
+ ADD_ASSOC_ZVAL_EX(&args, "options", options);
+ Z_ADDREF_P(options);
+ } else {
+ ADD_ASSOC_NULL_EX(&args, "options");
+ }
+
+ if (driverOptions) {
+ serializable_driver_options = php_phongo_manager_prepare_manager_for_hash(driverOptions, &free_driver_options);
+ ADD_ASSOC_ZVAL_EX(&args, "driverOptions", serializable_driver_options);
+ } else {
+ ADD_ASSOC_NULL_EX(&args, "driverOptions");
+ }
+
+ PHP_VAR_SERIALIZE_INIT(var_hash);
+ php_var_serialize(&var_buf, &args, &var_hash);
+ PHP_VAR_SERIALIZE_DESTROY(var_hash);
+
+ if (!EG(exception)) {
+ *hash_len = ZSTR_LEN(var_buf.s);
+ hash = estrndup(ZSTR_VAL(var_buf.s), *hash_len);
+ }
+
+ zval_ptr_dtor(&args);
+
+ if (free_driver_options) {
+ efree(serializable_driver_options);
+ }
+
+ smart_str_free(&var_buf);
+
+ return hash;
+}
+
+static bool php_phongo_extract_handshake_data(zval* driver, const char* key, char** value, size_t* value_len)
+{
+ zval* zvalue;
+
+ if (!php_array_exists(driver, key)) {
+ *value = NULL;
+ *value_len = 0;
+
+ return true;
+ }
+
+ zvalue = php_array_fetch(driver, key);
+
+ if (Z_TYPE_P(zvalue) != IS_STRING) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"%s\" handshake option to be a string, %s given", key, PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(zvalue));
+ return false;
+ }
+
+ *value = estrdup(Z_STRVAL_P(zvalue));
+ *value_len = Z_STRLEN_P(zvalue);
+
+ return true;
+}
+
+static char* php_phongo_concat_handshake_data(const char* default_value, const char* custom_value, size_t custom_value_len)
+{
+ char* ret;
+ /* Length of the returned value needs to include a trailing space and null byte */
+ size_t ret_len = strlen(default_value) + 2;
+
+ if (custom_value) {
+ /* Increase the length by that of the custom value as well as the separator length */
+ ret_len += custom_value_len + PHONGO_METADATA_SEPARATOR_LEN;
+ }
+
+ ret = ecalloc(ret_len, sizeof(char));
+
+ if (custom_value) {
+ snprintf(ret, ret_len, "%s%s%s ", default_value, PHONGO_METADATA_SEPARATOR, custom_value);
+ } else {
+ snprintf(ret, ret_len, "%s ", default_value);
+ }
+
+ return ret;
+}
+
+static void php_phongo_handshake_data_append(const char* name, size_t name_len, const char* version, size_t version_len, const char* platform, size_t platform_len)
+{
+ char* php_version_string;
+ size_t php_version_string_len;
+ char* driver_name;
+ char* driver_version;
+ char* full_platform;
+
+ php_version_string_len = strlen(PHP_VERSION) + PHONGO_METADATA_PHP_VERSION_PREFIX_LEN + 1;
+ php_version_string = ecalloc(php_version_string_len, sizeof(char));
+ snprintf(php_version_string, php_version_string_len, "%s%s", PHONGO_METADATA_PHP_VERSION_PREFIX, PHP_VERSION);
+
+ driver_name = php_phongo_concat_handshake_data("ext-mongodb:PHP", name, name_len);
+ driver_version = php_phongo_concat_handshake_data(PHP_MONGODB_VERSION, version, version_len);
+ full_platform = php_phongo_concat_handshake_data(php_version_string, platform, platform_len);
+
+ MONGOC_DEBUG(
+ "Setting driver handshake data: { name: '%s', version: '%s', platform: '%s' }",
+ driver_name,
+ driver_version,
+ full_platform);
+
+ mongoc_handshake_data_append(driver_name, driver_version, full_platform);
+
+ efree(php_version_string);
+ efree(driver_name);
+ efree(driver_version);
+ efree(full_platform);
+}
+
+static void php_phongo_set_handshake_data(zval* driverOptions)
+{
+ char* name = NULL;
+ size_t name_len = 0;
+ char* version = NULL;
+ size_t version_len = 0;
+ char* platform = NULL;
+ size_t platform_len = 0;
+
+ if (driverOptions && php_array_existsc(driverOptions, "driver")) {
+ zval* driver = php_array_fetchc(driverOptions, "driver");
+
+ if (Z_TYPE_P(driver) != IS_ARRAY) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"driver\" driver option to be an array, %s given", PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(driver));
+ return;
+ }
+
+ if (!php_phongo_extract_handshake_data(driver, "name", &name, &name_len)) {
+ /* Exception already thrown */
+ goto cleanup;
+ }
+
+ if (!php_phongo_extract_handshake_data(driver, "version", &version, &version_len)) {
+ /* Exception already thrown */
+ goto cleanup;
+ }
+
+ if (!php_phongo_extract_handshake_data(driver, "platform", &platform, &platform_len)) {
+ /* Exception already thrown */
+ goto cleanup;
+ }
+ }
+
+ php_phongo_handshake_data_append(name, name_len, version, version_len, platform, platform_len);
+
+cleanup:
+ if (name) {
+ efree(name);
+ }
+ if (version) {
+ efree(version);
+ }
+ if (platform) {
+ efree(platform);
+ }
+}
+
+static mongoc_client_t* php_phongo_make_mongo_client(const mongoc_uri_t* uri, zval* driverOptions) /* {{{ */
+{
+ const char * mongoc_version, *bson_version;
+ mongoc_client_t* client;
+ bson_error_t error = { 0 };
+
+#ifdef HAVE_SYSTEM_LIBMONGOC
+ mongoc_version = mongoc_get_version();
+#else
+ mongoc_version = "bundled";
+#endif
+
+#ifdef HAVE_SYSTEM_LIBBSON
+ bson_version = bson_get_version();
+#else
+ bson_version = "bundled";
+#endif
+
+ MONGOC_DEBUG(
+ "Creating Manager, phongo-%s[%s] - mongoc-%s(%s), libbson-%s(%s), php-%s",
+ PHP_MONGODB_VERSION,
+ PHP_MONGODB_STABILITY,
+ MONGOC_VERSION_S,
+ mongoc_version,
+ BSON_VERSION_S,
+ bson_version,
+ PHP_VERSION);
+
+ php_phongo_set_handshake_data(driverOptions);
+
+ if (!(client = mongoc_client_new_from_uri_with_error(uri, &error))) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Failed to parse URI options: %s", error.message);
+ }
+
+ return client;
+} /* }}} */
+
+/* Adds a client to the appropriate registry. Persistent and request-scoped
+ * clients each have their own registries (i.e. HashTables), which use different
+ * forms of memory allocation. Both registries are used for PID tracking.
+ * Returns true if the client was successfully added; otherwise, false. */
+bool php_phongo_client_register(php_phongo_manager_t* manager)
+{
+ bool is_persistent = manager->use_persistent_client;
+ php_phongo_pclient_t* pclient = pecalloc(1, sizeof(php_phongo_pclient_t), is_persistent);
+
+ pclient->client = manager->client;
+ pclient->created_by_pid = (int) getpid();
+ pclient->is_persistent = is_persistent;
+
+ if (is_persistent) {
+ MONGOC_DEBUG("Stored persistent client with hash: %s", manager->client_hash);
+ return zend_hash_str_update_ptr(&MONGODB_G(persistent_clients), manager->client_hash, manager->client_hash_len, pclient) != NULL;
+ } else {
+ MONGOC_DEBUG("Stored non-persistent client");
+ return zend_hash_next_index_insert_ptr(MONGODB_G(request_clients), pclient) != NULL;
+ }
+}
+
+/* Removes a client from the request-scoped registry. This function is a NOP for
+ * persistent clients, since they are destroyed along with their registry (i.e.
+ * HashTable) in GSHUTDOWN. Returns true if the client was successfully removed;
+ * otherwise, false. */
+bool php_phongo_client_unregister(php_phongo_manager_t* manager)
+{
+ zend_ulong index;
+ php_phongo_pclient_t* pclient;
+
+ /* Persistent clients do not get unregistered. */
+ if (manager->use_persistent_client) {
+ MONGOC_DEBUG("Not destroying persistent client for Manager");
+
+ return false;
+ }
+
+ /* Ensure the request-scoped registry is initialized. This is needed because
+ * RSHUTDOWN may occur before a Manager's free_object handler is
+ * executed. */
+ if (MONGODB_G(request_clients) == NULL) {
+ return false;
+ }
+
+ ZEND_HASH_FOREACH_NUM_KEY_PTR(MONGODB_G(request_clients), index, pclient)
+ {
+ if (pclient->client == manager->client) {
+ MONGOC_DEBUG("Destroying non-persistent client for Manager");
+
+ return zend_hash_index_del(MONGODB_G(request_clients), index) == SUCCESS;
+ }
+ }
+ ZEND_HASH_FOREACH_END();
+
+ return false;
+}
+
+static mongoc_client_t* php_phongo_find_persistent_client(const char* hash, size_t hash_len)
+{
+ php_phongo_pclient_t* pclient = zend_hash_str_find_ptr(&MONGODB_G(persistent_clients), hash, hash_len);
+
+ if (pclient) {
+ return pclient->client;
+ }
+
+ return NULL;
+}
+
+static bool phongo_manager_set_serverapi_opts(php_phongo_manager_t* manager, zval* driverOptions) /* {{{ */
+{
+ zval* zServerApi;
+ php_phongo_serverapi_t* server_api;
+ bson_error_t error = { 0 };
+
+ if (!driverOptions || !php_array_existsc(driverOptions, "serverApi")) {
+ return true;
+ }
+
+ zServerApi = php_array_fetch(driverOptions, "serverApi");
+
+ if (Z_TYPE_P(zServerApi) != IS_OBJECT || !instanceof_function(Z_OBJCE_P(zServerApi), php_phongo_serverapi_ce)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"serverApi\" driver option to be %s, %s given", ZSTR_VAL(php_phongo_serverapi_ce->name), PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(zServerApi));
+ return false;
+ }
+
+ server_api = Z_SERVERAPI_OBJ_P(zServerApi);
+
+ if (!mongoc_client_set_server_api(manager->client, server_api->server_api, &error)) {
+ phongo_throw_exception_from_bson_error_t(&error);
+ return false;
+ }
+
+ return true;
+} /* }}} */
+
+#ifdef MONGOC_ENABLE_CLIENT_SIDE_ENCRYPTION
+static bool phongo_manager_set_auto_encryption_opts(php_phongo_manager_t* manager, zval* driverOptions) /* {{{ */
+{
+ zval* zAutoEncryptionOpts;
+ bson_error_t error = { 0 };
+ mongoc_auto_encryption_opts_t* auto_encryption_opts = NULL;
+ bool retval = false;
+
+ if (!driverOptions || !php_array_existsc(driverOptions, "autoEncryption")) {
+ return true;
+ }
+
+ zAutoEncryptionOpts = php_array_fetch(driverOptions, "autoEncryption");
+
+ if (Z_TYPE_P(zAutoEncryptionOpts) != IS_ARRAY) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"autoEncryption\" driver option to be array, %s given", PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(zAutoEncryptionOpts));
+ return false;
+ }
+
+ auto_encryption_opts = mongoc_auto_encryption_opts_new();
+
+ if (php_array_existsc(zAutoEncryptionOpts, "keyVaultClient")) {
+ zval* key_vault_client = php_array_fetch(zAutoEncryptionOpts, "keyVaultClient");
+
+ if (Z_TYPE_P(key_vault_client) != IS_OBJECT || !instanceof_function(Z_OBJCE_P(key_vault_client), php_phongo_manager_ce)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"keyVaultClient\" encryption option to be %s, %s given", ZSTR_VAL(php_phongo_manager_ce->name), PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(key_vault_client));
+ goto cleanup;
+ }
+
+ /* Ensure the Manager and keyVaultClient are consistent in their use of
+ * persistent clients. A non-persistent Manager could theoretically use
+ * a persistent keyVaultClient, but this prohibition may help prevent
+ * users from inadvertently creating a persistent keyVaultClient. */
+ if (manager->use_persistent_client != Z_MANAGER_OBJ_P(key_vault_client)->use_persistent_client) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "The \"disableClientPersistence\" option for a Manager and its \"keyVaultClient\" must be the same");
+ goto cleanup;
+ }
+
+ mongoc_auto_encryption_opts_set_keyvault_client(auto_encryption_opts, Z_MANAGER_OBJ_P(key_vault_client)->client);
+
+ /* Copy the keyVaultClient to the Manager to allow for ref-counting (for
+ * non-persistent clients) and reset-on-fork behavior. */
+ ZVAL_ZVAL(&manager->key_vault_client_manager, key_vault_client, 1, 0);
+ }
+
+ if (php_array_existsc(zAutoEncryptionOpts, "keyVaultNamespace")) {
+ char* key_vault_ns;
+ char* db_name;
+ char* coll_name;
+ int plen;
+ zend_bool pfree;
+
+ key_vault_ns = php_array_fetch_string(zAutoEncryptionOpts, "keyVaultNamespace", &plen, &pfree);
+
+ if (!phongo_split_namespace(key_vault_ns, &db_name, &coll_name)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"keyVaultNamespace\" encryption option to contain a full collection name");
+
+ if (pfree) {
+ efree(key_vault_ns);
+ }
+
+ goto cleanup;
+ }
+
+ mongoc_auto_encryption_opts_set_keyvault_namespace(auto_encryption_opts, db_name, coll_name);
+
+ efree(db_name);
+ efree(coll_name);
+
+ if (pfree) {
+ efree(key_vault_ns);
+ }
+ }
+
+ if (php_array_existsc(zAutoEncryptionOpts, "kmsProviders")) {
+ zval* kms_providers = php_array_fetch(zAutoEncryptionOpts, "kmsProviders");
+ bson_t bson_providers = BSON_INITIALIZER;
+
+ if (Z_TYPE_P(kms_providers) != IS_OBJECT && Z_TYPE_P(kms_providers) != IS_ARRAY) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"kmsProviders\" encryption option to be an array or object");
+ goto cleanup;
+ }
+
+ php_phongo_zval_to_bson(kms_providers, PHONGO_BSON_NONE, &bson_providers, NULL);
+ if (EG(exception)) {
+ goto cleanup;
+ }
+
+ mongoc_auto_encryption_opts_set_kms_providers(auto_encryption_opts, &bson_providers);
+
+ bson_destroy(&bson_providers);
+ }
+
+ if (php_array_existsc(zAutoEncryptionOpts, "schemaMap")) {
+ zval* schema_map = php_array_fetch(zAutoEncryptionOpts, "schemaMap");
+ bson_t bson_map = BSON_INITIALIZER;
+
+ if (Z_TYPE_P(schema_map) != IS_OBJECT && Z_TYPE_P(schema_map) != IS_ARRAY) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"schemaMap\" encryption option to be an array or object");
+ goto cleanup;
+ }
+
+ php_phongo_zval_to_bson(schema_map, PHONGO_BSON_NONE, &bson_map, NULL);
+ if (EG(exception)) {
+ goto cleanup;
+ }
+
+ mongoc_auto_encryption_opts_set_schema_map(auto_encryption_opts, &bson_map);
+
+ bson_destroy(&bson_map);
+ }
+
+ if (php_array_existsc(zAutoEncryptionOpts, "tlsOptions")) {
+ zval* tls_options = php_array_fetch(zAutoEncryptionOpts, "tlsOptions");
+ bson_t bson_options = BSON_INITIALIZER;
+
+ if (Z_TYPE_P(tls_options) != IS_OBJECT && Z_TYPE_P(tls_options) != IS_ARRAY) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"tlsOptions\" encryption option to be an array or object");
+ goto cleanup;
+ }
+
+ php_phongo_zval_to_bson(tls_options, PHONGO_BSON_NONE, &bson_options, NULL);
+ if (EG(exception)) {
+ goto cleanup;
+ }
+
+ mongoc_auto_encryption_opts_set_tls_opts(auto_encryption_opts, &bson_options);
+
+ bson_destroy(&bson_options);
+ }
+
+ if (php_array_existsc(zAutoEncryptionOpts, "bypassAutoEncryption")) {
+ zend_bool bypass_auto_encryption = php_array_fetch_bool(zAutoEncryptionOpts, "bypassAutoEncryption");
+
+ mongoc_auto_encryption_opts_set_bypass_auto_encryption(auto_encryption_opts, bypass_auto_encryption);
+ }
+
+ if (php_array_existsc(zAutoEncryptionOpts, "extraOptions")) {
+ zval* extra_options = php_array_fetch(zAutoEncryptionOpts, "extraOptions");
+ bson_t bson_options = BSON_INITIALIZER;
+
+ if (Z_TYPE_P(extra_options) != IS_OBJECT && Z_TYPE_P(extra_options) != IS_ARRAY) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"extraOptions\" encryption option to be an array or object");
+ goto cleanup;
+ }
+
+ php_phongo_zval_to_bson(extra_options, PHONGO_BSON_NONE, &bson_options, NULL);
+ if (EG(exception)) {
+ goto cleanup;
+ }
+
+ mongoc_auto_encryption_opts_set_extra(auto_encryption_opts, &bson_options);
+
+ bson_destroy(&bson_options);
+ }
+
+ if (!mongoc_client_enable_auto_encryption(manager->client, auto_encryption_opts, &error)) {
+ phongo_throw_exception_from_bson_error_t(&error);
+ goto cleanup;
+ }
+
+ retval = true;
+
+cleanup:
+ mongoc_auto_encryption_opts_destroy(auto_encryption_opts);
+ return retval;
+}
+/* }}} */
+#else /* MONGOC_ENABLE_CLIENT_SIDE_ENCRYPTION */
+static bool phongo_manager_set_auto_encryption_opts(php_phongo_manager_t* manager, zval* driverOptions) /* {{{ */
+{
+ if (!driverOptions || !php_array_existsc(driverOptions, "autoEncryption")) {
+ return true;
+ }
+
+ phongo_throw_exception_no_cse(PHONGO_ERROR_INVALID_ARGUMENT, "Cannot enable automatic field-level encryption.");
+
+ return false;
+}
+/* }}} */
+#endif /* MONGOC_ENABLE_CLIENT_SIDE_ENCRYPTION */
+
+void phongo_manager_init(php_phongo_manager_t* manager, const char* uri_string, zval* options, zval* driverOptions) /* {{{ */
+{
+ bson_t bson_options = BSON_INITIALIZER;
+ mongoc_uri_t* uri = NULL;
+#ifdef MONGOC_ENABLE_SSL
+ mongoc_ssl_opt_t* ssl_opt = NULL;
+#endif
+
+ if (!(manager->client_hash = php_phongo_manager_make_client_hash(uri_string, options, driverOptions, &manager->client_hash_len))) {
+ /* Exception should already have been thrown and there is nothing to free */
+ return;
+ }
+
+ if (driverOptions && php_array_existsc(driverOptions, "disableClientPersistence")) {
+ manager->use_persistent_client = !php_array_fetchc_bool(driverOptions, "disableClientPersistence");
+ } else {
+ manager->use_persistent_client = true;
+ }
+
+ if (manager->use_persistent_client && (manager->client = php_phongo_find_persistent_client(manager->client_hash, manager->client_hash_len))) {
+ MONGOC_DEBUG("Found client for hash: %s", manager->client_hash);
+ goto cleanup;
+ }
+
+ if (options) {
+ php_phongo_zval_to_bson(options, PHONGO_BSON_NONE, &bson_options, NULL);
+ }
+
+ /* An exception may be thrown during BSON conversion */
+ if (EG(exception)) {
+ goto cleanup;
+ }
+
+ if (!(uri = php_phongo_make_uri(uri_string))) {
+ /* Exception should already have been thrown */
+ goto cleanup;
+ }
+
+ if (!php_phongo_apply_options_to_uri(uri, &bson_options) ||
+ !php_phongo_apply_rc_options_to_uri(uri, &bson_options) ||
+ !php_phongo_apply_rp_options_to_uri(uri, &bson_options) ||
+ !php_phongo_apply_wc_options_to_uri(uri, &bson_options)) {
+ /* Exception should already have been thrown */
+ goto cleanup;
+ }
+
+#ifdef MONGOC_ENABLE_SSL
+ if (!php_phongo_apply_driver_options_to_uri(uri, driverOptions)) {
+ /* Exception should already have been thrown */
+ goto cleanup;
+ }
+
+ ssl_opt = php_phongo_make_ssl_opt(uri, driverOptions);
+
+ /* An exception may be thrown during SSL option creation */
+ if (EG(exception)) {
+ goto cleanup;
+ }
+#endif
+
+ manager->client = php_phongo_make_mongo_client(uri, driverOptions);
+
+ if (!manager->client) {
+ /* Exception should already have been thrown */
+ goto cleanup;
+ }
+
+ mongoc_client_set_error_api(manager->client, MONGOC_ERROR_API_VERSION_2);
+
+#ifdef MONGOC_ENABLE_SSL
+ if (ssl_opt) {
+ mongoc_client_set_ssl_opts(manager->client, ssl_opt);
+ }
+#endif
+
+ if (!phongo_manager_set_auto_encryption_opts(manager, driverOptions)) {
+ /* Exception should already have been thrown */
+ goto cleanup;
+ }
+
+ if (!phongo_manager_set_serverapi_opts(manager, driverOptions)) {
+ /* Exception should already have been thrown */
+ goto cleanup;
+ }
+
+ if (!phongo_apm_set_callbacks(manager->client)) {
+ /* Exception should already have been thrown */
+ goto cleanup;
+ }
+
+ MONGOC_DEBUG("Created client with hash: %s", manager->client_hash);
+
+ /* Register the newly created client in the appropriate registry (for either
+ * persistent or request-scoped clients). */
+ if (!php_phongo_client_register(manager)) {
+ phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "Failed to add Manager client to internal registry");
+ goto cleanup;
+ }
+
+cleanup:
+ bson_destroy(&bson_options);
+
+ if (uri) {
+ mongoc_uri_destroy(uri);
+ }
+
+#ifdef MONGOC_ENABLE_SSL
+ if (ssl_opt) {
+ php_phongo_free_ssl_opt(ssl_opt);
+ }
+#endif
+} /* }}} */
+
+static void phongo_pclient_reset_once(php_phongo_pclient_t* pclient, int pid)
+{
+ if (pclient->last_reset_by_pid != pid) {
+ mongoc_client_reset(pclient->client);
+ pclient->last_reset_by_pid = pid;
+ }
+}
+
+/* Resets the libmongoc client if it has not already been reset for the current
+ * PID (based on information in the hash table of persisted libmongoc clients).
+ * This ensures that we do not reset a client multiple times from the same child
+ * process. */
+void php_phongo_client_reset_once(php_phongo_manager_t* manager, int pid)
+{
+ php_phongo_pclient_t* pclient;
+
+ /* Reset associated key vault client */
+ if (!Z_ISUNDEF(manager->key_vault_client_manager)) {
+ php_phongo_client_reset_once(Z_MANAGER_OBJ_P(&manager->key_vault_client_manager), pid);
+ }
+
+ if (manager->use_persistent_client) {
+ pclient = zend_hash_str_find_ptr(&MONGODB_G(persistent_clients), manager->client_hash, manager->client_hash_len);
+
+ if (pclient) {
+ phongo_pclient_reset_once(pclient, pid);
+ }
+
+ return;
+ }
+
+ ZEND_HASH_FOREACH_PTR(MONGODB_G(request_clients), pclient)
+ {
+ if (pclient->client == manager->client) {
+ phongo_pclient_reset_once(pclient, pid);
+
+ /* Request-scoped clients are only used by a single Manager, so we
+ * can return early after finding a match. */
+ return;
+ }
+ }
+ ZEND_HASH_FOREACH_END();
+}
+
+/* Returns whether a Manager exists in the request-scoped registry. If found and
+ * the output parameter is non-NULL, the Manager's index will be assigned. */
+static bool php_phongo_manager_exists(php_phongo_manager_t* manager, zend_ulong* index_out)
+{
+ zend_ulong index;
+ php_phongo_manager_t* value;
+
+ if (!MONGODB_G(managers) || zend_hash_num_elements(MONGODB_G(managers)) == 0) {
+ return false;
+ }
+
+ ZEND_HASH_FOREACH_NUM_KEY_PTR(MONGODB_G(managers), index, value)
+ {
+ if (value != manager) {
+ continue;
+ }
+
+ if (index_out) {
+ *index_out = index;
+ }
+
+ return true;
+ }
+ ZEND_HASH_FOREACH_END();
+
+ return false;
+}
+
+/* Adds a Manager to the request-scoped registry. Returns true if the Manager
+ * did not exist and was successfully added; otherwise, returns false. */
+bool php_phongo_manager_register(php_phongo_manager_t* manager)
+{
+ if (!MONGODB_G(managers)) {
+ return false;
+ }
+
+ if (php_phongo_manager_exists(manager, NULL)) {
+ return false;
+ }
+
+ return zend_hash_next_index_insert_ptr(MONGODB_G(managers), manager) != NULL;
+}
+
+/* Removes a Manager from the request-scoped registry. Returns true if the
+ * Manager was found and successfully removed; otherwise, false is returned. */
+bool php_phongo_manager_unregister(php_phongo_manager_t* manager)
+{
+ zend_ulong index;
+
+ /* Ensure the registry is initialized. This is needed because RSHUTDOWN may
+ * occur before a Manager's free_object handler is executed. */
+ if (!MONGODB_G(managers)) {
+ return false;
+ }
+
+ if (php_phongo_manager_exists(manager, &index)) {
+ return zend_hash_index_del(MONGODB_G(managers), index) == SUCCESS;
+ }
+
+ return false;
+}
+
+static void php_phongo_pclient_destroy(php_phongo_pclient_t* pclient)
+{
+ /* Do not destroy mongoc_client_t objects created by other processes. This
+ * ensures that we do not shutdown sockets that may still be in use by our
+ * parent process (see: PHPC-1522).
+ *
+ * This is a leak; however, we are already in GSHUTDOWN for a persistent
+ * clients. For a request-scoped client, we are either in the Manager's
+ * free_object handler or RSHUTDOWN, but there the application is capable of
+ * freeing its Manager and its client before forking. */
+ if (pclient->created_by_pid == getpid()) {
+ /* If we are in request shutdown, disable APM to avoid dispatching more
+ * events. This means that certain events (e.g. TopologyClosedEvent,
+ * command monitoring for endSessions) may not be observed. */
+ if (EG(flags) & EG_FLAGS_IN_SHUTDOWN) {
+ mongoc_client_set_apm_callbacks(pclient->client, NULL, NULL);
+ }
+ mongoc_client_destroy(pclient->client);
+ }
+
+ /* Persistent and request-scoped clients use different memory allocation */
+ pefree(pclient, pclient->is_persistent);
+}
+
+void php_phongo_pclient_destroy_ptr(zval* ptr)
+{
+ php_phongo_pclient_destroy(Z_PTR_P(ptr));
+}
diff --git a/mongodb-1.13.0/src/phongo_client.h b/mongodb-1.13.0/src/phongo_client.h
new file mode 100644
index 00000000..4851fd2b
--- /dev/null
+++ b/mongodb-1.13.0/src/phongo_client.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2022-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PHONGO_CLIENT_H
+#define PHONGO_CLIENT_H
+
+#include <php.h>
+
+#include "phongo_classes.h"
+
+void phongo_manager_init(php_phongo_manager_t* manager, const char* uri_string, zval* options, zval* driverOptions);
+
+void php_phongo_client_reset_once(php_phongo_manager_t* manager, int pid);
+bool php_phongo_client_register(php_phongo_manager_t* manager);
+bool php_phongo_client_unregister(php_phongo_manager_t* manager);
+
+bool php_phongo_manager_register(php_phongo_manager_t* manager);
+bool php_phongo_manager_unregister(php_phongo_manager_t* manager);
+
+void php_phongo_pclient_destroy_ptr(zval* ptr);
+
+#define PHONGO_RESET_CLIENT_IF_PID_DIFFERS(intern, manager) \
+ do { \
+ int pid = (int) getpid(); \
+ if ((intern)->created_by_pid != pid) { \
+ php_phongo_client_reset_once((manager), pid); \
+ } \
+ } while (0)
+
+#endif /* PHONGO_CLIENT_H */
diff --git a/mongodb-1.13.0/src/phongo_compat.c b/mongodb-1.13.0/src/phongo_compat.c
new file mode 100644
index 00000000..08cf9d10
--- /dev/null
+++ b/mongodb-1.13.0/src/phongo_compat.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2015-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <php.h>
+
+#ifdef ZEND_HASH_GET_APPLY_COUNT /* PHP 7.2 or earlier recursion protection */
+zend_bool php_phongo_zend_hash_apply_protection_begin(HashTable* ht)
+{
+ if (!ht) {
+ return 1;
+ }
+ if (ZEND_HASH_GET_APPLY_COUNT(ht) > 0) {
+ return 0;
+ }
+ if (ZEND_HASH_APPLY_PROTECTION(ht)) {
+ ZEND_HASH_INC_APPLY_COUNT(ht);
+ }
+ return 1;
+}
+
+zend_bool php_phongo_zend_hash_apply_protection_end(HashTable* ht)
+{
+ if (!ht) {
+ return 1;
+ }
+ if (ZEND_HASH_GET_APPLY_COUNT(ht) == 0) {
+ return 0;
+ }
+ if (ZEND_HASH_APPLY_PROTECTION(ht)) {
+ ZEND_HASH_DEC_APPLY_COUNT(ht);
+ }
+ return 1;
+}
+#else /* PHP 7.3 or later */
+zend_bool php_phongo_zend_hash_apply_protection_begin(zend_array* ht)
+{
+ if (GC_IS_RECURSIVE(ht)) {
+ return 0;
+ }
+ if (!(GC_FLAGS(ht) & GC_IMMUTABLE)) {
+ GC_PROTECT_RECURSION(ht);
+ }
+ return 1;
+}
+
+zend_bool php_phongo_zend_hash_apply_protection_end(zend_array* ht)
+{
+ if (!GC_IS_RECURSIVE(ht)) {
+ return 0;
+ }
+ if (!(GC_FLAGS(ht) & GC_IMMUTABLE)) {
+ GC_UNPROTECT_RECURSION(ht);
+ }
+ return 1;
+}
+#endif
diff --git a/mongodb-1.13.0/src/phongo_compat.h b/mongodb-1.13.0/src/phongo_compat.h
new file mode 100644
index 00000000..0345e66d
--- /dev/null
+++ b/mongodb-1.13.0/src/phongo_compat.h
@@ -0,0 +1,257 @@
+/*
+ * Copyright 2015-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PHONGO_COMPAT_H
+#define PHONGO_COMPAT_H
+
+#include <php.h>
+#include <Zend/zend_string.h>
+#include <Zend/zend_portability.h>
+
+#ifdef PHP_WIN32
+#include "config.w32.h"
+#else
+#include <php_config.h>
+#endif
+
+#ifndef PHP_FE_END
+#define PHP_FE_END \
+ { \
+ NULL, NULL, NULL \
+ }
+#endif
+
+#ifndef HASH_KEY_NON_EXISTENT
+#define HASH_KEY_NON_EXISTENT HASH_KEY_NON_EXISTANT
+#endif
+
+#if defined(__GNUC__)
+#define ARG_UNUSED __attribute__((unused))
+#else
+#define ARG_UNUSED
+#endif
+
+#if defined(__GNUC__)
+#define PHONGO_GNUC_CHECK_VERSION(major, minor) \
+ ((__GNUC__ > (major)) || \
+ ((__GNUC__ == (major)) && (__GNUC_MINOR__ >= (minor))))
+#else
+#define PHONGO_GNUC_CHECK_VERSION(major, minor) 0
+#endif
+
+#if PHONGO_GNUC_CHECK_VERSION(7, 0)
+#define PHONGO_BREAK_INTENTIONALLY_MISSING __attribute__((fallthrough));
+#elif defined(__clang__) && __clang_major__ >= 12
+#define PHONGO_BREAK_INTENTIONALLY_MISSING __attribute__((fallthrough));
+#else
+#define PHONGO_BREAK_INTENTIONALLY_MISSING
+#endif
+
+#if PHP_VERSION_ID >= 80000
+#define PHONGO_COMPAT_OBJ_P(val) Z_OBJ_P(val)
+#define phongo_compat_object_handler_type zend_object
+#define PHONGO_COMPAT_GET_OBJ(val) val
+#define PHONGO_COMPAT_SET_COMPARE_OBJECTS_HANDLER(type) php_phongo_handler_##type.compare = php_phongo_##type##_compare_objects;
+#else /* PHP_VERSION_ID < 80000 */
+#define PHONGO_COMPAT_OBJ_P(val) val
+#define phongo_compat_object_handler_type zval
+#define PHONGO_COMPAT_GET_OBJ(val) Z_OBJ_P(val)
+#define PHONGO_COMPAT_SET_COMPARE_OBJECTS_HANDLER(type) php_phongo_handler_##type.compare_objects = php_phongo_##type##_compare_objects;
+#define ZEND_COMPARE_OBJECTS_FALLBACK(o1, o2)
+#endif /* PHP_VERSION_ID >= 80000 */
+
+#if SIZEOF_ZEND_LONG == 8
+#define PHONGO_LONG_FORMAT PRId64
+#elif SIZEOF_ZEND_LONG == 4
+#define PHONGO_LONG_FORMAT PRId32
+#else
+#error Unsupported architecture (integers are neither 32-bit nor 64-bit)
+#endif
+
+#if PHP_VERSION_ID < 70300
+#define zend_object_alloc(obj_size, ce) ecalloc(1, obj_size + zend_object_properties_size(ce))
+#endif
+
+#define ADD_ASSOC_STRING(_zv, _key, _value) add_assoc_string_ex(_zv, ZEND_STRL(_key), (char*) (_value));
+#define ADD_ASSOC_STRINGL(_zv, _key, _value, _len) add_assoc_stringl_ex(_zv, ZEND_STRL(_key), (char*) (_value), _len);
+#define ADD_ASSOC_STRING_EX(_zv, _key, _key_len, _value, _value_len) add_assoc_stringl_ex(_zv, _key, _key_len, (char*) (_value), _value_len);
+#define ADD_ASSOC_LONG_EX(_zv, _key, _value) add_assoc_long_ex(_zv, ZEND_STRL(_key), _value);
+#define ADD_ASSOC_ZVAL_EX(_zv, _key, _value) add_assoc_zval_ex(_zv, ZEND_STRL(_key), _value);
+#define ADD_ASSOC_ZVAL(_zv, _key, _value) add_assoc_zval(_zv, _key, _value);
+#define ADD_ASSOC_NULL_EX(_zv, _key) add_assoc_null_ex(_zv, ZEND_STRL(_key));
+#define ADD_ASSOC_BOOL_EX(_zv, _key, _value) add_assoc_bool_ex(_zv, ZEND_STRL(_key), _value);
+#define ZVAL_INT64_STRING(_zv, _value) \
+ do { \
+ char tmp[24]; \
+ int tmp_len; \
+ tmp_len = snprintf(tmp, sizeof(tmp), "%" PRId64, (_value)); \
+ ZVAL_STRINGL((_zv), tmp, tmp_len); \
+ } while (0)
+#define ADD_ASSOC_INT64_AS_STRING(_zv, _key, _value) \
+ do { \
+ zval z_int; \
+ ZVAL_INT64_STRING(&z_int, (_value)); \
+ ADD_ASSOC_ZVAL_EX((_zv), (_key), &z_int); \
+ } while (0)
+#define ADD_NEXT_INDEX_STRINGL(_zv, _value, _len) add_next_index_stringl(_zv, _value, _len);
+#define PHONGO_RETVAL_SMART_STR(val) RETVAL_STRINGL(ZSTR_VAL((val).s), ZSTR_LEN((val).s));
+#define ZVAL_STATIC_INIT \
+ { \
+ { \
+ 0 \
+ } \
+ }
+
+#if SIZEOF_ZEND_LONG == 8
+#define ADD_INDEX_INT64(_zv, _index, _value) add_index_long((_zv), (_index), (_value))
+#define ADD_NEXT_INDEX_INT64(_zv, _value) add_next_index_long((_zv), (_value))
+#define ADD_ASSOC_INT64(_zv, _key, _value) add_assoc_long((_zv), (_key), (_value))
+#define ZVAL_INT64(_zv, _value) ZVAL_LONG((_zv), (_value))
+#elif SIZEOF_ZEND_LONG == 4
+#define ADD_INDEX_INT64(_zv, _index, _value) \
+ if ((_value) > INT32_MAX || (_value) < INT32_MIN) { \
+ zval zchild; \
+ php_phongo_bson_new_int64(&zchild, (_value)); \
+ add_index_zval((_zv), (_index), &zchild); \
+ } else { \
+ add_index_long((_zv), (_index), (_value)); \
+ }
+#define ADD_NEXT_INDEX_INT64(_zv, _value) \
+ if ((_value) > INT32_MAX || (_value) < INT32_MIN) { \
+ zval zchild; \
+ php_phongo_bson_new_int64(&zchild, (_value)); \
+ add_next_index_zval((_zv), &zchild); \
+ } else { \
+ add_next_index_long((_zv), (_value)); \
+ }
+#define ADD_ASSOC_INT64(_zv, _key, _value) \
+ if ((_value) > INT32_MAX || (_value) < INT32_MIN) { \
+ zval zchild; \
+ php_phongo_bson_new_int64(&zchild, (_value)); \
+ add_assoc_zval((_zv), (_key), &zchild); \
+ } else { \
+ add_assoc_long((_zv), (_key), (_value)); \
+ }
+#define ZVAL_INT64(_zv, _value) \
+ if ((_value) > INT32_MAX || (_value) < INT32_MIN) { \
+ php_phongo_bson_new_int64((_zv), (_value)); \
+ } else { \
+ ZVAL_LONG((_zv), (_value)); \
+ }
+#else /* SIZEOF_ZEND_LONG != 8 && SIZEOF_ZEND_LONG != 4 */
+#error Unsupported architecture (integers are neither 32-bit nor 64-bit)
+#endif /* SIZEOF_ZEND_LONG */
+
+#if PHP_VERSION_ID < 70300
+#define ZVAL_COPY_DEREF(z, v) \
+ do { \
+ zval* _z3 = (v); \
+ if (Z_OPT_REFCOUNTED_P(_z3)) { \
+ if (UNEXPECTED(Z_OPT_ISREF_P(_z3))) { \
+ _z3 = Z_REFVAL_P(_z3); \
+ if (Z_OPT_REFCOUNTED_P(_z3)) { \
+ Z_ADDREF_P(_z3); \
+ } \
+ } else { \
+ Z_ADDREF_P(_z3); \
+ } \
+ } \
+ ZVAL_COPY_VALUE(z, _z3); \
+ } while (0)
+#endif /* PHP_VERSION_ID < 70300 */
+
+#if PHP_VERSION_ID < 70300
+static inline zend_bool zend_ini_parse_bool(zend_string* str)
+{
+ if (zend_string_equals_literal_ci(str, "true") ||
+ zend_string_equals_literal_ci(str, "yes") ||
+ zend_string_equals_literal_ci(str, "on")) {
+ return 1;
+ } else {
+ return atoi(ZSTR_VAL(str)) != 0;
+ }
+}
+#endif /* PHP_VERSION_ID < 70300 */
+
+/* Compatibility macros to override error handling logic */
+#define PHONGO_PARSE_PARAMETERS_START(min_num_args, max_num_args) \
+ do { \
+ zend_error_handling error_handling; \
+ zend_replace_error_handling( \
+ EH_THROW, \
+ phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), \
+ &error_handling); \
+ ZEND_PARSE_PARAMETERS_START(min_num_args, max_num_args)
+
+#define PHONGO_PARSE_PARAMETERS_END() \
+ ZEND_PARSE_PARAMETERS_END_EX( \
+ zend_restore_error_handling(&error_handling); \
+ return ); \
+ zend_restore_error_handling(&error_handling); \
+ } \
+ while (0)
+
+#ifndef ZEND_PARSE_PARAMETERS_NONE
+#define PHONGO_PARSE_PARAMETERS_NONE() \
+ do { \
+ zend_error_handling error_handling; \
+ zend_replace_error_handling( \
+ EH_THROW, \
+ phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), \
+ &error_handling); \
+ if (zend_parse_parameters_none() == FAILURE) { \
+ zend_restore_error_handling(&error_handling); \
+ return; \
+ } \
+ zend_restore_error_handling(&error_handling); \
+ } while (0)
+#else
+#define PHONGO_PARSE_PARAMETERS_NONE() \
+ do { \
+ zend_error_handling error_handling; \
+ zend_replace_error_handling( \
+ EH_THROW, \
+ phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), \
+ &error_handling); \
+ if (UNEXPECTED(ZEND_NUM_ARGS() != 0)) { \
+ zend_wrong_parameters_none_error(); \
+ zend_restore_error_handling(&error_handling); \
+ return; \
+ } \
+ zend_restore_error_handling(&error_handling); \
+ } while (0)
+#endif
+
+/* Z_PARAM_OBJECT_OF_CLASS_OR_NULL was introduced in PHP 8.0.
+ * See: https://github.com/php/php-src/commit/e93d20ad7ebc1075ef1248a663935ee5ea69f1cd */
+#ifndef Z_PARAM_OBJECT_OF_CLASS_OR_NULL
+#define Z_PARAM_OBJECT_OF_CLASS_OR_NULL(dest, _ce) \
+ Z_PARAM_OBJECT_OF_CLASS_EX(dest, _ce, 1, 0)
+#endif
+
+/* Per https://wiki.php.net/rfc/internal_method_return_types, "Non-final
+ * internal method return types - when possible - are declared tentatively in
+ * PHP 8.1, and they will become enforced in PHP 9.0." This can be revisited
+ * when more general typing improvements are made in PHPC-1709. */
+#ifndef ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX
+#define ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(name, return_reference, required_num_args, type, allow_null) \
+ ZEND_BEGIN_ARG_INFO_EX(name, 0, return_reference, required_num_args)
+#endif
+
+zend_bool php_phongo_zend_hash_apply_protection_begin(HashTable* ht);
+zend_bool php_phongo_zend_hash_apply_protection_end(HashTable* ht);
+
+#endif /* PHONGO_COMPAT_H */
diff --git a/mongodb-1.13.0/src/phongo_error.c b/mongodb-1.13.0/src/phongo_error.c
new file mode 100644
index 00000000..bd49b7f4
--- /dev/null
+++ b/mongodb-1.13.0/src/phongo_error.c
@@ -0,0 +1,218 @@
+/*
+ * Copyright 2022-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bson/bson.h"
+#include "mongoc/mongoc.h"
+
+#include <php.h>
+#include <Zend/zend_exceptions.h>
+
+#include "php_phongo.h"
+#include "phongo_error.h"
+
+/* This constant is used for determining if a server error for an exceeded query
+ * or command should select ExecutionTimeoutException. */
+#define PHONGO_SERVER_ERROR_EXCEEDED_TIME_LIMIT 50
+
+void phongo_add_exception_prop(const char* prop, int prop_len, zval* value)
+{
+ if (EG(exception)) {
+ zval ex;
+ ZVAL_OBJ(&ex, EG(exception));
+ zend_update_property(Z_OBJCE(ex), PHONGO_COMPAT_OBJ_P(&ex), prop, prop_len, value);
+ }
+}
+
+zend_class_entry* phongo_exception_from_phongo_domain(php_phongo_error_domain_t domain)
+{
+ switch (domain) {
+ case PHONGO_ERROR_INVALID_ARGUMENT:
+ return php_phongo_invalidargumentexception_ce;
+ case PHONGO_ERROR_LOGIC:
+ return php_phongo_logicexception_ce;
+ case PHONGO_ERROR_RUNTIME:
+ return php_phongo_runtimeexception_ce;
+ case PHONGO_ERROR_UNEXPECTED_VALUE:
+ return php_phongo_unexpectedvalueexception_ce;
+ case PHONGO_ERROR_MONGOC_FAILED:
+ return php_phongo_runtimeexception_ce;
+ case PHONGO_ERROR_CONNECTION_FAILED:
+ return php_phongo_connectionexception_ce;
+ }
+
+ MONGOC_ERROR("Resolving unknown phongo error domain: %d", domain);
+ return php_phongo_runtimeexception_ce;
+}
+
+zend_class_entry* phongo_exception_from_mongoc_domain(mongoc_error_domain_t domain, mongoc_error_code_t code)
+{
+ if (domain == MONGOC_ERROR_CLIENT) {
+ if (code == MONGOC_ERROR_CLIENT_AUTHENTICATE) {
+ return php_phongo_authenticationexception_ce;
+ }
+
+ if (code == MONGOC_ERROR_CLIENT_INVALID_ENCRYPTION_ARG) {
+ return php_phongo_invalidargumentexception_ce;
+ }
+ }
+
+ if (domain == MONGOC_ERROR_COMMAND && code == MONGOC_ERROR_COMMAND_INVALID_ARG) {
+ return php_phongo_invalidargumentexception_ce;
+ }
+
+ if (domain == MONGOC_ERROR_SERVER) {
+ if (code == PHONGO_SERVER_ERROR_EXCEEDED_TIME_LIMIT) {
+ return php_phongo_executiontimeoutexception_ce;
+ }
+
+ return php_phongo_serverexception_ce;
+ }
+
+ if (domain == MONGOC_ERROR_SERVER_SELECTION && code == MONGOC_ERROR_SERVER_SELECTION_FAILURE) {
+ return php_phongo_connectiontimeoutexception_ce;
+ }
+
+ if (domain == MONGOC_ERROR_STREAM) {
+ if (code == MONGOC_ERROR_STREAM_SOCKET) {
+ return php_phongo_connectiontimeoutexception_ce;
+ }
+
+ return php_phongo_connectionexception_ce;
+ }
+
+ if (domain == MONGOC_ERROR_WRITE_CONCERN) {
+ return php_phongo_serverexception_ce;
+ }
+
+ if (domain == MONGOC_ERROR_PROTOCOL && code == MONGOC_ERROR_PROTOCOL_BAD_WIRE_VERSION) {
+ return php_phongo_connectionexception_ce;
+ }
+
+ if (domain == MONGOC_ERROR_CLIENT_SIDE_ENCRYPTION) {
+ return php_phongo_encryptionexception_ce;
+ }
+
+ return php_phongo_runtimeexception_ce;
+}
+
+void phongo_throw_exception(php_phongo_error_domain_t domain, const char* format, ...)
+{
+ va_list args;
+ char* message;
+ int message_len;
+
+ va_start(args, format);
+ message_len = vspprintf(&message, 0, format, args);
+ zend_throw_exception(phongo_exception_from_phongo_domain(domain), message, 0);
+ efree(message);
+ va_end(args);
+}
+
+static int phongo_exception_append_error_labels(zval* labels, const bson_iter_t* iter)
+{
+ bson_iter_t error_labels;
+ uint32_t label_count = 0;
+
+ if (!BSON_ITER_HOLDS_ARRAY(iter) || !bson_iter_recurse(iter, &error_labels)) {
+ return label_count;
+ }
+
+ while (bson_iter_next(&error_labels)) {
+ if (BSON_ITER_HOLDS_UTF8(&error_labels)) {
+ const char* error_label;
+ uint32_t error_label_len;
+
+ error_label = bson_iter_utf8(&error_labels, &error_label_len);
+ ADD_NEXT_INDEX_STRINGL(labels, error_label, error_label_len);
+ label_count++;
+ }
+ }
+
+ return label_count;
+}
+
+void phongo_exception_add_error_labels(const bson_t* reply)
+{
+ bson_iter_t iter, child;
+ zval labels;
+ uint32_t label_count = 0;
+
+ if (!reply) {
+ return;
+ }
+
+ array_init(&labels);
+
+ if (bson_iter_init_find(&iter, reply, "errorLabels")) {
+ label_count += phongo_exception_append_error_labels(&labels, &iter);
+ }
+
+ if (bson_iter_init_find(&iter, reply, "writeConcernError") && BSON_ITER_HOLDS_DOCUMENT(&iter) &&
+ bson_iter_recurse(&iter, &child) && bson_iter_find(&child, "errorLabels")) {
+ label_count += phongo_exception_append_error_labels(&labels, &child);
+ }
+
+ /* mongoc_write_result_t always reports writeConcernErrors in an array, so
+ * we must iterate this to collect WCE labels for BulkWrite replies. */
+ if (bson_iter_init_find(&iter, reply, "writeConcernErrors") && BSON_ITER_HOLDS_ARRAY(&iter) && bson_iter_recurse(&iter, &child)) {
+ bson_iter_t wce;
+
+ while (bson_iter_next(&child)) {
+ if (BSON_ITER_HOLDS_DOCUMENT(&child) && bson_iter_recurse(&child, &wce) && bson_iter_find(&wce, "errorLabels")) {
+ label_count += phongo_exception_append_error_labels(&labels, &wce);
+ }
+ }
+ }
+
+ if (label_count > 0) {
+ phongo_add_exception_prop(ZEND_STRL("errorLabels"), &labels);
+ }
+
+ zval_ptr_dtor(&labels);
+}
+
+void phongo_throw_exception_from_bson_error_t_and_reply(bson_error_t* error, const bson_t* reply)
+{
+ /* Server errors (other than ExceededTimeLimit) and write concern errors
+ * may use CommandException and report the result document for the
+ * failed command. For BC, ExceededTimeLimit errors will continue to use
+ * ExcecutionTimeoutException and omit the result document. */
+ if (reply && ((error->domain == MONGOC_ERROR_SERVER && error->code != PHONGO_SERVER_ERROR_EXCEEDED_TIME_LIMIT) || error->domain == MONGOC_ERROR_WRITE_CONCERN)) {
+ zval zv;
+
+ zend_throw_exception(php_phongo_commandexception_ce, error->message, error->code);
+ if (php_phongo_bson_to_zval(bson_get_data(reply), reply->len, &zv)) {
+ phongo_add_exception_prop(ZEND_STRL("resultDocument"), &zv);
+ }
+
+ zval_ptr_dtor(&zv);
+ } else {
+ zend_throw_exception(phongo_exception_from_mongoc_domain(error->domain, error->code), error->message, error->code);
+ }
+ phongo_exception_add_error_labels(reply);
+}
+
+void phongo_throw_exception_from_bson_error_t(bson_error_t* error)
+{
+ phongo_throw_exception_from_bson_error_t_and_reply(error, NULL);
+}
+
+#ifndef MONGOC_ENABLE_CLIENT_SIDE_ENCRYPTION
+void phongo_throw_exception_no_cse(php_phongo_error_domain_t domain, const char* message) /* {{{ */
+{
+ phongo_throw_exception(domain, "%s Please recompile with support for libmongocrypt using the with-mongodb-client-side-encryption configure switch.", message);
+}
+#endif /* MONGOC_ENABLE_CLIENT_SIDE_ENCRYPTION */
diff --git a/mongodb-1.13.0/src/phongo_error.h b/mongodb-1.13.0/src/phongo_error.h
new file mode 100644
index 00000000..1d90d2de
--- /dev/null
+++ b/mongodb-1.13.0/src/phongo_error.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2022-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PHONGO_ERROR_H
+#define PHONGO_ERROR_H
+
+#include "bson/bson.h"
+#include "mongoc/mongoc.h"
+
+typedef enum {
+ PHONGO_ERROR_INVALID_ARGUMENT = 1,
+ PHONGO_ERROR_RUNTIME = 2,
+ PHONGO_ERROR_UNEXPECTED_VALUE = 8,
+ PHONGO_ERROR_MONGOC_FAILED = 3,
+ PHONGO_ERROR_CONNECTION_FAILED = 7,
+ PHONGO_ERROR_LOGIC = 9
+} php_phongo_error_domain_t;
+
+void phongo_add_exception_prop(const char* prop, int prop_len, zval* value);
+zend_class_entry* phongo_exception_from_mongoc_domain(mongoc_error_domain_t domain, mongoc_error_code_t code);
+zend_class_entry* phongo_exception_from_phongo_domain(php_phongo_error_domain_t domain);
+void phongo_exception_add_error_labels(const bson_t* reply);
+void phongo_throw_exception(php_phongo_error_domain_t domain, const char* format, ...);
+void phongo_throw_exception_from_bson_error_t(bson_error_t* error);
+void phongo_throw_exception_from_bson_error_t_and_reply(bson_error_t* error, const bson_t* reply);
+
+#ifndef MONGOC_ENABLE_CLIENT_SIDE_ENCRYPTION
+void phongo_throw_exception_no_cse(php_phongo_error_domain_t domain, const char* message);
+#endif /* MONGOC_ENABLE_CLIENT_SIDE_ENCRYPTION */
+
+#endif /* PHONGO_ERROR_H */
diff --git a/mongodb-1.13.0/src/phongo_execute.c b/mongodb-1.13.0/src/phongo_execute.c
new file mode 100644
index 00000000..48b2f8d4
--- /dev/null
+++ b/mongodb-1.13.0/src/phongo_execute.c
@@ -0,0 +1,621 @@
+/*
+ * Copyright 2022-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bson/bson.h"
+#include "mongoc/mongoc.h"
+
+#include <php.h>
+#include <Zend/zend_exceptions.h>
+
+#include "php_array_api.h"
+
+#include "php_phongo.h"
+#include "phongo_error.h"
+#include "phongo_execute.h"
+#include "phongo_util.h"
+
+#include "MongoDB/Cursor.h"
+#include "MongoDB/ReadPreference.h"
+#include "MongoDB/Session.h"
+#include "MongoDB/WriteResult.h"
+
+static void phongo_cursor_init(zval* return_value, zval* manager, mongoc_cursor_t* cursor, zval* readPreference, zval* session) /* {{{ */
+{
+ php_phongo_cursor_t* intern;
+
+ object_init_ex(return_value, php_phongo_cursor_ce);
+
+ intern = Z_CURSOR_OBJ_P(return_value);
+ intern->cursor = cursor;
+ intern->server_id = mongoc_cursor_get_hint(cursor);
+ intern->advanced = false;
+ intern->current = 0;
+
+ ZVAL_ZVAL(&intern->manager, manager, 1, 0);
+
+ if (readPreference) {
+ ZVAL_ZVAL(&intern->read_preference, readPreference, 1, 0);
+ }
+
+ if (session) {
+ ZVAL_ZVAL(&intern->session, session, 1, 0);
+ }
+} /* }}} */
+
+static void phongo_cursor_init_for_command(zval* return_value, zval* manager, mongoc_cursor_t* cursor, const char* db, zval* command, zval* readPreference, zval* session) /* {{{ */
+{
+ php_phongo_cursor_t* intern;
+
+ phongo_cursor_init(return_value, manager, cursor, readPreference, session);
+ intern = Z_CURSOR_OBJ_P(return_value);
+
+ intern->database = estrdup(db);
+
+ ZVAL_ZVAL(&intern->command, command, 1, 0);
+} /* }}} */
+
+static void phongo_cursor_init_for_query(zval* return_value, zval* manager, mongoc_cursor_t* cursor, const char* namespace, zval* query, zval* readPreference, zval* session) /* {{{ */
+{
+ php_phongo_cursor_t* intern;
+
+ phongo_cursor_init(return_value, manager, cursor, readPreference, session);
+ intern = Z_CURSOR_OBJ_P(return_value);
+
+ /* namespace has already been validated by phongo_execute_query() */
+ phongo_split_namespace(namespace, &intern->database, &intern->collection);
+
+ /* cursor has already been advanced by phongo_execute_query() calling
+ * phongo_cursor_advance_and_check_for_error() */
+ intern->advanced = true;
+
+ ZVAL_ZVAL(&intern->query, query, 1, 0);
+} /* }}} */
+
+static bson_t* create_wrapped_command_envelope(const char* db, bson_t* reply)
+{
+ bson_t* tmp;
+ size_t max_ns_len = strlen(db) + 5 + 1; /* db + ".$cmd" + '\0' */
+ char* ns = emalloc(max_ns_len);
+
+ snprintf(ns, max_ns_len, "%s.$cmd", db);
+ tmp = BCON_NEW("cursor", "{", "id", BCON_INT64(0), "ns", BCON_UTF8(ns), "firstBatch", "[", BCON_DOCUMENT(reply), "]", "}");
+ efree(ns);
+
+ return tmp;
+}
+
+static zval* phongo_create_implicit_session(zval* manager) /* {{{ */
+{
+ mongoc_client_session_t* cs;
+ zval* zsession;
+
+ cs = mongoc_client_start_session(Z_MANAGER_OBJ_P(manager)->client, NULL, NULL);
+
+ if (!cs) {
+ return NULL;
+ }
+
+ zsession = ecalloc(1, sizeof(zval));
+
+ phongo_session_init(zsession, manager, cs);
+
+ return zsession;
+} /* }}} */
+
+/* Parses the "readConcern" option for an execute method. If mongoc_opts is not
+ * NULL, the option will be appended. On error, false is returned and an
+ * exception is thrown. */
+static bool phongo_parse_read_concern(zval* options, bson_t* mongoc_opts) /* {{{ */
+{
+ zval* option = NULL;
+ mongoc_read_concern_t* read_concern;
+
+ if (!options) {
+ return true;
+ }
+
+ if (Z_TYPE_P(options) != IS_ARRAY) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected options to be array, %s given", PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(options));
+ return false;
+ }
+
+ option = php_array_fetchc(options, "readConcern");
+
+ if (!option) {
+ return true;
+ }
+
+ if (Z_TYPE_P(option) != IS_OBJECT || !instanceof_function(Z_OBJCE_P(option), php_phongo_readconcern_ce)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"readConcern\" option to be %s, %s given", ZSTR_VAL(php_phongo_readconcern_ce->name), PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(option));
+ return false;
+ }
+
+ read_concern = Z_READCONCERN_OBJ_P(option)->read_concern;
+
+ if (mongoc_opts && !mongoc_read_concern_append(read_concern, mongoc_opts)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Error appending \"readConcern\" option");
+ return false;
+ }
+
+ return true;
+} /* }}} */
+
+/* Parses the "readPreference" option for an execute method. If zreadPreference
+ * is not NULL, it will be assigned to the option. On error, false is returned
+ * and an exception is thrown. */
+bool phongo_parse_read_preference(zval* options, zval** zreadPreference) /* {{{ */
+{
+ zval* option = NULL;
+
+ if (!options) {
+ return true;
+ }
+
+ if (Z_TYPE_P(options) != IS_ARRAY) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected options to be array, %s given", PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(options));
+ return false;
+ }
+
+ option = php_array_fetchc(options, "readPreference");
+
+ if (!option) {
+ return true;
+ }
+
+ if (Z_TYPE_P(option) != IS_OBJECT || !instanceof_function(Z_OBJCE_P(option), php_phongo_readpreference_ce)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"readPreference\" option to be %s, %s given", ZSTR_VAL(php_phongo_readpreference_ce->name), PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(option));
+ return false;
+ }
+
+ if (zreadPreference) {
+ *zreadPreference = option;
+ }
+
+ return true;
+} /* }}} */
+
+/* Parses the "session" option for an execute method. The client object should
+ * correspond to the Manager executing the operation and will be used to ensure
+ * that the session is correctly associated with that client. If mongoc_opts is
+ * not NULL, the option will be appended. If zsession is not NULL, it will be
+ * assigned to the option. On error, false is returned and an exception is
+ * thrown. */
+bool phongo_parse_session(zval* options, mongoc_client_t* client, bson_t* mongoc_opts, zval** zsession) /* {{{ */
+{
+ zval* option = NULL;
+ const mongoc_client_session_t* client_session;
+
+ if (!options) {
+ return true;
+ }
+
+ if (Z_TYPE_P(options) != IS_ARRAY) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected options to be array, %s given", PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(options));
+ return false;
+ }
+
+ option = php_array_fetchc(options, "session");
+
+ if (!option) {
+ return true;
+ }
+
+ if (Z_TYPE_P(option) != IS_OBJECT || !instanceof_function(Z_OBJCE_P(option), php_phongo_session_ce)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"session\" option to be %s, %s given", ZSTR_VAL(php_phongo_session_ce->name), PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(option));
+ return false;
+ }
+
+ client_session = Z_SESSION_OBJ_P(option)->client_session;
+
+ if (client != mongoc_client_session_get_client(client_session)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Cannot use Session started from a different Manager");
+ return false;
+ }
+
+ if (mongoc_opts && !mongoc_client_session_append(client_session, mongoc_opts, NULL)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Error appending \"session\" option");
+ return false;
+ }
+
+ if (zsession) {
+ *zsession = option;
+ }
+
+ return true;
+} /* }}} */
+
+/* Parses the "writeConcern" option for an execute method. If mongoc_opts is not
+ * NULL, the option will be appended. If zwriteConcern is not NULL, it will be
+ * assigned to the option. On error, false is returned and an exception is
+ * thrown. */
+static bool phongo_parse_write_concern(zval* options, bson_t* mongoc_opts, zval** zwriteConcern) /* {{{ */
+{
+ zval* option = NULL;
+ mongoc_write_concern_t* write_concern;
+
+ if (!options) {
+ return true;
+ }
+
+ if (Z_TYPE_P(options) != IS_ARRAY) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected options to be array, %s given", PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(options));
+ return false;
+ }
+
+ option = php_array_fetchc(options, "writeConcern");
+
+ if (!option) {
+ return true;
+ }
+
+ if (Z_TYPE_P(option) != IS_OBJECT || !instanceof_function(Z_OBJCE_P(option), php_phongo_writeconcern_ce)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"writeConcern\" option to be %s, %s given", ZSTR_VAL(php_phongo_writeconcern_ce->name), PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(option));
+ return false;
+ }
+
+ write_concern = Z_WRITECONCERN_OBJ_P(option)->write_concern;
+
+ if (mongoc_opts && !mongoc_write_concern_append(write_concern, mongoc_opts)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Error appending \"writeConcern\" option");
+ return false;
+ }
+
+ if (zwriteConcern) {
+ *zwriteConcern = option;
+ }
+
+ return true;
+}
+
+bool phongo_execute_bulk_write(zval* manager, const char* namespace, php_phongo_bulkwrite_t* bulk_write, zval* options, uint32_t server_id, zval* return_value) /* {{{ */
+{
+ mongoc_client_t* client = NULL;
+ bson_error_t error = { 0 };
+ int success;
+ bson_t reply = BSON_INITIALIZER;
+ mongoc_bulk_operation_t* bulk = bulk_write->bulk;
+ php_phongo_writeresult_t* writeresult;
+ zval* zwriteConcern = NULL;
+ zval* zsession = NULL;
+ const mongoc_write_concern_t* write_concern = NULL;
+
+ client = Z_MANAGER_OBJ_P(manager)->client;
+
+ if (bulk_write->executed) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "BulkWrite objects may only be executed once and this instance has already been executed");
+ return false;
+ }
+
+ if (!phongo_split_namespace(namespace, &bulk_write->database, &bulk_write->collection)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s: %s", "Invalid namespace provided", namespace);
+ return false;
+ }
+
+ if (!phongo_parse_session(options, client, NULL, &zsession)) {
+ /* Exception should already have been thrown */
+ return false;
+ }
+
+ if (!phongo_parse_write_concern(options, NULL, &zwriteConcern)) {
+ /* Exception should already have been thrown */
+ return false;
+ }
+
+ /* If a write concern was not specified, libmongoc will use the client's
+ * write concern; however, we should still fetch it for the write result.
+ * Additionally, we need to check if an unacknowledged write concern would
+ * conflict with an explicit session. */
+ write_concern = zwriteConcern ? Z_WRITECONCERN_OBJ_P(zwriteConcern)->write_concern : mongoc_client_get_write_concern(client);
+
+ if (zsession && !mongoc_write_concern_is_acknowledged(write_concern)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Cannot combine \"session\" option with an unacknowledged write concern");
+ return false;
+ }
+
+ mongoc_bulk_operation_set_database(bulk, bulk_write->database);
+ mongoc_bulk_operation_set_collection(bulk, bulk_write->collection);
+ mongoc_bulk_operation_set_client(bulk, client);
+ mongoc_bulk_operation_set_hint(bulk, server_id);
+
+ if (zsession) {
+ ZVAL_ZVAL(&bulk_write->session, zsession, 1, 0);
+ mongoc_bulk_operation_set_client_session(bulk, Z_SESSION_OBJ_P(zsession)->client_session);
+ }
+
+ if (zwriteConcern) {
+ mongoc_bulk_operation_set_write_concern(bulk, Z_WRITECONCERN_OBJ_P(zwriteConcern)->write_concern);
+ }
+
+ success = mongoc_bulk_operation_execute(bulk, &reply, &error);
+ bulk_write->executed = true;
+
+ writeresult = phongo_writeresult_init(return_value, &reply, manager, mongoc_bulk_operation_get_hint(bulk));
+ writeresult->write_concern = mongoc_write_concern_copy(write_concern);
+
+ /* A BulkWriteException is always thrown if mongoc_bulk_operation_execute()
+ * fails to ensure that the write result is accessible. If the error does
+ * not originate from the server (e.g. socket error), throw the appropriate
+ * exception first. It will be included in BulkWriteException's message and
+ * will also be accessible via Exception::getPrevious(). */
+ if (!success) {
+ if (error.domain != MONGOC_ERROR_SERVER && error.domain != MONGOC_ERROR_WRITE_CONCERN) {
+ phongo_throw_exception_from_bson_error_t_and_reply(&error, &reply);
+ }
+
+ /* Argument errors occur before command execution, so there is no need
+ * to layer this InvalidArgumentException behind a BulkWriteException.
+ * In practice, this will be a "Cannot do an empty bulk write" error. */
+ if (error.domain == MONGOC_ERROR_COMMAND && error.code == MONGOC_ERROR_COMMAND_INVALID_ARG) {
+ goto cleanup;
+ }
+
+ if (EG(exception)) {
+ char* message;
+
+ (void) spprintf(&message, 0, "Bulk write failed due to previous %s: %s", PHONGO_ZVAL_EXCEPTION_NAME(EG(exception)), error.message);
+ zend_throw_exception(php_phongo_bulkwriteexception_ce, message, 0);
+ efree(message);
+ } else {
+ zend_throw_exception(php_phongo_bulkwriteexception_ce, error.message, error.code);
+ }
+
+ /* Ensure error labels are added to the final BulkWriteException. If a
+ * previous exception was also thrown, error labels will already have
+ * been added by phongo_throw_exception_from_bson_error_t_and_reply. */
+ phongo_exception_add_error_labels(&reply);
+ phongo_add_exception_prop(ZEND_STRL("writeResult"), return_value);
+ }
+
+cleanup:
+ bson_destroy(&reply);
+
+ return success;
+} /* }}} */
+
+bool phongo_execute_command(zval* manager, php_phongo_command_type_t type, const char* db, zval* zcommand, zval* options, uint32_t server_id, zval* return_value) /* {{{ */
+{
+ mongoc_client_t* client;
+ const php_phongo_command_t* command;
+ bson_iter_t iter;
+ bson_t reply;
+ bson_error_t error = { 0 };
+ bson_t opts = BSON_INITIALIZER;
+ mongoc_cursor_t* cmd_cursor;
+ zval* zreadPreference = NULL;
+ zval* zsession = NULL;
+ bool result = false;
+ bool free_reply = false;
+ bool free_zsession = false;
+ bool is_unacknowledged_write_concern = false;
+
+ client = Z_MANAGER_OBJ_P(manager)->client;
+ command = Z_COMMAND_OBJ_P(zcommand);
+
+ if ((type & PHONGO_OPTION_READ_CONCERN) && !phongo_parse_read_concern(options, &opts)) {
+ /* Exception should already have been thrown */
+ goto cleanup;
+ }
+
+ if ((type & PHONGO_OPTION_READ_PREFERENCE) && !phongo_parse_read_preference(options, &zreadPreference)) {
+ /* Exception should already have been thrown */
+ goto cleanup;
+ }
+
+ if (!phongo_parse_session(options, client, &opts, &zsession)) {
+ /* Exception should already have been thrown */
+ goto cleanup;
+ }
+
+ if (type & PHONGO_OPTION_WRITE_CONCERN) {
+ zval* zwriteConcern = NULL;
+
+ if (!phongo_parse_write_concern(options, &opts, &zwriteConcern)) {
+ /* Exception should already have been thrown */
+ goto cleanup;
+ }
+
+ /* Determine if the explicit or inherited write concern is
+ * unacknowledged so that we can ensure it does not conflict with an
+ * explicit or implicit session. */
+ if (zwriteConcern) {
+ is_unacknowledged_write_concern = !mongoc_write_concern_is_acknowledged(Z_WRITECONCERN_OBJ_P(zwriteConcern)->write_concern);
+ } else if (type != PHONGO_COMMAND_RAW) {
+ is_unacknowledged_write_concern = !mongoc_write_concern_is_acknowledged(mongoc_client_get_write_concern(client));
+ }
+ }
+
+ if (zsession && is_unacknowledged_write_concern) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Cannot combine \"session\" option with an unacknowledged write concern");
+ goto cleanup;
+ }
+
+ /* If an explicit session was not provided and the effective write concern
+ * is not unacknowledged, attempt to create an implicit client session
+ * (ignoring any errors). */
+ if (!zsession && !is_unacknowledged_write_concern) {
+ zsession = phongo_create_implicit_session(manager);
+
+ if (zsession) {
+ free_zsession = true;
+
+ if (!mongoc_client_session_append(Z_SESSION_OBJ_P(zsession)->client_session, &opts, NULL)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Error appending implicit \"sessionId\" option");
+ goto cleanup;
+ }
+ }
+ }
+
+ if (!BSON_APPEND_INT32(&opts, "serverId", server_id)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Error appending \"serverId\" option");
+ goto cleanup;
+ }
+
+ /* Although "opts" already always includes the serverId option, the read
+ * preference is added to the command parts, which is relevant for mongos
+ * command construction. */
+ switch (type) {
+ case PHONGO_COMMAND_RAW:
+ result = mongoc_client_command_with_opts(client, db, command->bson, phongo_read_preference_from_zval(zreadPreference), &opts, &reply, &error);
+ break;
+ case PHONGO_COMMAND_READ:
+ result = mongoc_client_read_command_with_opts(client, db, command->bson, phongo_read_preference_from_zval(zreadPreference), &opts, &reply, &error);
+ break;
+ case PHONGO_COMMAND_WRITE:
+ result = mongoc_client_write_command_with_opts(client, db, command->bson, &opts, &reply, &error);
+ break;
+ case PHONGO_COMMAND_READ_WRITE:
+ /* We can pass NULL as readPreference, as this argument was added historically, but has no function */
+ result = mongoc_client_read_write_command_with_opts(client, db, command->bson, NULL, &opts, &reply, &error);
+ break;
+ default:
+ /* Should never happen, but if it does: exception */
+ phongo_throw_exception(PHONGO_ERROR_LOGIC, "Type '%d' should never have been passed to phongo_execute_command, please file a bug report", type);
+ goto cleanup;
+ }
+
+ free_reply = true;
+
+ if (!result) {
+ phongo_throw_exception_from_bson_error_t_and_reply(&error, &reply);
+ goto cleanup;
+ }
+
+ /* According to mongoc_cursor_new_from_command_reply_with_opts(), the reply
+ * bson_t is ultimately destroyed on both success and failure. */
+ if (bson_iter_init_find(&iter, &reply, "cursor") && BSON_ITER_HOLDS_DOCUMENT(&iter)) {
+ bson_t initial_reply = BSON_INITIALIZER;
+ bson_t cursor_opts = BSON_INITIALIZER;
+ bson_error_t error = { 0 };
+
+ bson_copy_to(&reply, &initial_reply);
+
+ bson_append_int32(&cursor_opts, "serverId", -1, server_id);
+
+ if (command->max_await_time_ms) {
+ bson_append_bool(&cursor_opts, "awaitData", -1, 1);
+ bson_append_int64(&cursor_opts, "maxAwaitTimeMS", -1, command->max_await_time_ms);
+ bson_append_bool(&cursor_opts, "tailable", -1, 1);
+ }
+
+ if (command->batch_size) {
+ bson_append_int64(&cursor_opts, "batchSize", -1, command->batch_size);
+ }
+
+ if (zsession && !mongoc_client_session_append(Z_SESSION_OBJ_P(zsession)->client_session, &cursor_opts, &error)) {
+ phongo_throw_exception_from_bson_error_t(&error);
+ bson_destroy(&initial_reply);
+ bson_destroy(&cursor_opts);
+ result = false;
+ goto cleanup;
+ }
+
+ cmd_cursor = mongoc_cursor_new_from_command_reply_with_opts(client, &initial_reply, &cursor_opts);
+ bson_destroy(&cursor_opts);
+ } else {
+ bson_t cursor_opts = BSON_INITIALIZER;
+ bson_t* wrapped_reply = create_wrapped_command_envelope(db, &reply);
+
+ bson_append_int32(&cursor_opts, "serverId", -1, server_id);
+ cmd_cursor = mongoc_cursor_new_from_command_reply_with_opts(client, wrapped_reply, &cursor_opts);
+ bson_destroy(&cursor_opts);
+ }
+
+ phongo_cursor_init_for_command(return_value, manager, cmd_cursor, db, zcommand, zreadPreference, zsession);
+
+cleanup:
+ bson_destroy(&opts);
+
+ if (free_reply) {
+ bson_destroy(&reply);
+ }
+
+ if (free_zsession) {
+ zval_ptr_dtor(zsession);
+ efree(zsession);
+ }
+
+ return result;
+} /* }}} */
+
+bool phongo_execute_query(zval* manager, const char* namespace, zval* zquery, zval* options, uint32_t server_id, zval* return_value) /* {{{ */
+{
+ mongoc_client_t* client;
+ const php_phongo_query_t* query;
+ bson_t opts = BSON_INITIALIZER;
+ mongoc_cursor_t* cursor;
+ char* dbname;
+ char* collname;
+ mongoc_collection_t* collection;
+ zval* zreadPreference = NULL;
+ zval* zsession = NULL;
+
+ client = Z_MANAGER_OBJ_P(manager)->client;
+
+ if (!phongo_split_namespace(namespace, &dbname, &collname)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s: %s", "Invalid namespace provided", namespace);
+ return false;
+ }
+ collection = mongoc_client_get_collection(client, dbname, collname);
+ efree(dbname);
+ efree(collname);
+
+ query = Z_QUERY_OBJ_P(zquery);
+
+ bson_copy_to(query->opts, &opts);
+
+ if (query->read_concern) {
+ mongoc_collection_set_read_concern(collection, query->read_concern);
+ }
+
+ if (!phongo_parse_read_preference(options, &zreadPreference)) {
+ /* Exception should already have been thrown */
+ mongoc_collection_destroy(collection);
+ bson_destroy(&opts);
+ return false;
+ }
+
+ if (!phongo_parse_session(options, client, &opts, &zsession)) {
+ /* Exception should already have been thrown */
+ mongoc_collection_destroy(collection);
+ bson_destroy(&opts);
+ return false;
+ }
+
+ if (!BSON_APPEND_INT32(&opts, "serverId", server_id)) {
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Error appending \"serverId\" option");
+ mongoc_collection_destroy(collection);
+ bson_destroy(&opts);
+ return false;
+ }
+
+ cursor = mongoc_collection_find_with_opts(collection, query->filter, &opts, phongo_read_preference_from_zval(zreadPreference));
+ mongoc_collection_destroy(collection);
+ bson_destroy(&opts);
+
+ /* maxAwaitTimeMS must be set before the cursor is sent */
+ if (query->max_await_time_ms) {
+ mongoc_cursor_set_max_await_time_ms(cursor, query->max_await_time_ms);
+ }
+
+ if (!phongo_cursor_advance_and_check_for_error(cursor)) {
+ mongoc_cursor_destroy(cursor);
+ return false;
+ }
+
+ phongo_cursor_init_for_query(return_value, manager, cursor, namespace, zquery, zreadPreference, zsession);
+
+ return true;
+} /* }}} */
diff --git a/mongodb-1.13.0/src/phongo_execute.h b/mongodb-1.13.0/src/phongo_execute.h
new file mode 100644
index 00000000..47312b9e
--- /dev/null
+++ b/mongodb-1.13.0/src/phongo_execute.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2022-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PHONGO_EXECUTE_H
+#define PHONGO_EXECUTE_H
+
+#include "bson/bson.h"
+#include "mongoc/mongoc.h"
+
+#include <php.h>
+
+/* This enum is used for processing options and selecting a libmongoc function
+ * to use in phongo_execute_command. The values are important, as READ and WRITE
+ * are also used as a bit field to determine whether readPreference,
+ * readConcern, and writeConcern options are parsed. */
+typedef enum {
+ PHONGO_OPTION_READ_CONCERN = 0x01,
+ PHONGO_OPTION_READ_PREFERENCE = 0x02,
+ PHONGO_OPTION_WRITE_CONCERN = 0x04,
+ PHONGO_COMMAND_RAW = 0x07,
+ PHONGO_COMMAND_READ = 0x03,
+ PHONGO_COMMAND_WRITE = 0x04,
+ PHONGO_COMMAND_READ_WRITE = 0x05,
+} php_phongo_command_type_t;
+
+bool phongo_execute_bulk_write(zval* manager, const char* namespace, php_phongo_bulkwrite_t* bulk_write, zval* zwriteConcern, uint32_t server_id, zval* return_value);
+bool phongo_execute_command(zval* manager, php_phongo_command_type_t type, const char* db, zval* zcommand, zval* zreadPreference, uint32_t server_id, zval* return_value);
+bool phongo_execute_query(zval* manager, const char* namespace, zval* zquery, zval* zreadPreference, uint32_t server_id, zval* return_value);
+
+bool phongo_parse_read_preference(zval* options, zval** zreadPreference);
+bool phongo_parse_session(zval* options, mongoc_client_t* client, bson_t* mongoc_opts, zval** zsession);
+
+#endif /* PHONGO_EXECUTE_H */
diff --git a/mongodb-1.13.0/src/phongo_ini.c b/mongodb-1.13.0/src/phongo_ini.c
new file mode 100644
index 00000000..c0bad3b5
--- /dev/null
+++ b/mongodb-1.13.0/src/phongo_ini.c
@@ -0,0 +1,146 @@
+/*
+ * Copyright 2021-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bson/bson.h"
+#include "mongoc/mongoc.h"
+
+#include <php.h>
+#include <main/php_open_temporary_file.h>
+#include <ext/date/php_date.h>
+
+#include "php_phongo.h"
+#include "phongo_ini.h"
+
+extern bool mongoc_global_mock_service_id;
+
+ZEND_EXTERN_MODULE_GLOBALS(mongodb)
+
+static void phongo_log(mongoc_log_level_t log_level, const char* log_domain, const char* message, void* user_data)
+{
+ struct timeval tv;
+ time_t t;
+ zend_long tu;
+ zend_string* dt;
+
+ bson_gettimeofday(&tv);
+ t = tv.tv_sec;
+ tu = tv.tv_usec;
+
+ dt = php_format_date((char*) ZEND_STRL("Y-m-d\\TH:i:s"), t, 0);
+
+ fprintf(MONGODB_G(debug_fd), "[%s.%06" PHONGO_LONG_FORMAT "+00:00] %10s: %-8s> %s\n", ZSTR_VAL(dt), tu, log_domain, mongoc_log_level_str(log_level), message);
+ fflush(MONGODB_G(debug_fd));
+ efree(dt);
+}
+
+void phongo_log_disable(FILE* stream)
+{
+ mongoc_log_trace_disable();
+ mongoc_log_set_handler(NULL, NULL);
+
+ /* Close any previously opened log file (excluding stderr/stdout) */
+ if (stream && stream != stderr && stream != stdout) {
+ fclose(stream);
+ }
+}
+
+static PHP_INI_MH(OnUpdateDebug)
+{
+ char* tmp_dir = NULL;
+
+ phongo_log_disable(MONGODB_G(debug_fd));
+ MONGODB_G(debug_fd) = NULL;
+
+ if (!new_value || (new_value && !ZSTR_VAL(new_value)[0]) || strcasecmp("0", ZSTR_VAL(new_value)) == 0 || strcasecmp("off", ZSTR_VAL(new_value)) == 0 || strcasecmp("no", ZSTR_VAL(new_value)) == 0 || strcasecmp("false", ZSTR_VAL(new_value)) == 0) {
+ return OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
+ }
+
+ if (strcasecmp(ZSTR_VAL(new_value), "stderr") == 0) {
+ MONGODB_G(debug_fd) = stderr;
+ } else if (strcasecmp(ZSTR_VAL(new_value), "stdout") == 0) {
+ MONGODB_G(debug_fd) = stdout;
+ } else if (
+ strcasecmp("1", ZSTR_VAL(new_value)) == 0 ||
+ strcasecmp("on", ZSTR_VAL(new_value)) == 0 ||
+ strcasecmp("yes", ZSTR_VAL(new_value)) == 0 ||
+ strcasecmp("true", ZSTR_VAL(new_value)) == 0) {
+
+ tmp_dir = NULL;
+ } else {
+ tmp_dir = ZSTR_VAL(new_value);
+ }
+
+ if (!MONGODB_G(debug_fd)) {
+ time_t t;
+ int fd = -1;
+ char* prefix;
+ int len;
+ zend_string* filename;
+
+ time(&t);
+ len = spprintf(&prefix, 0, "PHONGO-%ld", t);
+
+ fd = php_open_temporary_fd(tmp_dir, prefix, &filename);
+ if (fd != -1) {
+ const char* path = ZSTR_VAL(filename);
+ MONGODB_G(debug_fd) = VCWD_FOPEN(path, "a");
+ }
+ efree(filename);
+ efree(prefix);
+ close(fd);
+ }
+
+ mongoc_log_trace_enable();
+ mongoc_log_set_handler(phongo_log, NULL);
+
+ return OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
+}
+
+static PHP_INI_MH(OnUpdateMockServiceId)
+{
+ mongoc_global_mock_service_id = zend_ini_parse_bool(new_value);
+
+ return SUCCESS;
+}
+
+static PHP_INI_DISP(DisplayMockServiceId)
+{
+ if (mongoc_global_mock_service_id) {
+ ZEND_PUTS("On");
+ } else {
+ ZEND_PUTS("Off");
+ }
+}
+
+void phongo_display_ini_entries(ZEND_MODULE_INFO_FUNC_ARGS)
+{
+ DISPLAY_INI_ENTRIES();
+}
+
+void phongo_register_ini_entries(INIT_FUNC_ARGS)
+{
+ PHP_INI_BEGIN()
+ STD_PHP_INI_ENTRY("mongodb.debug", "", PHP_INI_ALL, OnUpdateDebug, debug, zend_mongodb_globals, mongodb_globals)
+ PHP_INI_ENTRY_EX("mongodb.mock_service_id", "0", PHP_INI_ALL, OnUpdateMockServiceId, DisplayMockServiceId)
+ PHP_INI_END()
+
+ REGISTER_INI_ENTRIES();
+}
+
+void phongo_unregister_ini_entries(SHUTDOWN_FUNC_ARGS)
+{
+ UNREGISTER_INI_ENTRIES();
+}
diff --git a/mongodb-1.13.0/src/phongo_ini.h b/mongodb-1.13.0/src/phongo_ini.h
new file mode 100644
index 00000000..fc0208f8
--- /dev/null
+++ b/mongodb-1.13.0/src/phongo_ini.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2021-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PHONGO_INI_H
+#define PHONGO_INI_H
+
+#include <php.h>
+#include <stdio.h>
+
+void phongo_log_disable(FILE* stream);
+void phongo_display_ini_entries(ZEND_MODULE_INFO_FUNC_ARGS);
+void phongo_register_ini_entries(INIT_FUNC_ARGS);
+void phongo_unregister_ini_entries(SHUTDOWN_FUNC_ARGS);
+
+#endif /* PHONGO_INI_H */
diff --git a/mongodb-1.13.0/src/phongo_structs.h b/mongodb-1.13.0/src/phongo_structs.h
new file mode 100644
index 00000000..8d37ef40
--- /dev/null
+++ b/mongodb-1.13.0/src/phongo_structs.h
@@ -0,0 +1,355 @@
+/*
+ * Copyright 2015-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PHONGO_STRUCTS_H
+#define PHONGO_STRUCTS_H
+
+#include "bson/bson.h"
+#include "mongoc/mongoc.h"
+
+#include <php.h>
+
+#include "phongo_bson.h"
+
+typedef struct {
+ mongoc_bulk_operation_t* bulk;
+ size_t num_ops;
+ bool ordered;
+ int bypass;
+ char* database;
+ char* collection;
+ bool executed;
+ zval session;
+ zend_object std;
+} php_phongo_bulkwrite_t;
+
+typedef struct {
+ mongoc_client_encryption_t* client_encryption;
+ zval key_vault_client_manager;
+ zend_object std;
+} php_phongo_clientencryption_t;
+
+typedef struct {
+ bson_t* bson;
+ uint32_t max_await_time_ms;
+ uint32_t batch_size;
+ zend_object std;
+} php_phongo_command_t;
+
+typedef struct {
+ mongoc_cursor_t* cursor;
+ zval manager;
+ int created_by_pid;
+ uint32_t server_id;
+ bool advanced;
+ php_phongo_bson_state visitor_data;
+ long current;
+ char* database;
+ char* collection;
+ zval query;
+ zval command;
+ zval read_preference;
+ zval session;
+ zend_object std;
+} php_phongo_cursor_t;
+
+typedef struct {
+ bool initialized;
+ int64_t id;
+ HashTable* properties;
+ zend_object std;
+} php_phongo_cursorid_t;
+
+typedef struct {
+ mongoc_client_t* client;
+ int created_by_pid;
+ char* client_hash;
+ size_t client_hash_len;
+ bool use_persistent_client;
+ zval key_vault_client_manager;
+ HashTable* subscribers;
+ zend_object std;
+} php_phongo_manager_t;
+
+typedef struct {
+ bson_t* filter;
+ bson_t* opts;
+ mongoc_read_concern_t* read_concern;
+ uint32_t max_await_time_ms;
+ zend_object std;
+} php_phongo_query_t;
+
+typedef struct {
+ mongoc_read_concern_t* read_concern;
+ HashTable* properties;
+ zend_object std;
+} php_phongo_readconcern_t;
+
+typedef struct {
+ mongoc_read_prefs_t* read_preference;
+ HashTable* properties;
+ zend_object std;
+} php_phongo_readpreference_t;
+
+typedef struct {
+ zval manager;
+ int created_by_pid;
+ uint32_t server_id;
+ zend_object std;
+} php_phongo_server_t;
+
+typedef struct {
+ mongoc_server_api_t* server_api;
+ HashTable* properties;
+ zend_object std;
+} php_phongo_serverapi_t;
+
+typedef struct {
+ mongoc_server_description_t* server_description;
+ HashTable* properties;
+ zend_object std;
+} php_phongo_serverdescription_t;
+
+typedef struct {
+ mongoc_client_session_t* client_session;
+ zval manager;
+ int created_by_pid;
+ zend_object std;
+} php_phongo_session_t;
+
+typedef struct {
+ mongoc_topology_description_t* topology_description;
+ HashTable* properties;
+ zend_object std;
+} php_phongo_topologydescription_t;
+
+typedef struct {
+ HashTable* properties;
+ mongoc_write_concern_t* write_concern;
+ zend_object std;
+} php_phongo_writeconcern_t;
+
+typedef struct {
+ int code;
+ char* message;
+ zval info;
+ zend_object std;
+} php_phongo_writeconcernerror_t;
+
+typedef struct {
+ int code;
+ char* message;
+ zval info;
+ uint32_t index;
+ zend_object std;
+} php_phongo_writeerror_t;
+
+typedef struct {
+ mongoc_write_concern_t* write_concern;
+ bson_t* reply;
+ zval manager;
+ uint32_t server_id;
+ zend_object std;
+} php_phongo_writeresult_t;
+
+typedef struct {
+ char* data;
+ int data_len;
+ uint8_t type;
+ HashTable* properties;
+ zend_object std;
+} php_phongo_binary_t;
+
+typedef struct {
+ char* ref;
+ size_t ref_len;
+ char id[25];
+ HashTable* properties;
+ zend_object std;
+} php_phongo_dbpointer_t;
+
+typedef struct {
+ bool initialized;
+ bson_decimal128_t decimal;
+ HashTable* properties;
+ zend_object std;
+} php_phongo_decimal128_t;
+
+typedef struct {
+ bool initialized;
+ int64_t integer;
+ HashTable* properties;
+ zend_object std;
+} php_phongo_int64_t;
+
+typedef struct {
+ char* code;
+ size_t code_len;
+ bson_t* scope;
+ HashTable* properties;
+ zend_object std;
+} php_phongo_javascript_t;
+
+typedef struct {
+ zend_object std;
+} php_phongo_maxkey_t;
+
+typedef struct {
+ zend_object std;
+} php_phongo_minkey_t;
+
+typedef struct {
+ bool initialized;
+ char oid[25];
+ HashTable* properties;
+ zend_object std;
+} php_phongo_objectid_t;
+
+typedef struct {
+ char* pattern;
+ int pattern_len;
+ char* flags;
+ int flags_len;
+ HashTable* properties;
+ zend_object std;
+} php_phongo_regex_t;
+
+typedef struct {
+ char* symbol;
+ size_t symbol_len;
+ HashTable* properties;
+ zend_object std;
+} php_phongo_symbol_t;
+
+typedef struct {
+ bool initialized;
+ uint32_t increment;
+ uint32_t timestamp;
+ HashTable* properties;
+ zend_object std;
+} php_phongo_timestamp_t;
+
+typedef struct {
+ zend_object std;
+} php_phongo_undefined_t;
+
+typedef struct {
+ bool initialized;
+ int64_t milliseconds;
+ HashTable* properties;
+ zend_object std;
+} php_phongo_utcdatetime_t;
+
+typedef struct {
+ zval manager;
+ char* command_name;
+ uint32_t server_id;
+ uint64_t operation_id;
+ uint64_t request_id;
+ uint64_t duration_micros;
+ bson_t* reply;
+ zval z_error;
+ bool has_service_id;
+ bson_oid_t service_id;
+ zend_object std;
+} php_phongo_commandfailedevent_t;
+
+typedef struct {
+ zval manager;
+ char* command_name;
+ uint32_t server_id;
+ uint64_t operation_id;
+ uint64_t request_id;
+ bson_t* command;
+ char* database_name;
+ bool has_service_id;
+ bson_oid_t service_id;
+ zend_object std;
+} php_phongo_commandstartedevent_t;
+
+typedef struct {
+ zval manager;
+ char* command_name;
+ uint32_t server_id;
+ uint64_t operation_id;
+ uint64_t request_id;
+ uint64_t duration_micros;
+ bson_t* reply;
+ bool has_service_id;
+ bson_oid_t service_id;
+ zend_object std;
+} php_phongo_commandsucceededevent_t;
+
+typedef struct {
+ bson_oid_t topology_id;
+ mongoc_host_list_t host;
+ mongoc_server_description_t* new_server_description;
+ mongoc_server_description_t* old_server_description;
+ zend_object std;
+} php_phongo_serverchangedevent_t;
+
+typedef struct {
+ bson_oid_t topology_id;
+ mongoc_host_list_t host;
+ zend_object std;
+} php_phongo_serverclosedevent_t;
+
+typedef struct {
+ bool awaited;
+ uint64_t duration_micros;
+ zval z_error;
+ mongoc_host_list_t host;
+ zend_object std;
+} php_phongo_serverheartbeatfailedevent_t;
+
+typedef struct {
+ bool awaited;
+ mongoc_host_list_t host;
+ zend_object std;
+} php_phongo_serverheartbeatstartedevent_t;
+
+typedef struct {
+ bool awaited;
+ uint64_t duration_micros;
+ mongoc_host_list_t host;
+ bson_t* reply;
+ zend_object std;
+} php_phongo_serverheartbeatsucceededevent_t;
+
+typedef struct {
+ bson_oid_t topology_id;
+ mongoc_host_list_t host;
+ zend_object std;
+} php_phongo_serveropeningevent_t;
+
+typedef struct {
+ bson_oid_t topology_id;
+ mongoc_topology_description_t* new_topology_description;
+ mongoc_topology_description_t* old_topology_description;
+ zend_object std;
+} php_phongo_topologychangedevent_t;
+
+typedef struct {
+ bson_oid_t topology_id;
+ zend_object std;
+} php_phongo_topologyclosedevent_t;
+
+typedef struct {
+ bson_oid_t topology_id;
+ zend_object std;
+} php_phongo_topologyopeningevent_t;
+
+#endif /* PHONGO_STRUCTS */
diff --git a/mongodb-1.13.0/src/phongo_util.c b/mongodb-1.13.0/src/phongo_util.c
new file mode 100644
index 00000000..cc4f168b
--- /dev/null
+++ b/mongodb-1.13.0/src/phongo_util.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2022-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bson/bson.h"
+#include "mongoc/mongoc.h"
+
+#include <php.h>
+
+#include "phongo_util.h"
+
+/* If options is not an array, insert it as a field in a newly allocated array.
+ * This may be used to convert legacy options (e.g. ReadPreference option for
+ * an executeQuery method) into an options array.
+ *
+ * A pointer to the array zval will always be returned. If allocated is set to
+ * true, php_phongo_prep_legacy_option_free() should be used to free the array
+ * zval later. */
+zval* php_phongo_prep_legacy_option(zval* options, const char* key, bool* allocated) /* {{{ */
+{
+ *allocated = false;
+
+ if (options && Z_TYPE_P(options) != IS_ARRAY) {
+ zval* new_options = ecalloc(1, sizeof(zval));
+
+ array_init_size(new_options, 1);
+ add_assoc_zval(new_options, key, options);
+ Z_ADDREF_P(options);
+ *allocated = true;
+
+ return new_options;
+ }
+
+ return options;
+} /* }}} */
+
+void php_phongo_prep_legacy_option_free(zval* options) /* {{{ */
+{
+ zval_ptr_dtor(options);
+ efree(options);
+} /* }}} */
+
+bool php_phongo_parse_int64(int64_t* retval, const char* data, size_t data_len) /* {{{ */
+{
+ int64_t value;
+ char* endptr = NULL;
+
+ /* bson_ascii_strtoll() sets errno if conversion fails. If conversion
+ * succeeds, we still want to ensure that the entire string was parsed. */
+ value = bson_ascii_strtoll(data, &endptr, 10);
+
+ if (errno || (endptr && endptr != ((const char*) data + data_len))) {
+ return false;
+ }
+
+ *retval = value;
+
+ return true;
+} /* }}} */
+
+/* Splits a namespace name into the database and collection names, allocated with estrdup. */
+bool phongo_split_namespace(const char* namespace, char** dbname, char** cname) /* {{{ */
+{
+ char* dot = strchr(namespace, '.');
+
+ if (!dot) {
+ return false;
+ }
+
+ if (cname) {
+ *cname = estrdup(namespace + (dot - namespace) + 1);
+ }
+ if (dbname) {
+ *dbname = estrndup(namespace, dot - namespace);
+ }
+
+ return true;
+} /* }}} */
diff --git a/mongodb-1.13.0/src/phongo_util.h b/mongodb-1.13.0/src/phongo_util.h
new file mode 100644
index 00000000..41914480
--- /dev/null
+++ b/mongodb-1.13.0/src/phongo_util.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2022-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PHONGO_UTIL_H
+#define PHONGO_UTIL_H
+
+zval* php_phongo_prep_legacy_option(zval* options, const char* key, bool* allocated);
+void php_phongo_prep_legacy_option_free(zval* options);
+
+bool php_phongo_parse_int64(int64_t* retval, const char* data, size_t data_len);
+
+bool phongo_split_namespace(const char* namespace, char** dbname, char** cname);
+
+#endif /* PHONGO_UTIL_H */
diff --git a/mongodb-1.13.0/src/phongo_version.h b/mongodb-1.13.0/src/phongo_version.h
new file mode 100644
index 00000000..db15d176
--- /dev/null
+++ b/mongodb-1.13.0/src/phongo_version.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2014-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PHONGO_VERSION_H
+#define PHONGO_VERSION_H
+
+/* clang-format off */
+#define PHP_MONGODB_VERSION "1.13.0"
+#define PHP_MONGODB_STABILITY "stable"
+#define PHP_MONGODB_VERSION_DESC 1,13,0,1
+/* clang-format on */
+
+#endif /* PHONGO_VERSION_H */
diff --git a/mongodb-1.12.0/tests/apm/bug0950-001.phpt b/mongodb-1.13.0/tests/apm/bug0950-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/apm/bug0950-001.phpt
rename to mongodb-1.13.0/tests/apm/bug0950-001.phpt
diff --git a/mongodb-1.12.0/tests/apm/bug0950-002.phpt b/mongodb-1.13.0/tests/apm/bug0950-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/apm/bug0950-002.phpt
rename to mongodb-1.13.0/tests/apm/bug0950-002.phpt
diff --git a/mongodb-1.12.0/tests/apm/commandFailedEvent-001.phpt b/mongodb-1.13.0/tests/apm/commandFailedEvent-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/apm/commandFailedEvent-001.phpt
rename to mongodb-1.13.0/tests/apm/commandFailedEvent-001.phpt
diff --git a/mongodb-1.12.0/tests/apm/commandFailedEvent-002.phpt b/mongodb-1.13.0/tests/apm/commandFailedEvent-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/apm/commandFailedEvent-002.phpt
rename to mongodb-1.13.0/tests/apm/commandFailedEvent-002.phpt
diff --git a/mongodb-1.12.0/tests/apm/commandFailedEvent-debug-001.phpt b/mongodb-1.13.0/tests/apm/commandFailedEvent-debug-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/apm/commandFailedEvent-debug-001.phpt
rename to mongodb-1.13.0/tests/apm/commandFailedEvent-debug-001.phpt
diff --git a/mongodb-1.13.0/tests/apm/commandFailedEvent-getReply-001.phpt b/mongodb-1.13.0/tests/apm/commandFailedEvent-getReply-001.phpt
new file mode 100644
index 00000000..6b1901f9
--- /dev/null
+++ b/mongodb-1.13.0/tests/apm/commandFailedEvent-getReply-001.phpt
@@ -0,0 +1,59 @@
+--TEST--
+MongoDB\Driver\Monitoring\CommandFailedEvent::getReply()
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_live(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+
+class MySubscriber implements MongoDB\Driver\Monitoring\CommandSubscriber
+{
+ public function commandStarted( \MongoDB\Driver\Monitoring\CommandStartedEvent $event )
+ {
+ echo "started: ", $event->getCommandName(), "\n";
+ }
+
+ public function commandSucceeded( \MongoDB\Driver\Monitoring\CommandSucceededEvent $event )
+ {
+ var_dump($event);
+ }
+
+ public function commandFailed( \MongoDB\Driver\Monitoring\CommandFailedEvent $event )
+ {
+ echo "failed: ", $event->getCommandName(), "\n";
+ var_dump($event->getReply());
+ }
+}
+
+$subscriber = new MySubscriber;
+
+MongoDB\Driver\Monitoring\addSubscriber( $subscriber );
+
+$command = new MongoDB\Driver\Command([
+ 'findAndModify' => COLLECTION_NAME,
+ 'query' => ['_id' => 'foo'],
+ 'upsert' => true,
+ 'new' => true,
+]);
+
+try {
+ $manager->executeWriteCommand(DATABASE_NAME, $command);
+} catch (MongoDB\Driver\Exception\CommandException $e) {}
+
+?>
+--EXPECTF--
+started: findAndModify
+failed: findAndModify
+object(stdClass)#%d (%d) {%A
+ ["ok"]=>
+ float(0)
+ ["errmsg"]=>
+ string(49) "Either an update or remove=true must be specified"
+ ["code"]=>
+ int(9)
+ ["codeName"]=>
+ string(13) "FailedToParse"%A
+}
diff --git a/mongodb-1.12.0/tests/apm/commandFailedEvent-getServiceId-001.phpt b/mongodb-1.13.0/tests/apm/commandFailedEvent-getServiceId-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/apm/commandFailedEvent-getServiceId-001.phpt
rename to mongodb-1.13.0/tests/apm/commandFailedEvent-getServiceId-001.phpt
diff --git a/mongodb-1.12.0/tests/apm/commandFailedEvent-getServiceId-002.phpt b/mongodb-1.13.0/tests/apm/commandFailedEvent-getServiceId-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/apm/commandFailedEvent-getServiceId-002.phpt
rename to mongodb-1.13.0/tests/apm/commandFailedEvent-getServiceId-002.phpt
diff --git a/mongodb-1.12.0/tests/apm/commandStartedEvent-001.phpt b/mongodb-1.13.0/tests/apm/commandStartedEvent-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/apm/commandStartedEvent-001.phpt
rename to mongodb-1.13.0/tests/apm/commandStartedEvent-001.phpt
diff --git a/mongodb-1.13.0/tests/apm/commandStartedEvent-002.phpt b/mongodb-1.13.0/tests/apm/commandStartedEvent-002.phpt
new file mode 100644
index 00000000..acce0c77
--- /dev/null
+++ b/mongodb-1.13.0/tests/apm/commandStartedEvent-002.phpt
@@ -0,0 +1,41 @@
+--TEST--
+MongoDB\Driver\Monitoring\CommandStartedEvent during mongoc_client_destroy()
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_not_live(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+class MySubscriber implements MongoDB\Driver\Monitoring\CommandSubscriber
+{
+ public function commandStarted(MongoDB\Driver\Monitoring\CommandStartedEvent $event)
+ {
+ printf("Observed commandStarted for %s\n", $event->getCommandName());
+ }
+
+ public function commandSucceeded(MongoDB\Driver\Monitoring\CommandSucceededEvent $event) {}
+
+ public function commandFailed(MongoDB\Driver\Monitoring\CommandFailedEvent $event) {}
+}
+
+$manager = create_test_manager(URI, [], ['disableClientPersistence' => true]);
+
+$singleSubscriber = new MySubscriber();
+$manager->addSubscriber($singleSubscriber);
+
+$command = new MongoDB\Driver\Command(['ping' => 1]);
+$manager->executeCommand(DATABASE_NAME, $command);
+
+/* Events dispatched during mongoc_client_destroy can only be observed before
+ * RSHUTDOWN. This means that we must use a non-persistent client and free it
+ * before the script ends. */
+unset($manager);
+
+?>
+===DONE===
+--EXPECT--
+Observed commandStarted for ping
+Observed commandStarted for endSessions
+===DONE===
diff --git a/mongodb-1.12.0/tests/apm/commandStartedEvent-debug-001.phpt b/mongodb-1.13.0/tests/apm/commandStartedEvent-debug-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/apm/commandStartedEvent-debug-001.phpt
rename to mongodb-1.13.0/tests/apm/commandStartedEvent-debug-001.phpt
diff --git a/mongodb-1.12.0/tests/apm/commandStartedEvent-getServiceId-001.phpt b/mongodb-1.13.0/tests/apm/commandStartedEvent-getServiceId-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/apm/commandStartedEvent-getServiceId-001.phpt
rename to mongodb-1.13.0/tests/apm/commandStartedEvent-getServiceId-001.phpt
diff --git a/mongodb-1.12.0/tests/apm/commandStartedEvent-getServiceId-002.phpt b/mongodb-1.13.0/tests/apm/commandStartedEvent-getServiceId-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/apm/commandStartedEvent-getServiceId-002.phpt
rename to mongodb-1.13.0/tests/apm/commandStartedEvent-getServiceId-002.phpt
diff --git a/mongodb-1.12.0/tests/apm/commandSucceededEvent-001.phpt b/mongodb-1.13.0/tests/apm/commandSucceededEvent-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/apm/commandSucceededEvent-001.phpt
rename to mongodb-1.13.0/tests/apm/commandSucceededEvent-001.phpt
diff --git a/mongodb-1.12.0/tests/apm/commandSucceededEvent-002.phpt b/mongodb-1.13.0/tests/apm/commandSucceededEvent-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/apm/commandSucceededEvent-002.phpt
rename to mongodb-1.13.0/tests/apm/commandSucceededEvent-002.phpt
diff --git a/mongodb-1.12.0/tests/apm/commandSucceededEvent-debug-001.phpt b/mongodb-1.13.0/tests/apm/commandSucceededEvent-debug-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/apm/commandSucceededEvent-debug-001.phpt
rename to mongodb-1.13.0/tests/apm/commandSucceededEvent-debug-001.phpt
diff --git a/mongodb-1.12.0/tests/apm/commandSucceededEvent-getServiceId-001.phpt b/mongodb-1.13.0/tests/apm/commandSucceededEvent-getServiceId-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/apm/commandSucceededEvent-getServiceId-001.phpt
rename to mongodb-1.13.0/tests/apm/commandSucceededEvent-getServiceId-001.phpt
diff --git a/mongodb-1.12.0/tests/apm/commandSucceededEvent-getServiceId-002.phpt b/mongodb-1.13.0/tests/apm/commandSucceededEvent-getServiceId-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/apm/commandSucceededEvent-getServiceId-002.phpt
rename to mongodb-1.13.0/tests/apm/commandSucceededEvent-getServiceId-002.phpt
diff --git a/mongodb-1.12.0/tests/apm/monitoring-addSubscriber-001.phpt b/mongodb-1.13.0/tests/apm/monitoring-addSubscriber-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/apm/monitoring-addSubscriber-001.phpt
rename to mongodb-1.13.0/tests/apm/monitoring-addSubscriber-001.phpt
diff --git a/mongodb-1.12.0/tests/apm/monitoring-addSubscriber-002.phpt b/mongodb-1.13.0/tests/apm/monitoring-addSubscriber-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/apm/monitoring-addSubscriber-002.phpt
rename to mongodb-1.13.0/tests/apm/monitoring-addSubscriber-002.phpt
diff --git a/mongodb-1.12.0/tests/apm/monitoring-addSubscriber-003.phpt b/mongodb-1.13.0/tests/apm/monitoring-addSubscriber-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/apm/monitoring-addSubscriber-003.phpt
rename to mongodb-1.13.0/tests/apm/monitoring-addSubscriber-003.phpt
diff --git a/mongodb-1.12.0/tests/apm/monitoring-addSubscriber-004.phpt b/mongodb-1.13.0/tests/apm/monitoring-addSubscriber-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/apm/monitoring-addSubscriber-004.phpt
rename to mongodb-1.13.0/tests/apm/monitoring-addSubscriber-004.phpt
diff --git a/mongodb-1.12.0/tests/apm/monitoring-removeSubscriber-001.phpt b/mongodb-1.13.0/tests/apm/monitoring-removeSubscriber-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/apm/monitoring-removeSubscriber-001.phpt
rename to mongodb-1.13.0/tests/apm/monitoring-removeSubscriber-001.phpt
diff --git a/mongodb-1.12.0/tests/apm/monitoring-removeSubscriber-002.phpt b/mongodb-1.13.0/tests/apm/monitoring-removeSubscriber-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/apm/monitoring-removeSubscriber-002.phpt
rename to mongodb-1.13.0/tests/apm/monitoring-removeSubscriber-002.phpt
diff --git a/mongodb-1.13.0/tests/apm/serverChangedEvent-001.phpt b/mongodb-1.13.0/tests/apm/serverChangedEvent-001.phpt
new file mode 100644
index 00000000..8f5883a8
--- /dev/null
+++ b/mongodb-1.13.0/tests/apm/serverChangedEvent-001.phpt
@@ -0,0 +1,81 @@
+--TEST--
+MongoDB\Driver\Monitoring\ServerChangedEvent
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_live(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+class MySubscriber implements MongoDB\Driver\Monitoring\SDAMSubscriber
+{
+ private $isObserved = false;
+
+ public function serverChanged(MongoDB\Driver\Monitoring\ServerChangedEvent $event)
+ {
+ // Ignore multiple events for the purpose of this test
+ if ($this->isObserved) {
+ return;
+ }
+
+ $this->isObserved = true;
+
+ printf("getHost() returns a string: %s\n", is_string($event->getHost()) ? 'yes' : 'no');
+ printf("getPort() returns an integer: %s\n", is_integer($event->getPort()) ? 'yes' : 'no');
+ printf("getTopologyId() returns an ObjectId: %s\n", ($event->getTopologyId() instanceof MongoDB\BSON\ObjectId) ? 'yes' : 'no');
+ printf("getNewDescription() returns a ServerDescription: %s\n", ($event->getNewDescription() instanceof MongoDB\Driver\ServerDescription) ? 'yes' : 'no');
+ printf("getPreviousDescription() returns a ServerDescription: %s\n", ($event->getPreviousDescription() instanceof MongoDB\Driver\ServerDescription) ? 'yes' : 'no');
+
+ var_dump($event);
+ }
+
+ public function serverClosed(MongoDB\Driver\Monitoring\ServerClosedEvent $event) {}
+
+ public function serverHeartbeatFailed(MongoDB\Driver\Monitoring\ServerHeartbeatFailedEvent $event) {}
+
+ public function serverHeartbeatStarted(MongoDB\Driver\Monitoring\serverHeartbeatStartedEvent $event) {}
+
+ public function serverHeartbeatSucceeded(MongoDB\Driver\Monitoring\ServerHeartbeatSucceededEvent $event) {}
+
+ public function serverOpening(MongoDB\Driver\Monitoring\ServerOpeningEvent $event) {}
+
+ public function topologyChanged(MongoDB\Driver\Monitoring\TopologyChangedEvent $event) {}
+
+ public function topologyClosed(MongoDB\Driver\Monitoring\TopologyClosedEvent $event) {}
+
+ public function topologyOpening(MongoDB\Driver\Monitoring\TopologyOpeningEvent $event) {}
+}
+
+$m = create_test_manager();
+$m->addSubscriber(new MySubscriber);
+
+$command = new MongoDB\Driver\Command(['ping' => 1]);
+$m->executeCommand(DATABASE_NAME, $command);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+getHost() returns a string: yes
+getPort() returns an integer: yes
+getTopologyId() returns an ObjectId: yes
+getNewDescription() returns a ServerDescription: yes
+getPreviousDescription() returns a ServerDescription: yes
+object(MongoDB\Driver\Monitoring\ServerChangedEvent)#%d (%d) {
+ ["host"]=>
+ string(%d) "%s"
+ ["port"]=>
+ int(%d)
+ ["topologyId"]=>
+ object(MongoDB\BSON\ObjectId)#%d (%d) {
+ ["oid"]=>
+ string(24) "%x"
+ }
+ ["newDescription"]=>
+ object(MongoDB\Driver\ServerDescription)#%d (%d) {%A
+ }
+ ["oldDescription"]=>
+ object(MongoDB\Driver\ServerDescription)#%d (%d) {%A
+ }
+}
+===DONE===
diff --git a/mongodb-1.13.0/tests/apm/serverClosedEvent-001.phpt b/mongodb-1.13.0/tests/apm/serverClosedEvent-001.phpt
new file mode 100644
index 00000000..b2351af1
--- /dev/null
+++ b/mongodb-1.13.0/tests/apm/serverClosedEvent-001.phpt
@@ -0,0 +1,79 @@
+--TEST--
+MongoDB\Driver\Monitoring\ServerClosedEvent
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_load_balanced(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+class MySubscriber implements MongoDB\Driver\Monitoring\SDAMSubscriber
+{
+ private $isObserved = false;
+
+ public function serverChanged(MongoDB\Driver\Monitoring\ServerChangedEvent $event) {}
+
+ public function serverClosed(MongoDB\Driver\Monitoring\ServerClosedEvent $event)
+ {
+ // Ignore multiple events for the purpose of this test
+ if ($this->isObserved) {
+ return;
+ }
+
+ $this->isObserved = true;
+
+ printf("getHost() returns a string: %s\n", is_string($event->getHost()) ? 'yes' : 'no');
+ printf("getPort() returns an integer: %s\n", is_integer($event->getPort()) ? 'yes' : 'no');
+ printf("getTopologyId() returns an ObjectId: %s\n", ($event->getTopologyId() instanceof MongoDB\BSON\ObjectId) ? 'yes' : 'no');
+
+ var_dump($event);
+ }
+
+ public function serverHeartbeatFailed(MongoDB\Driver\Monitoring\ServerHeartbeatFailedEvent $event) {}
+
+ public function serverHeartbeatStarted(MongoDB\Driver\Monitoring\serverHeartbeatStartedEvent $event) {}
+
+ public function serverHeartbeatSucceeded(MongoDB\Driver\Monitoring\ServerHeartbeatSucceededEvent $event) {}
+
+ public function serverOpening(MongoDB\Driver\Monitoring\ServerOpeningEvent $event) {}
+
+ public function topologyChanged(MongoDB\Driver\Monitoring\TopologyChangedEvent $event) {}
+
+ public function topologyClosed(MongoDB\Driver\Monitoring\TopologyClosedEvent $event) {}
+
+ public function topologyOpening(MongoDB\Driver\Monitoring\TopologyOpeningEvent $event) {}
+}
+
+/* Note: load balanced topologies will always emit ServerClosedEvent before
+ * TopologyClosedEvent. That is easier than adding a non-member to a replica set
+ * URI. A non-persistent client is used to make observation possible. */
+$m = create_test_manager(URI, [], ['disableClientPersistence' => true]);
+$m->addSubscriber(new MySubscriber);
+
+$command = new MongoDB\Driver\Command(['ping' => 1]);
+$m->executeCommand(DATABASE_NAME, $command);
+
+/* Events dispatched during mongoc_client_destroy can only be observed before
+ * RSHUTDOWN. This means that we must use a non-persistent client and free it
+ * before the script ends. */
+unset($m);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+getHost() returns a string: yes
+getPort() returns an integer: yes
+getTopologyId() returns an ObjectId: yes
+object(MongoDB\Driver\Monitoring\ServerClosedEvent)#%d (%d) {
+ ["host"]=>
+ string(%d) "%s"
+ ["port"]=>
+ int(%d)
+ ["topologyId"]=>
+ object(MongoDB\BSON\ObjectId)#%d (%d) {
+ ["oid"]=>
+ string(24) "%x"
+ }
+}
+===DONE===
diff --git a/mongodb-1.13.0/tests/apm/serverHeartbeatFailedEvent-001.phpt b/mongodb-1.13.0/tests/apm/serverHeartbeatFailedEvent-001.phpt
new file mode 100644
index 00000000..5e88ebac
--- /dev/null
+++ b/mongodb-1.13.0/tests/apm/serverHeartbeatFailedEvent-001.phpt
@@ -0,0 +1,83 @@
+--TEST--
+MongoDB\Driver\Monitoring\ServerHeartbeatFailedEvent
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_live(); ?>
+<?php skip_if_no_failcommand_failpoint(); ?>
+<?php skip_if_not_standalone(); ?>
+<?php skip_if_auth(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+class MySubscriber implements MongoDB\Driver\Monitoring\SDAMSubscriber
+{
+ public function serverChanged(MongoDB\Driver\Monitoring\ServerChangedEvent $event) {}
+
+ public function serverClosed(MongoDB\Driver\Monitoring\ServerClosedEvent $event) {}
+
+ public function serverHeartbeatFailed(MongoDB\Driver\Monitoring\ServerHeartbeatFailedEvent $event)
+ {
+ printf("getDurationMicros() returns an integer: %s\n", is_integer($event->getDurationMicros()) ? 'yes' : 'no');
+ printf("getError() returns an Exception: %s\n", ($event->getError() instanceof Exception) ? 'yes' : 'no');
+ printf("getHost() returns a string: %s\n", is_string($event->getHost()) ? 'yes' : 'no');
+ printf("getPort() returns an integer: %s\n", is_integer($event->getPort()) ? 'yes' : 'no');
+ printf("isAwaited() returns a bool: %s\n", is_bool($event->isAwaited()) ? 'yes' : 'no');
+
+ var_dump($event);
+ }
+
+ public function serverHeartbeatStarted(MongoDB\Driver\Monitoring\serverHeartbeatStartedEvent $event) {}
+
+ public function serverHeartbeatSucceeded(MongoDB\Driver\Monitoring\ServerHeartbeatSucceededEvent $event) {}
+
+ public function serverOpening(MongoDB\Driver\Monitoring\ServerOpeningEvent $event) {}
+
+ public function topologyChanged(MongoDB\Driver\Monitoring\TopologyChangedEvent $event) {}
+
+ public function topologyClosed(MongoDB\Driver\Monitoring\TopologyClosedEvent $event) {}
+
+ public function topologyOpening(MongoDB\Driver\Monitoring\TopologyOpeningEvent $event) {}
+}
+
+/* Use a separate client to configure the fail point and trigger a heartbeat
+ * failure on the second client under test. This test should not be run on
+ * load balanced or sharded clusters with multiple mongoses, since we can not
+ * reliably select the same target server across two clients. */
+$m2 = create_test_manager(URI, [], ['disableClientPersistence' => true]);
+configureFailPoint($m2, 'failCommand', ['times' => 1], ['failCommands' => ['isMaster', 'hello'], 'closeConnection' => true]);
+
+$m = create_test_manager(URI, [], ['disableClientPersistence' => true]);
+$m->addSubscriber(new MySubscriber);
+$command = new MongoDB\Driver\Command(['ping' => 1]);
+
+throws(function() use ($m, $command) {
+ $m->executeCommand(DATABASE_NAME, $command);
+}, MongoDB\Driver\Exception\ConnectionTimeoutException::class);
+
+configureFailPoint($m2, 'failCommand', 'off');
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+getDurationMicros() returns an integer: yes
+getError() returns an Exception: yes
+getHost() returns a string: yes
+getPort() returns an integer: yes
+isAwaited() returns a bool: yes
+object(MongoDB\Driver\Monitoring\ServerHeartbeatFailedEvent)#%d (%d) {
+ ["host"]=>
+ string(%d) "%s"
+ ["port"]=>
+ int(%d)
+ ["awaited"]=>
+ bool(%s)
+ ["durationMicros"]=>
+ int(%d)
+ ["error"]=>
+ object(MongoDB\Driver\Exception\RuntimeException)#%d (%d) {%A
+ }
+}
+OK: Got MongoDB\Driver\Exception\ConnectionTimeoutException
+===DONE===
diff --git a/mongodb-1.13.0/tests/apm/serverHeartbeatStartedEvent-001.phpt b/mongodb-1.13.0/tests/apm/serverHeartbeatStartedEvent-001.phpt
new file mode 100644
index 00000000..7cf3e73d
--- /dev/null
+++ b/mongodb-1.13.0/tests/apm/serverHeartbeatStartedEvent-001.phpt
@@ -0,0 +1,68 @@
+--TEST--
+MongoDB\Driver\Monitoring\ServerHeartbeatStartedEvent
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_live(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+class MySubscriber implements MongoDB\Driver\Monitoring\SDAMSubscriber
+{
+ private $isObserved = false;
+
+ public function serverChanged(MongoDB\Driver\Monitoring\ServerChangedEvent $event) {}
+
+ public function serverClosed(MongoDB\Driver\Monitoring\ServerClosedEvent $event) {}
+
+ public function serverHeartbeatFailed(MongoDB\Driver\Monitoring\ServerHeartbeatFailedEvent $event) {}
+
+ public function serverHeartbeatStarted(MongoDB\Driver\Monitoring\serverHeartbeatStartedEvent $event)
+ {
+ // Ignore multiple events for the purpose of this test
+ if ($this->isObserved) {
+ return;
+ }
+
+ $this->isObserved = true;
+
+ printf("getHost() returns a string: %s\n", is_string($event->getHost()) ? 'yes' : 'no');
+ printf("getPort() returns an integer: %s\n", is_integer($event->getPort()) ? 'yes' : 'no');
+ printf("isAwaited() returns a bool: %s\n", is_bool($event->isAwaited()) ? 'yes' : 'no');
+
+ var_dump($event);
+ }
+
+ public function serverHeartbeatSucceeded(MongoDB\Driver\Monitoring\ServerHeartbeatSucceededEvent $event) {}
+
+ public function serverOpening(MongoDB\Driver\Monitoring\ServerOpeningEvent $event) {}
+
+ public function topologyChanged(MongoDB\Driver\Monitoring\TopologyChangedEvent $event) {}
+
+ public function topologyClosed(MongoDB\Driver\Monitoring\TopologyClosedEvent $event) {}
+
+ public function topologyOpening(MongoDB\Driver\Monitoring\TopologyOpeningEvent $event) {}
+}
+
+$m = create_test_manager();
+$m->addSubscriber(new MySubscriber);
+
+$command = new MongoDB\Driver\Command(['ping' => 1]);
+$m->executeCommand(DATABASE_NAME, $command);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+getHost() returns a string: yes
+getPort() returns an integer: yes
+isAwaited() returns a bool: yes
+object(MongoDB\Driver\Monitoring\ServerHeartbeatStartedEvent)#%d (%d) {
+ ["host"]=>
+ string(%d) "%s"
+ ["port"]=>
+ int(%d)
+ ["awaited"]=>
+ bool(%s)
+}
+===DONE===
diff --git a/mongodb-1.13.0/tests/apm/serverHeartbeatSucceededEvent-001.phpt b/mongodb-1.13.0/tests/apm/serverHeartbeatSucceededEvent-001.phpt
new file mode 100644
index 00000000..e614e525
--- /dev/null
+++ b/mongodb-1.13.0/tests/apm/serverHeartbeatSucceededEvent-001.phpt
@@ -0,0 +1,75 @@
+--TEST--
+MongoDB\Driver\Monitoring\ServerHeartbeatSucceededEvent
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_live(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+class MySubscriber implements MongoDB\Driver\Monitoring\SDAMSubscriber
+{
+ private $isObserved = false;
+
+ public function serverChanged(MongoDB\Driver\Monitoring\ServerChangedEvent $event) {}
+
+ public function serverClosed(MongoDB\Driver\Monitoring\ServerClosedEvent $event) {}
+
+ public function serverHeartbeatFailed(MongoDB\Driver\Monitoring\ServerHeartbeatFailedEvent $event) {}
+
+ public function serverHeartbeatStarted(MongoDB\Driver\Monitoring\serverHeartbeatStartedEvent $event) {}
+
+ public function serverHeartbeatSucceeded(MongoDB\Driver\Monitoring\ServerHeartbeatSucceededEvent $event)
+ {
+ // Ignore multiple events for the purpose of this test
+ if ($this->isObserved) {
+ return;
+ }
+
+ $this->isObserved = true;
+
+ printf("getDurationMicros() returns an integer: %s\n", is_integer($event->getDurationMicros()) ? 'yes' : 'no');
+ printf("getHost() returns a string: %s\n", is_string($event->getHost()) ? 'yes' : 'no');
+ printf("getPort() returns an integer: %s\n", is_integer($event->getPort()) ? 'yes' : 'no');
+ printf("getReply() returns an object: %s\n", is_object($event->getReply()) ? 'yes' : 'no');
+ printf("isAwaited() returns a bool: %s\n", is_bool($event->isAwaited()) ? 'yes' : 'no');
+
+ var_dump($event);
+ }
+
+ public function serverOpening(MongoDB\Driver\Monitoring\ServerOpeningEvent $event) {}
+
+ public function topologyChanged(MongoDB\Driver\Monitoring\TopologyChangedEvent $event) {}
+
+ public function topologyClosed(MongoDB\Driver\Monitoring\TopologyClosedEvent $event) {}
+
+ public function topologyOpening(MongoDB\Driver\Monitoring\TopologyOpeningEvent $event) {}
+}
+
+$m = create_test_manager();
+$m->addSubscriber(new MySubscriber);
+
+$command = new MongoDB\Driver\Command(['ping' => 1]);
+$m->executeCommand(DATABASE_NAME, $command);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+getDurationMicros() returns an integer: yes
+getHost() returns a string: yes
+getPort() returns an integer: yes
+getReply() returns an object: yes
+isAwaited() returns a bool: yes
+object(MongoDB\Driver\Monitoring\ServerHeartbeatSucceededEvent)#%d (%d) {
+ ["host"]=>
+ string(%d) "%s"
+ ["port"]=>
+ int(%d)
+ ["awaited"]=>
+ bool(%s)
+ ["reply"]=>
+ object(stdClass)#%d (%d) {%A
+ }
+}
+===DONE===
diff --git a/mongodb-1.13.0/tests/apm/serverOpeningEvent-001.phpt b/mongodb-1.13.0/tests/apm/serverOpeningEvent-001.phpt
new file mode 100644
index 00000000..8ee76e4a
--- /dev/null
+++ b/mongodb-1.13.0/tests/apm/serverOpeningEvent-001.phpt
@@ -0,0 +1,71 @@
+--TEST--
+MongoDB\Driver\Monitoring\ServerOpeningEvent
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_live(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+class MySubscriber implements MongoDB\Driver\Monitoring\SDAMSubscriber
+{
+ private $isObserved = false;
+
+ public function serverChanged(MongoDB\Driver\Monitoring\ServerChangedEvent $event) {}
+
+ public function serverClosed(MongoDB\Driver\Monitoring\ServerClosedEvent $event) {}
+
+ public function serverHeartbeatFailed(MongoDB\Driver\Monitoring\ServerHeartbeatFailedEvent $event) {}
+
+ public function serverHeartbeatStarted(MongoDB\Driver\Monitoring\serverHeartbeatStartedEvent $event) {}
+
+ public function serverHeartbeatSucceeded(MongoDB\Driver\Monitoring\ServerHeartbeatSucceededEvent $event) {}
+
+ public function serverOpening(MongoDB\Driver\Monitoring\ServerOpeningEvent $event)
+ {
+ // Ignore multiple events for the purpose of this test
+ if ($this->isObserved) {
+ return;
+ }
+
+ $this->isObserved = true;
+
+ printf("getHost() returns a string: %s\n", is_string($event->getHost()) ? 'yes' : 'no');
+ printf("getPort() returns an integer: %s\n", is_integer($event->getPort()) ? 'yes' : 'no');
+ printf("getTopologyId() returns an ObjectId: %s\n", ($event->getTopologyId() instanceof MongoDB\BSON\ObjectId) ? 'yes' : 'no');
+
+ var_dump($event);
+ }
+
+ public function topologyChanged(MongoDB\Driver\Monitoring\TopologyChangedEvent $event) {}
+
+ public function topologyClosed(MongoDB\Driver\Monitoring\TopologyClosedEvent $event) {}
+
+ public function topologyOpening(MongoDB\Driver\Monitoring\TopologyOpeningEvent $event) {}
+}
+
+$m = create_test_manager();
+$m->addSubscriber(new MySubscriber);
+
+$command = new MongoDB\Driver\Command(['ping' => 1]);
+$m->executeCommand(DATABASE_NAME, $command);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+getHost() returns a string: yes
+getPort() returns an integer: yes
+getTopologyId() returns an ObjectId: yes
+object(MongoDB\Driver\Monitoring\ServerOpeningEvent)#%d (%d) {
+ ["host"]=>
+ string(%d) "%s"
+ ["port"]=>
+ int(%d)
+ ["topologyId"]=>
+ object(MongoDB\BSON\ObjectId)#%d (%d) {
+ ["oid"]=>
+ string(24) "%x"
+ }
+}
+===DONE===
diff --git a/mongodb-1.13.0/tests/apm/topologyChangedEvent-001.phpt b/mongodb-1.13.0/tests/apm/topologyChangedEvent-001.phpt
new file mode 100644
index 00000000..003e431c
--- /dev/null
+++ b/mongodb-1.13.0/tests/apm/topologyChangedEvent-001.phpt
@@ -0,0 +1,73 @@
+--TEST--
+MongoDB\Driver\Monitoring\TopologyChangedEvent
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_live(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+class MySubscriber implements MongoDB\Driver\Monitoring\SDAMSubscriber
+{
+ private $isObserved = false;
+
+ public function serverChanged(MongoDB\Driver\Monitoring\ServerChangedEvent $event) {}
+
+ public function serverClosed(MongoDB\Driver\Monitoring\ServerClosedEvent $event) {}
+
+ public function serverHeartbeatFailed(MongoDB\Driver\Monitoring\ServerHeartbeatFailedEvent $event) {}
+
+ public function serverHeartbeatStarted(MongoDB\Driver\Monitoring\serverHeartbeatStartedEvent $event) {}
+
+ public function serverHeartbeatSucceeded(MongoDB\Driver\Monitoring\ServerHeartbeatSucceededEvent $event) {}
+
+ public function serverOpening(MongoDB\Driver\Monitoring\ServerOpeningEvent $event) {}
+
+ public function topologyChanged(MongoDB\Driver\Monitoring\TopologyChangedEvent $event)
+ {
+ // Ignore multiple events for the purpose of this test
+ if ($this->isObserved) {
+ return;
+ }
+
+ $this->isObserved = true;
+
+ printf("getTopologyId() returns an ObjectId: %s\n", ($event->getTopologyId() instanceof MongoDB\BSON\ObjectId) ? 'yes' : 'no');
+ printf("getNewDescription() returns a TopologyDescription: %s\n", ($event->getNewDescription() instanceof MongoDB\Driver\TopologyDescription) ? 'yes' : 'no');
+ printf("getPreviousDescription() returns a TopologyDescription: %s\n", ($event->getPreviousDescription() instanceof MongoDB\Driver\TopologyDescription) ? 'yes' : 'no');
+
+ var_dump($event);
+ }
+
+ public function topologyClosed(MongoDB\Driver\Monitoring\TopologyClosedEvent $event) {}
+
+ public function topologyOpening(MongoDB\Driver\Monitoring\TopologyOpeningEvent $event) {}
+}
+
+$m = create_test_manager();
+$m->addSubscriber(new MySubscriber);
+
+$command = new MongoDB\Driver\Command(['ping' => 1]);
+$m->executeCommand(DATABASE_NAME, $command);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+getTopologyId() returns an ObjectId: yes
+getNewDescription() returns a TopologyDescription: yes
+getPreviousDescription() returns a TopologyDescription: yes
+object(MongoDB\Driver\Monitoring\TopologyChangedEvent)#%d (%d) {
+ ["topologyId"]=>
+ object(MongoDB\BSON\ObjectId)#%d (%d) {
+ ["oid"]=>
+ string(24) "%x"
+ }
+ ["newDescription"]=>
+ object(MongoDB\Driver\TopologyDescription)#%d (%d) {%A
+ }
+ ["oldDescription"]=>
+ object(MongoDB\Driver\TopologyDescription)#%d (%d) {%A
+ }
+}
+===DONE===
diff --git a/mongodb-1.13.0/tests/apm/topologyClosedEvent-001.phpt b/mongodb-1.13.0/tests/apm/topologyClosedEvent-001.phpt
new file mode 100644
index 00000000..cd0ec992
--- /dev/null
+++ b/mongodb-1.13.0/tests/apm/topologyClosedEvent-001.phpt
@@ -0,0 +1,62 @@
+--TEST--
+MongoDB\Driver\Monitoring\TopologyClosedEvent
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_live(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+class MySubscriber implements MongoDB\Driver\Monitoring\SDAMSubscriber
+{
+ public function serverChanged(MongoDB\Driver\Monitoring\ServerChangedEvent $event) {}
+
+ public function serverClosed(MongoDB\Driver\Monitoring\ServerClosedEvent $event) {}
+
+ public function serverHeartbeatFailed(MongoDB\Driver\Monitoring\ServerHeartbeatFailedEvent $event) {}
+
+ public function serverHeartbeatStarted(MongoDB\Driver\Monitoring\serverHeartbeatStartedEvent $event) {}
+
+ public function serverHeartbeatSucceeded(MongoDB\Driver\Monitoring\ServerHeartbeatSucceededEvent $event) {}
+
+ public function serverOpening(MongoDB\Driver\Monitoring\ServerOpeningEvent $event) {}
+
+ public function topologyChanged(MongoDB\Driver\Monitoring\TopologyChangedEvent $event) {}
+
+ public function topologyClosed(MongoDB\Driver\Monitoring\TopologyClosedEvent $event)
+ {
+ printf("getTopologyId() returns an ObjectId: %s\n", ($event->getTopologyId() instanceof MongoDB\BSON\ObjectId) ? 'yes' : 'no');
+
+ var_dump($event);
+ }
+
+ public function topologyOpening(MongoDB\Driver\Monitoring\TopologyOpeningEvent $event) {}
+}
+
+/* Note: TopologyChangedEvent can only be observed for non-persistent clients.
+ * Persistent clients are destroyed in GSHUTDOWN, long after any PHP objects
+ * (including subscribers) are freed. */
+$m = create_test_manager(URI, [], ['disableClientPersistence' => true]);
+$m->addSubscriber(new MySubscriber);
+
+$command = new MongoDB\Driver\Command(['ping' => 1]);
+$m->executeCommand(DATABASE_NAME, $command);
+
+/* Events dispatched during mongoc_client_destroy can only be observed before
+ * RSHUTDOWN. This means that we must use a non-persistent client and free it
+ * before the script ends. */
+unset($m);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+getTopologyId() returns an ObjectId: yes
+object(MongoDB\Driver\Monitoring\TopologyClosedEvent)#%d (%d) {
+ ["topologyId"]=>
+ object(MongoDB\BSON\ObjectId)#%d (%d) {
+ ["oid"]=>
+ string(24) "%x"
+ }
+}
+===DONE===
diff --git a/mongodb-1.13.0/tests/apm/topologyOpeningEvent-001.phpt b/mongodb-1.13.0/tests/apm/topologyOpeningEvent-001.phpt
new file mode 100644
index 00000000..abb6f009
--- /dev/null
+++ b/mongodb-1.13.0/tests/apm/topologyOpeningEvent-001.phpt
@@ -0,0 +1,54 @@
+--TEST--
+MongoDB\Driver\Monitoring\TopologyOpeningEvent
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_live(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+class MySubscriber implements MongoDB\Driver\Monitoring\SDAMSubscriber
+{
+ public function serverChanged(MongoDB\Driver\Monitoring\ServerChangedEvent $event) {}
+
+ public function serverClosed(MongoDB\Driver\Monitoring\ServerClosedEvent $event) {}
+
+ public function serverHeartbeatFailed(MongoDB\Driver\Monitoring\ServerHeartbeatFailedEvent $event) {}
+
+ public function serverHeartbeatStarted(MongoDB\Driver\Monitoring\serverHeartbeatStartedEvent $event) {}
+
+ public function serverHeartbeatSucceeded(MongoDB\Driver\Monitoring\ServerHeartbeatSucceededEvent $event) {}
+
+ public function serverOpening(MongoDB\Driver\Monitoring\ServerOpeningEvent $event) {}
+
+ public function topologyChanged(MongoDB\Driver\Monitoring\TopologyChangedEvent $event) {}
+
+ public function topologyClosed(MongoDB\Driver\Monitoring\TopologyClosedEvent $event) {}
+
+ public function topologyOpening(MongoDB\Driver\Monitoring\TopologyOpeningEvent $event)
+ {
+ printf("getTopologyId() returns an ObjectId: %s\n", ($event->getTopologyId() instanceof MongoDB\BSON\ObjectId) ? 'yes' : 'no');
+
+ var_dump($event);
+ }
+}
+
+$m = create_test_manager();
+$m->addSubscriber(new MySubscriber);
+
+$command = new MongoDB\Driver\Command(['ping' => 1]);
+$m->executeCommand(DATABASE_NAME, $command);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+getTopologyId() returns an ObjectId: yes
+object(MongoDB\Driver\Monitoring\TopologyOpeningEvent)#%d (%d) {
+ ["topologyId"]=>
+ object(MongoDB\BSON\ObjectId)#%d (%d) {
+ ["oid"]=>
+ string(24) "%x"
+ }
+}
+===DONE===
diff --git a/mongodb-1.13.0/tests/apm/topologyOpeningEvent-002.phpt b/mongodb-1.13.0/tests/apm/topologyOpeningEvent-002.phpt
new file mode 100644
index 00000000..94d3ed39
--- /dev/null
+++ b/mongodb-1.13.0/tests/apm/topologyOpeningEvent-002.phpt
@@ -0,0 +1,79 @@
+--TEST--
+MongoDB\Driver\Monitoring\TopologyOpeningEvent shares topology ID with other events
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_live(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+class MySubscriber implements MongoDB\Driver\Monitoring\SDAMSubscriber
+{
+ private $topologyId;
+ public $numAssertions = 0;
+
+ public function serverChanged(MongoDB\Driver\Monitoring\ServerChangedEvent $event)
+ {
+ $this->assertSameTopologyId($event);
+ }
+
+ public function serverClosed(MongoDB\Driver\Monitoring\ServerClosedEvent $event)
+ {
+ $this->assertSameTopologyId($event);
+ }
+
+ public function serverHeartbeatFailed(MongoDB\Driver\Monitoring\ServerHeartbeatFailedEvent $event) {}
+
+ public function serverHeartbeatStarted(MongoDB\Driver\Monitoring\serverHeartbeatStartedEvent $event) {}
+
+ public function serverHeartbeatSucceeded(MongoDB\Driver\Monitoring\ServerHeartbeatSucceededEvent $event) {}
+
+ public function serverOpening(MongoDB\Driver\Monitoring\ServerOpeningEvent $event)
+ {
+ $this->assertSameTopologyId($event);
+ }
+
+ public function topologyChanged(MongoDB\Driver\Monitoring\TopologyChangedEvent $event)
+ {
+ $this->assertSameTopologyId($event);
+ }
+
+ public function topologyClosed(MongoDB\Driver\Monitoring\TopologyClosedEvent $event)
+ {
+ $this->assertSameTopologyId($event);
+ }
+
+ public function topologyOpening(MongoDB\Driver\Monitoring\TopologyOpeningEvent $event)
+ {
+ $this->topologyId = $event->getTopologyId();
+ }
+
+ private function assertSameTopologyId($event)
+ {
+ $this->numAssertions++;
+
+ if ($event->getTopologyId() != $this->topologyId) {
+ throw new UnexpectedValueException(sprintf('Topology ID "%s" from %s does not match "%s" from TopologyOpeningEvent', $event->getTopologyId(), (new ReflectionClass($event))->getShortName(), $this->topologyId));
+ }
+ }
+}
+
+$subscriber = new MySubscriber;
+
+$m = create_test_manager();
+$m->addSubscriber($subscriber);
+
+$command = new MongoDB\Driver\Command(['ping' => 1]);
+$m->executeCommand(DATABASE_NAME, $command);
+
+/* Rather than expecting a specific number or sequence of events, we can expect
+ * that at least one assertion was made and trust that any failures would have
+ * resulted in an exception being thrown by assertSameTopologyId(). */
+var_dump($subscriber->numAssertions > 1);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+bool(true)
+===DONE===
diff --git a/mongodb-1.12.0/tests/bson-corpus/array-decodeError-001.phpt b/mongodb-1.13.0/tests/bson-corpus/array-decodeError-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/array-decodeError-001.phpt
rename to mongodb-1.13.0/tests/bson-corpus/array-decodeError-001.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/array-decodeError-002.phpt b/mongodb-1.13.0/tests/bson-corpus/array-decodeError-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/array-decodeError-002.phpt
rename to mongodb-1.13.0/tests/bson-corpus/array-decodeError-002.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/array-decodeError-003.phpt b/mongodb-1.13.0/tests/bson-corpus/array-decodeError-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/array-decodeError-003.phpt
rename to mongodb-1.13.0/tests/bson-corpus/array-decodeError-003.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/array-valid-001.phpt b/mongodb-1.13.0/tests/bson-corpus/array-valid-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/array-valid-001.phpt
rename to mongodb-1.13.0/tests/bson-corpus/array-valid-001.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/array-valid-002.phpt b/mongodb-1.13.0/tests/bson-corpus/array-valid-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/array-valid-002.phpt
rename to mongodb-1.13.0/tests/bson-corpus/array-valid-002.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/array-valid-003.phpt b/mongodb-1.13.0/tests/bson-corpus/array-valid-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/array-valid-003.phpt
rename to mongodb-1.13.0/tests/bson-corpus/array-valid-003.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/array-valid-004.phpt b/mongodb-1.13.0/tests/bson-corpus/array-valid-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/array-valid-004.phpt
rename to mongodb-1.13.0/tests/bson-corpus/array-valid-004.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/array-valid-005.phpt b/mongodb-1.13.0/tests/bson-corpus/array-valid-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/array-valid-005.phpt
rename to mongodb-1.13.0/tests/bson-corpus/array-valid-005.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/binary-decodeError-001.phpt b/mongodb-1.13.0/tests/bson-corpus/binary-decodeError-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/binary-decodeError-001.phpt
rename to mongodb-1.13.0/tests/bson-corpus/binary-decodeError-001.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/binary-decodeError-002.phpt b/mongodb-1.13.0/tests/bson-corpus/binary-decodeError-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/binary-decodeError-002.phpt
rename to mongodb-1.13.0/tests/bson-corpus/binary-decodeError-002.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/binary-decodeError-003.phpt b/mongodb-1.13.0/tests/bson-corpus/binary-decodeError-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/binary-decodeError-003.phpt
rename to mongodb-1.13.0/tests/bson-corpus/binary-decodeError-003.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/binary-decodeError-004.phpt b/mongodb-1.13.0/tests/bson-corpus/binary-decodeError-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/binary-decodeError-004.phpt
rename to mongodb-1.13.0/tests/bson-corpus/binary-decodeError-004.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/binary-decodeError-005.phpt b/mongodb-1.13.0/tests/bson-corpus/binary-decodeError-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/binary-decodeError-005.phpt
rename to mongodb-1.13.0/tests/bson-corpus/binary-decodeError-005.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/binary-parseError-001.phpt b/mongodb-1.13.0/tests/bson-corpus/binary-parseError-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/binary-parseError-001.phpt
rename to mongodb-1.13.0/tests/bson-corpus/binary-parseError-001.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/binary-parseError-002.phpt b/mongodb-1.13.0/tests/bson-corpus/binary-parseError-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/binary-parseError-002.phpt
rename to mongodb-1.13.0/tests/bson-corpus/binary-parseError-002.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/binary-parseError-003.phpt b/mongodb-1.13.0/tests/bson-corpus/binary-parseError-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/binary-parseError-003.phpt
rename to mongodb-1.13.0/tests/bson-corpus/binary-parseError-003.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/binary-parseError-004.phpt b/mongodb-1.13.0/tests/bson-corpus/binary-parseError-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/binary-parseError-004.phpt
rename to mongodb-1.13.0/tests/bson-corpus/binary-parseError-004.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/binary-parseError-005.phpt b/mongodb-1.13.0/tests/bson-corpus/binary-parseError-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/binary-parseError-005.phpt
rename to mongodb-1.13.0/tests/bson-corpus/binary-parseError-005.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/binary-valid-001.phpt b/mongodb-1.13.0/tests/bson-corpus/binary-valid-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/binary-valid-001.phpt
rename to mongodb-1.13.0/tests/bson-corpus/binary-valid-001.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/binary-valid-002.phpt b/mongodb-1.13.0/tests/bson-corpus/binary-valid-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/binary-valid-002.phpt
rename to mongodb-1.13.0/tests/bson-corpus/binary-valid-002.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/binary-valid-003.phpt b/mongodb-1.13.0/tests/bson-corpus/binary-valid-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/binary-valid-003.phpt
rename to mongodb-1.13.0/tests/bson-corpus/binary-valid-003.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/binary-valid-004.phpt b/mongodb-1.13.0/tests/bson-corpus/binary-valid-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/binary-valid-004.phpt
rename to mongodb-1.13.0/tests/bson-corpus/binary-valid-004.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/binary-valid-005.phpt b/mongodb-1.13.0/tests/bson-corpus/binary-valid-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/binary-valid-005.phpt
rename to mongodb-1.13.0/tests/bson-corpus/binary-valid-005.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/binary-valid-006.phpt b/mongodb-1.13.0/tests/bson-corpus/binary-valid-006.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/binary-valid-006.phpt
rename to mongodb-1.13.0/tests/bson-corpus/binary-valid-006.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/binary-valid-007.phpt b/mongodb-1.13.0/tests/bson-corpus/binary-valid-007.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/binary-valid-007.phpt
rename to mongodb-1.13.0/tests/bson-corpus/binary-valid-007.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/binary-valid-008.phpt b/mongodb-1.13.0/tests/bson-corpus/binary-valid-008.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/binary-valid-008.phpt
rename to mongodb-1.13.0/tests/bson-corpus/binary-valid-008.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/binary-valid-009.phpt b/mongodb-1.13.0/tests/bson-corpus/binary-valid-009.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/binary-valid-009.phpt
rename to mongodb-1.13.0/tests/bson-corpus/binary-valid-009.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/binary-valid-010.phpt b/mongodb-1.13.0/tests/bson-corpus/binary-valid-010.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/binary-valid-010.phpt
rename to mongodb-1.13.0/tests/bson-corpus/binary-valid-010.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/binary-valid-011.phpt b/mongodb-1.13.0/tests/bson-corpus/binary-valid-011.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/binary-valid-011.phpt
rename to mongodb-1.13.0/tests/bson-corpus/binary-valid-011.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/binary-valid-012.phpt b/mongodb-1.13.0/tests/bson-corpus/binary-valid-012.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/binary-valid-012.phpt
rename to mongodb-1.13.0/tests/bson-corpus/binary-valid-012.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/binary-valid-013.phpt b/mongodb-1.13.0/tests/bson-corpus/binary-valid-013.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/binary-valid-013.phpt
rename to mongodb-1.13.0/tests/bson-corpus/binary-valid-013.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/boolean-decodeError-001.phpt b/mongodb-1.13.0/tests/bson-corpus/boolean-decodeError-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/boolean-decodeError-001.phpt
rename to mongodb-1.13.0/tests/bson-corpus/boolean-decodeError-001.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/boolean-decodeError-002.phpt b/mongodb-1.13.0/tests/bson-corpus/boolean-decodeError-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/boolean-decodeError-002.phpt
rename to mongodb-1.13.0/tests/bson-corpus/boolean-decodeError-002.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/boolean-valid-001.phpt b/mongodb-1.13.0/tests/bson-corpus/boolean-valid-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/boolean-valid-001.phpt
rename to mongodb-1.13.0/tests/bson-corpus/boolean-valid-001.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/boolean-valid-002.phpt b/mongodb-1.13.0/tests/bson-corpus/boolean-valid-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/boolean-valid-002.phpt
rename to mongodb-1.13.0/tests/bson-corpus/boolean-valid-002.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/code-decodeError-001.phpt b/mongodb-1.13.0/tests/bson-corpus/code-decodeError-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/code-decodeError-001.phpt
rename to mongodb-1.13.0/tests/bson-corpus/code-decodeError-001.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/code-decodeError-002.phpt b/mongodb-1.13.0/tests/bson-corpus/code-decodeError-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/code-decodeError-002.phpt
rename to mongodb-1.13.0/tests/bson-corpus/code-decodeError-002.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/code-decodeError-003.phpt b/mongodb-1.13.0/tests/bson-corpus/code-decodeError-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/code-decodeError-003.phpt
rename to mongodb-1.13.0/tests/bson-corpus/code-decodeError-003.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/code-decodeError-004.phpt b/mongodb-1.13.0/tests/bson-corpus/code-decodeError-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/code-decodeError-004.phpt
rename to mongodb-1.13.0/tests/bson-corpus/code-decodeError-004.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/code-decodeError-005.phpt b/mongodb-1.13.0/tests/bson-corpus/code-decodeError-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/code-decodeError-005.phpt
rename to mongodb-1.13.0/tests/bson-corpus/code-decodeError-005.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/code-decodeError-006.phpt b/mongodb-1.13.0/tests/bson-corpus/code-decodeError-006.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/code-decodeError-006.phpt
rename to mongodb-1.13.0/tests/bson-corpus/code-decodeError-006.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/code-decodeError-007.phpt b/mongodb-1.13.0/tests/bson-corpus/code-decodeError-007.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/code-decodeError-007.phpt
rename to mongodb-1.13.0/tests/bson-corpus/code-decodeError-007.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/code-valid-001.phpt b/mongodb-1.13.0/tests/bson-corpus/code-valid-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/code-valid-001.phpt
rename to mongodb-1.13.0/tests/bson-corpus/code-valid-001.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/code-valid-002.phpt b/mongodb-1.13.0/tests/bson-corpus/code-valid-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/code-valid-002.phpt
rename to mongodb-1.13.0/tests/bson-corpus/code-valid-002.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/code-valid-003.phpt b/mongodb-1.13.0/tests/bson-corpus/code-valid-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/code-valid-003.phpt
rename to mongodb-1.13.0/tests/bson-corpus/code-valid-003.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/code-valid-004.phpt b/mongodb-1.13.0/tests/bson-corpus/code-valid-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/code-valid-004.phpt
rename to mongodb-1.13.0/tests/bson-corpus/code-valid-004.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/code-valid-005.phpt b/mongodb-1.13.0/tests/bson-corpus/code-valid-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/code-valid-005.phpt
rename to mongodb-1.13.0/tests/bson-corpus/code-valid-005.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/code-valid-006.phpt b/mongodb-1.13.0/tests/bson-corpus/code-valid-006.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/code-valid-006.phpt
rename to mongodb-1.13.0/tests/bson-corpus/code-valid-006.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/code_w_scope-decodeError-001.phpt b/mongodb-1.13.0/tests/bson-corpus/code_w_scope-decodeError-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/code_w_scope-decodeError-001.phpt
rename to mongodb-1.13.0/tests/bson-corpus/code_w_scope-decodeError-001.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/code_w_scope-decodeError-002.phpt b/mongodb-1.13.0/tests/bson-corpus/code_w_scope-decodeError-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/code_w_scope-decodeError-002.phpt
rename to mongodb-1.13.0/tests/bson-corpus/code_w_scope-decodeError-002.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/code_w_scope-decodeError-003.phpt b/mongodb-1.13.0/tests/bson-corpus/code_w_scope-decodeError-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/code_w_scope-decodeError-003.phpt
rename to mongodb-1.13.0/tests/bson-corpus/code_w_scope-decodeError-003.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/code_w_scope-decodeError-004.phpt b/mongodb-1.13.0/tests/bson-corpus/code_w_scope-decodeError-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/code_w_scope-decodeError-004.phpt
rename to mongodb-1.13.0/tests/bson-corpus/code_w_scope-decodeError-004.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/code_w_scope-decodeError-005.phpt b/mongodb-1.13.0/tests/bson-corpus/code_w_scope-decodeError-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/code_w_scope-decodeError-005.phpt
rename to mongodb-1.13.0/tests/bson-corpus/code_w_scope-decodeError-005.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/code_w_scope-decodeError-006.phpt b/mongodb-1.13.0/tests/bson-corpus/code_w_scope-decodeError-006.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/code_w_scope-decodeError-006.phpt
rename to mongodb-1.13.0/tests/bson-corpus/code_w_scope-decodeError-006.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/code_w_scope-decodeError-007.phpt b/mongodb-1.13.0/tests/bson-corpus/code_w_scope-decodeError-007.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/code_w_scope-decodeError-007.phpt
rename to mongodb-1.13.0/tests/bson-corpus/code_w_scope-decodeError-007.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/code_w_scope-decodeError-008.phpt b/mongodb-1.13.0/tests/bson-corpus/code_w_scope-decodeError-008.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/code_w_scope-decodeError-008.phpt
rename to mongodb-1.13.0/tests/bson-corpus/code_w_scope-decodeError-008.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/code_w_scope-decodeError-009.phpt b/mongodb-1.13.0/tests/bson-corpus/code_w_scope-decodeError-009.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/code_w_scope-decodeError-009.phpt
rename to mongodb-1.13.0/tests/bson-corpus/code_w_scope-decodeError-009.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/code_w_scope-decodeError-010.phpt b/mongodb-1.13.0/tests/bson-corpus/code_w_scope-decodeError-010.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/code_w_scope-decodeError-010.phpt
rename to mongodb-1.13.0/tests/bson-corpus/code_w_scope-decodeError-010.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/code_w_scope-decodeError-011.phpt b/mongodb-1.13.0/tests/bson-corpus/code_w_scope-decodeError-011.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/code_w_scope-decodeError-011.phpt
rename to mongodb-1.13.0/tests/bson-corpus/code_w_scope-decodeError-011.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/code_w_scope-valid-001.phpt b/mongodb-1.13.0/tests/bson-corpus/code_w_scope-valid-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/code_w_scope-valid-001.phpt
rename to mongodb-1.13.0/tests/bson-corpus/code_w_scope-valid-001.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/code_w_scope-valid-002.phpt b/mongodb-1.13.0/tests/bson-corpus/code_w_scope-valid-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/code_w_scope-valid-002.phpt
rename to mongodb-1.13.0/tests/bson-corpus/code_w_scope-valid-002.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/code_w_scope-valid-003.phpt b/mongodb-1.13.0/tests/bson-corpus/code_w_scope-valid-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/code_w_scope-valid-003.phpt
rename to mongodb-1.13.0/tests/bson-corpus/code_w_scope-valid-003.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/code_w_scope-valid-004.phpt b/mongodb-1.13.0/tests/bson-corpus/code_w_scope-valid-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/code_w_scope-valid-004.phpt
rename to mongodb-1.13.0/tests/bson-corpus/code_w_scope-valid-004.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/code_w_scope-valid-005.phpt b/mongodb-1.13.0/tests/bson-corpus/code_w_scope-valid-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/code_w_scope-valid-005.phpt
rename to mongodb-1.13.0/tests/bson-corpus/code_w_scope-valid-005.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/datetime-decodeError-001.phpt b/mongodb-1.13.0/tests/bson-corpus/datetime-decodeError-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/datetime-decodeError-001.phpt
rename to mongodb-1.13.0/tests/bson-corpus/datetime-decodeError-001.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/datetime-valid-001.phpt b/mongodb-1.13.0/tests/bson-corpus/datetime-valid-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/datetime-valid-001.phpt
rename to mongodb-1.13.0/tests/bson-corpus/datetime-valid-001.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/datetime-valid-002.phpt b/mongodb-1.13.0/tests/bson-corpus/datetime-valid-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/datetime-valid-002.phpt
rename to mongodb-1.13.0/tests/bson-corpus/datetime-valid-002.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/datetime-valid-003.phpt b/mongodb-1.13.0/tests/bson-corpus/datetime-valid-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/datetime-valid-003.phpt
rename to mongodb-1.13.0/tests/bson-corpus/datetime-valid-003.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/datetime-valid-004.phpt b/mongodb-1.13.0/tests/bson-corpus/datetime-valid-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/datetime-valid-004.phpt
rename to mongodb-1.13.0/tests/bson-corpus/datetime-valid-004.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/datetime-valid-005.phpt b/mongodb-1.13.0/tests/bson-corpus/datetime-valid-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/datetime-valid-005.phpt
rename to mongodb-1.13.0/tests/bson-corpus/datetime-valid-005.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/dbpointer-decodeError-001.phpt b/mongodb-1.13.0/tests/bson-corpus/dbpointer-decodeError-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/dbpointer-decodeError-001.phpt
rename to mongodb-1.13.0/tests/bson-corpus/dbpointer-decodeError-001.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/dbpointer-decodeError-002.phpt b/mongodb-1.13.0/tests/bson-corpus/dbpointer-decodeError-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/dbpointer-decodeError-002.phpt
rename to mongodb-1.13.0/tests/bson-corpus/dbpointer-decodeError-002.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/dbpointer-decodeError-003.phpt b/mongodb-1.13.0/tests/bson-corpus/dbpointer-decodeError-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/dbpointer-decodeError-003.phpt
rename to mongodb-1.13.0/tests/bson-corpus/dbpointer-decodeError-003.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/dbpointer-decodeError-004.phpt b/mongodb-1.13.0/tests/bson-corpus/dbpointer-decodeError-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/dbpointer-decodeError-004.phpt
rename to mongodb-1.13.0/tests/bson-corpus/dbpointer-decodeError-004.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/dbpointer-decodeError-005.phpt b/mongodb-1.13.0/tests/bson-corpus/dbpointer-decodeError-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/dbpointer-decodeError-005.phpt
rename to mongodb-1.13.0/tests/bson-corpus/dbpointer-decodeError-005.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/dbpointer-decodeError-006.phpt b/mongodb-1.13.0/tests/bson-corpus/dbpointer-decodeError-006.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/dbpointer-decodeError-006.phpt
rename to mongodb-1.13.0/tests/bson-corpus/dbpointer-decodeError-006.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/dbpointer-valid-001.phpt b/mongodb-1.13.0/tests/bson-corpus/dbpointer-valid-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/dbpointer-valid-001.phpt
rename to mongodb-1.13.0/tests/bson-corpus/dbpointer-valid-001.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/dbpointer-valid-002.phpt b/mongodb-1.13.0/tests/bson-corpus/dbpointer-valid-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/dbpointer-valid-002.phpt
rename to mongodb-1.13.0/tests/bson-corpus/dbpointer-valid-002.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/dbpointer-valid-003.phpt b/mongodb-1.13.0/tests/bson-corpus/dbpointer-valid-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/dbpointer-valid-003.phpt
rename to mongodb-1.13.0/tests/bson-corpus/dbpointer-valid-003.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/dbref-valid-001.phpt b/mongodb-1.13.0/tests/bson-corpus/dbref-valid-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/dbref-valid-001.phpt
rename to mongodb-1.13.0/tests/bson-corpus/dbref-valid-001.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/dbref-valid-002.phpt b/mongodb-1.13.0/tests/bson-corpus/dbref-valid-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/dbref-valid-002.phpt
rename to mongodb-1.13.0/tests/bson-corpus/dbref-valid-002.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/dbref-valid-003.phpt b/mongodb-1.13.0/tests/bson-corpus/dbref-valid-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/dbref-valid-003.phpt
rename to mongodb-1.13.0/tests/bson-corpus/dbref-valid-003.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/dbref-valid-004.phpt b/mongodb-1.13.0/tests/bson-corpus/dbref-valid-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/dbref-valid-004.phpt
rename to mongodb-1.13.0/tests/bson-corpus/dbref-valid-004.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/dbref-valid-005.phpt b/mongodb-1.13.0/tests/bson-corpus/dbref-valid-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/dbref-valid-005.phpt
rename to mongodb-1.13.0/tests/bson-corpus/dbref-valid-005.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/dbref-valid-006.phpt b/mongodb-1.13.0/tests/bson-corpus/dbref-valid-006.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/dbref-valid-006.phpt
rename to mongodb-1.13.0/tests/bson-corpus/dbref-valid-006.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/dbref-valid-007.phpt b/mongodb-1.13.0/tests/bson-corpus/dbref-valid-007.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/dbref-valid-007.phpt
rename to mongodb-1.13.0/tests/bson-corpus/dbref-valid-007.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/dbref-valid-008.phpt b/mongodb-1.13.0/tests/bson-corpus/dbref-valid-008.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/dbref-valid-008.phpt
rename to mongodb-1.13.0/tests/bson-corpus/dbref-valid-008.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/dbref-valid-009.phpt b/mongodb-1.13.0/tests/bson-corpus/dbref-valid-009.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/dbref-valid-009.phpt
rename to mongodb-1.13.0/tests/bson-corpus/dbref-valid-009.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-001.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-001.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-001.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-002.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-002.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-002.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-003.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-003.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-003.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-004.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-004.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-004.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-005.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-005.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-005.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-006.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-006.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-006.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-006.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-007.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-007.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-007.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-007.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-008.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-008.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-008.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-008.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-009.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-009.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-009.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-009.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-010.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-010.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-010.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-010.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-011.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-011.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-011.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-011.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-012.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-012.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-012.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-012.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-013.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-013.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-013.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-013.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-014.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-014.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-014.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-014.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-015.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-015.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-015.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-015.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-016.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-016.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-016.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-016.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-017.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-017.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-017.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-017.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-018.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-018.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-018.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-018.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-019.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-019.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-019.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-019.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-020.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-020.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-020.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-020.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-021.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-021.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-021.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-021.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-022.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-022.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-022.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-022.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-023.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-023.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-023.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-023.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-024.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-024.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-024.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-024.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-025.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-025.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-025.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-025.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-026.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-026.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-026.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-026.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-027.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-027.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-027.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-027.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-028.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-028.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-028.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-028.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-029.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-029.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-029.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-029.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-030.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-030.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-030.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-030.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-031.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-031.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-031.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-031.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-032.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-032.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-032.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-032.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-033.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-033.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-033.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-033.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-034.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-034.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-034.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-034.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-035.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-035.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-035.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-035.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-036.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-036.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-036.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-036.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-037.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-037.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-037.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-037.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-038.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-038.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-038.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-038.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-039.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-039.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-039.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-039.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-040.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-040.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-040.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-040.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-041.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-041.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-041.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-041.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-042.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-042.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-042.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-042.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-043.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-043.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-043.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-043.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-044.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-044.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-044.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-044.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-045.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-045.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-045.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-045.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-046.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-046.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-046.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-046.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-047.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-047.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-047.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-047.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-048.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-048.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-048.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-048.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-049.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-049.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-049.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-049.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-050.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-050.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-050.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-050.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-051.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-051.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-051.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-051.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-052.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-052.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-052.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-052.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-053.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-053.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-053.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-053.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-054.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-054.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-054.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-054.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-055.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-055.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-055.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-055.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-056.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-056.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-1-valid-056.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-1-valid-056.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-001.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-001.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-001.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-002.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-002.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-002.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-003.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-003.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-003.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-004.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-004.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-004.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-005.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-005.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-005.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-006.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-006.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-006.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-006.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-007.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-007.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-007.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-007.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-008.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-008.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-008.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-008.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-009.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-009.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-009.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-009.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-010.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-010.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-010.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-010.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-011.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-011.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-011.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-011.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-012.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-012.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-012.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-012.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-013.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-013.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-013.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-013.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-014.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-014.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-014.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-014.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-015.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-015.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-015.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-015.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-016.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-016.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-016.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-016.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-017.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-017.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-017.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-017.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-018.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-018.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-018.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-018.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-019.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-019.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-019.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-019.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-020.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-020.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-020.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-020.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-021.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-021.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-021.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-021.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-022.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-022.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-022.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-022.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-023.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-023.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-023.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-023.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-024.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-024.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-024.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-024.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-025.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-025.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-025.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-025.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-026.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-026.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-026.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-026.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-027.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-027.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-027.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-027.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-028.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-028.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-028.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-028.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-029.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-029.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-029.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-029.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-030.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-030.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-030.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-030.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-031.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-031.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-031.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-031.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-032.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-032.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-032.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-032.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-033.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-033.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-033.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-033.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-034.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-034.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-034.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-034.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-035.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-035.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-035.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-035.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-036.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-036.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-036.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-036.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-037.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-037.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-037.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-037.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-038.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-038.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-038.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-038.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-039.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-039.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-039.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-039.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-040.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-040.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-040.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-040.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-041.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-041.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-041.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-041.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-042.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-042.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-042.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-042.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-043.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-043.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-043.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-043.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-044.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-044.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-044.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-044.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-045.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-045.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-045.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-045.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-046.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-046.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-046.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-046.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-047.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-047.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-047.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-047.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-048.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-048.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-048.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-048.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-049.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-049.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-049.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-049.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-050.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-050.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-050.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-050.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-051.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-051.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-051.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-051.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-052.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-052.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-052.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-052.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-053.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-053.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-053.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-053.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-054.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-054.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-054.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-054.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-055.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-055.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-055.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-055.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-056.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-056.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-056.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-056.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-057.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-057.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-057.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-057.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-058.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-058.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-058.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-058.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-059.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-059.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-059.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-059.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-060.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-060.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-060.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-060.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-061.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-061.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-061.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-061.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-062.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-062.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-062.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-062.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-063.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-063.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-063.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-063.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-064.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-064.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-064.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-064.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-065.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-065.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-065.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-065.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-066.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-066.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-066.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-066.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-067.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-067.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-067.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-067.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-068.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-068.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-068.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-068.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-069.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-069.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-069.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-069.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-070.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-070.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-070.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-070.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-071.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-071.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-071.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-071.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-072.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-072.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-072.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-072.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-073.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-073.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-073.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-073.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-074.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-074.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-074.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-074.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-075.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-075.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-075.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-075.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-076.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-076.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-076.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-076.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-077.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-077.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-077.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-077.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-078.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-078.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-078.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-078.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-079.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-079.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-079.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-079.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-080.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-080.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-080.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-080.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-081.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-081.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-081.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-081.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-082.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-082.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-082.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-082.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-083.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-083.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-083.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-083.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-084.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-084.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-084.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-084.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-085.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-085.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-085.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-085.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-086.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-086.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-086.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-086.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-087.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-087.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-087.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-087.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-088.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-088.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-088.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-088.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-089.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-089.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-089.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-089.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-090.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-090.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-090.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-090.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-091.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-091.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-091.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-091.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-092.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-092.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-092.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-092.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-093.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-093.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-093.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-093.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-094.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-094.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-094.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-094.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-095.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-095.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-095.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-095.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-096.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-096.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-096.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-096.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-097.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-097.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-097.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-097.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-098.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-098.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-098.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-098.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-099.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-099.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-099.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-099.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-100.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-100.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-100.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-100.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-101.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-101.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-101.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-101.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-102.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-102.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-102.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-102.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-103.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-103.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-103.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-103.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-104.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-104.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-104.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-104.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-105.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-105.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-105.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-105.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-106.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-106.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-106.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-106.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-107.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-107.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-107.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-107.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-108.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-108.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-108.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-108.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-109.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-109.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-109.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-109.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-110.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-110.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-110.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-110.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-111.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-111.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-111.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-111.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-112.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-112.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-112.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-112.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-113.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-113.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-113.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-113.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-114.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-114.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-114.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-114.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-115.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-115.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-115.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-115.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-116.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-116.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-116.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-116.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-117.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-117.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-117.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-117.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-118.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-118.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-118.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-118.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-119.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-119.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-119.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-119.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-120.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-120.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-120.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-120.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-121.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-121.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-121.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-121.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-122.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-122.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-122.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-122.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-123.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-123.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-123.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-123.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-124.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-124.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-124.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-124.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-125.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-125.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-125.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-125.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-126.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-126.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-126.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-126.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-127.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-127.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-127.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-127.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-128.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-128.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-128.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-128.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-129.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-129.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-129.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-129.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-130.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-130.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-130.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-130.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-131.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-131.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-131.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-131.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-132.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-132.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-132.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-132.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-133.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-133.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-133.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-133.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-134.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-134.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-134.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-134.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-135.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-135.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-135.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-135.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-136.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-136.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-136.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-136.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-137.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-137.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-137.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-137.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-138.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-138.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-138.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-138.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-139.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-139.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-139.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-139.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-140.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-140.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-140.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-140.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-141.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-141.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-141.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-141.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-142.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-142.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-142.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-142.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-143.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-143.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-143.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-143.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-144.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-144.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-144.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-144.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-145.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-145.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-145.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-145.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-146.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-146.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-146.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-146.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-147.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-147.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-147.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-147.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-148.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-148.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-148.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-148.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-149.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-149.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-149.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-149.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-150.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-150.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-150.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-150.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-151.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-151.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-151.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-151.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-152.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-152.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-152.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-152.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-153.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-153.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-153.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-153.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-154.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-154.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-154.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-154.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-155.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-155.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-155.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-155.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-156.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-156.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-156.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-156.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-157.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-157.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-2-valid-157.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-2-valid-157.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-001.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-001.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-001.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-002.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-002.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-002.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-003.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-003.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-003.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-004.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-004.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-004.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-005.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-005.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-005.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-006.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-006.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-006.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-006.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-007.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-007.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-007.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-007.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-008.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-008.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-008.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-008.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-009.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-009.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-009.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-009.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-010.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-010.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-010.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-010.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-011.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-011.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-011.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-011.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-012.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-012.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-012.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-012.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-013.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-013.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-013.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-013.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-014.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-014.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-014.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-014.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-015.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-015.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-015.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-015.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-016.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-016.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-016.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-016.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-017.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-017.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-017.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-017.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-018.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-018.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-018.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-018.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-019.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-019.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-019.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-019.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-020.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-020.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-020.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-020.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-021.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-021.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-021.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-021.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-022.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-022.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-022.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-022.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-023.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-023.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-023.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-023.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-024.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-024.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-024.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-024.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-025.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-025.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-025.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-025.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-026.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-026.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-026.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-026.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-027.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-027.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-027.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-027.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-028.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-028.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-028.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-028.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-029.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-029.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-029.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-029.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-030.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-030.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-030.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-030.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-031.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-031.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-031.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-031.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-032.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-032.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-032.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-032.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-033.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-033.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-033.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-033.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-034.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-034.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-034.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-034.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-035.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-035.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-035.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-035.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-036.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-036.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-036.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-036.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-037.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-037.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-037.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-037.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-038.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-038.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-038.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-038.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-039.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-039.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-039.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-039.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-040.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-040.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-040.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-040.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-041.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-041.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-041.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-041.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-042.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-042.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-042.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-042.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-043.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-043.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-043.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-043.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-044.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-044.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-044.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-044.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-045.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-045.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-045.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-045.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-046.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-046.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-046.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-046.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-047.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-047.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-047.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-047.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-048.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-048.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-048.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-048.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-049.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-049.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-049.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-049.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-050.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-050.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-050.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-050.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-051.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-051.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-051.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-051.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-052.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-052.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-052.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-052.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-053.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-053.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-053.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-053.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-054.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-054.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-054.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-054.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-055.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-055.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-055.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-055.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-056.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-056.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-056.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-056.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-057.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-057.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-057.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-057.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-058.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-058.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-058.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-058.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-059.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-059.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-059.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-059.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-060.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-060.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-060.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-060.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-061.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-061.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-061.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-061.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-062.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-062.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-062.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-062.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-063.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-063.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-063.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-063.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-064.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-064.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-064.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-064.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-065.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-065.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-065.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-065.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-066.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-066.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-066.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-066.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-067.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-067.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-067.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-067.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-068.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-068.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-068.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-068.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-069.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-069.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-069.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-069.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-070.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-070.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-070.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-070.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-071.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-071.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-071.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-071.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-072.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-072.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-072.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-072.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-073.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-073.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-073.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-073.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-074.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-074.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-074.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-074.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-075.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-075.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-075.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-075.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-076.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-076.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-076.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-076.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-077.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-077.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-077.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-077.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-078.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-078.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-078.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-078.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-079.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-079.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-079.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-079.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-080.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-080.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-080.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-080.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-081.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-081.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-081.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-081.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-082.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-082.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-082.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-082.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-083.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-083.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-083.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-083.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-084.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-084.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-084.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-084.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-085.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-085.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-085.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-085.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-086.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-086.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-086.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-086.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-087.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-087.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-087.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-087.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-088.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-088.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-088.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-088.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-089.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-089.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-089.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-089.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-090.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-090.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-090.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-090.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-091.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-091.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-091.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-091.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-092.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-092.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-092.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-092.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-093.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-093.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-093.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-093.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-094.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-094.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-094.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-094.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-095.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-095.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-095.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-095.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-096.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-096.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-096.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-096.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-097.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-097.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-097.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-097.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-098.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-098.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-098.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-098.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-099.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-099.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-099.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-099.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-100.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-100.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-100.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-100.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-101.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-101.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-101.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-101.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-102.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-102.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-102.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-102.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-103.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-103.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-103.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-103.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-104.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-104.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-104.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-104.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-105.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-105.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-105.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-105.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-106.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-106.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-106.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-106.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-107.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-107.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-107.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-107.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-108.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-108.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-108.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-108.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-109.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-109.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-109.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-109.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-110.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-110.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-110.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-110.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-111.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-111.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-111.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-111.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-112.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-112.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-112.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-112.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-113.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-113.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-113.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-113.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-114.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-114.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-114.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-114.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-115.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-115.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-115.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-115.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-116.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-116.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-116.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-116.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-117.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-117.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-117.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-117.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-118.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-118.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-118.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-118.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-119.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-119.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-119.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-119.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-120.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-120.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-120.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-120.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-121.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-121.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-121.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-121.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-122.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-122.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-122.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-122.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-123.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-123.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-123.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-123.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-124.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-124.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-124.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-124.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-125.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-125.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-125.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-125.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-126.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-126.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-126.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-126.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-127.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-127.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-127.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-127.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-128.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-128.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-128.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-128.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-129.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-129.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-129.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-129.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-130.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-130.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-130.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-130.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-131.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-131.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-131.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-131.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-132.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-132.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-132.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-132.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-133.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-133.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-133.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-133.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-134.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-134.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-134.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-134.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-135.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-135.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-135.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-135.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-136.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-136.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-136.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-136.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-137.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-137.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-137.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-137.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-138.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-138.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-138.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-138.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-139.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-139.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-139.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-139.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-140.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-140.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-140.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-140.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-141.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-141.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-141.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-141.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-142.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-142.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-142.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-142.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-143.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-143.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-143.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-143.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-144.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-144.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-144.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-144.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-145.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-145.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-145.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-145.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-146.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-146.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-146.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-146.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-147.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-147.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-147.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-147.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-148.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-148.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-148.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-148.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-149.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-149.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-149.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-149.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-150.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-150.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-150.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-150.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-151.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-151.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-151.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-151.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-152.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-152.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-152.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-152.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-153.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-153.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-153.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-153.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-154.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-154.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-154.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-154.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-155.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-155.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-155.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-155.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-156.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-156.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-156.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-156.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-157.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-157.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-157.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-157.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-158.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-158.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-158.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-158.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-159.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-159.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-159.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-159.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-160.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-160.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-160.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-160.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-161.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-161.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-161.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-161.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-162.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-162.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-162.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-162.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-163.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-163.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-163.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-163.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-164.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-164.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-164.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-164.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-165.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-165.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-165.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-165.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-166.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-166.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-166.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-166.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-167.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-167.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-167.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-167.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-168.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-168.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-168.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-168.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-169.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-169.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-169.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-169.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-170.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-170.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-170.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-170.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-171.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-171.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-171.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-171.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-172.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-172.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-172.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-172.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-173.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-173.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-173.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-173.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-174.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-174.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-174.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-174.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-175.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-175.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-175.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-175.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-176.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-176.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-176.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-176.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-177.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-177.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-177.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-177.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-178.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-178.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-178.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-178.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-179.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-179.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-179.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-179.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-180.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-180.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-180.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-180.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-181.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-181.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-181.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-181.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-182.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-182.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-182.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-182.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-183.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-183.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-183.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-183.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-184.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-184.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-184.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-184.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-185.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-185.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-185.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-185.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-186.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-186.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-186.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-186.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-187.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-187.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-187.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-187.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-188.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-188.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-188.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-188.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-189.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-189.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-189.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-189.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-190.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-190.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-190.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-190.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-191.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-191.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-191.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-191.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-192.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-192.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-192.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-192.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-193.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-193.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-193.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-193.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-194.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-194.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-194.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-194.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-195.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-195.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-195.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-195.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-196.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-196.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-196.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-196.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-197.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-197.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-197.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-197.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-198.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-198.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-198.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-198.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-199.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-199.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-199.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-199.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-200.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-200.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-200.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-200.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-201.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-201.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-201.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-201.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-202.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-202.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-202.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-202.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-203.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-203.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-203.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-203.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-204.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-204.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-204.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-204.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-205.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-205.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-205.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-205.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-206.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-206.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-206.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-206.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-207.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-207.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-207.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-207.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-208.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-208.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-208.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-208.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-209.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-209.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-209.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-209.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-210.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-210.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-210.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-210.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-211.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-211.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-211.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-211.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-212.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-212.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-212.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-212.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-213.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-213.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-213.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-213.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-214.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-214.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-214.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-214.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-215.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-215.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-215.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-215.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-216.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-216.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-216.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-216.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-217.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-217.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-217.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-217.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-218.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-218.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-218.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-218.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-219.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-219.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-219.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-219.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-220.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-220.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-220.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-220.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-221.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-221.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-221.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-221.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-222.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-222.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-222.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-222.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-223.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-223.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-223.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-223.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-224.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-224.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-224.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-224.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-225.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-225.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-225.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-225.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-226.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-226.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-226.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-226.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-227.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-227.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-227.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-227.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-228.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-228.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-228.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-228.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-229.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-229.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-229.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-229.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-230.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-230.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-230.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-230.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-231.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-231.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-231.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-231.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-232.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-232.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-232.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-232.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-233.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-233.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-233.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-233.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-234.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-234.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-234.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-234.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-235.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-235.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-235.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-235.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-236.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-236.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-236.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-236.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-237.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-237.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-237.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-237.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-238.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-238.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-238.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-238.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-239.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-239.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-239.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-239.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-240.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-240.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-240.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-240.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-241.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-241.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-241.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-241.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-242.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-242.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-242.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-242.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-243.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-243.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-243.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-243.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-244.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-244.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-244.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-244.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-245.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-245.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-245.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-245.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-246.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-246.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-246.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-246.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-247.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-247.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-247.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-247.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-248.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-248.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-248.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-248.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-249.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-249.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-249.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-249.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-250.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-250.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-250.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-250.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-251.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-251.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-251.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-251.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-252.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-252.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-252.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-252.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-253.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-253.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-253.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-253.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-254.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-254.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-254.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-254.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-255.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-255.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-255.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-255.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-256.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-256.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-256.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-256.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-257.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-257.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-257.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-257.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-258.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-258.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-258.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-258.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-259.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-259.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-259.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-259.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-260.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-260.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-260.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-260.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-261.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-261.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-261.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-261.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-262.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-262.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-262.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-262.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-263.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-263.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-263.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-263.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-264.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-264.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-264.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-264.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-265.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-265.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-265.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-265.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-266.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-266.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-266.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-266.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-267.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-267.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-267.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-267.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-268.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-268.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-268.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-268.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-269.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-269.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-269.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-269.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-270.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-270.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-270.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-270.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-271.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-271.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-271.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-271.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-272.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-272.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-272.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-272.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-273.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-273.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-273.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-273.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-274.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-274.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-274.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-274.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-275.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-275.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-275.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-275.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-276.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-276.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-276.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-276.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-277.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-277.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-277.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-277.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-278.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-278.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-278.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-278.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-279.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-279.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-279.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-279.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-280.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-280.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-280.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-280.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-281.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-281.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-281.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-281.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-282.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-282.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-282.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-282.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-283.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-283.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-283.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-283.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-284.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-284.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-284.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-284.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-285.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-285.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-285.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-285.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-286.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-286.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-286.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-286.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-287.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-287.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-287.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-287.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-288.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-288.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-288.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-288.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-289.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-289.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-289.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-289.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-290.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-290.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-290.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-290.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-291.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-291.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-291.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-291.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-292.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-292.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-292.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-292.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-293.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-293.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-293.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-293.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-294.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-294.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-294.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-294.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-295.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-295.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-295.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-295.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-296.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-296.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-296.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-296.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-297.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-297.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-297.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-297.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-298.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-298.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-298.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-298.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-299.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-299.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-299.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-299.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-300.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-300.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-300.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-300.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-301.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-301.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-301.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-301.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-302.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-302.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-302.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-302.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-303.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-303.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-303.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-303.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-304.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-304.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-304.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-304.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-305.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-305.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-305.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-305.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-306.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-306.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-306.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-306.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-307.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-307.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-307.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-307.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-308.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-308.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-3-valid-308.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-3-valid-308.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-4-parseError-001.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-4-parseError-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-4-parseError-001.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-4-parseError-001.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-4-parseError-002.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-4-parseError-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-4-parseError-002.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-4-parseError-002.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-4-parseError-003.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-4-parseError-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-4-parseError-003.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-4-parseError-003.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-4-parseError-004.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-4-parseError-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-4-parseError-004.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-4-parseError-004.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-4-parseError-005.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-4-parseError-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-4-parseError-005.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-4-parseError-005.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-4-parseError-006.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-4-parseError-006.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-4-parseError-006.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-4-parseError-006.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-4-parseError-007.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-4-parseError-007.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-4-parseError-007.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-4-parseError-007.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-4-parseError-008.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-4-parseError-008.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-4-parseError-008.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-4-parseError-008.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-4-parseError-009.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-4-parseError-009.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-4-parseError-009.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-4-parseError-009.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-4-parseError-010.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-4-parseError-010.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-4-parseError-010.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-4-parseError-010.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-4-parseError-011.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-4-parseError-011.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-4-parseError-011.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-4-parseError-011.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-4-parseError-012.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-4-parseError-012.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-4-parseError-012.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-4-parseError-012.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-4-parseError-013.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-4-parseError-013.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-4-parseError-013.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-4-parseError-013.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-4-parseError-014.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-4-parseError-014.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-4-parseError-014.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-4-parseError-014.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-4-parseError-015.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-4-parseError-015.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-4-parseError-015.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-4-parseError-015.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-4-parseError-016.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-4-parseError-016.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-4-parseError-016.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-4-parseError-016.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-4-parseError-017.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-4-parseError-017.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-4-parseError-017.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-4-parseError-017.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-4-parseError-018.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-4-parseError-018.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-4-parseError-018.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-4-parseError-018.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-4-parseError-019.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-4-parseError-019.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-4-parseError-019.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-4-parseError-019.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-4-parseError-020.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-4-parseError-020.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-4-parseError-020.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-4-parseError-020.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-4-valid-001.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-4-valid-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-4-valid-001.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-4-valid-001.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-4-valid-002.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-4-valid-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-4-valid-002.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-4-valid-002.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-4-valid-003.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-4-valid-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-4-valid-003.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-4-valid-003.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-4-valid-004.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-4-valid-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-4-valid-004.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-4-valid-004.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-4-valid-005.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-4-valid-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-4-valid-005.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-4-valid-005.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-4-valid-006.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-4-valid-006.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-4-valid-006.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-4-valid-006.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-4-valid-007.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-4-valid-007.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-4-valid-007.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-4-valid-007.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-4-valid-008.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-4-valid-008.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-4-valid-008.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-4-valid-008.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-4-valid-009.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-4-valid-009.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-4-valid-009.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-4-valid-009.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-4-valid-010.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-4-valid-010.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-4-valid-010.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-4-valid-010.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-4-valid-011.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-4-valid-011.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-4-valid-011.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-4-valid-011.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-4-valid-012.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-4-valid-012.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-4-valid-012.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-4-valid-012.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-4-valid-013.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-4-valid-013.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-4-valid-013.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-4-valid-013.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-001.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-001.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-001.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-002.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-002.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-002.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-003.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-003.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-003.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-004.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-004.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-004.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-005.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-005.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-005.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-006.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-006.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-006.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-006.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-007.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-007.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-007.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-007.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-008.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-008.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-008.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-008.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-009.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-009.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-009.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-009.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-010.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-010.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-010.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-010.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-011.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-011.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-011.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-011.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-012.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-012.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-012.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-012.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-013.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-013.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-013.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-013.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-014.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-014.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-014.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-014.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-015.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-015.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-015.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-015.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-016.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-016.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-016.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-016.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-017.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-017.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-017.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-017.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-018.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-018.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-018.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-018.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-019.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-019.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-019.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-019.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-020.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-020.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-020.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-020.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-021.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-021.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-021.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-021.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-022.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-022.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-022.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-022.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-023.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-023.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-023.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-023.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-024.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-024.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-024.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-024.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-025.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-025.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-025.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-025.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-026.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-026.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-026.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-026.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-027.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-027.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-027.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-027.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-028.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-028.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-028.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-028.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-029.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-029.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-029.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-029.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-030.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-030.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-030.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-030.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-031.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-031.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-031.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-031.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-032.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-032.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-032.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-032.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-033.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-033.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-033.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-033.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-034.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-034.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-034.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-034.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-035.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-035.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-035.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-035.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-036.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-036.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-036.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-036.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-037.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-037.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-037.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-037.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-038.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-038.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-038.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-038.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-039.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-039.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-039.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-039.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-040.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-040.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-040.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-040.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-041.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-041.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-041.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-041.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-042.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-042.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-042.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-042.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-043.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-043.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-043.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-043.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-044.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-044.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-044.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-044.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-045.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-045.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-045.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-045.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-046.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-046.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-046.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-046.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-047.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-047.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-047.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-047.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-048.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-048.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-048.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-048.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-049.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-049.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-049.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-049.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-050.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-050.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-050.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-050.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-051.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-051.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-051.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-051.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-052.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-052.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-052.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-052.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-053.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-053.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-053.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-053.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-054.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-054.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-054.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-054.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-055.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-055.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-055.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-055.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-056.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-056.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-056.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-056.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-057.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-057.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-057.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-057.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-058.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-058.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-058.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-058.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-059.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-059.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-059.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-059.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-060.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-060.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-060.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-060.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-061.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-061.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-061.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-061.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-062.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-062.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-062.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-062.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-063.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-063.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-063.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-063.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-064.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-064.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-064.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-064.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-065.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-065.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-065.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-065.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-066.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-066.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-066.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-066.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-067.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-067.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-5-valid-067.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-5-valid-067.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-001.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-001.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-001.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-002.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-002.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-002.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-003.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-003.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-003.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-004.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-004.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-004.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-005.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-005.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-005.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-006.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-006.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-006.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-006.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-007.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-007.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-007.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-007.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-008.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-008.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-008.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-008.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-009.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-009.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-009.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-009.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-010.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-010.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-010.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-010.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-011.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-011.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-011.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-011.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-012.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-012.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-012.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-012.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-013.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-013.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-013.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-013.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-014.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-014.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-014.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-014.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-015.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-015.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-015.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-015.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-016.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-016.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-016.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-016.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-017.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-017.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-017.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-017.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-018.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-018.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-018.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-018.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-019.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-019.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-019.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-019.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-020.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-020.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-020.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-020.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-021.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-021.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-021.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-021.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-022.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-022.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-022.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-022.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-023.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-023.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-023.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-023.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-024.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-024.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-024.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-024.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-025.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-025.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-025.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-025.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-026.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-026.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-026.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-026.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-027.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-027.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-027.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-027.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-028.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-028.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-028.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-028.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-029.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-029.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-029.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-029.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-030.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-030.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-030.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-030.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-031.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-031.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-6-parseError-031.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-6-parseError-031.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-001.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-001.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-001.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-002.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-002.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-002.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-003.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-003.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-003.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-004.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-004.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-004.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-005.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-005.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-005.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-006.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-006.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-006.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-006.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-007.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-007.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-007.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-007.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-008.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-008.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-008.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-008.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-009.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-009.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-009.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-009.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-010.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-010.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-010.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-010.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-011.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-011.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-011.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-011.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-012.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-012.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-012.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-012.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-013.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-013.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-013.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-013.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-014.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-014.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-014.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-014.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-015.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-015.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-015.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-015.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-016.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-016.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-016.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-016.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-017.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-017.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-017.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-017.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-018.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-018.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-018.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-018.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-019.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-019.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-019.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-019.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-020.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-020.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-020.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-020.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-021.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-021.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-021.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-021.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-022.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-022.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-022.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-022.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-023.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-023.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-023.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-023.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-024.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-024.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-024.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-024.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-025.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-025.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-025.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-025.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-026.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-026.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-026.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-026.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-027.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-027.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-027.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-027.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-028.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-028.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-028.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-028.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-029.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-029.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-029.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-029.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-030.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-030.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-030.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-030.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-031.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-031.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-031.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-031.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-032.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-032.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-032.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-032.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-033.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-033.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-033.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-033.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-034.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-034.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-034.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-034.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-035.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-035.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-035.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-035.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-036.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-036.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-036.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-036.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-037.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-037.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-037.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-037.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-038.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-038.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-038.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-038.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-039.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-039.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-039.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-039.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-040.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-040.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-040.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-040.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-041.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-041.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-041.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-041.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-042.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-042.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-042.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-042.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-043.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-043.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-043.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-043.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-044.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-044.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-044.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-044.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-045.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-045.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-045.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-045.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-046.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-046.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-046.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-046.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-047.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-047.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-047.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-047.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-048.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-048.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-048.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-048.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-049.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-049.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-049.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-049.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-050.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-050.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-050.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-050.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-051.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-051.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-051.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-051.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-052.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-052.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-052.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-052.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-053.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-053.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-053.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-053.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-054.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-054.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-054.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-054.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-055.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-055.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-055.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-055.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-056.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-056.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-056.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-056.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-057.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-057.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-057.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-057.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-058.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-058.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-058.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-058.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-059.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-059.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-059.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-059.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-060.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-060.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-060.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-060.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-061.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-061.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-061.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-061.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-062.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-062.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-062.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-062.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-063.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-063.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-063.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-063.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-064.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-064.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-064.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-064.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-065.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-065.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-065.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-065.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-066.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-066.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-066.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-066.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-067.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-067.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-067.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-067.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-068.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-068.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-068.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-068.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-069.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-069.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-069.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-069.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-070.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-070.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-070.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-070.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-071.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-071.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-071.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-071.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-072.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-072.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-072.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-072.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-073.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-073.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-073.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-073.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-074.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-074.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-074.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-074.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-075.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-075.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-075.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-075.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-076.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-076.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-076.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-076.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-077.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-077.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-077.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-077.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-078.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-078.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-078.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-078.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-079.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-079.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-079.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-079.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-080.phpt b/mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-080.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/decimal128-7-parseError-080.phpt
rename to mongodb-1.13.0/tests/bson-corpus/decimal128-7-parseError-080.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/document-decodeError-001.phpt b/mongodb-1.13.0/tests/bson-corpus/document-decodeError-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/document-decodeError-001.phpt
rename to mongodb-1.13.0/tests/bson-corpus/document-decodeError-001.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/document-decodeError-002.phpt b/mongodb-1.13.0/tests/bson-corpus/document-decodeError-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/document-decodeError-002.phpt
rename to mongodb-1.13.0/tests/bson-corpus/document-decodeError-002.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/document-decodeError-003.phpt b/mongodb-1.13.0/tests/bson-corpus/document-decodeError-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/document-decodeError-003.phpt
rename to mongodb-1.13.0/tests/bson-corpus/document-decodeError-003.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/document-decodeError-004.phpt b/mongodb-1.13.0/tests/bson-corpus/document-decodeError-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/document-decodeError-004.phpt
rename to mongodb-1.13.0/tests/bson-corpus/document-decodeError-004.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/document-valid-001.phpt b/mongodb-1.13.0/tests/bson-corpus/document-valid-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/document-valid-001.phpt
rename to mongodb-1.13.0/tests/bson-corpus/document-valid-001.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/document-valid-002.phpt b/mongodb-1.13.0/tests/bson-corpus/document-valid-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/document-valid-002.phpt
rename to mongodb-1.13.0/tests/bson-corpus/document-valid-002.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/document-valid-003.phpt b/mongodb-1.13.0/tests/bson-corpus/document-valid-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/document-valid-003.phpt
rename to mongodb-1.13.0/tests/bson-corpus/document-valid-003.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/document-valid-004.phpt b/mongodb-1.13.0/tests/bson-corpus/document-valid-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/document-valid-004.phpt
rename to mongodb-1.13.0/tests/bson-corpus/document-valid-004.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/document-valid-005.phpt b/mongodb-1.13.0/tests/bson-corpus/document-valid-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/document-valid-005.phpt
rename to mongodb-1.13.0/tests/bson-corpus/document-valid-005.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/document-valid-006.phpt b/mongodb-1.13.0/tests/bson-corpus/document-valid-006.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/document-valid-006.phpt
rename to mongodb-1.13.0/tests/bson-corpus/document-valid-006.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/document-valid-007.phpt b/mongodb-1.13.0/tests/bson-corpus/document-valid-007.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/document-valid-007.phpt
rename to mongodb-1.13.0/tests/bson-corpus/document-valid-007.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/double-decodeError-001.phpt b/mongodb-1.13.0/tests/bson-corpus/double-decodeError-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/double-decodeError-001.phpt
rename to mongodb-1.13.0/tests/bson-corpus/double-decodeError-001.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/double-valid-001.phpt b/mongodb-1.13.0/tests/bson-corpus/double-valid-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/double-valid-001.phpt
rename to mongodb-1.13.0/tests/bson-corpus/double-valid-001.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/double-valid-002.phpt b/mongodb-1.13.0/tests/bson-corpus/double-valid-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/double-valid-002.phpt
rename to mongodb-1.13.0/tests/bson-corpus/double-valid-002.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/double-valid-003.phpt b/mongodb-1.13.0/tests/bson-corpus/double-valid-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/double-valid-003.phpt
rename to mongodb-1.13.0/tests/bson-corpus/double-valid-003.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/double-valid-004.phpt b/mongodb-1.13.0/tests/bson-corpus/double-valid-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/double-valid-004.phpt
rename to mongodb-1.13.0/tests/bson-corpus/double-valid-004.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/double-valid-005.phpt b/mongodb-1.13.0/tests/bson-corpus/double-valid-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/double-valid-005.phpt
rename to mongodb-1.13.0/tests/bson-corpus/double-valid-005.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/double-valid-006.phpt b/mongodb-1.13.0/tests/bson-corpus/double-valid-006.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/double-valid-006.phpt
rename to mongodb-1.13.0/tests/bson-corpus/double-valid-006.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/double-valid-007.phpt b/mongodb-1.13.0/tests/bson-corpus/double-valid-007.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/double-valid-007.phpt
rename to mongodb-1.13.0/tests/bson-corpus/double-valid-007.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/double-valid-008.phpt b/mongodb-1.13.0/tests/bson-corpus/double-valid-008.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/double-valid-008.phpt
rename to mongodb-1.13.0/tests/bson-corpus/double-valid-008.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/double-valid-009.phpt b/mongodb-1.13.0/tests/bson-corpus/double-valid-009.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/double-valid-009.phpt
rename to mongodb-1.13.0/tests/bson-corpus/double-valid-009.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/double-valid-010.phpt b/mongodb-1.13.0/tests/bson-corpus/double-valid-010.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/double-valid-010.phpt
rename to mongodb-1.13.0/tests/bson-corpus/double-valid-010.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/double-valid-011.phpt b/mongodb-1.13.0/tests/bson-corpus/double-valid-011.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/double-valid-011.phpt
rename to mongodb-1.13.0/tests/bson-corpus/double-valid-011.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/double-valid-012.phpt b/mongodb-1.13.0/tests/bson-corpus/double-valid-012.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/double-valid-012.phpt
rename to mongodb-1.13.0/tests/bson-corpus/double-valid-012.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/int32-decodeError-001.phpt b/mongodb-1.13.0/tests/bson-corpus/int32-decodeError-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/int32-decodeError-001.phpt
rename to mongodb-1.13.0/tests/bson-corpus/int32-decodeError-001.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/int32-valid-001.phpt b/mongodb-1.13.0/tests/bson-corpus/int32-valid-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/int32-valid-001.phpt
rename to mongodb-1.13.0/tests/bson-corpus/int32-valid-001.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/int32-valid-002.phpt b/mongodb-1.13.0/tests/bson-corpus/int32-valid-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/int32-valid-002.phpt
rename to mongodb-1.13.0/tests/bson-corpus/int32-valid-002.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/int32-valid-003.phpt b/mongodb-1.13.0/tests/bson-corpus/int32-valid-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/int32-valid-003.phpt
rename to mongodb-1.13.0/tests/bson-corpus/int32-valid-003.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/int32-valid-004.phpt b/mongodb-1.13.0/tests/bson-corpus/int32-valid-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/int32-valid-004.phpt
rename to mongodb-1.13.0/tests/bson-corpus/int32-valid-004.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/int32-valid-005.phpt b/mongodb-1.13.0/tests/bson-corpus/int32-valid-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/int32-valid-005.phpt
rename to mongodb-1.13.0/tests/bson-corpus/int32-valid-005.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/int64-decodeError-001.phpt b/mongodb-1.13.0/tests/bson-corpus/int64-decodeError-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/int64-decodeError-001.phpt
rename to mongodb-1.13.0/tests/bson-corpus/int64-decodeError-001.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/int64-valid-001.phpt b/mongodb-1.13.0/tests/bson-corpus/int64-valid-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/int64-valid-001.phpt
rename to mongodb-1.13.0/tests/bson-corpus/int64-valid-001.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/int64-valid-002.phpt b/mongodb-1.13.0/tests/bson-corpus/int64-valid-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/int64-valid-002.phpt
rename to mongodb-1.13.0/tests/bson-corpus/int64-valid-002.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/int64-valid-003.phpt b/mongodb-1.13.0/tests/bson-corpus/int64-valid-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/int64-valid-003.phpt
rename to mongodb-1.13.0/tests/bson-corpus/int64-valid-003.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/int64-valid-004.phpt b/mongodb-1.13.0/tests/bson-corpus/int64-valid-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/int64-valid-004.phpt
rename to mongodb-1.13.0/tests/bson-corpus/int64-valid-004.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/int64-valid-005.phpt b/mongodb-1.13.0/tests/bson-corpus/int64-valid-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/int64-valid-005.phpt
rename to mongodb-1.13.0/tests/bson-corpus/int64-valid-005.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/maxkey-valid-001.phpt b/mongodb-1.13.0/tests/bson-corpus/maxkey-valid-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/maxkey-valid-001.phpt
rename to mongodb-1.13.0/tests/bson-corpus/maxkey-valid-001.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/minkey-valid-001.phpt b/mongodb-1.13.0/tests/bson-corpus/minkey-valid-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/minkey-valid-001.phpt
rename to mongodb-1.13.0/tests/bson-corpus/minkey-valid-001.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/multi-type-deprecated-valid-001.phpt b/mongodb-1.13.0/tests/bson-corpus/multi-type-deprecated-valid-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/multi-type-deprecated-valid-001.phpt
rename to mongodb-1.13.0/tests/bson-corpus/multi-type-deprecated-valid-001.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/multi-type-valid-001.phpt b/mongodb-1.13.0/tests/bson-corpus/multi-type-valid-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/multi-type-valid-001.phpt
rename to mongodb-1.13.0/tests/bson-corpus/multi-type-valid-001.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/null-valid-001.phpt b/mongodb-1.13.0/tests/bson-corpus/null-valid-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/null-valid-001.phpt
rename to mongodb-1.13.0/tests/bson-corpus/null-valid-001.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/oid-decodeError-001.phpt b/mongodb-1.13.0/tests/bson-corpus/oid-decodeError-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/oid-decodeError-001.phpt
rename to mongodb-1.13.0/tests/bson-corpus/oid-decodeError-001.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/oid-valid-001.phpt b/mongodb-1.13.0/tests/bson-corpus/oid-valid-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/oid-valid-001.phpt
rename to mongodb-1.13.0/tests/bson-corpus/oid-valid-001.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/oid-valid-002.phpt b/mongodb-1.13.0/tests/bson-corpus/oid-valid-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/oid-valid-002.phpt
rename to mongodb-1.13.0/tests/bson-corpus/oid-valid-002.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/oid-valid-003.phpt b/mongodb-1.13.0/tests/bson-corpus/oid-valid-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/oid-valid-003.phpt
rename to mongodb-1.13.0/tests/bson-corpus/oid-valid-003.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/regex-decodeError-001.phpt b/mongodb-1.13.0/tests/bson-corpus/regex-decodeError-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/regex-decodeError-001.phpt
rename to mongodb-1.13.0/tests/bson-corpus/regex-decodeError-001.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/regex-decodeError-002.phpt b/mongodb-1.13.0/tests/bson-corpus/regex-decodeError-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/regex-decodeError-002.phpt
rename to mongodb-1.13.0/tests/bson-corpus/regex-decodeError-002.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/regex-valid-001.phpt b/mongodb-1.13.0/tests/bson-corpus/regex-valid-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/regex-valid-001.phpt
rename to mongodb-1.13.0/tests/bson-corpus/regex-valid-001.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/regex-valid-002.phpt b/mongodb-1.13.0/tests/bson-corpus/regex-valid-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/regex-valid-002.phpt
rename to mongodb-1.13.0/tests/bson-corpus/regex-valid-002.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/regex-valid-003.phpt b/mongodb-1.13.0/tests/bson-corpus/regex-valid-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/regex-valid-003.phpt
rename to mongodb-1.13.0/tests/bson-corpus/regex-valid-003.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/regex-valid-004.phpt b/mongodb-1.13.0/tests/bson-corpus/regex-valid-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/regex-valid-004.phpt
rename to mongodb-1.13.0/tests/bson-corpus/regex-valid-004.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/regex-valid-005.phpt b/mongodb-1.13.0/tests/bson-corpus/regex-valid-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/regex-valid-005.phpt
rename to mongodb-1.13.0/tests/bson-corpus/regex-valid-005.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/regex-valid-006.phpt b/mongodb-1.13.0/tests/bson-corpus/regex-valid-006.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/regex-valid-006.phpt
rename to mongodb-1.13.0/tests/bson-corpus/regex-valid-006.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/regex-valid-007.phpt b/mongodb-1.13.0/tests/bson-corpus/regex-valid-007.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/regex-valid-007.phpt
rename to mongodb-1.13.0/tests/bson-corpus/regex-valid-007.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/regex-valid-008.phpt b/mongodb-1.13.0/tests/bson-corpus/regex-valid-008.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/regex-valid-008.phpt
rename to mongodb-1.13.0/tests/bson-corpus/regex-valid-008.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/regex-valid-009.phpt b/mongodb-1.13.0/tests/bson-corpus/regex-valid-009.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/regex-valid-009.phpt
rename to mongodb-1.13.0/tests/bson-corpus/regex-valid-009.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/string-decodeError-001.phpt b/mongodb-1.13.0/tests/bson-corpus/string-decodeError-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/string-decodeError-001.phpt
rename to mongodb-1.13.0/tests/bson-corpus/string-decodeError-001.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/string-decodeError-002.phpt b/mongodb-1.13.0/tests/bson-corpus/string-decodeError-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/string-decodeError-002.phpt
rename to mongodb-1.13.0/tests/bson-corpus/string-decodeError-002.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/string-decodeError-003.phpt b/mongodb-1.13.0/tests/bson-corpus/string-decodeError-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/string-decodeError-003.phpt
rename to mongodb-1.13.0/tests/bson-corpus/string-decodeError-003.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/string-decodeError-004.phpt b/mongodb-1.13.0/tests/bson-corpus/string-decodeError-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/string-decodeError-004.phpt
rename to mongodb-1.13.0/tests/bson-corpus/string-decodeError-004.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/string-decodeError-005.phpt b/mongodb-1.13.0/tests/bson-corpus/string-decodeError-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/string-decodeError-005.phpt
rename to mongodb-1.13.0/tests/bson-corpus/string-decodeError-005.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/string-decodeError-006.phpt b/mongodb-1.13.0/tests/bson-corpus/string-decodeError-006.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/string-decodeError-006.phpt
rename to mongodb-1.13.0/tests/bson-corpus/string-decodeError-006.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/string-decodeError-007.phpt b/mongodb-1.13.0/tests/bson-corpus/string-decodeError-007.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/string-decodeError-007.phpt
rename to mongodb-1.13.0/tests/bson-corpus/string-decodeError-007.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/string-valid-001.phpt b/mongodb-1.13.0/tests/bson-corpus/string-valid-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/string-valid-001.phpt
rename to mongodb-1.13.0/tests/bson-corpus/string-valid-001.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/string-valid-002.phpt b/mongodb-1.13.0/tests/bson-corpus/string-valid-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/string-valid-002.phpt
rename to mongodb-1.13.0/tests/bson-corpus/string-valid-002.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/string-valid-003.phpt b/mongodb-1.13.0/tests/bson-corpus/string-valid-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/string-valid-003.phpt
rename to mongodb-1.13.0/tests/bson-corpus/string-valid-003.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/string-valid-004.phpt b/mongodb-1.13.0/tests/bson-corpus/string-valid-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/string-valid-004.phpt
rename to mongodb-1.13.0/tests/bson-corpus/string-valid-004.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/string-valid-005.phpt b/mongodb-1.13.0/tests/bson-corpus/string-valid-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/string-valid-005.phpt
rename to mongodb-1.13.0/tests/bson-corpus/string-valid-005.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/string-valid-006.phpt b/mongodb-1.13.0/tests/bson-corpus/string-valid-006.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/string-valid-006.phpt
rename to mongodb-1.13.0/tests/bson-corpus/string-valid-006.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/string-valid-007.phpt b/mongodb-1.13.0/tests/bson-corpus/string-valid-007.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/string-valid-007.phpt
rename to mongodb-1.13.0/tests/bson-corpus/string-valid-007.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/symbol-decodeError-001.phpt b/mongodb-1.13.0/tests/bson-corpus/symbol-decodeError-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/symbol-decodeError-001.phpt
rename to mongodb-1.13.0/tests/bson-corpus/symbol-decodeError-001.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/symbol-decodeError-002.phpt b/mongodb-1.13.0/tests/bson-corpus/symbol-decodeError-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/symbol-decodeError-002.phpt
rename to mongodb-1.13.0/tests/bson-corpus/symbol-decodeError-002.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/symbol-decodeError-003.phpt b/mongodb-1.13.0/tests/bson-corpus/symbol-decodeError-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/symbol-decodeError-003.phpt
rename to mongodb-1.13.0/tests/bson-corpus/symbol-decodeError-003.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/symbol-decodeError-004.phpt b/mongodb-1.13.0/tests/bson-corpus/symbol-decodeError-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/symbol-decodeError-004.phpt
rename to mongodb-1.13.0/tests/bson-corpus/symbol-decodeError-004.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/symbol-decodeError-005.phpt b/mongodb-1.13.0/tests/bson-corpus/symbol-decodeError-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/symbol-decodeError-005.phpt
rename to mongodb-1.13.0/tests/bson-corpus/symbol-decodeError-005.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/symbol-decodeError-006.phpt b/mongodb-1.13.0/tests/bson-corpus/symbol-decodeError-006.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/symbol-decodeError-006.phpt
rename to mongodb-1.13.0/tests/bson-corpus/symbol-decodeError-006.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/symbol-decodeError-007.phpt b/mongodb-1.13.0/tests/bson-corpus/symbol-decodeError-007.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/symbol-decodeError-007.phpt
rename to mongodb-1.13.0/tests/bson-corpus/symbol-decodeError-007.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/symbol-valid-001.phpt b/mongodb-1.13.0/tests/bson-corpus/symbol-valid-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/symbol-valid-001.phpt
rename to mongodb-1.13.0/tests/bson-corpus/symbol-valid-001.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/symbol-valid-002.phpt b/mongodb-1.13.0/tests/bson-corpus/symbol-valid-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/symbol-valid-002.phpt
rename to mongodb-1.13.0/tests/bson-corpus/symbol-valid-002.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/symbol-valid-003.phpt b/mongodb-1.13.0/tests/bson-corpus/symbol-valid-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/symbol-valid-003.phpt
rename to mongodb-1.13.0/tests/bson-corpus/symbol-valid-003.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/symbol-valid-004.phpt b/mongodb-1.13.0/tests/bson-corpus/symbol-valid-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/symbol-valid-004.phpt
rename to mongodb-1.13.0/tests/bson-corpus/symbol-valid-004.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/symbol-valid-005.phpt b/mongodb-1.13.0/tests/bson-corpus/symbol-valid-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/symbol-valid-005.phpt
rename to mongodb-1.13.0/tests/bson-corpus/symbol-valid-005.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/symbol-valid-006.phpt b/mongodb-1.13.0/tests/bson-corpus/symbol-valid-006.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/symbol-valid-006.phpt
rename to mongodb-1.13.0/tests/bson-corpus/symbol-valid-006.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/timestamp-decodeError-001.phpt b/mongodb-1.13.0/tests/bson-corpus/timestamp-decodeError-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/timestamp-decodeError-001.phpt
rename to mongodb-1.13.0/tests/bson-corpus/timestamp-decodeError-001.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/timestamp-valid-001.phpt b/mongodb-1.13.0/tests/bson-corpus/timestamp-valid-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/timestamp-valid-001.phpt
rename to mongodb-1.13.0/tests/bson-corpus/timestamp-valid-001.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/timestamp-valid-002.phpt b/mongodb-1.13.0/tests/bson-corpus/timestamp-valid-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/timestamp-valid-002.phpt
rename to mongodb-1.13.0/tests/bson-corpus/timestamp-valid-002.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/timestamp-valid-003.phpt b/mongodb-1.13.0/tests/bson-corpus/timestamp-valid-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/timestamp-valid-003.phpt
rename to mongodb-1.13.0/tests/bson-corpus/timestamp-valid-003.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/timestamp-valid-004.phpt b/mongodb-1.13.0/tests/bson-corpus/timestamp-valid-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/timestamp-valid-004.phpt
rename to mongodb-1.13.0/tests/bson-corpus/timestamp-valid-004.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-decodeError-001.phpt b/mongodb-1.13.0/tests/bson-corpus/top-decodeError-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-decodeError-001.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-decodeError-001.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-decodeError-002.phpt b/mongodb-1.13.0/tests/bson-corpus/top-decodeError-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-decodeError-002.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-decodeError-002.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-decodeError-003.phpt b/mongodb-1.13.0/tests/bson-corpus/top-decodeError-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-decodeError-003.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-decodeError-003.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-decodeError-004.phpt b/mongodb-1.13.0/tests/bson-corpus/top-decodeError-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-decodeError-004.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-decodeError-004.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-decodeError-005.phpt b/mongodb-1.13.0/tests/bson-corpus/top-decodeError-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-decodeError-005.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-decodeError-005.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-decodeError-006.phpt b/mongodb-1.13.0/tests/bson-corpus/top-decodeError-006.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-decodeError-006.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-decodeError-006.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-decodeError-007.phpt b/mongodb-1.13.0/tests/bson-corpus/top-decodeError-007.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-decodeError-007.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-decodeError-007.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-decodeError-008.phpt b/mongodb-1.13.0/tests/bson-corpus/top-decodeError-008.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-decodeError-008.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-decodeError-008.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-decodeError-009.phpt b/mongodb-1.13.0/tests/bson-corpus/top-decodeError-009.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-decodeError-009.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-decodeError-009.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-decodeError-010.phpt b/mongodb-1.13.0/tests/bson-corpus/top-decodeError-010.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-decodeError-010.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-decodeError-010.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-decodeError-011.phpt b/mongodb-1.13.0/tests/bson-corpus/top-decodeError-011.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-decodeError-011.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-decodeError-011.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-decodeError-012.phpt b/mongodb-1.13.0/tests/bson-corpus/top-decodeError-012.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-decodeError-012.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-decodeError-012.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-decodeError-013.phpt b/mongodb-1.13.0/tests/bson-corpus/top-decodeError-013.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-decodeError-013.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-decodeError-013.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-decodeError-014.phpt b/mongodb-1.13.0/tests/bson-corpus/top-decodeError-014.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-decodeError-014.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-decodeError-014.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-decodeError-015.phpt b/mongodb-1.13.0/tests/bson-corpus/top-decodeError-015.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-decodeError-015.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-decodeError-015.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-parseError-001.phpt b/mongodb-1.13.0/tests/bson-corpus/top-parseError-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-parseError-001.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-parseError-001.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-parseError-002.phpt b/mongodb-1.13.0/tests/bson-corpus/top-parseError-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-parseError-002.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-parseError-002.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-parseError-003.phpt b/mongodb-1.13.0/tests/bson-corpus/top-parseError-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-parseError-003.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-parseError-003.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-parseError-004.phpt b/mongodb-1.13.0/tests/bson-corpus/top-parseError-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-parseError-004.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-parseError-004.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-parseError-005.phpt b/mongodb-1.13.0/tests/bson-corpus/top-parseError-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-parseError-005.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-parseError-005.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-parseError-006.phpt b/mongodb-1.13.0/tests/bson-corpus/top-parseError-006.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-parseError-006.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-parseError-006.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-parseError-007.phpt b/mongodb-1.13.0/tests/bson-corpus/top-parseError-007.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-parseError-007.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-parseError-007.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-parseError-008.phpt b/mongodb-1.13.0/tests/bson-corpus/top-parseError-008.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-parseError-008.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-parseError-008.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-parseError-009.phpt b/mongodb-1.13.0/tests/bson-corpus/top-parseError-009.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-parseError-009.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-parseError-009.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-parseError-010.phpt b/mongodb-1.13.0/tests/bson-corpus/top-parseError-010.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-parseError-010.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-parseError-010.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-parseError-011.phpt b/mongodb-1.13.0/tests/bson-corpus/top-parseError-011.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-parseError-011.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-parseError-011.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-parseError-012.phpt b/mongodb-1.13.0/tests/bson-corpus/top-parseError-012.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-parseError-012.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-parseError-012.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-parseError-013.phpt b/mongodb-1.13.0/tests/bson-corpus/top-parseError-013.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-parseError-013.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-parseError-013.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-parseError-014.phpt b/mongodb-1.13.0/tests/bson-corpus/top-parseError-014.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-parseError-014.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-parseError-014.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-parseError-015.phpt b/mongodb-1.13.0/tests/bson-corpus/top-parseError-015.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-parseError-015.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-parseError-015.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-parseError-016.phpt b/mongodb-1.13.0/tests/bson-corpus/top-parseError-016.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-parseError-016.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-parseError-016.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-parseError-017.phpt b/mongodb-1.13.0/tests/bson-corpus/top-parseError-017.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-parseError-017.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-parseError-017.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-parseError-018.phpt b/mongodb-1.13.0/tests/bson-corpus/top-parseError-018.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-parseError-018.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-parseError-018.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-parseError-019.phpt b/mongodb-1.13.0/tests/bson-corpus/top-parseError-019.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-parseError-019.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-parseError-019.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-parseError-020.phpt b/mongodb-1.13.0/tests/bson-corpus/top-parseError-020.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-parseError-020.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-parseError-020.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-parseError-021.phpt b/mongodb-1.13.0/tests/bson-corpus/top-parseError-021.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-parseError-021.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-parseError-021.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-parseError-022.phpt b/mongodb-1.13.0/tests/bson-corpus/top-parseError-022.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-parseError-022.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-parseError-022.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-parseError-023.phpt b/mongodb-1.13.0/tests/bson-corpus/top-parseError-023.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-parseError-023.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-parseError-023.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-parseError-024.phpt b/mongodb-1.13.0/tests/bson-corpus/top-parseError-024.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-parseError-024.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-parseError-024.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-parseError-025.phpt b/mongodb-1.13.0/tests/bson-corpus/top-parseError-025.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-parseError-025.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-parseError-025.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-parseError-026.phpt b/mongodb-1.13.0/tests/bson-corpus/top-parseError-026.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-parseError-026.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-parseError-026.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-parseError-027.phpt b/mongodb-1.13.0/tests/bson-corpus/top-parseError-027.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-parseError-027.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-parseError-027.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-parseError-028.phpt b/mongodb-1.13.0/tests/bson-corpus/top-parseError-028.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-parseError-028.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-parseError-028.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-parseError-029.phpt b/mongodb-1.13.0/tests/bson-corpus/top-parseError-029.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-parseError-029.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-parseError-029.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-parseError-030.phpt b/mongodb-1.13.0/tests/bson-corpus/top-parseError-030.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-parseError-030.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-parseError-030.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-parseError-031.phpt b/mongodb-1.13.0/tests/bson-corpus/top-parseError-031.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-parseError-031.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-parseError-031.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-parseError-032.phpt b/mongodb-1.13.0/tests/bson-corpus/top-parseError-032.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-parseError-032.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-parseError-032.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-parseError-033.phpt b/mongodb-1.13.0/tests/bson-corpus/top-parseError-033.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-parseError-033.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-parseError-033.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-parseError-034.phpt b/mongodb-1.13.0/tests/bson-corpus/top-parseError-034.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-parseError-034.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-parseError-034.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-parseError-035.phpt b/mongodb-1.13.0/tests/bson-corpus/top-parseError-035.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-parseError-035.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-parseError-035.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-parseError-036.phpt b/mongodb-1.13.0/tests/bson-corpus/top-parseError-036.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-parseError-036.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-parseError-036.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-parseError-037.phpt b/mongodb-1.13.0/tests/bson-corpus/top-parseError-037.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-parseError-037.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-parseError-037.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-parseError-038.phpt b/mongodb-1.13.0/tests/bson-corpus/top-parseError-038.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-parseError-038.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-parseError-038.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-parseError-039.phpt b/mongodb-1.13.0/tests/bson-corpus/top-parseError-039.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-parseError-039.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-parseError-039.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-parseError-040.phpt b/mongodb-1.13.0/tests/bson-corpus/top-parseError-040.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-parseError-040.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-parseError-040.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-parseError-041.phpt b/mongodb-1.13.0/tests/bson-corpus/top-parseError-041.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-parseError-041.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-parseError-041.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-parseError-042.phpt b/mongodb-1.13.0/tests/bson-corpus/top-parseError-042.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-parseError-042.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-parseError-042.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-parseError-043.phpt b/mongodb-1.13.0/tests/bson-corpus/top-parseError-043.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-parseError-043.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-parseError-043.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-parseError-044.phpt b/mongodb-1.13.0/tests/bson-corpus/top-parseError-044.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-parseError-044.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-parseError-044.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-valid-001.phpt b/mongodb-1.13.0/tests/bson-corpus/top-valid-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-valid-001.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-valid-001.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-valid-002.phpt b/mongodb-1.13.0/tests/bson-corpus/top-valid-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-valid-002.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-valid-002.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-valid-003.phpt b/mongodb-1.13.0/tests/bson-corpus/top-valid-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-valid-003.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-valid-003.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/top-valid-004.phpt b/mongodb-1.13.0/tests/bson-corpus/top-valid-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/top-valid-004.phpt
rename to mongodb-1.13.0/tests/bson-corpus/top-valid-004.phpt
diff --git a/mongodb-1.12.0/tests/bson-corpus/undefined-valid-001.phpt b/mongodb-1.13.0/tests/bson-corpus/undefined-valid-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson-corpus/undefined-valid-001.phpt
rename to mongodb-1.13.0/tests/bson-corpus/undefined-valid-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-binary-001.phpt b/mongodb-1.13.0/tests/bson/bson-binary-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-binary-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-binary-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-binary-clone-001.phpt b/mongodb-1.13.0/tests/bson/bson-binary-clone-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-binary-clone-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-binary-clone-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-binary-compare-001.phpt b/mongodb-1.13.0/tests/bson/bson-binary-compare-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-binary-compare-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-binary-compare-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-binary-compare-002.phpt b/mongodb-1.13.0/tests/bson/bson-binary-compare-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-binary-compare-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-binary-compare-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-binary-get_properties-001.phpt b/mongodb-1.13.0/tests/bson/bson-binary-get_properties-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-binary-get_properties-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-binary-get_properties-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-binary-get_properties-002.phpt b/mongodb-1.13.0/tests/bson/bson-binary-get_properties-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-binary-get_properties-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-binary-get_properties-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-binary-jsonserialize-001.phpt b/mongodb-1.13.0/tests/bson/bson-binary-jsonserialize-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-binary-jsonserialize-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-binary-jsonserialize-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-binary-jsonserialize-002.phpt b/mongodb-1.13.0/tests/bson/bson-binary-jsonserialize-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-binary-jsonserialize-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-binary-jsonserialize-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-binary-serialization-001.phpt b/mongodb-1.13.0/tests/bson/bson-binary-serialization-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-binary-serialization-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-binary-serialization-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-binary-serialization-002.phpt b/mongodb-1.13.0/tests/bson/bson-binary-serialization-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-binary-serialization-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-binary-serialization-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-binary-serialization_error-001.phpt b/mongodb-1.13.0/tests/bson/bson-binary-serialization_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-binary-serialization_error-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-binary-serialization_error-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-binary-serialization_error-002.phpt b/mongodb-1.13.0/tests/bson/bson-binary-serialization_error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-binary-serialization_error-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-binary-serialization_error-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-binary-serialization_error-003.phpt b/mongodb-1.13.0/tests/bson/bson-binary-serialization_error-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-binary-serialization_error-003.phpt
rename to mongodb-1.13.0/tests/bson/bson-binary-serialization_error-003.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-binary-serialization_error-004.phpt b/mongodb-1.13.0/tests/bson/bson-binary-serialization_error-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-binary-serialization_error-004.phpt
rename to mongodb-1.13.0/tests/bson/bson-binary-serialization_error-004.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-binary-serialization_error-005.phpt b/mongodb-1.13.0/tests/bson/bson-binary-serialization_error-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-binary-serialization_error-005.phpt
rename to mongodb-1.13.0/tests/bson/bson-binary-serialization_error-005.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-binary-serialization_error-006.phpt b/mongodb-1.13.0/tests/bson/bson-binary-serialization_error-006.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-binary-serialization_error-006.phpt
rename to mongodb-1.13.0/tests/bson/bson-binary-serialization_error-006.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-binary-set_state-001.phpt b/mongodb-1.13.0/tests/bson/bson-binary-set_state-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-binary-set_state-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-binary-set_state-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-binary-set_state_error-001.phpt b/mongodb-1.13.0/tests/bson/bson-binary-set_state_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-binary-set_state_error-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-binary-set_state_error-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-binary-set_state_error-002.phpt b/mongodb-1.13.0/tests/bson/bson-binary-set_state_error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-binary-set_state_error-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-binary-set_state_error-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-binary-set_state_error-003.phpt b/mongodb-1.13.0/tests/bson/bson-binary-set_state_error-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-binary-set_state_error-003.phpt
rename to mongodb-1.13.0/tests/bson/bson-binary-set_state_error-003.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-binary-tostring-001.phpt b/mongodb-1.13.0/tests/bson/bson-binary-tostring-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-binary-tostring-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-binary-tostring-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-binary_error-001.phpt b/mongodb-1.13.0/tests/bson/bson-binary_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-binary_error-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-binary_error-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-binary_error-002.phpt b/mongodb-1.13.0/tests/bson/bson-binary_error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-binary_error-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-binary_error-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-binary_error-003.phpt b/mongodb-1.13.0/tests/bson/bson-binary_error-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-binary_error-003.phpt
rename to mongodb-1.13.0/tests/bson/bson-binary_error-003.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-binary_error-004.phpt b/mongodb-1.13.0/tests/bson/bson-binary_error-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-binary_error-004.phpt
rename to mongodb-1.13.0/tests/bson/bson-binary_error-004.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-binaryinterface-001.phpt b/mongodb-1.13.0/tests/bson/bson-binaryinterface-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-binaryinterface-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-binaryinterface-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-dbpointer-001.phpt b/mongodb-1.13.0/tests/bson/bson-dbpointer-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-dbpointer-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-dbpointer-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-dbpointer-002.phpt b/mongodb-1.13.0/tests/bson/bson-dbpointer-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-dbpointer-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-dbpointer-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-dbpointer-clone-001.phpt b/mongodb-1.13.0/tests/bson/bson-dbpointer-clone-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-dbpointer-clone-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-dbpointer-clone-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-dbpointer-compare-001.phpt b/mongodb-1.13.0/tests/bson/bson-dbpointer-compare-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-dbpointer-compare-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-dbpointer-compare-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-dbpointer-get_properties-001.phpt b/mongodb-1.13.0/tests/bson/bson-dbpointer-get_properties-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-dbpointer-get_properties-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-dbpointer-get_properties-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-dbpointer-get_properties-002.phpt b/mongodb-1.13.0/tests/bson/bson-dbpointer-get_properties-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-dbpointer-get_properties-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-dbpointer-get_properties-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-dbpointer-jsonserialize-001.phpt b/mongodb-1.13.0/tests/bson/bson-dbpointer-jsonserialize-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-dbpointer-jsonserialize-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-dbpointer-jsonserialize-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-dbpointer-jsonserialize-003.phpt b/mongodb-1.13.0/tests/bson/bson-dbpointer-jsonserialize-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-dbpointer-jsonserialize-003.phpt
rename to mongodb-1.13.0/tests/bson/bson-dbpointer-jsonserialize-003.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-dbpointer-serialization-001.phpt b/mongodb-1.13.0/tests/bson/bson-dbpointer-serialization-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-dbpointer-serialization-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-dbpointer-serialization-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-dbpointer-serialization-002.phpt b/mongodb-1.13.0/tests/bson/bson-dbpointer-serialization-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-dbpointer-serialization-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-dbpointer-serialization-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-dbpointer-serialization_error-001.phpt b/mongodb-1.13.0/tests/bson/bson-dbpointer-serialization_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-dbpointer-serialization_error-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-dbpointer-serialization_error-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-dbpointer-serialization_error-002.phpt b/mongodb-1.13.0/tests/bson/bson-dbpointer-serialization_error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-dbpointer-serialization_error-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-dbpointer-serialization_error-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-dbpointer-serialization_error-003.phpt b/mongodb-1.13.0/tests/bson/bson-dbpointer-serialization_error-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-dbpointer-serialization_error-003.phpt
rename to mongodb-1.13.0/tests/bson/bson-dbpointer-serialization_error-003.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-dbpointer-serialization_error-004.phpt b/mongodb-1.13.0/tests/bson/bson-dbpointer-serialization_error-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-dbpointer-serialization_error-004.phpt
rename to mongodb-1.13.0/tests/bson/bson-dbpointer-serialization_error-004.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-dbpointer-tostring-001.phpt b/mongodb-1.13.0/tests/bson/bson-dbpointer-tostring-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-dbpointer-tostring-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-dbpointer-tostring-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-dbpointer_error-002.phpt b/mongodb-1.13.0/tests/bson/bson-dbpointer_error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-dbpointer_error-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-dbpointer_error-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-decimal128-001.phpt b/mongodb-1.13.0/tests/bson/bson-decimal128-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-decimal128-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-decimal128-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-decimal128-002.phpt b/mongodb-1.13.0/tests/bson/bson-decimal128-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-decimal128-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-decimal128-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-decimal128-003.phpt b/mongodb-1.13.0/tests/bson/bson-decimal128-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-decimal128-003.phpt
rename to mongodb-1.13.0/tests/bson/bson-decimal128-003.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-decimal128-004.phpt b/mongodb-1.13.0/tests/bson/bson-decimal128-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-decimal128-004.phpt
rename to mongodb-1.13.0/tests/bson/bson-decimal128-004.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-decimal128-clone-001.phpt b/mongodb-1.13.0/tests/bson/bson-decimal128-clone-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-decimal128-clone-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-decimal128-clone-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-decimal128-get_properties-001.phpt b/mongodb-1.13.0/tests/bson/bson-decimal128-get_properties-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-decimal128-get_properties-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-decimal128-get_properties-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-decimal128-get_properties-002.phpt b/mongodb-1.13.0/tests/bson/bson-decimal128-get_properties-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-decimal128-get_properties-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-decimal128-get_properties-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-decimal128-jsonserialize-001.phpt b/mongodb-1.13.0/tests/bson/bson-decimal128-jsonserialize-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-decimal128-jsonserialize-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-decimal128-jsonserialize-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-decimal128-jsonserialize-002.phpt b/mongodb-1.13.0/tests/bson/bson-decimal128-jsonserialize-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-decimal128-jsonserialize-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-decimal128-jsonserialize-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-decimal128-serialization-001.phpt b/mongodb-1.13.0/tests/bson/bson-decimal128-serialization-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-decimal128-serialization-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-decimal128-serialization-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-decimal128-serialization-002.phpt b/mongodb-1.13.0/tests/bson/bson-decimal128-serialization-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-decimal128-serialization-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-decimal128-serialization-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-decimal128-serialization_error-001.phpt b/mongodb-1.13.0/tests/bson/bson-decimal128-serialization_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-decimal128-serialization_error-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-decimal128-serialization_error-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-decimal128-serialization_error-002.phpt b/mongodb-1.13.0/tests/bson/bson-decimal128-serialization_error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-decimal128-serialization_error-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-decimal128-serialization_error-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-decimal128-serialization_error-003.phpt b/mongodb-1.13.0/tests/bson/bson-decimal128-serialization_error-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-decimal128-serialization_error-003.phpt
rename to mongodb-1.13.0/tests/bson/bson-decimal128-serialization_error-003.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-decimal128-serialization_error-004.phpt b/mongodb-1.13.0/tests/bson/bson-decimal128-serialization_error-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-decimal128-serialization_error-004.phpt
rename to mongodb-1.13.0/tests/bson/bson-decimal128-serialization_error-004.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-decimal128-set_state-001.phpt b/mongodb-1.13.0/tests/bson/bson-decimal128-set_state-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-decimal128-set_state-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-decimal128-set_state-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-decimal128-set_state_error-001.phpt b/mongodb-1.13.0/tests/bson/bson-decimal128-set_state_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-decimal128-set_state_error-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-decimal128-set_state_error-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-decimal128-set_state_error-002.phpt b/mongodb-1.13.0/tests/bson/bson-decimal128-set_state_error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-decimal128-set_state_error-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-decimal128-set_state_error-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-decimal128_error-001.phpt b/mongodb-1.13.0/tests/bson/bson-decimal128_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-decimal128_error-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-decimal128_error-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-decimal128_error-002.phpt b/mongodb-1.13.0/tests/bson/bson-decimal128_error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-decimal128_error-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-decimal128_error-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-decimal128interface-001.phpt b/mongodb-1.13.0/tests/bson/bson-decimal128interface-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-decimal128interface-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-decimal128interface-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-decode-001.phpt b/mongodb-1.13.0/tests/bson/bson-decode-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-decode-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-decode-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-decode-002.phpt b/mongodb-1.13.0/tests/bson/bson-decode-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-decode-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-decode-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-encode-001.phpt b/mongodb-1.13.0/tests/bson/bson-encode-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-encode-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-encode-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-encode-002.phpt b/mongodb-1.13.0/tests/bson/bson-encode-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-encode-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-encode-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-encode-003.phpt b/mongodb-1.13.0/tests/bson/bson-encode-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-encode-003.phpt
rename to mongodb-1.13.0/tests/bson/bson-encode-003.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-encode-004.phpt b/mongodb-1.13.0/tests/bson/bson-encode-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-encode-004.phpt
rename to mongodb-1.13.0/tests/bson/bson-encode-004.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-encode-005.phpt b/mongodb-1.13.0/tests/bson/bson-encode-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-encode-005.phpt
rename to mongodb-1.13.0/tests/bson/bson-encode-005.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-fromJSON-001.phpt b/mongodb-1.13.0/tests/bson/bson-fromJSON-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-fromJSON-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-fromJSON-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-fromJSON-002.phpt b/mongodb-1.13.0/tests/bson/bson-fromJSON-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-fromJSON-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-fromJSON-002.phpt
diff --git a/mongodb-1.13.0/tests/bson/bson-fromJSON-003.phpt b/mongodb-1.13.0/tests/bson/bson-fromJSON-003.phpt
new file mode 100644
index 00000000..bb20a719
--- /dev/null
+++ b/mongodb-1.13.0/tests/bson/bson-fromJSON-003.phpt
@@ -0,0 +1,18 @@
+--TEST--
+MongoDB\BSON\fromJSON(): Decoding JSON with duplicate field names
+--FILE--
+<?php
+
+require_once __DIR__ . '/../utils/basic.inc';
+
+/* Note: this is a regression test for libmongoc's JSON encoder. It is not
+ * advisable to use duplicate keys in BSON documents. */
+hex_dump(fromJSON('{ "foo": "bar", "foo": "baz" }'));
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+ 0 : 1f 00 00 00 02 66 6f 6f 00 04 00 00 00 62 61 72 [.....foo.....bar]
+ 10 : 00 02 66 6f 6f 00 04 00 00 00 62 61 7a 00 00 [..foo.....baz..]
+===DONE===
diff --git a/mongodb-1.12.0/tests/bson/bson-fromJSON_error-001.phpt b/mongodb-1.13.0/tests/bson/bson-fromJSON_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-fromJSON_error-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-fromJSON_error-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-fromPHP-001.phpt b/mongodb-1.13.0/tests/bson/bson-fromPHP-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-fromPHP-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-fromPHP-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-fromPHP-002.phpt b/mongodb-1.13.0/tests/bson/bson-fromPHP-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-fromPHP-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-fromPHP-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-fromPHP-003.phpt b/mongodb-1.13.0/tests/bson/bson-fromPHP-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-fromPHP-003.phpt
rename to mongodb-1.13.0/tests/bson/bson-fromPHP-003.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-fromPHP-005.phpt b/mongodb-1.13.0/tests/bson/bson-fromPHP-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-fromPHP-005.phpt
rename to mongodb-1.13.0/tests/bson/bson-fromPHP-005.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-fromPHP-006.phpt b/mongodb-1.13.0/tests/bson/bson-fromPHP-006.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-fromPHP-006.phpt
rename to mongodb-1.13.0/tests/bson/bson-fromPHP-006.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-fromPHP_error-001.phpt b/mongodb-1.13.0/tests/bson/bson-fromPHP_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-fromPHP_error-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-fromPHP_error-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-fromPHP_error-002.phpt b/mongodb-1.13.0/tests/bson/bson-fromPHP_error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-fromPHP_error-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-fromPHP_error-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-fromPHP_error-003.phpt b/mongodb-1.13.0/tests/bson/bson-fromPHP_error-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-fromPHP_error-003.phpt
rename to mongodb-1.13.0/tests/bson/bson-fromPHP_error-003.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-fromPHP_error-004.phpt b/mongodb-1.13.0/tests/bson/bson-fromPHP_error-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-fromPHP_error-004.phpt
rename to mongodb-1.13.0/tests/bson/bson-fromPHP_error-004.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-fromPHP_error-005.phpt b/mongodb-1.13.0/tests/bson/bson-fromPHP_error-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-fromPHP_error-005.phpt
rename to mongodb-1.13.0/tests/bson/bson-fromPHP_error-005.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-fromPHP_error-006.phpt b/mongodb-1.13.0/tests/bson/bson-fromPHP_error-006.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-fromPHP_error-006.phpt
rename to mongodb-1.13.0/tests/bson/bson-fromPHP_error-006.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-fromPHP_error-007.phpt b/mongodb-1.13.0/tests/bson/bson-fromPHP_error-007.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-fromPHP_error-007.phpt
rename to mongodb-1.13.0/tests/bson/bson-fromPHP_error-007.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-fromPHP_error-008.phpt b/mongodb-1.13.0/tests/bson/bson-fromPHP_error-008.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-fromPHP_error-008.phpt
rename to mongodb-1.13.0/tests/bson/bson-fromPHP_error-008.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-generate-document-id.phpt b/mongodb-1.13.0/tests/bson/bson-generate-document-id.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-generate-document-id.phpt
rename to mongodb-1.13.0/tests/bson/bson-generate-document-id.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-int64-001.phpt b/mongodb-1.13.0/tests/bson/bson-int64-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-int64-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-int64-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-int64-002.phpt b/mongodb-1.13.0/tests/bson/bson-int64-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-int64-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-int64-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-int64-003.phpt b/mongodb-1.13.0/tests/bson/bson-int64-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-int64-003.phpt
rename to mongodb-1.13.0/tests/bson/bson-int64-003.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-int64-clone-001.phpt b/mongodb-1.13.0/tests/bson/bson-int64-clone-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-int64-clone-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-int64-clone-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-int64-compare-001.phpt b/mongodb-1.13.0/tests/bson/bson-int64-compare-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-int64-compare-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-int64-compare-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-int64-debug-001.phpt b/mongodb-1.13.0/tests/bson/bson-int64-debug-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-int64-debug-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-int64-debug-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-int64-get_properties-001.phpt b/mongodb-1.13.0/tests/bson/bson-int64-get_properties-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-int64-get_properties-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-int64-get_properties-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-int64-get_properties-002.phpt b/mongodb-1.13.0/tests/bson/bson-int64-get_properties-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-int64-get_properties-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-int64-get_properties-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-int64-jsonserialize-001.phpt b/mongodb-1.13.0/tests/bson/bson-int64-jsonserialize-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-int64-jsonserialize-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-int64-jsonserialize-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-int64-jsonserialize-002.phpt b/mongodb-1.13.0/tests/bson/bson-int64-jsonserialize-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-int64-jsonserialize-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-int64-jsonserialize-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-int64-serialization-001.phpt b/mongodb-1.13.0/tests/bson/bson-int64-serialization-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-int64-serialization-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-int64-serialization-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-int64-serialization-002.phpt b/mongodb-1.13.0/tests/bson/bson-int64-serialization-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-int64-serialization-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-int64-serialization-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-int64-serialization_error-001.phpt b/mongodb-1.13.0/tests/bson/bson-int64-serialization_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-int64-serialization_error-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-int64-serialization_error-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-int64-serialization_error-002.phpt b/mongodb-1.13.0/tests/bson/bson-int64-serialization_error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-int64-serialization_error-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-int64-serialization_error-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-int64-serialization_error-003.phpt b/mongodb-1.13.0/tests/bson/bson-int64-serialization_error-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-int64-serialization_error-003.phpt
rename to mongodb-1.13.0/tests/bson/bson-int64-serialization_error-003.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-int64-serialization_error-004.phpt b/mongodb-1.13.0/tests/bson/bson-int64-serialization_error-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-int64-serialization_error-004.phpt
rename to mongodb-1.13.0/tests/bson/bson-int64-serialization_error-004.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-int64-tostring-001.phpt b/mongodb-1.13.0/tests/bson/bson-int64-tostring-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-int64-tostring-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-int64-tostring-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-int64_error-001.phpt b/mongodb-1.13.0/tests/bson/bson-int64_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-int64_error-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-int64_error-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-javascript-001.phpt b/mongodb-1.13.0/tests/bson/bson-javascript-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-javascript-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-javascript-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-javascript-002.phpt b/mongodb-1.13.0/tests/bson/bson-javascript-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-javascript-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-javascript-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-javascript-clone-001.phpt b/mongodb-1.13.0/tests/bson/bson-javascript-clone-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-javascript-clone-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-javascript-clone-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-javascript-compare-001.phpt b/mongodb-1.13.0/tests/bson/bson-javascript-compare-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-javascript-compare-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-javascript-compare-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-javascript-compare-002.phpt b/mongodb-1.13.0/tests/bson/bson-javascript-compare-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-javascript-compare-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-javascript-compare-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-javascript-getCode-001.phpt b/mongodb-1.13.0/tests/bson/bson-javascript-getCode-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-javascript-getCode-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-javascript-getCode-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-javascript-getScope-001.phpt b/mongodb-1.13.0/tests/bson/bson-javascript-getScope-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-javascript-getScope-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-javascript-getScope-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-javascript-get_properties-001.phpt b/mongodb-1.13.0/tests/bson/bson-javascript-get_properties-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-javascript-get_properties-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-javascript-get_properties-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-javascript-get_properties-002.phpt b/mongodb-1.13.0/tests/bson/bson-javascript-get_properties-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-javascript-get_properties-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-javascript-get_properties-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-javascript-jsonserialize-001.phpt b/mongodb-1.13.0/tests/bson/bson-javascript-jsonserialize-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-javascript-jsonserialize-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-javascript-jsonserialize-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-javascript-jsonserialize-002.phpt b/mongodb-1.13.0/tests/bson/bson-javascript-jsonserialize-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-javascript-jsonserialize-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-javascript-jsonserialize-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-javascript-jsonserialize-003.phpt b/mongodb-1.13.0/tests/bson/bson-javascript-jsonserialize-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-javascript-jsonserialize-003.phpt
rename to mongodb-1.13.0/tests/bson/bson-javascript-jsonserialize-003.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-javascript-jsonserialize-004.phpt b/mongodb-1.13.0/tests/bson/bson-javascript-jsonserialize-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-javascript-jsonserialize-004.phpt
rename to mongodb-1.13.0/tests/bson/bson-javascript-jsonserialize-004.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-javascript-serialization-001.phpt b/mongodb-1.13.0/tests/bson/bson-javascript-serialization-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-javascript-serialization-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-javascript-serialization-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-javascript-serialization-002.phpt b/mongodb-1.13.0/tests/bson/bson-javascript-serialization-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-javascript-serialization-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-javascript-serialization-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-javascript-serialization_error-001.phpt b/mongodb-1.13.0/tests/bson/bson-javascript-serialization_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-javascript-serialization_error-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-javascript-serialization_error-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-javascript-serialization_error-002.phpt b/mongodb-1.13.0/tests/bson/bson-javascript-serialization_error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-javascript-serialization_error-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-javascript-serialization_error-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-javascript-serialization_error-003.phpt b/mongodb-1.13.0/tests/bson/bson-javascript-serialization_error-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-javascript-serialization_error-003.phpt
rename to mongodb-1.13.0/tests/bson/bson-javascript-serialization_error-003.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-javascript-serialization_error-004.phpt b/mongodb-1.13.0/tests/bson/bson-javascript-serialization_error-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-javascript-serialization_error-004.phpt
rename to mongodb-1.13.0/tests/bson/bson-javascript-serialization_error-004.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-javascript-serialization_error-005.phpt b/mongodb-1.13.0/tests/bson/bson-javascript-serialization_error-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-javascript-serialization_error-005.phpt
rename to mongodb-1.13.0/tests/bson/bson-javascript-serialization_error-005.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-javascript-serialization_error-006.phpt b/mongodb-1.13.0/tests/bson/bson-javascript-serialization_error-006.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-javascript-serialization_error-006.phpt
rename to mongodb-1.13.0/tests/bson/bson-javascript-serialization_error-006.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-javascript-set_state-001.phpt b/mongodb-1.13.0/tests/bson/bson-javascript-set_state-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-javascript-set_state-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-javascript-set_state-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-javascript-set_state_error-001.phpt b/mongodb-1.13.0/tests/bson/bson-javascript-set_state_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-javascript-set_state_error-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-javascript-set_state_error-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-javascript-set_state_error-002.phpt b/mongodb-1.13.0/tests/bson/bson-javascript-set_state_error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-javascript-set_state_error-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-javascript-set_state_error-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-javascript-set_state_error-003.phpt b/mongodb-1.13.0/tests/bson/bson-javascript-set_state_error-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-javascript-set_state_error-003.phpt
rename to mongodb-1.13.0/tests/bson/bson-javascript-set_state_error-003.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-javascript-tostring-001.phpt b/mongodb-1.13.0/tests/bson/bson-javascript-tostring-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-javascript-tostring-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-javascript-tostring-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-javascript_error-001.phpt b/mongodb-1.13.0/tests/bson/bson-javascript_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-javascript_error-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-javascript_error-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-javascript_error-002.phpt b/mongodb-1.13.0/tests/bson/bson-javascript_error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-javascript_error-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-javascript_error-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-javascript_error-003.phpt b/mongodb-1.13.0/tests/bson/bson-javascript_error-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-javascript_error-003.phpt
rename to mongodb-1.13.0/tests/bson/bson-javascript_error-003.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-javascriptinterface-001.phpt b/mongodb-1.13.0/tests/bson/bson-javascriptinterface-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-javascriptinterface-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-javascriptinterface-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-maxkey-001.phpt b/mongodb-1.13.0/tests/bson/bson-maxkey-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-maxkey-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-maxkey-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-maxkey-clone-001.phpt b/mongodb-1.13.0/tests/bson/bson-maxkey-clone-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-maxkey-clone-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-maxkey-clone-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-maxkey-compare-001.phpt b/mongodb-1.13.0/tests/bson/bson-maxkey-compare-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-maxkey-compare-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-maxkey-compare-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-maxkey-jsonserialize-001.phpt b/mongodb-1.13.0/tests/bson/bson-maxkey-jsonserialize-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-maxkey-jsonserialize-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-maxkey-jsonserialize-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-maxkey-jsonserialize-002.phpt b/mongodb-1.13.0/tests/bson/bson-maxkey-jsonserialize-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-maxkey-jsonserialize-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-maxkey-jsonserialize-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-maxkey-serialization-001.phpt b/mongodb-1.13.0/tests/bson/bson-maxkey-serialization-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-maxkey-serialization-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-maxkey-serialization-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-maxkey-serialization-002.phpt b/mongodb-1.13.0/tests/bson/bson-maxkey-serialization-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-maxkey-serialization-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-maxkey-serialization-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-maxkey-set_state-001.phpt b/mongodb-1.13.0/tests/bson/bson-maxkey-set_state-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-maxkey-set_state-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-maxkey-set_state-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-maxkey_error-001.phpt b/mongodb-1.13.0/tests/bson/bson-maxkey_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-maxkey_error-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-maxkey_error-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-maxkeyinterface-001.phpt b/mongodb-1.13.0/tests/bson/bson-maxkeyinterface-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-maxkeyinterface-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-maxkeyinterface-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-minkey-001.phpt b/mongodb-1.13.0/tests/bson/bson-minkey-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-minkey-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-minkey-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-minkey-clone-001.phpt b/mongodb-1.13.0/tests/bson/bson-minkey-clone-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-minkey-clone-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-minkey-clone-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-minkey-compare-001.phpt b/mongodb-1.13.0/tests/bson/bson-minkey-compare-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-minkey-compare-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-minkey-compare-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-minkey-jsonserialize-001.phpt b/mongodb-1.13.0/tests/bson/bson-minkey-jsonserialize-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-minkey-jsonserialize-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-minkey-jsonserialize-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-minkey-jsonserialize-002.phpt b/mongodb-1.13.0/tests/bson/bson-minkey-jsonserialize-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-minkey-jsonserialize-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-minkey-jsonserialize-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-minkey-serialization-001.phpt b/mongodb-1.13.0/tests/bson/bson-minkey-serialization-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-minkey-serialization-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-minkey-serialization-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-minkey-serialization-002.phpt b/mongodb-1.13.0/tests/bson/bson-minkey-serialization-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-minkey-serialization-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-minkey-serialization-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-minkey-set_state-001.phpt b/mongodb-1.13.0/tests/bson/bson-minkey-set_state-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-minkey-set_state-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-minkey-set_state-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-minkey_error-001.phpt b/mongodb-1.13.0/tests/bson/bson-minkey_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-minkey_error-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-minkey_error-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-minkeyinterface-001.phpt b/mongodb-1.13.0/tests/bson/bson-minkeyinterface-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-minkeyinterface-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-minkeyinterface-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-objectid-001.phpt b/mongodb-1.13.0/tests/bson/bson-objectid-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-objectid-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-objectid-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-objectid-002.phpt b/mongodb-1.13.0/tests/bson/bson-objectid-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-objectid-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-objectid-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-objectid-003.phpt b/mongodb-1.13.0/tests/bson/bson-objectid-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-objectid-003.phpt
rename to mongodb-1.13.0/tests/bson/bson-objectid-003.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-objectid-004.phpt b/mongodb-1.13.0/tests/bson/bson-objectid-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-objectid-004.phpt
rename to mongodb-1.13.0/tests/bson/bson-objectid-004.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-objectid-clone-001.phpt b/mongodb-1.13.0/tests/bson/bson-objectid-clone-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-objectid-clone-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-objectid-clone-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-objectid-compare-001.phpt b/mongodb-1.13.0/tests/bson/bson-objectid-compare-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-objectid-compare-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-objectid-compare-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-objectid-compare-002.phpt b/mongodb-1.13.0/tests/bson/bson-objectid-compare-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-objectid-compare-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-objectid-compare-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-objectid-getTimestamp-001.phpt b/mongodb-1.13.0/tests/bson/bson-objectid-getTimestamp-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-objectid-getTimestamp-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-objectid-getTimestamp-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-objectid-getTimestamp-002.phpt b/mongodb-1.13.0/tests/bson/bson-objectid-getTimestamp-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-objectid-getTimestamp-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-objectid-getTimestamp-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-objectid-get_properties-001.phpt b/mongodb-1.13.0/tests/bson/bson-objectid-get_properties-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-objectid-get_properties-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-objectid-get_properties-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-objectid-get_properties-002.phpt b/mongodb-1.13.0/tests/bson/bson-objectid-get_properties-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-objectid-get_properties-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-objectid-get_properties-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-objectid-jsonserialize-001.phpt b/mongodb-1.13.0/tests/bson/bson-objectid-jsonserialize-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-objectid-jsonserialize-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-objectid-jsonserialize-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-objectid-jsonserialize-002.phpt b/mongodb-1.13.0/tests/bson/bson-objectid-jsonserialize-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-objectid-jsonserialize-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-objectid-jsonserialize-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-objectid-serialization-001.phpt b/mongodb-1.13.0/tests/bson/bson-objectid-serialization-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-objectid-serialization-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-objectid-serialization-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-objectid-serialization-002.phpt b/mongodb-1.13.0/tests/bson/bson-objectid-serialization-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-objectid-serialization-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-objectid-serialization-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-objectid-serialization_error-001.phpt b/mongodb-1.13.0/tests/bson/bson-objectid-serialization_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-objectid-serialization_error-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-objectid-serialization_error-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-objectid-serialization_error-002.phpt b/mongodb-1.13.0/tests/bson/bson-objectid-serialization_error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-objectid-serialization_error-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-objectid-serialization_error-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-objectid-serialization_error-003.phpt b/mongodb-1.13.0/tests/bson/bson-objectid-serialization_error-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-objectid-serialization_error-003.phpt
rename to mongodb-1.13.0/tests/bson/bson-objectid-serialization_error-003.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-objectid-serialization_error-004.phpt b/mongodb-1.13.0/tests/bson/bson-objectid-serialization_error-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-objectid-serialization_error-004.phpt
rename to mongodb-1.13.0/tests/bson/bson-objectid-serialization_error-004.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-objectid-set_state-001.phpt b/mongodb-1.13.0/tests/bson/bson-objectid-set_state-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-objectid-set_state-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-objectid-set_state-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-objectid-set_state_error-001.phpt b/mongodb-1.13.0/tests/bson/bson-objectid-set_state_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-objectid-set_state_error-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-objectid-set_state_error-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-objectid-set_state_error-002.phpt b/mongodb-1.13.0/tests/bson/bson-objectid-set_state_error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-objectid-set_state_error-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-objectid-set_state_error-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-objectid-tostring_error-001.phpt b/mongodb-1.13.0/tests/bson/bson-objectid-tostring_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-objectid-tostring_error-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-objectid-tostring_error-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-objectid_error-001.phpt b/mongodb-1.13.0/tests/bson/bson-objectid_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-objectid_error-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-objectid_error-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-objectid_error-002.phpt b/mongodb-1.13.0/tests/bson/bson-objectid_error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-objectid_error-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-objectid_error-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-objectid_error-003.phpt b/mongodb-1.13.0/tests/bson/bson-objectid_error-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-objectid_error-003.phpt
rename to mongodb-1.13.0/tests/bson/bson-objectid_error-003.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-objectidinterface-001.phpt b/mongodb-1.13.0/tests/bson/bson-objectidinterface-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-objectidinterface-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-objectidinterface-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-regex-001.phpt b/mongodb-1.13.0/tests/bson/bson-regex-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-regex-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-regex-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-regex-002.phpt b/mongodb-1.13.0/tests/bson/bson-regex-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-regex-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-regex-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-regex-003.phpt b/mongodb-1.13.0/tests/bson/bson-regex-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-regex-003.phpt
rename to mongodb-1.13.0/tests/bson/bson-regex-003.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-regex-004.phpt b/mongodb-1.13.0/tests/bson/bson-regex-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-regex-004.phpt
rename to mongodb-1.13.0/tests/bson/bson-regex-004.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-regex-005.phpt b/mongodb-1.13.0/tests/bson/bson-regex-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-regex-005.phpt
rename to mongodb-1.13.0/tests/bson/bson-regex-005.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-regex-clone-001.phpt b/mongodb-1.13.0/tests/bson/bson-regex-clone-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-regex-clone-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-regex-clone-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-regex-compare-001.phpt b/mongodb-1.13.0/tests/bson/bson-regex-compare-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-regex-compare-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-regex-compare-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-regex-compare-002.phpt b/mongodb-1.13.0/tests/bson/bson-regex-compare-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-regex-compare-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-regex-compare-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-regex-get_properties-001.phpt b/mongodb-1.13.0/tests/bson/bson-regex-get_properties-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-regex-get_properties-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-regex-get_properties-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-regex-get_properties-002.phpt b/mongodb-1.13.0/tests/bson/bson-regex-get_properties-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-regex-get_properties-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-regex-get_properties-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-regex-jsonserialize-001.phpt b/mongodb-1.13.0/tests/bson/bson-regex-jsonserialize-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-regex-jsonserialize-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-regex-jsonserialize-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-regex-jsonserialize-002.phpt b/mongodb-1.13.0/tests/bson/bson-regex-jsonserialize-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-regex-jsonserialize-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-regex-jsonserialize-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-regex-jsonserialize-003.phpt b/mongodb-1.13.0/tests/bson/bson-regex-jsonserialize-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-regex-jsonserialize-003.phpt
rename to mongodb-1.13.0/tests/bson/bson-regex-jsonserialize-003.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-regex-jsonserialize-004.phpt b/mongodb-1.13.0/tests/bson/bson-regex-jsonserialize-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-regex-jsonserialize-004.phpt
rename to mongodb-1.13.0/tests/bson/bson-regex-jsonserialize-004.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-regex-serialization-001.phpt b/mongodb-1.13.0/tests/bson/bson-regex-serialization-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-regex-serialization-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-regex-serialization-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-regex-serialization-002.phpt b/mongodb-1.13.0/tests/bson/bson-regex-serialization-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-regex-serialization-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-regex-serialization-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-regex-serialization-003.phpt b/mongodb-1.13.0/tests/bson/bson-regex-serialization-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-regex-serialization-003.phpt
rename to mongodb-1.13.0/tests/bson/bson-regex-serialization-003.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-regex-serialization-004.phpt b/mongodb-1.13.0/tests/bson/bson-regex-serialization-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-regex-serialization-004.phpt
rename to mongodb-1.13.0/tests/bson/bson-regex-serialization-004.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-regex-serialization-005.phpt b/mongodb-1.13.0/tests/bson/bson-regex-serialization-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-regex-serialization-005.phpt
rename to mongodb-1.13.0/tests/bson/bson-regex-serialization-005.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-regex-serialization-006.phpt b/mongodb-1.13.0/tests/bson/bson-regex-serialization-006.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-regex-serialization-006.phpt
rename to mongodb-1.13.0/tests/bson/bson-regex-serialization-006.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-regex-serialization_error-001.phpt b/mongodb-1.13.0/tests/bson/bson-regex-serialization_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-regex-serialization_error-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-regex-serialization_error-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-regex-serialization_error-002.phpt b/mongodb-1.13.0/tests/bson/bson-regex-serialization_error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-regex-serialization_error-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-regex-serialization_error-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-regex-serialization_error-003.phpt b/mongodb-1.13.0/tests/bson/bson-regex-serialization_error-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-regex-serialization_error-003.phpt
rename to mongodb-1.13.0/tests/bson/bson-regex-serialization_error-003.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-regex-serialization_error-004.phpt b/mongodb-1.13.0/tests/bson/bson-regex-serialization_error-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-regex-serialization_error-004.phpt
rename to mongodb-1.13.0/tests/bson/bson-regex-serialization_error-004.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-regex-set_state-001.phpt b/mongodb-1.13.0/tests/bson/bson-regex-set_state-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-regex-set_state-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-regex-set_state-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-regex-set_state-002.phpt b/mongodb-1.13.0/tests/bson/bson-regex-set_state-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-regex-set_state-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-regex-set_state-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-regex-set_state_error-001.phpt b/mongodb-1.13.0/tests/bson/bson-regex-set_state_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-regex-set_state_error-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-regex-set_state_error-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-regex-set_state_error-002.phpt b/mongodb-1.13.0/tests/bson/bson-regex-set_state_error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-regex-set_state_error-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-regex-set_state_error-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-regex_error-001.phpt b/mongodb-1.13.0/tests/bson/bson-regex_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-regex_error-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-regex_error-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-regex_error-002.phpt b/mongodb-1.13.0/tests/bson/bson-regex_error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-regex_error-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-regex_error-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-regex_error-003.phpt b/mongodb-1.13.0/tests/bson/bson-regex_error-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-regex_error-003.phpt
rename to mongodb-1.13.0/tests/bson/bson-regex_error-003.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-regexinterface-001.phpt b/mongodb-1.13.0/tests/bson/bson-regexinterface-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-regexinterface-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-regexinterface-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-symbol-001.phpt b/mongodb-1.13.0/tests/bson/bson-symbol-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-symbol-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-symbol-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-symbol-clone-001.phpt b/mongodb-1.13.0/tests/bson/bson-symbol-clone-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-symbol-clone-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-symbol-clone-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-symbol-compare-001.phpt b/mongodb-1.13.0/tests/bson/bson-symbol-compare-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-symbol-compare-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-symbol-compare-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-symbol-get_properties-001.phpt b/mongodb-1.13.0/tests/bson/bson-symbol-get_properties-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-symbol-get_properties-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-symbol-get_properties-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-symbol-get_properties-002.phpt b/mongodb-1.13.0/tests/bson/bson-symbol-get_properties-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-symbol-get_properties-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-symbol-get_properties-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-symbol-jsonserialize-001.phpt b/mongodb-1.13.0/tests/bson/bson-symbol-jsonserialize-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-symbol-jsonserialize-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-symbol-jsonserialize-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-symbol-jsonserialize-002.phpt b/mongodb-1.13.0/tests/bson/bson-symbol-jsonserialize-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-symbol-jsonserialize-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-symbol-jsonserialize-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-symbol-serialization-001.phpt b/mongodb-1.13.0/tests/bson/bson-symbol-serialization-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-symbol-serialization-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-symbol-serialization-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-symbol-serialization-002.phpt b/mongodb-1.13.0/tests/bson/bson-symbol-serialization-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-symbol-serialization-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-symbol-serialization-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-symbol-serialization_error-001.phpt b/mongodb-1.13.0/tests/bson/bson-symbol-serialization_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-symbol-serialization_error-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-symbol-serialization_error-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-symbol-serialization_error-002.phpt b/mongodb-1.13.0/tests/bson/bson-symbol-serialization_error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-symbol-serialization_error-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-symbol-serialization_error-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-symbol-serialization_error-003.phpt b/mongodb-1.13.0/tests/bson/bson-symbol-serialization_error-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-symbol-serialization_error-003.phpt
rename to mongodb-1.13.0/tests/bson/bson-symbol-serialization_error-003.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-symbol-serialization_error-004.phpt b/mongodb-1.13.0/tests/bson/bson-symbol-serialization_error-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-symbol-serialization_error-004.phpt
rename to mongodb-1.13.0/tests/bson/bson-symbol-serialization_error-004.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-symbol-tostring-001.phpt b/mongodb-1.13.0/tests/bson/bson-symbol-tostring-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-symbol-tostring-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-symbol-tostring-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-symbol_error-001.phpt b/mongodb-1.13.0/tests/bson/bson-symbol_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-symbol_error-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-symbol_error-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-timestamp-001.phpt b/mongodb-1.13.0/tests/bson/bson-timestamp-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-timestamp-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-timestamp-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-timestamp-002.phpt b/mongodb-1.13.0/tests/bson/bson-timestamp-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-timestamp-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-timestamp-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-timestamp-003.phpt b/mongodb-1.13.0/tests/bson/bson-timestamp-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-timestamp-003.phpt
rename to mongodb-1.13.0/tests/bson/bson-timestamp-003.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-timestamp-004.phpt b/mongodb-1.13.0/tests/bson/bson-timestamp-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-timestamp-004.phpt
rename to mongodb-1.13.0/tests/bson/bson-timestamp-004.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-timestamp-005.phpt b/mongodb-1.13.0/tests/bson/bson-timestamp-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-timestamp-005.phpt
rename to mongodb-1.13.0/tests/bson/bson-timestamp-005.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-timestamp-clone-001.phpt b/mongodb-1.13.0/tests/bson/bson-timestamp-clone-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-timestamp-clone-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-timestamp-clone-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-timestamp-compare-001.phpt b/mongodb-1.13.0/tests/bson/bson-timestamp-compare-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-timestamp-compare-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-timestamp-compare-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-timestamp-getIncrement-001.phpt b/mongodb-1.13.0/tests/bson/bson-timestamp-getIncrement-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-timestamp-getIncrement-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-timestamp-getIncrement-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-timestamp-getTimestamp-001.phpt b/mongodb-1.13.0/tests/bson/bson-timestamp-getTimestamp-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-timestamp-getTimestamp-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-timestamp-getTimestamp-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-timestamp-get_properties-001.phpt b/mongodb-1.13.0/tests/bson/bson-timestamp-get_properties-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-timestamp-get_properties-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-timestamp-get_properties-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-timestamp-get_properties-002.phpt b/mongodb-1.13.0/tests/bson/bson-timestamp-get_properties-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-timestamp-get_properties-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-timestamp-get_properties-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-timestamp-jsonserialize-001.phpt b/mongodb-1.13.0/tests/bson/bson-timestamp-jsonserialize-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-timestamp-jsonserialize-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-timestamp-jsonserialize-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-timestamp-jsonserialize-002.phpt b/mongodb-1.13.0/tests/bson/bson-timestamp-jsonserialize-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-timestamp-jsonserialize-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-timestamp-jsonserialize-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-timestamp-serialization-001.phpt b/mongodb-1.13.0/tests/bson/bson-timestamp-serialization-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-timestamp-serialization-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-timestamp-serialization-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-timestamp-serialization-002.phpt b/mongodb-1.13.0/tests/bson/bson-timestamp-serialization-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-timestamp-serialization-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-timestamp-serialization-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-timestamp-serialization-003.phpt b/mongodb-1.13.0/tests/bson/bson-timestamp-serialization-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-timestamp-serialization-003.phpt
rename to mongodb-1.13.0/tests/bson/bson-timestamp-serialization-003.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-timestamp-serialization-004.phpt b/mongodb-1.13.0/tests/bson/bson-timestamp-serialization-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-timestamp-serialization-004.phpt
rename to mongodb-1.13.0/tests/bson/bson-timestamp-serialization-004.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-timestamp-serialization_error-001.phpt b/mongodb-1.13.0/tests/bson/bson-timestamp-serialization_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-timestamp-serialization_error-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-timestamp-serialization_error-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-timestamp-serialization_error-002.phpt b/mongodb-1.13.0/tests/bson/bson-timestamp-serialization_error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-timestamp-serialization_error-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-timestamp-serialization_error-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-timestamp-serialization_error-003.phpt b/mongodb-1.13.0/tests/bson/bson-timestamp-serialization_error-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-timestamp-serialization_error-003.phpt
rename to mongodb-1.13.0/tests/bson/bson-timestamp-serialization_error-003.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-timestamp-serialization_error-004.phpt b/mongodb-1.13.0/tests/bson/bson-timestamp-serialization_error-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-timestamp-serialization_error-004.phpt
rename to mongodb-1.13.0/tests/bson/bson-timestamp-serialization_error-004.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-timestamp-serialization_error-005.phpt b/mongodb-1.13.0/tests/bson/bson-timestamp-serialization_error-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-timestamp-serialization_error-005.phpt
rename to mongodb-1.13.0/tests/bson/bson-timestamp-serialization_error-005.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-timestamp-serialization_error-006.phpt b/mongodb-1.13.0/tests/bson/bson-timestamp-serialization_error-006.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-timestamp-serialization_error-006.phpt
rename to mongodb-1.13.0/tests/bson/bson-timestamp-serialization_error-006.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-timestamp-serialization_error-007.phpt b/mongodb-1.13.0/tests/bson/bson-timestamp-serialization_error-007.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-timestamp-serialization_error-007.phpt
rename to mongodb-1.13.0/tests/bson/bson-timestamp-serialization_error-007.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-timestamp-serialization_error-008.phpt b/mongodb-1.13.0/tests/bson/bson-timestamp-serialization_error-008.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-timestamp-serialization_error-008.phpt
rename to mongodb-1.13.0/tests/bson/bson-timestamp-serialization_error-008.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-timestamp-set_state-001.phpt b/mongodb-1.13.0/tests/bson/bson-timestamp-set_state-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-timestamp-set_state-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-timestamp-set_state-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-timestamp-set_state-002.phpt b/mongodb-1.13.0/tests/bson/bson-timestamp-set_state-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-timestamp-set_state-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-timestamp-set_state-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-timestamp-set_state_error-001.phpt b/mongodb-1.13.0/tests/bson/bson-timestamp-set_state_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-timestamp-set_state_error-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-timestamp-set_state_error-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-timestamp-set_state_error-002.phpt b/mongodb-1.13.0/tests/bson/bson-timestamp-set_state_error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-timestamp-set_state_error-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-timestamp-set_state_error-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-timestamp-set_state_error-003.phpt b/mongodb-1.13.0/tests/bson/bson-timestamp-set_state_error-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-timestamp-set_state_error-003.phpt
rename to mongodb-1.13.0/tests/bson/bson-timestamp-set_state_error-003.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-timestamp-set_state_error-004.phpt b/mongodb-1.13.0/tests/bson/bson-timestamp-set_state_error-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-timestamp-set_state_error-004.phpt
rename to mongodb-1.13.0/tests/bson/bson-timestamp-set_state_error-004.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-timestamp_error-001.phpt b/mongodb-1.13.0/tests/bson/bson-timestamp_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-timestamp_error-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-timestamp_error-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-timestamp_error-002.phpt b/mongodb-1.13.0/tests/bson/bson-timestamp_error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-timestamp_error-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-timestamp_error-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-timestamp_error-003.phpt b/mongodb-1.13.0/tests/bson/bson-timestamp_error-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-timestamp_error-003.phpt
rename to mongodb-1.13.0/tests/bson/bson-timestamp_error-003.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-timestamp_error-004.phpt b/mongodb-1.13.0/tests/bson/bson-timestamp_error-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-timestamp_error-004.phpt
rename to mongodb-1.13.0/tests/bson/bson-timestamp_error-004.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-timestamp_error-005.phpt b/mongodb-1.13.0/tests/bson/bson-timestamp_error-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-timestamp_error-005.phpt
rename to mongodb-1.13.0/tests/bson/bson-timestamp_error-005.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-timestamp_error-006.phpt b/mongodb-1.13.0/tests/bson/bson-timestamp_error-006.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-timestamp_error-006.phpt
rename to mongodb-1.13.0/tests/bson/bson-timestamp_error-006.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-timestampinterface-001.phpt b/mongodb-1.13.0/tests/bson/bson-timestampinterface-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-timestampinterface-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-timestampinterface-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-toCanonicalJSON-001.phpt b/mongodb-1.13.0/tests/bson/bson-toCanonicalJSON-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-toCanonicalJSON-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-toCanonicalJSON-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-toCanonicalJSON-002.phpt b/mongodb-1.13.0/tests/bson/bson-toCanonicalJSON-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-toCanonicalJSON-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-toCanonicalJSON-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-toCanonicalJSON_error-001.phpt b/mongodb-1.13.0/tests/bson/bson-toCanonicalJSON_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-toCanonicalJSON_error-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-toCanonicalJSON_error-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-toCanonicalJSON_error-002.phpt b/mongodb-1.13.0/tests/bson/bson-toCanonicalJSON_error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-toCanonicalJSON_error-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-toCanonicalJSON_error-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-toCanonicalJSON_error-003.phpt b/mongodb-1.13.0/tests/bson/bson-toCanonicalJSON_error-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-toCanonicalJSON_error-003.phpt
rename to mongodb-1.13.0/tests/bson/bson-toCanonicalJSON_error-003.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-toJSON-001.phpt b/mongodb-1.13.0/tests/bson/bson-toJSON-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-toJSON-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-toJSON-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-toJSON-002.phpt b/mongodb-1.13.0/tests/bson/bson-toJSON-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-toJSON-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-toJSON-002.phpt
diff --git a/mongodb-1.13.0/tests/bson/bson-toJSON-003.phpt b/mongodb-1.13.0/tests/bson/bson-toJSON-003.phpt
new file mode 100644
index 00000000..60cf80e7
--- /dev/null
+++ b/mongodb-1.13.0/tests/bson/bson-toJSON-003.phpt
@@ -0,0 +1,17 @@
+--TEST--
+MongoDB\BSON\toJSON(): Encoding JSON with duplicate field names
+--FILE--
+<?php
+
+require_once __DIR__ . '/../utils/basic.inc';
+
+/* Note: this is a regression test for libmongoc's JSON encoder. It is not
+ * advisable to use duplicate keys in BSON documents. */
+echo toJSON(fromJSON('{ "foo": "bar", "foo": "baz" }')), "\n";
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+{ "foo" : "bar", "foo" : "baz" }
+===DONE===
diff --git a/mongodb-1.12.0/tests/bson/bson-toJSON_error-001.phpt b/mongodb-1.13.0/tests/bson/bson-toJSON_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-toJSON_error-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-toJSON_error-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-toJSON_error-002.phpt b/mongodb-1.13.0/tests/bson/bson-toJSON_error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-toJSON_error-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-toJSON_error-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-toJSON_error-003.phpt b/mongodb-1.13.0/tests/bson/bson-toJSON_error-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-toJSON_error-003.phpt
rename to mongodb-1.13.0/tests/bson/bson-toJSON_error-003.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-toPHP-001.phpt b/mongodb-1.13.0/tests/bson/bson-toPHP-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-toPHP-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-toPHP-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-toPHP-002.phpt b/mongodb-1.13.0/tests/bson/bson-toPHP-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-toPHP-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-toPHP-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-toPHP-003.phpt b/mongodb-1.13.0/tests/bson/bson-toPHP-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-toPHP-003.phpt
rename to mongodb-1.13.0/tests/bson/bson-toPHP-003.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-toPHP-004.phpt b/mongodb-1.13.0/tests/bson/bson-toPHP-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-toPHP-004.phpt
rename to mongodb-1.13.0/tests/bson/bson-toPHP-004.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-toPHP-006.phpt b/mongodb-1.13.0/tests/bson/bson-toPHP-006.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-toPHP-006.phpt
rename to mongodb-1.13.0/tests/bson/bson-toPHP-006.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-toPHP-007.phpt b/mongodb-1.13.0/tests/bson/bson-toPHP-007.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-toPHP-007.phpt
rename to mongodb-1.13.0/tests/bson/bson-toPHP-007.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-toPHP-008.phpt b/mongodb-1.13.0/tests/bson/bson-toPHP-008.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-toPHP-008.phpt
rename to mongodb-1.13.0/tests/bson/bson-toPHP-008.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-toPHP-009.phpt b/mongodb-1.13.0/tests/bson/bson-toPHP-009.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-toPHP-009.phpt
rename to mongodb-1.13.0/tests/bson/bson-toPHP-009.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-toPHP-010.phpt b/mongodb-1.13.0/tests/bson/bson-toPHP-010.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-toPHP-010.phpt
rename to mongodb-1.13.0/tests/bson/bson-toPHP-010.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-toPHP-011.phpt b/mongodb-1.13.0/tests/bson/bson-toPHP-011.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-toPHP-011.phpt
rename to mongodb-1.13.0/tests/bson/bson-toPHP-011.phpt
diff --git a/mongodb-1.13.0/tests/bson/bson-toPHP-012.phpt b/mongodb-1.13.0/tests/bson/bson-toPHP-012.phpt
new file mode 100644
index 00000000..5f6e178e
--- /dev/null
+++ b/mongodb-1.13.0/tests/bson/bson-toPHP-012.phpt
@@ -0,0 +1,20 @@
+--TEST--
+MongoDB\BSON\toPHP(): Decoding BSON with duplicate field names
+--FILE--
+<?php
+
+require_once __DIR__ . '/../utils/basic.inc';
+
+/* Note: this is a regression test. It is not advisable to use duplicate keys in
+ * BSON documents. */
+var_dump(toPHP(fromJSON('{ "foo": "bar", "foo": "baz" }')));
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+object(stdClass)#%d (%d) {
+ ["foo"]=>
+ string(3) "baz"
+}
+===DONE===
diff --git a/mongodb-1.12.0/tests/bson/bson-toPHP_error-001.phpt b/mongodb-1.13.0/tests/bson/bson-toPHP_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-toPHP_error-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-toPHP_error-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-toPHP_error-002.phpt b/mongodb-1.13.0/tests/bson/bson-toPHP_error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-toPHP_error-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-toPHP_error-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-toPHP_error-003.phpt b/mongodb-1.13.0/tests/bson/bson-toPHP_error-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-toPHP_error-003.phpt
rename to mongodb-1.13.0/tests/bson/bson-toPHP_error-003.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-toPHP_error-004.phpt b/mongodb-1.13.0/tests/bson/bson-toPHP_error-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-toPHP_error-004.phpt
rename to mongodb-1.13.0/tests/bson/bson-toPHP_error-004.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-toPHP_error-005.phpt b/mongodb-1.13.0/tests/bson/bson-toPHP_error-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-toPHP_error-005.phpt
rename to mongodb-1.13.0/tests/bson/bson-toPHP_error-005.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-toPHP_error-006.phpt b/mongodb-1.13.0/tests/bson/bson-toPHP_error-006.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-toPHP_error-006.phpt
rename to mongodb-1.13.0/tests/bson/bson-toPHP_error-006.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-toRelaxedJSON-001.phpt b/mongodb-1.13.0/tests/bson/bson-toRelaxedJSON-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-toRelaxedJSON-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-toRelaxedJSON-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-toRelaxedJSON-002.phpt b/mongodb-1.13.0/tests/bson/bson-toRelaxedJSON-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-toRelaxedJSON-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-toRelaxedJSON-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-toRelaxedJSON_error-001.phpt b/mongodb-1.13.0/tests/bson/bson-toRelaxedJSON_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-toRelaxedJSON_error-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-toRelaxedJSON_error-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-toRelaxedJSON_error-002.phpt b/mongodb-1.13.0/tests/bson/bson-toRelaxedJSON_error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-toRelaxedJSON_error-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-toRelaxedJSON_error-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-toRelaxedJSON_error-003.phpt b/mongodb-1.13.0/tests/bson/bson-toRelaxedJSON_error-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-toRelaxedJSON_error-003.phpt
rename to mongodb-1.13.0/tests/bson/bson-toRelaxedJSON_error-003.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-undefined-001.phpt b/mongodb-1.13.0/tests/bson/bson-undefined-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-undefined-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-undefined-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-undefined-clone-001.phpt b/mongodb-1.13.0/tests/bson/bson-undefined-clone-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-undefined-clone-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-undefined-clone-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-undefined-compare-001.phpt b/mongodb-1.13.0/tests/bson/bson-undefined-compare-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-undefined-compare-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-undefined-compare-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-undefined-jsonserialize-001.phpt b/mongodb-1.13.0/tests/bson/bson-undefined-jsonserialize-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-undefined-jsonserialize-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-undefined-jsonserialize-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-undefined-jsonserialize-002.phpt b/mongodb-1.13.0/tests/bson/bson-undefined-jsonserialize-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-undefined-jsonserialize-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-undefined-jsonserialize-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-undefined-serialization-001.phpt b/mongodb-1.13.0/tests/bson/bson-undefined-serialization-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-undefined-serialization-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-undefined-serialization-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-undefined-serialization-002.phpt b/mongodb-1.13.0/tests/bson/bson-undefined-serialization-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-undefined-serialization-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-undefined-serialization-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-undefined-tostring-001.phpt b/mongodb-1.13.0/tests/bson/bson-undefined-tostring-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-undefined-tostring-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-undefined-tostring-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-undefined_error-001.phpt b/mongodb-1.13.0/tests/bson/bson-undefined_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-undefined_error-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-undefined_error-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-unknown-001.phpt b/mongodb-1.13.0/tests/bson/bson-unknown-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-unknown-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-unknown-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-utcdatetime-001.phpt b/mongodb-1.13.0/tests/bson/bson-utcdatetime-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-utcdatetime-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-utcdatetime-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-utcdatetime-002.phpt b/mongodb-1.13.0/tests/bson/bson-utcdatetime-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-utcdatetime-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-utcdatetime-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-utcdatetime-003.phpt b/mongodb-1.13.0/tests/bson/bson-utcdatetime-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-utcdatetime-003.phpt
rename to mongodb-1.13.0/tests/bson/bson-utcdatetime-003.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-utcdatetime-004.phpt b/mongodb-1.13.0/tests/bson/bson-utcdatetime-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-utcdatetime-004.phpt
rename to mongodb-1.13.0/tests/bson/bson-utcdatetime-004.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-utcdatetime-005.phpt b/mongodb-1.13.0/tests/bson/bson-utcdatetime-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-utcdatetime-005.phpt
rename to mongodb-1.13.0/tests/bson/bson-utcdatetime-005.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-utcdatetime-006.phpt b/mongodb-1.13.0/tests/bson/bson-utcdatetime-006.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-utcdatetime-006.phpt
rename to mongodb-1.13.0/tests/bson/bson-utcdatetime-006.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-utcdatetime-007.phpt b/mongodb-1.13.0/tests/bson/bson-utcdatetime-007.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-utcdatetime-007.phpt
rename to mongodb-1.13.0/tests/bson/bson-utcdatetime-007.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-utcdatetime-clone-001.phpt b/mongodb-1.13.0/tests/bson/bson-utcdatetime-clone-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-utcdatetime-clone-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-utcdatetime-clone-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-utcdatetime-compare-001.phpt b/mongodb-1.13.0/tests/bson/bson-utcdatetime-compare-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-utcdatetime-compare-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-utcdatetime-compare-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-utcdatetime-get_properties-001.phpt b/mongodb-1.13.0/tests/bson/bson-utcdatetime-get_properties-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-utcdatetime-get_properties-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-utcdatetime-get_properties-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-utcdatetime-get_properties-002.phpt b/mongodb-1.13.0/tests/bson/bson-utcdatetime-get_properties-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-utcdatetime-get_properties-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-utcdatetime-get_properties-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-utcdatetime-int-size-001.phpt b/mongodb-1.13.0/tests/bson/bson-utcdatetime-int-size-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-utcdatetime-int-size-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-utcdatetime-int-size-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-utcdatetime-int-size-002.phpt b/mongodb-1.13.0/tests/bson/bson-utcdatetime-int-size-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-utcdatetime-int-size-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-utcdatetime-int-size-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-utcdatetime-jsonserialize-001.phpt b/mongodb-1.13.0/tests/bson/bson-utcdatetime-jsonserialize-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-utcdatetime-jsonserialize-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-utcdatetime-jsonserialize-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-utcdatetime-jsonserialize-002.phpt b/mongodb-1.13.0/tests/bson/bson-utcdatetime-jsonserialize-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-utcdatetime-jsonserialize-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-utcdatetime-jsonserialize-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-utcdatetime-serialization-001.phpt b/mongodb-1.13.0/tests/bson/bson-utcdatetime-serialization-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-utcdatetime-serialization-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-utcdatetime-serialization-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-utcdatetime-serialization-002.phpt b/mongodb-1.13.0/tests/bson/bson-utcdatetime-serialization-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-utcdatetime-serialization-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-utcdatetime-serialization-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-utcdatetime-serialization-003.phpt b/mongodb-1.13.0/tests/bson/bson-utcdatetime-serialization-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-utcdatetime-serialization-003.phpt
rename to mongodb-1.13.0/tests/bson/bson-utcdatetime-serialization-003.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-utcdatetime-serialization-004.phpt b/mongodb-1.13.0/tests/bson/bson-utcdatetime-serialization-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-utcdatetime-serialization-004.phpt
rename to mongodb-1.13.0/tests/bson/bson-utcdatetime-serialization-004.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-utcdatetime-serialization_error-001.phpt b/mongodb-1.13.0/tests/bson/bson-utcdatetime-serialization_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-utcdatetime-serialization_error-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-utcdatetime-serialization_error-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-utcdatetime-serialization_error-002.phpt b/mongodb-1.13.0/tests/bson/bson-utcdatetime-serialization_error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-utcdatetime-serialization_error-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-utcdatetime-serialization_error-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-utcdatetime-serialization_error-003.phpt b/mongodb-1.13.0/tests/bson/bson-utcdatetime-serialization_error-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-utcdatetime-serialization_error-003.phpt
rename to mongodb-1.13.0/tests/bson/bson-utcdatetime-serialization_error-003.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-utcdatetime-serialization_error-004.phpt b/mongodb-1.13.0/tests/bson/bson-utcdatetime-serialization_error-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-utcdatetime-serialization_error-004.phpt
rename to mongodb-1.13.0/tests/bson/bson-utcdatetime-serialization_error-004.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-utcdatetime-set_state-001.phpt b/mongodb-1.13.0/tests/bson/bson-utcdatetime-set_state-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-utcdatetime-set_state-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-utcdatetime-set_state-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-utcdatetime-set_state-002.phpt b/mongodb-1.13.0/tests/bson/bson-utcdatetime-set_state-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-utcdatetime-set_state-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-utcdatetime-set_state-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-utcdatetime-set_state_error-001.phpt b/mongodb-1.13.0/tests/bson/bson-utcdatetime-set_state_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-utcdatetime-set_state_error-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-utcdatetime-set_state_error-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-utcdatetime-set_state_error-002.phpt b/mongodb-1.13.0/tests/bson/bson-utcdatetime-set_state_error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-utcdatetime-set_state_error-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-utcdatetime-set_state_error-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-utcdatetime-todatetime-001.phpt b/mongodb-1.13.0/tests/bson/bson-utcdatetime-todatetime-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-utcdatetime-todatetime-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-utcdatetime-todatetime-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-utcdatetime-todatetime-002.phpt b/mongodb-1.13.0/tests/bson/bson-utcdatetime-todatetime-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-utcdatetime-todatetime-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-utcdatetime-todatetime-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-utcdatetime-tostring-001.phpt b/mongodb-1.13.0/tests/bson/bson-utcdatetime-tostring-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-utcdatetime-tostring-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-utcdatetime-tostring-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-utcdatetime_error-001.phpt b/mongodb-1.13.0/tests/bson/bson-utcdatetime_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-utcdatetime_error-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-utcdatetime_error-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-utcdatetime_error-002.phpt b/mongodb-1.13.0/tests/bson/bson-utcdatetime_error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-utcdatetime_error-002.phpt
rename to mongodb-1.13.0/tests/bson/bson-utcdatetime_error-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-utcdatetime_error-003.phpt b/mongodb-1.13.0/tests/bson/bson-utcdatetime_error-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-utcdatetime_error-003.phpt
rename to mongodb-1.13.0/tests/bson/bson-utcdatetime_error-003.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-utcdatetime_error-004.phpt b/mongodb-1.13.0/tests/bson/bson-utcdatetime_error-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-utcdatetime_error-004.phpt
rename to mongodb-1.13.0/tests/bson/bson-utcdatetime_error-004.phpt
diff --git a/mongodb-1.12.0/tests/bson/bson-utcdatetimeinterface-001.phpt b/mongodb-1.13.0/tests/bson/bson-utcdatetimeinterface-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bson-utcdatetimeinterface-001.phpt
rename to mongodb-1.13.0/tests/bson/bson-utcdatetimeinterface-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bug0274.phpt b/mongodb-1.13.0/tests/bson/bug0274.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bug0274.phpt
rename to mongodb-1.13.0/tests/bson/bug0274.phpt
diff --git a/mongodb-1.12.0/tests/bson/bug0325.phpt b/mongodb-1.13.0/tests/bson/bug0325.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bug0325.phpt
rename to mongodb-1.13.0/tests/bson/bug0325.phpt
diff --git a/mongodb-1.12.0/tests/bson/bug0334-001.phpt b/mongodb-1.13.0/tests/bson/bug0334-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bug0334-001.phpt
rename to mongodb-1.13.0/tests/bson/bug0334-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bug0334-002.phpt b/mongodb-1.13.0/tests/bson/bug0334-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bug0334-002.phpt
rename to mongodb-1.13.0/tests/bson/bug0334-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bug0341.phpt b/mongodb-1.13.0/tests/bson/bug0341.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bug0341.phpt
rename to mongodb-1.13.0/tests/bson/bug0341.phpt
diff --git a/mongodb-1.12.0/tests/bson/bug0347.phpt b/mongodb-1.13.0/tests/bson/bug0347.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bug0347.phpt
rename to mongodb-1.13.0/tests/bson/bug0347.phpt
diff --git a/mongodb-1.12.0/tests/bson/bug0528.phpt b/mongodb-1.13.0/tests/bson/bug0528.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bug0528.phpt
rename to mongodb-1.13.0/tests/bson/bug0528.phpt
diff --git a/mongodb-1.12.0/tests/bson/bug0531-001.phpt b/mongodb-1.13.0/tests/bson/bug0531-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bug0531-001.phpt
rename to mongodb-1.13.0/tests/bson/bug0531-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bug0544.phpt b/mongodb-1.13.0/tests/bson/bug0544.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bug0544.phpt
rename to mongodb-1.13.0/tests/bson/bug0544.phpt
diff --git a/mongodb-1.12.0/tests/bson/bug0592.phpt b/mongodb-1.13.0/tests/bson/bug0592.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bug0592.phpt
rename to mongodb-1.13.0/tests/bson/bug0592.phpt
diff --git a/mongodb-1.12.0/tests/bson/bug0623.phpt b/mongodb-1.13.0/tests/bson/bug0623.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bug0623.phpt
rename to mongodb-1.13.0/tests/bson/bug0623.phpt
diff --git a/mongodb-1.12.0/tests/bson/bug0631.phpt b/mongodb-1.13.0/tests/bson/bug0631.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bug0631.phpt
rename to mongodb-1.13.0/tests/bson/bug0631.phpt
diff --git a/mongodb-1.12.0/tests/bson/bug0672.phpt b/mongodb-1.13.0/tests/bson/bug0672.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bug0672.phpt
rename to mongodb-1.13.0/tests/bson/bug0672.phpt
diff --git a/mongodb-1.12.0/tests/bson/bug0894-001.phpt b/mongodb-1.13.0/tests/bson/bug0894-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bug0894-001.phpt
rename to mongodb-1.13.0/tests/bson/bug0894-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bug0923-001.phpt b/mongodb-1.13.0/tests/bson/bug0923-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bug0923-001.phpt
rename to mongodb-1.13.0/tests/bson/bug0923-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bug0923-002.phpt b/mongodb-1.13.0/tests/bson/bug0923-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bug0923-002.phpt
rename to mongodb-1.13.0/tests/bson/bug0923-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bug0939-001.phpt b/mongodb-1.13.0/tests/bson/bug0939-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bug0939-001.phpt
rename to mongodb-1.13.0/tests/bson/bug0939-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bug0974-001.phpt b/mongodb-1.13.0/tests/bson/bug0974-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bug0974-001.phpt
rename to mongodb-1.13.0/tests/bson/bug0974-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bug1006-001.phpt b/mongodb-1.13.0/tests/bson/bug1006-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bug1006-001.phpt
rename to mongodb-1.13.0/tests/bson/bug1006-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bug1006-002.phpt b/mongodb-1.13.0/tests/bson/bug1006-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bug1006-002.phpt
rename to mongodb-1.13.0/tests/bson/bug1006-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bug1053.phpt b/mongodb-1.13.0/tests/bson/bug1053.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bug1053.phpt
rename to mongodb-1.13.0/tests/bson/bug1053.phpt
diff --git a/mongodb-1.12.0/tests/bson/bug1067.phpt b/mongodb-1.13.0/tests/bson/bug1067.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bug1067.phpt
rename to mongodb-1.13.0/tests/bson/bug1067.phpt
diff --git a/mongodb-1.12.0/tests/bson/bug1266.phpt b/mongodb-1.13.0/tests/bson/bug1266.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bug1266.phpt
rename to mongodb-1.13.0/tests/bson/bug1266.phpt
diff --git a/mongodb-1.12.0/tests/bson/bug1598-001.phpt b/mongodb-1.13.0/tests/bson/bug1598-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bug1598-001.phpt
rename to mongodb-1.13.0/tests/bson/bug1598-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bug1598-002.phpt b/mongodb-1.13.0/tests/bson/bug1598-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bug1598-002.phpt
rename to mongodb-1.13.0/tests/bson/bug1598-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bug1839-001.phpt b/mongodb-1.13.0/tests/bson/bug1839-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bug1839-001.phpt
rename to mongodb-1.13.0/tests/bson/bug1839-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/bug1839-002.phpt b/mongodb-1.13.0/tests/bson/bug1839-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bug1839-002.phpt
rename to mongodb-1.13.0/tests/bson/bug1839-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/bug1839-003.phpt b/mongodb-1.13.0/tests/bson/bug1839-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bug1839-003.phpt
rename to mongodb-1.13.0/tests/bson/bug1839-003.phpt
diff --git a/mongodb-1.12.0/tests/bson/bug1839-004.phpt b/mongodb-1.13.0/tests/bson/bug1839-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bug1839-004.phpt
rename to mongodb-1.13.0/tests/bson/bug1839-004.phpt
diff --git a/mongodb-1.12.0/tests/bson/bug1839-005.phpt b/mongodb-1.13.0/tests/bson/bug1839-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bug1839-005.phpt
rename to mongodb-1.13.0/tests/bson/bug1839-005.phpt
diff --git a/mongodb-1.12.0/tests/bson/bug1839-006.phpt b/mongodb-1.13.0/tests/bson/bug1839-006.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bug1839-006.phpt
rename to mongodb-1.13.0/tests/bson/bug1839-006.phpt
diff --git a/mongodb-1.12.0/tests/bson/bug1839-007.phpt b/mongodb-1.13.0/tests/bson/bug1839-007.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bug1839-007.phpt
rename to mongodb-1.13.0/tests/bson/bug1839-007.phpt
diff --git a/mongodb-1.12.0/tests/bson/bug1839-008.phpt b/mongodb-1.13.0/tests/bson/bug1839-008.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/bug1839-008.phpt
rename to mongodb-1.13.0/tests/bson/bug1839-008.phpt
diff --git a/mongodb-1.12.0/tests/bson/typemap-001.phpt b/mongodb-1.13.0/tests/bson/typemap-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/typemap-001.phpt
rename to mongodb-1.13.0/tests/bson/typemap-001.phpt
diff --git a/mongodb-1.12.0/tests/bson/typemap-002.phpt b/mongodb-1.13.0/tests/bson/typemap-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/typemap-002.phpt
rename to mongodb-1.13.0/tests/bson/typemap-002.phpt
diff --git a/mongodb-1.12.0/tests/bson/typemap-003.phpt b/mongodb-1.13.0/tests/bson/typemap-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/typemap-003.phpt
rename to mongodb-1.13.0/tests/bson/typemap-003.phpt
diff --git a/mongodb-1.12.0/tests/bson/typemap-004.phpt b/mongodb-1.13.0/tests/bson/typemap-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/typemap-004.phpt
rename to mongodb-1.13.0/tests/bson/typemap-004.phpt
diff --git a/mongodb-1.12.0/tests/bson/typemap-005.phpt b/mongodb-1.13.0/tests/bson/typemap-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/typemap-005.phpt
rename to mongodb-1.13.0/tests/bson/typemap-005.phpt
diff --git a/mongodb-1.12.0/tests/bson/typemap-006.phpt b/mongodb-1.13.0/tests/bson/typemap-006.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/typemap-006.phpt
rename to mongodb-1.13.0/tests/bson/typemap-006.phpt
diff --git a/mongodb-1.12.0/tests/bson/typemap-007.phpt b/mongodb-1.13.0/tests/bson/typemap-007.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bson/typemap-007.phpt
rename to mongodb-1.13.0/tests/bson/typemap-007.phpt
diff --git a/mongodb-1.12.0/tests/bulk/bug0667.phpt b/mongodb-1.13.0/tests/bulk/bug0667.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bulk/bug0667.phpt
rename to mongodb-1.13.0/tests/bulk/bug0667.phpt
diff --git a/mongodb-1.12.0/tests/bulk/bulkwrite-count-001.phpt b/mongodb-1.13.0/tests/bulk/bulkwrite-count-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bulk/bulkwrite-count-001.phpt
rename to mongodb-1.13.0/tests/bulk/bulkwrite-count-001.phpt
diff --git a/mongodb-1.12.0/tests/bulk/bulkwrite-countable-001.phpt b/mongodb-1.13.0/tests/bulk/bulkwrite-countable-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bulk/bulkwrite-countable-001.phpt
rename to mongodb-1.13.0/tests/bulk/bulkwrite-countable-001.phpt
diff --git a/mongodb-1.12.0/tests/bulk/bulkwrite-debug-001.phpt b/mongodb-1.13.0/tests/bulk/bulkwrite-debug-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bulk/bulkwrite-debug-001.phpt
rename to mongodb-1.13.0/tests/bulk/bulkwrite-debug-001.phpt
diff --git a/mongodb-1.13.0/tests/bulk/bulkwrite-debug-002.phpt b/mongodb-1.13.0/tests/bulk/bulkwrite-debug-002.phpt
new file mode 100644
index 00000000..485f6352
--- /dev/null
+++ b/mongodb-1.13.0/tests/bulk/bulkwrite-debug-002.phpt
@@ -0,0 +1,67 @@
+--TEST--
+MongoDB\Driver\BulkWrite debug output after execution
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_live(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+
+$tests = [
+ [],
+ ['session' => $manager->startSession()],
+];
+
+foreach ($tests as $options) {
+ $bulk = new MongoDB\Driver\BulkWrite();
+ $bulk->insert(['foo' => 'bar']);
+ $manager->executeBulkWrite(NS, $bulk, $options);
+ var_dump($bulk);
+}
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+object(MongoDB\Driver\BulkWrite)#%d (%d) {
+ ["database"]=>
+ %s
+ ["collection"]=>
+ %s
+ ["ordered"]=>
+ bool(true)
+ ["bypassDocumentValidation"]=>
+ NULL
+ ["executed"]=>
+ bool(true)
+ ["server_id"]=>
+ int(%d)
+ ["session"]=>
+ NULL
+ ["write_concern"]=>
+ NULL
+}
+object(MongoDB\Driver\BulkWrite)#%d (%d) {
+ ["database"]=>
+ %s
+ ["collection"]=>
+ %s
+ ["ordered"]=>
+ bool(true)
+ ["bypassDocumentValidation"]=>
+ NULL
+ ["executed"]=>
+ bool(true)
+ ["server_id"]=>
+ int(%d)
+ ["session"]=>
+ object(MongoDB\Driver\Session)#%d (%d) {
+ %a
+ }
+ ["write_concern"]=>
+ NULL
+}
+===DONE===
diff --git a/mongodb-1.12.0/tests/bulk/bulkwrite-delete-001.phpt b/mongodb-1.13.0/tests/bulk/bulkwrite-delete-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bulk/bulkwrite-delete-001.phpt
rename to mongodb-1.13.0/tests/bulk/bulkwrite-delete-001.phpt
diff --git a/mongodb-1.12.0/tests/bulk/bulkwrite-delete-002.phpt b/mongodb-1.13.0/tests/bulk/bulkwrite-delete-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bulk/bulkwrite-delete-002.phpt
rename to mongodb-1.13.0/tests/bulk/bulkwrite-delete-002.phpt
diff --git a/mongodb-1.12.0/tests/bulk/bulkwrite-delete_error-001.phpt b/mongodb-1.13.0/tests/bulk/bulkwrite-delete_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bulk/bulkwrite-delete_error-001.phpt
rename to mongodb-1.13.0/tests/bulk/bulkwrite-delete_error-001.phpt
diff --git a/mongodb-1.12.0/tests/bulk/bulkwrite-delete_error-002.phpt b/mongodb-1.13.0/tests/bulk/bulkwrite-delete_error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bulk/bulkwrite-delete_error-002.phpt
rename to mongodb-1.13.0/tests/bulk/bulkwrite-delete_error-002.phpt
diff --git a/mongodb-1.12.0/tests/bulk/bulkwrite-delete_error-003.phpt b/mongodb-1.13.0/tests/bulk/bulkwrite-delete_error-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bulk/bulkwrite-delete_error-003.phpt
rename to mongodb-1.13.0/tests/bulk/bulkwrite-delete_error-003.phpt
diff --git a/mongodb-1.13.0/tests/bulk/bulkwrite-delete_error-005.phpt b/mongodb-1.13.0/tests/bulk/bulkwrite-delete_error-005.phpt
new file mode 100644
index 00000000..c353ad18
--- /dev/null
+++ b/mongodb-1.13.0/tests/bulk/bulkwrite-delete_error-005.phpt
@@ -0,0 +1,26 @@
+--TEST--
+MongoDB\Driver\BulkWrite::delete() hint option requires MongoDB 4.4 (server-side error)
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_live(); ?>
+<?php skip_if_server_version('>=', '4.3.4'); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+
+$bulk = new MongoDB\Driver\BulkWrite;
+$bulk->delete(['_id' => 1], ['hint' => '_id_']);
+
+echo throws(function() use ($manager, $bulk) {
+ $manager->executeBulkWrite(NS, $bulk);
+}, 'MongoDB\Driver\Exception\BulkWriteException'), "\n";
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+OK: Got MongoDB\Driver\Exception\BulkWriteException
+BSON field 'delete.deletes.hint' is an unknown field.
+===DONE===
diff --git a/mongodb-1.12.0/tests/bulk/bulkwrite-insert-001.phpt b/mongodb-1.13.0/tests/bulk/bulkwrite-insert-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bulk/bulkwrite-insert-001.phpt
rename to mongodb-1.13.0/tests/bulk/bulkwrite-insert-001.phpt
diff --git a/mongodb-1.12.0/tests/bulk/bulkwrite-insert-004.phpt b/mongodb-1.13.0/tests/bulk/bulkwrite-insert-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bulk/bulkwrite-insert-004.phpt
rename to mongodb-1.13.0/tests/bulk/bulkwrite-insert-004.phpt
diff --git a/mongodb-1.12.0/tests/bulk/bulkwrite-insert_error-001.phpt b/mongodb-1.13.0/tests/bulk/bulkwrite-insert_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bulk/bulkwrite-insert_error-001.phpt
rename to mongodb-1.13.0/tests/bulk/bulkwrite-insert_error-001.phpt
diff --git a/mongodb-1.12.0/tests/bulk/bulkwrite-insert_error-002.phpt b/mongodb-1.13.0/tests/bulk/bulkwrite-insert_error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bulk/bulkwrite-insert_error-002.phpt
rename to mongodb-1.13.0/tests/bulk/bulkwrite-insert_error-002.phpt
diff --git a/mongodb-1.12.0/tests/bulk/bulkwrite-insert_error-003.phpt b/mongodb-1.13.0/tests/bulk/bulkwrite-insert_error-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bulk/bulkwrite-insert_error-003.phpt
rename to mongodb-1.13.0/tests/bulk/bulkwrite-insert_error-003.phpt
diff --git a/mongodb-1.12.0/tests/bulk/bulkwrite-update-001.phpt b/mongodb-1.13.0/tests/bulk/bulkwrite-update-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bulk/bulkwrite-update-001.phpt
rename to mongodb-1.13.0/tests/bulk/bulkwrite-update-001.phpt
diff --git a/mongodb-1.13.0/tests/bulk/bulkwrite-update-002.phpt b/mongodb-1.13.0/tests/bulk/bulkwrite-update-002.phpt
new file mode 100644
index 00000000..b8a57212
--- /dev/null
+++ b/mongodb-1.13.0/tests/bulk/bulkwrite-update-002.phpt
@@ -0,0 +1,83 @@
+--TEST--
+MongoDB\Driver\BulkWrite::update() with arrayFilters option
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_live(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+
+$bulk = new MongoDB\Driver\BulkWrite();
+
+$bulk->insert([ '_id' => 1, 'grades' => [ 95, 92, 90 ] ]);
+$bulk->insert([ '_id' => 2, 'grades' => [ 98, 100, 102 ] ]);
+$bulk->insert([ '_id' => 3, 'grades' => [ 95, 110, 100 ] ]);
+
+$manager->executeBulkWrite(DATABASE_NAME . '.' . COLLECTION_NAME, $bulk);
+
+$updateBulk = new MongoDB\Driver\BulkWrite();
+
+$query = ['grades' => ['$gte' => 100]];
+$update = [ '$set' => [ 'grades.$[element]' => 100 ] ];
+$options = [
+ 'arrayFilters' => [ [ 'element' => [ '$gte' => 100 ] ] ],
+ 'multi' => true
+];
+
+$updateBulk->update($query, $update, $options);
+$manager->executeBulkWrite(DATABASE_NAME . '.' . COLLECTION_NAME, $updateBulk);
+
+$cursor = $manager->executeQuery( DATABASE_NAME . '.' . COLLECTION_NAME, new \MongoDB\Driver\Query([]));
+var_dump($cursor->toArray());
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+array(%d) {
+ [0]=>
+ object(stdClass)#%d (%d) {
+ ["_id"]=>
+ int(1)
+ ["grades"]=>
+ array(%d) {
+ [0]=>
+ int(95)
+ [1]=>
+ int(92)
+ [2]=>
+ int(90)
+ }
+ }
+ [1]=>
+ object(stdClass)#%d (%d) {
+ ["_id"]=>
+ int(2)
+ ["grades"]=>
+ array(%d) {
+ [0]=>
+ int(98)
+ [1]=>
+ int(100)
+ [2]=>
+ int(100)
+ }
+ }
+ [2]=>
+ object(stdClass)#%d (%d) {
+ ["_id"]=>
+ int(3)
+ ["grades"]=>
+ array(%d) {
+ [0]=>
+ int(95)
+ [1]=>
+ int(100)
+ [2]=>
+ int(100)
+ }
+ }
+}
+===DONE===
diff --git a/mongodb-1.12.0/tests/bulk/bulkwrite-update-003.phpt b/mongodb-1.13.0/tests/bulk/bulkwrite-update-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bulk/bulkwrite-update-003.phpt
rename to mongodb-1.13.0/tests/bulk/bulkwrite-update-003.phpt
diff --git a/mongodb-1.12.0/tests/bulk/bulkwrite-update-004.phpt b/mongodb-1.13.0/tests/bulk/bulkwrite-update-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bulk/bulkwrite-update-004.phpt
rename to mongodb-1.13.0/tests/bulk/bulkwrite-update-004.phpt
diff --git a/mongodb-1.12.0/tests/bulk/bulkwrite-update_error-001.phpt b/mongodb-1.13.0/tests/bulk/bulkwrite-update_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bulk/bulkwrite-update_error-001.phpt
rename to mongodb-1.13.0/tests/bulk/bulkwrite-update_error-001.phpt
diff --git a/mongodb-1.12.0/tests/bulk/bulkwrite-update_error-002.phpt b/mongodb-1.13.0/tests/bulk/bulkwrite-update_error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bulk/bulkwrite-update_error-002.phpt
rename to mongodb-1.13.0/tests/bulk/bulkwrite-update_error-002.phpt
diff --git a/mongodb-1.12.0/tests/bulk/bulkwrite-update_error-003.phpt b/mongodb-1.13.0/tests/bulk/bulkwrite-update_error-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bulk/bulkwrite-update_error-003.phpt
rename to mongodb-1.13.0/tests/bulk/bulkwrite-update_error-003.phpt
diff --git a/mongodb-1.12.0/tests/bulk/bulkwrite-update_error-004.phpt b/mongodb-1.13.0/tests/bulk/bulkwrite-update_error-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bulk/bulkwrite-update_error-004.phpt
rename to mongodb-1.13.0/tests/bulk/bulkwrite-update_error-004.phpt
diff --git a/mongodb-1.12.0/tests/bulk/bulkwrite-update_error-005.phpt b/mongodb-1.13.0/tests/bulk/bulkwrite-update_error-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bulk/bulkwrite-update_error-005.phpt
rename to mongodb-1.13.0/tests/bulk/bulkwrite-update_error-005.phpt
diff --git a/mongodb-1.13.0/tests/bulk/bulkwrite-update_error-008.phpt b/mongodb-1.13.0/tests/bulk/bulkwrite-update_error-008.phpt
new file mode 100644
index 00000000..5de3ca34
--- /dev/null
+++ b/mongodb-1.13.0/tests/bulk/bulkwrite-update_error-008.phpt
@@ -0,0 +1,26 @@
+--TEST--
+MongoDB\Driver\BulkWrite::update() hint option requires MongoDB 4.2 (server-side error)
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_live(); ?>
+<?php skip_if_server_version('>=', '4.2'); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+
+$bulk = new MongoDB\Driver\BulkWrite;
+$bulk->update(['_id' => 1], ['$set' => ['x' => 11]], ['hint' => '_id_']);
+
+echo throws(function() use ($manager, $bulk) {
+ $manager->executeBulkWrite(NS, $bulk);
+}, 'MongoDB\Driver\Exception\BulkWriteException'), "\n";
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+OK: Got MongoDB\Driver\Exception\BulkWriteException
+BSON field 'update.updates.hint' is an unknown field.
+===DONE===
diff --git a/mongodb-1.12.0/tests/bulk/bulkwrite_error-001.phpt b/mongodb-1.13.0/tests/bulk/bulkwrite_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bulk/bulkwrite_error-001.phpt
rename to mongodb-1.13.0/tests/bulk/bulkwrite_error-001.phpt
diff --git a/mongodb-1.12.0/tests/bulk/bulkwrite_error-002.phpt b/mongodb-1.13.0/tests/bulk/bulkwrite_error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bulk/bulkwrite_error-002.phpt
rename to mongodb-1.13.0/tests/bulk/bulkwrite_error-002.phpt
diff --git a/mongodb-1.12.0/tests/bulk/write-0001.phpt b/mongodb-1.13.0/tests/bulk/write-0001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bulk/write-0001.phpt
rename to mongodb-1.13.0/tests/bulk/write-0001.phpt
diff --git a/mongodb-1.12.0/tests/bulk/write-0002.phpt b/mongodb-1.13.0/tests/bulk/write-0002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/bulk/write-0002.phpt
rename to mongodb-1.13.0/tests/bulk/write-0002.phpt
diff --git a/mongodb-1.13.0/tests/causal-consistency/causal-consistency-001.phpt b/mongodb-1.13.0/tests/causal-consistency/causal-consistency-001.phpt
new file mode 100644
index 00000000..19a2e7d2
--- /dev/null
+++ b/mongodb-1.13.0/tests/causal-consistency/causal-consistency-001.phpt
@@ -0,0 +1,26 @@
+--TEST--
+Causal consistency: new session has no operation time
+--DESCRIPTION--
+Causal consistency spec prose test #1
+https://github.com/mongodb/specifications/blob/master/source/causal-consistency/causal-consistency.rst#test-plan
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_not_replica_set_or_sharded_cluster_with_replica_set(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+$session = $manager->startSession();
+
+echo "Initial operation time:\n";
+var_dump($session->getOperationTime());
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+Initial operation time:
+NULL
+===DONE===
diff --git a/mongodb-1.13.0/tests/causal-consistency/causal-consistency-002.phpt b/mongodb-1.13.0/tests/causal-consistency/causal-consistency-002.phpt
new file mode 100644
index 00000000..4c2d5bbf
--- /dev/null
+++ b/mongodb-1.13.0/tests/causal-consistency/causal-consistency-002.phpt
@@ -0,0 +1,35 @@
+--TEST--
+Causal consistency: first read in session does not include afterClusterTime
+--DESCRIPTION--
+Causal consistency spec prose test #2
+https://github.com/mongodb/specifications/blob/master/source/causal-consistency/causal-consistency.rst#test-plan
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_not_replica_set_or_sharded_cluster_with_replica_set(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+require_once __DIR__ . "/../utils/observer.php";
+
+(new CommandObserver)->observe(
+ function() {
+ $manager = create_test_manager();
+ $session = $manager->startSession();
+
+ $query = new MongoDB\Driver\Query([]);
+ $manager->executeQuery(NS, $query, ['session' => $session]);
+ },
+ function(stdClass $command)
+ {
+ $hasAfterClusterTime = isset($command->readConcern->afterClusterTime);
+ printf("Read includes afterClusterTime: %s\n", ($hasAfterClusterTime ? 'yes' : 'no'));
+ }
+);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+Read includes afterClusterTime: no
+===DONE===
diff --git a/mongodb-1.13.0/tests/causal-consistency/causal-consistency-003.phpt b/mongodb-1.13.0/tests/causal-consistency/causal-consistency-003.phpt
new file mode 100644
index 00000000..89240e09
--- /dev/null
+++ b/mongodb-1.13.0/tests/causal-consistency/causal-consistency-003.phpt
@@ -0,0 +1,116 @@
+--TEST--
+Causal consistency: first read or write in session updates operationTime
+--DESCRIPTION--
+Causal consistency spec prose test #3
+https://github.com/mongodb/specifications/blob/master/source/causal-consistency/causal-consistency.rst#test-plan
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_not_replica_set_or_sharded_cluster_with_replica_set(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+class Test implements MongoDB\Driver\Monitoring\CommandSubscriber
+{
+ private $lastSeenOperationTime;
+
+ public function executeBulkWrite()
+ {
+ $this->lastSeenOperationTime = null;
+
+ MongoDB\Driver\Monitoring\addSubscriber($this);
+
+ $manager = create_test_manager();
+ $session = $manager->startSession();
+
+ $bulk = new MongoDB\Driver\BulkWrite;
+ $bulk->insert(['x' => 1]);
+ $manager->executeBulkWrite(NS, $bulk, ['session' => $session]);
+
+ printf("Session reports last seen operationTime: %s\n", ($session->getOperationTime() == $this->lastSeenOperationTime) ? 'yes' : 'no');
+
+ MongoDB\Driver\Monitoring\removeSubscriber($this);
+ }
+
+ public function executeCommand()
+ {
+ $this->lastSeenOperationTime = null;
+
+ MongoDB\Driver\Monitoring\addSubscriber($this);
+
+ $manager = create_test_manager();
+ $session = $manager->startSession();
+
+ $command = new MongoDB\Driver\Command(['ping' => 1]);
+ $manager->executeCommand(DATABASE_NAME, $command, ['session' => $session]);
+
+ printf("Session reports last seen operationTime: %s\n", ($session->getOperationTime() == $this->lastSeenOperationTime) ? 'yes' : 'no');
+
+ MongoDB\Driver\Monitoring\removeSubscriber($this);
+ }
+
+ public function executeQuery()
+ {
+ $this->lastSeenOperationTime = null;
+
+ MongoDB\Driver\Monitoring\addSubscriber($this);
+
+ $manager = create_test_manager();
+ $session = $manager->startSession();
+
+ $query = new MongoDB\Driver\Query([]);
+ $manager->executeQuery(NS, $query, ['session' => $session]);
+
+ printf("Session reports last seen operationTime: %s\n", ($session->getOperationTime() == $this->lastSeenOperationTime) ? 'yes' : 'no');
+
+ MongoDB\Driver\Monitoring\removeSubscriber($this);
+ }
+
+ public function commandStarted(MongoDB\Driver\Monitoring\CommandStartedEvent $event)
+ {
+ }
+
+ public function commandSucceeded(MongoDB\Driver\Monitoring\CommandSucceededEvent $event)
+ {
+ $reply = $event->getReply();
+ $hasOperationTime = isset($reply->{'operationTime'});
+
+ printf("%s command reply includes operationTime: %s\n", $event->getCommandName(), $hasOperationTime ? 'yes' : 'no');
+
+ if ($hasOperationTime) {
+ $this->lastSeenOperationTime = $reply->operationTime;
+ }
+ }
+
+ public function commandFailed(MongoDB\Driver\Monitoring\CommandFailedEvent $event)
+ {
+ }
+}
+
+echo "Testing executeBulkWrite()\n";
+(new Test)->executeBulkWrite();
+
+echo "\nTesting executeCommand()\n";
+(new Test)->executeCommand();
+
+echo "\nTesting executeQuery()\n";
+(new Test)->executeQuery();
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+Testing executeBulkWrite()
+insert command reply includes operationTime: yes
+Session reports last seen operationTime: yes
+
+Testing executeCommand()
+ping command reply includes operationTime: yes
+Session reports last seen operationTime: yes
+
+Testing executeQuery()
+find command reply includes operationTime: yes
+Session reports last seen operationTime: yes
+===DONE===
diff --git a/mongodb-1.13.0/tests/causal-consistency/causal-consistency-004.phpt b/mongodb-1.13.0/tests/causal-consistency/causal-consistency-004.phpt
new file mode 100644
index 00000000..6c36698e
--- /dev/null
+++ b/mongodb-1.13.0/tests/causal-consistency/causal-consistency-004.phpt
@@ -0,0 +1,139 @@
+--TEST--
+Causal consistency: first read or write in session updates operationTime (even on error)
+--DESCRIPTION--
+Causal consistency spec prose test #3
+https://github.com/mongodb/specifications/blob/master/source/causal-consistency/causal-consistency.rst#test-plan
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_not_replica_set_or_sharded_cluster_with_replica_set(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+class Test implements MongoDB\Driver\Monitoring\CommandSubscriber
+{
+ private $lastSeenOperationTime;
+
+ public function executeBulkWrite()
+ {
+ $this->lastSeenOperationTime = null;
+
+ MongoDB\Driver\Monitoring\addSubscriber($this);
+
+ $manager = create_test_manager();
+ $session = $manager->startSession();
+
+ $bulk = new MongoDB\Driver\BulkWrite;
+ $bulk->insert(['_id' => 1]);
+ $bulk->insert(['_id' => 1]);
+
+ throws(function() use ($manager, $bulk, $session) {
+ $manager->executeBulkWrite(NS, $bulk, ['session' => $session]);
+ }, 'MongoDB\Driver\Exception\BulkWriteException');
+
+ printf("Session reports last seen operationTime: %s\n", ($session->getOperationTime() == $this->lastSeenOperationTime) ? 'yes' : 'no');
+
+ MongoDB\Driver\Monitoring\removeSubscriber($this);
+ }
+
+ public function executeCommand()
+ {
+ $this->lastSeenOperationTime = null;
+
+ MongoDB\Driver\Monitoring\addSubscriber($this);
+
+ $manager = create_test_manager();
+ $session = $manager->startSession();
+
+ $command = new MongoDB\Driver\Command([
+ 'aggregate' => COLLECTION_NAME,
+ 'pipeline' => [
+ ['$unsupportedOperator' => 1],
+ ],
+ 'cursor' => new stdClass,
+ ]);
+
+ throws(function() use ($manager, $command, $session) {
+ $manager->executeCommand(DATABASE_NAME, $command, ['session' => $session]);
+ }, 'MongoDB\Driver\Exception\RuntimeException');
+
+ /* We cannot access the server reply if an exception is thrown for a
+ * failed command (see: PHPC-1076). For the time being, just assert that
+ * the operationTime is not null. */
+ printf("Session has non-null operationTime: %s\n", ($session->getOperationTime() !== null ? 'yes' : 'no'));
+
+ MongoDB\Driver\Monitoring\removeSubscriber($this);
+ }
+
+ public function executeQuery()
+ {
+ $this->lastSeenOperationTime = null;
+
+ MongoDB\Driver\Monitoring\addSubscriber($this);
+
+ $manager = create_test_manager();
+ $session = $manager->startSession();
+
+ $query = new MongoDB\Driver\Query(['$unsupportedOperator' => 1]);
+
+ throws(function() use ($manager, $query, $session) {
+ $manager->executeQuery(NS, $query, ['session' => $session]);
+ }, 'MongoDB\Driver\Exception\RuntimeException');
+
+ /* We cannot access the server reply if an exception is thrown for a
+ * failed command (see: PHPC-1076). For the time being, just assert that
+ * the operationTime is not null. */
+ printf("Session has non-null operationTime: %s\n", ($session->getOperationTime() !== null ? 'yes' : 'no'));
+
+ MongoDB\Driver\Monitoring\removeSubscriber($this);
+ }
+
+ public function commandStarted(MongoDB\Driver\Monitoring\CommandStartedEvent $event)
+ {
+ }
+
+ public function commandSucceeded(MongoDB\Driver\Monitoring\CommandSucceededEvent $event)
+ {
+ $reply = $event->getReply();
+ $hasOperationTime = isset($reply->operationTime);
+
+ printf("%s command reply includes operationTime: %s\n", $event->getCommandName(), $hasOperationTime ? 'yes' : 'no');
+
+ if ($hasOperationTime) {
+ $this->lastSeenOperationTime = $reply->operationTime;
+ }
+ }
+
+ public function commandFailed(MongoDB\Driver\Monitoring\CommandFailedEvent $event)
+ {
+ }
+}
+
+echo "Testing executeBulkWrite()\n";
+(new Test)->executeBulkWrite();
+
+echo "\nTesting executeCommand()\n";
+(new Test)->executeCommand();
+
+echo "\nTesting executeQuery()\n";
+(new Test)->executeQuery();
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+Testing executeBulkWrite()
+insert command reply includes operationTime: yes
+OK: Got MongoDB\Driver\Exception\BulkWriteException
+Session reports last seen operationTime: yes
+
+Testing executeCommand()
+OK: Got MongoDB\Driver\Exception\RuntimeException
+Session has non-null operationTime: yes
+
+Testing executeQuery()
+OK: Got MongoDB\Driver\Exception\RuntimeException
+Session has non-null operationTime: yes
+===DONE===
diff --git a/mongodb-1.13.0/tests/causal-consistency/causal-consistency-005.phpt b/mongodb-1.13.0/tests/causal-consistency/causal-consistency-005.phpt
new file mode 100644
index 00000000..d01c94a4
--- /dev/null
+++ b/mongodb-1.13.0/tests/causal-consistency/causal-consistency-005.phpt
@@ -0,0 +1,105 @@
+--TEST--
+Causal consistency: second read's afterClusterTime uses last reply's operationTime
+--DESCRIPTION--
+Causal consistency spec prose test #4 and #5
+https://github.com/mongodb/specifications/blob/master/source/causal-consistency/causal-consistency.rst#test-plan
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_not_replica_set_or_sharded_cluster_with_replica_set(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+class Test implements MongoDB\Driver\Monitoring\CommandSubscriber
+{
+ private $lastSeenOperationTime;
+
+ public function executeReadAfterRead()
+ {
+ $this->lastSeenOperationTime = null;
+
+ MongoDB\Driver\Monitoring\addSubscriber($this);
+
+ $manager = create_test_manager();
+ $session = $manager->startSession();
+
+ $query = new MongoDB\Driver\Query([]);
+ $manager->executeQuery(NS, $query, ['session' => $session]);
+ $manager->executeQuery(NS, $query, ['session' => $session]);
+
+ MongoDB\Driver\Monitoring\removeSubscriber($this);
+ }
+
+ public function executeReadAfterWrite()
+ {
+ $this->lastSeenOperationTime = null;
+
+ MongoDB\Driver\Monitoring\addSubscriber($this);
+
+ $manager = create_test_manager();
+ $session = $manager->startSession();
+
+ $bulk = new MongoDB\Driver\BulkWrite;
+ $bulk->insert(['x' => 1]);
+ $manager->executeBulkWrite(NS, $bulk, ['session' => $session]);
+
+ $query = new MongoDB\Driver\Query([]);
+ $manager->executeQuery(NS, $query, ['session' => $session]);
+
+ MongoDB\Driver\Monitoring\removeSubscriber($this);
+ }
+
+ public function commandStarted(MongoDB\Driver\Monitoring\CommandStartedEvent $event)
+ {
+ $command = $event->getCommand();
+ $hasAfterClusterTime = isset($command->readConcern->afterClusterTime);
+ printf("%s command includes afterClusterTime: %s\n", $event->getCommandName(), ($hasAfterClusterTime ? 'yes' : 'no'));
+
+ if ($hasAfterClusterTime && $this->lastSeenOperationTime !== null) {
+ printf("%s command uses last seen operationTime: %s\n", $event->getCommandName(), ($command->readConcern->afterClusterTime == $this->lastSeenOperationTime) ? 'yes' : 'no');
+ }
+ }
+
+ public function commandSucceeded(MongoDB\Driver\Monitoring\CommandSucceededEvent $event)
+ {
+ $reply = $event->getReply();
+ $hasOperationTime = isset($reply->operationTime);
+
+ printf("%s command reply includes operationTime: %s\n", $event->getCommandName(), $hasOperationTime ? 'yes' : 'no');
+
+ if ($hasOperationTime) {
+ $this->lastSeenOperationTime = $reply->operationTime;
+ }
+ }
+
+ public function commandFailed(MongoDB\Driver\Monitoring\CommandFailedEvent $event)
+ {
+ }
+}
+
+echo "Testing read after read\n";
+(new Test)->executeReadAfterRead();
+
+echo "\nTesting read after write\n";
+(new Test)->executeReadAfterWrite();
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+Testing read after read
+find command includes afterClusterTime: no
+find command reply includes operationTime: yes
+find command includes afterClusterTime: yes
+find command uses last seen operationTime: yes
+find command reply includes operationTime: yes
+
+Testing read after write
+insert command includes afterClusterTime: no
+insert command reply includes operationTime: yes
+find command includes afterClusterTime: yes
+find command uses last seen operationTime: yes
+find command reply includes operationTime: yes
+===DONE===
diff --git a/mongodb-1.13.0/tests/causal-consistency/causal-consistency-006.phpt b/mongodb-1.13.0/tests/causal-consistency/causal-consistency-006.phpt
new file mode 100644
index 00000000..e8470035
--- /dev/null
+++ b/mongodb-1.13.0/tests/causal-consistency/causal-consistency-006.phpt
@@ -0,0 +1,120 @@
+--TEST--
+Causal consistency: second read's afterClusterTime uses last reply's operationTime (even on error)
+--DESCRIPTION--
+Causal consistency spec prose test #4 and #5
+https://github.com/mongodb/specifications/blob/master/source/causal-consistency/causal-consistency.rst#test-plan
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_not_replica_set_or_sharded_cluster_with_replica_set(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+class Test implements MongoDB\Driver\Monitoring\CommandSubscriber
+{
+ private $lastSeenOperationTime;
+
+ public function executeReadAfterReadError()
+ {
+ $this->lastSeenOperationTime = null;
+
+ MongoDB\Driver\Monitoring\addSubscriber($this);
+
+ $manager = create_test_manager();
+ $session = $manager->startSession();
+
+ $query = new MongoDB\Driver\Query(['$unsupportedOperator' => 1]);
+
+ throws(function() use ($manager, $query, $session) {
+ $manager->executeQuery(NS, $query, ['session' => $session]);
+ }, 'MongoDB\Driver\Exception\RuntimeException');
+
+ /* We cannot access the server reply if an exception is thrown for a
+ * failed command (see: PHPC-1076). For the time being, just assert that
+ * the operationTime is not null. */
+ printf("Session has non-null operationTime: %s\n", ($session->getOperationTime() !== null ? 'yes' : 'no'));
+
+ $query = new MongoDB\Driver\Query([]);
+ $manager->executeQuery(NS, $query, ['session' => $session]);
+
+ MongoDB\Driver\Monitoring\removeSubscriber($this);
+ }
+
+ public function executeReadAfterWriteError()
+ {
+ $this->lastSeenOperationTime = null;
+
+ MongoDB\Driver\Monitoring\addSubscriber($this);
+
+ $manager = create_test_manager();
+ $session = $manager->startSession();
+
+ $bulk = new MongoDB\Driver\BulkWrite;
+ $bulk->insert(['_id' => 1]);
+ $bulk->insert(['_id' => 1]);
+
+ throws(function() use ($manager, $bulk, $session) {
+ $manager->executeBulkWrite(NS, $bulk, ['session' => $session]);
+ }, 'MongoDB\Driver\Exception\BulkWriteException');
+
+ $query = new MongoDB\Driver\Query([]);
+ $manager->executeQuery(NS, $query, ['session' => $session]);
+
+ MongoDB\Driver\Monitoring\removeSubscriber($this);
+ }
+
+ public function commandStarted(MongoDB\Driver\Monitoring\CommandStartedEvent $event)
+ {
+ $command = $event->getCommand();
+ $hasAfterClusterTime = isset($command->readConcern->afterClusterTime);
+ printf("%s command includes afterClusterTime: %s\n", $event->getCommandName(), ($hasAfterClusterTime ? 'yes' : 'no'));
+
+ if ($hasAfterClusterTime && $this->lastSeenOperationTime !== null) {
+ printf("%s command uses last seen operationTime: %s\n", $event->getCommandName(), ($command->readConcern->afterClusterTime == $this->lastSeenOperationTime) ? 'yes' : 'no');
+ }
+ }
+
+ public function commandSucceeded(MongoDB\Driver\Monitoring\CommandSucceededEvent $event)
+ {
+ $reply = $event->getReply();
+ $hasOperationTime = isset($reply->operationTime);
+
+ printf("%s command reply includes operationTime: %s\n", $event->getCommandName(), $hasOperationTime ? 'yes' : 'no');
+
+ if ($hasOperationTime) {
+ $this->lastSeenOperationTime = $reply->operationTime;
+ }
+ }
+
+ public function commandFailed(MongoDB\Driver\Monitoring\CommandFailedEvent $event)
+ {
+ }
+}
+
+echo "\nTesting read after read error\n";
+(new Test)->executeReadAfterReadError();
+
+echo "\nTesting read after write error\n";
+(new Test)->executeReadAfterWriteError();
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+Testing read after read error
+find command includes afterClusterTime: no
+OK: Got MongoDB\Driver\Exception\RuntimeException
+Session has non-null operationTime: yes
+find command includes afterClusterTime: yes
+find command reply includes operationTime: yes
+
+Testing read after write error
+insert command includes afterClusterTime: no
+insert command reply includes operationTime: yes
+OK: Got MongoDB\Driver\Exception\BulkWriteException
+find command includes afterClusterTime: yes
+find command uses last seen operationTime: yes
+find command reply includes operationTime: yes
+===DONE===
diff --git a/mongodb-1.13.0/tests/causal-consistency/causal-consistency-007.phpt b/mongodb-1.13.0/tests/causal-consistency/causal-consistency-007.phpt
new file mode 100644
index 00000000..e2a45a34
--- /dev/null
+++ b/mongodb-1.13.0/tests/causal-consistency/causal-consistency-007.phpt
@@ -0,0 +1,37 @@
+--TEST--
+Causal consistency: reads in non-causally consistent session never include afterClusterTime
+--DESCRIPTION--
+Causal consistency spec prose test #6
+https://github.com/mongodb/specifications/blob/master/source/causal-consistency/causal-consistency.rst#test-plan
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_not_replica_set_or_sharded_cluster_with_replica_set(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+require_once __DIR__ . "/../utils/observer.php";
+
+(new CommandObserver)->observe(
+ function() {
+ $manager = create_test_manager();
+ $session = $manager->startSession(['causalConsistency' => false]);
+
+ $query = new MongoDB\Driver\Query([]);
+ $manager->executeQuery(NS, $query, ['session' => $session]);
+ $manager->executeQuery(NS, $query, ['session' => $session]);
+ },
+ function(stdClass $command)
+ {
+ $hasAfterClusterTime = isset($command->readConcern->afterClusterTime);
+ printf("Read includes afterClusterTime: %s\n", ($hasAfterClusterTime ? 'yes' : 'no'));
+ }
+);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+Read includes afterClusterTime: no
+Read includes afterClusterTime: no
+===DONE===
diff --git a/mongodb-1.13.0/tests/causal-consistency/causal-consistency-008.phpt b/mongodb-1.13.0/tests/causal-consistency/causal-consistency-008.phpt
new file mode 100644
index 00000000..f9e9a5a8
--- /dev/null
+++ b/mongodb-1.13.0/tests/causal-consistency/causal-consistency-008.phpt
@@ -0,0 +1,37 @@
+--TEST--
+Causal consistency: reads in causally consistent session never include afterClusterTime for unsupported deployment
+--DESCRIPTION--
+Causal consistency spec prose test #7
+https://github.com/mongodb/specifications/blob/master/source/causal-consistency/causal-consistency.rst#test-plan
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_not_standalone(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+require_once __DIR__ . "/../utils/observer.php";
+
+(new CommandObserver)->observe(
+ function() {
+ $manager = create_test_manager();
+ $session = $manager->startSession(['causalConsistency' => true]);
+
+ $query = new MongoDB\Driver\Query([]);
+ $manager->executeQuery(NS, $query, ['session' => $session]);
+ $manager->executeQuery(NS, $query, ['session' => $session]);
+ },
+ function(stdClass $command)
+ {
+ $hasAfterClusterTime = isset($command->readConcern->afterClusterTime);
+ printf("Read includes afterClusterTime: %s\n", ($hasAfterClusterTime ? 'yes' : 'no'));
+ }
+);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+Read includes afterClusterTime: no
+Read includes afterClusterTime: no
+===DONE===
diff --git a/mongodb-1.13.0/tests/causal-consistency/causal-consistency-009.phpt b/mongodb-1.13.0/tests/causal-consistency/causal-consistency-009.phpt
new file mode 100644
index 00000000..94496886
--- /dev/null
+++ b/mongodb-1.13.0/tests/causal-consistency/causal-consistency-009.phpt
@@ -0,0 +1,42 @@
+--TEST--
+Causal consistency: default read concern includes afterClusterTime but not level
+--DESCRIPTION--
+Causal consistency spec prose test #8
+https://github.com/mongodb/specifications/blob/master/source/causal-consistency/causal-consistency.rst#test-plan
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_not_replica_set_or_sharded_cluster_with_replica_set(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+require_once __DIR__ . "/../utils/observer.php";
+
+(new CommandObserver)->observe(
+ function() {
+ $manager = create_test_manager();
+ $session = $manager->startSession();
+
+ $query = new MongoDB\Driver\Query([]);
+ $manager->executeQuery(NS, $query, ['session' => $session]);
+ $manager->executeQuery(NS, $query, ['session' => $session]);
+ },
+ function(stdClass $command)
+ {
+ $hasAfterClusterTime = isset($command->readConcern->afterClusterTime);
+ printf("Read concern includes afterClusterTime: %s\n", ($hasAfterClusterTime ? 'yes' : 'no'));
+
+ $hasLevel = isset($command->readConcern->level);
+ printf("Read concern includes level: %s\n", ($hasLevel ? 'yes' : 'no'));
+ }
+);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+Read concern includes afterClusterTime: no
+Read concern includes level: no
+Read concern includes afterClusterTime: yes
+Read concern includes level: no
+===DONE===
diff --git a/mongodb-1.13.0/tests/causal-consistency/causal-consistency-010.phpt b/mongodb-1.13.0/tests/causal-consistency/causal-consistency-010.phpt
new file mode 100644
index 00000000..d64c9872
--- /dev/null
+++ b/mongodb-1.13.0/tests/causal-consistency/causal-consistency-010.phpt
@@ -0,0 +1,43 @@
+--TEST--
+Causal consistency: custom read concern merges afterClusterTime and level
+--DESCRIPTION--
+Causal consistency spec prose test #9
+https://github.com/mongodb/specifications/blob/master/source/causal-consistency/causal-consistency.rst#test-plan
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_not_replica_set_or_sharded_cluster_with_replica_set(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+require_once __DIR__ . "/../utils/observer.php";
+
+(new CommandObserver)->observe(
+ function() {
+ $manager = create_test_manager();
+ $session = $manager->startSession();
+
+ $readConcern = new MongoDB\Driver\ReadConcern(MongoDB\Driver\ReadConcern::MAJORITY);
+ $query = new MongoDB\Driver\Query([], ['readConcern' => $readConcern]);
+ $manager->executeQuery(NS, $query, ['session' => $session]);
+ $manager->executeQuery(NS, $query, ['session' => $session]);
+ },
+ function(stdClass $command)
+ {
+ $hasAfterClusterTime = isset($command->readConcern->afterClusterTime);
+ printf("Read concern includes afterClusterTime: %s\n", ($hasAfterClusterTime ? 'yes' : 'no'));
+
+ $hasLevel = isset($command->readConcern->level);
+ printf("Read concern includes level: %s\n", ($hasLevel ? 'yes' : 'no'));
+ }
+);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+Read concern includes afterClusterTime: no
+Read concern includes level: yes
+Read concern includes afterClusterTime: yes
+Read concern includes level: yes
+===DONE===
diff --git a/mongodb-1.13.0/tests/causal-consistency/causal-consistency-011.phpt b/mongodb-1.13.0/tests/causal-consistency/causal-consistency-011.phpt
new file mode 100644
index 00000000..13cc68b8
--- /dev/null
+++ b/mongodb-1.13.0/tests/causal-consistency/causal-consistency-011.phpt
@@ -0,0 +1,38 @@
+--TEST--
+Causal consistency: $clusterTime is not sent in commands to unsupported deployments
+--DESCRIPTION--
+Causal consistency spec prose test #11
+https://github.com/mongodb/specifications/blob/master/source/causal-consistency/causal-consistency.rst#test-plan
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_not_live(); ?>
+<?php skip_if_not_standalone(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+require_once __DIR__ . "/../utils/observer.php";
+
+(new CommandObserver)->observe(
+ function() {
+ $manager = create_test_manager();
+ $session = $manager->startSession();
+
+ $query = new MongoDB\Driver\Query([]);
+ $manager->executeQuery(NS, $query, ['session' => $session]);
+ $manager->executeQuery(NS, $query, ['session' => $session]);
+ },
+ function(stdClass $command)
+ {
+ $hasClusterTime = isset($command->{'$clusterTime'});
+ printf("Command includes \$clusterTime: %s\n", ($hasClusterTime ? 'yes' : 'no'));
+ }
+);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+Command includes $clusterTime: no
+Command includes $clusterTime: no
+===DONE===
diff --git a/mongodb-1.13.0/tests/causal-consistency/causal-consistency-012.phpt b/mongodb-1.13.0/tests/causal-consistency/causal-consistency-012.phpt
new file mode 100644
index 00000000..738cc6e8
--- /dev/null
+++ b/mongodb-1.13.0/tests/causal-consistency/causal-consistency-012.phpt
@@ -0,0 +1,38 @@
+--TEST--
+Causal consistency: $clusterTime is sent in commands to supported deployments
+--DESCRIPTION--
+Causal consistency spec prose test #12
+https://github.com/mongodb/specifications/blob/master/source/causal-consistency/causal-consistency.rst#test-plan
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_load_balanced(); /* TODO: CDRIVER-4174 */ ?>
+<?php skip_if_not_replica_set_or_sharded_cluster_with_replica_set(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+require_once __DIR__ . "/../utils/observer.php";
+
+(new CommandObserver)->observe(
+ function() {
+ $manager = create_test_manager();
+ $session = $manager->startSession();
+
+ $query = new MongoDB\Driver\Query([]);
+ $manager->executeQuery(NS, $query, ['session' => $session]);
+ $manager->executeQuery(NS, $query, ['session' => $session]);
+ },
+ function(stdClass $command)
+ {
+ $hasClusterTime = isset($command->{'$clusterTime'});
+ printf("Command includes \$clusterTime: %s\n", ($hasClusterTime ? 'yes' : 'no'));
+ }
+);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+Command includes $clusterTime: yes
+Command includes $clusterTime: yes
+===DONE===
diff --git a/mongodb-1.12.0/tests/clientEncryption/clientEncryption-constants.phpt b/mongodb-1.13.0/tests/clientEncryption/clientEncryption-constants.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/clientEncryption/clientEncryption-constants.phpt
rename to mongodb-1.13.0/tests/clientEncryption/clientEncryption-constants.phpt
diff --git a/mongodb-1.12.0/tests/clientEncryption/clientEncryption-createDataKey-001.phpt b/mongodb-1.13.0/tests/clientEncryption/clientEncryption-createDataKey-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/clientEncryption/clientEncryption-createDataKey-001.phpt
rename to mongodb-1.13.0/tests/clientEncryption/clientEncryption-createDataKey-001.phpt
diff --git a/mongodb-1.12.0/tests/clientEncryption/clientEncryption-createDataKey_error-001.phpt b/mongodb-1.13.0/tests/clientEncryption/clientEncryption-createDataKey_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/clientEncryption/clientEncryption-createDataKey_error-001.phpt
rename to mongodb-1.13.0/tests/clientEncryption/clientEncryption-createDataKey_error-001.phpt
diff --git a/mongodb-1.13.0/tests/clientEncryption/clientEncryption-decrypt-001.phpt b/mongodb-1.13.0/tests/clientEncryption/clientEncryption-decrypt-001.phpt
new file mode 100644
index 00000000..c76971b6
--- /dev/null
+++ b/mongodb-1.13.0/tests/clientEncryption/clientEncryption-decrypt-001.phpt
@@ -0,0 +1,27 @@
+--TEST--
+MongoDB\Driver\ClientEncryption::decrypt()
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongocrypt(); ?>
+<?php skip_if_not_live(); ?>
+<?php skip_if_not_server_storage_engine('wiredTiger'); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$key = base64_decode('Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk');
+
+$manager = create_test_manager();
+$clientEncryption = $manager->createClientEncryption(['keyVaultNamespace' => 'default.keys', 'kmsProviders' => ['local' => ['key' => new MongoDB\BSON\Binary($key, 0)]]]);
+
+$key = $clientEncryption->createDataKey('local');
+
+$encrypted = $clientEncryption->encrypt('top-secret', ['keyId' => $key, 'algorithm' => MongoDB\Driver\ClientEncryption::AEAD_AES_256_CBC_HMAC_SHA_512_DETERMINISTIC]);
+var_dump($clientEncryption->decrypt($encrypted));
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+string(10) "top-secret"
+===DONE===
diff --git a/mongodb-1.13.0/tests/clientEncryption/clientEncryption-encrypt-001.phpt b/mongodb-1.13.0/tests/clientEncryption/clientEncryption-encrypt-001.phpt
new file mode 100644
index 00000000..9dd1922f
--- /dev/null
+++ b/mongodb-1.13.0/tests/clientEncryption/clientEncryption-encrypt-001.phpt
@@ -0,0 +1,31 @@
+--TEST--
+MongoDB\Driver\ClientEncryption::encrypt()
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongocrypt(); ?>
+<?php skip_if_not_live(); ?>
+<?php skip_if_not_server_storage_engine('wiredTiger'); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$key = base64_decode('Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk');
+
+$manager = create_test_manager();
+$clientEncryption = $manager->createClientEncryption(['keyVaultNamespace' => 'default.keys', 'kmsProviders' => ['local' => ['key' => new MongoDB\BSON\Binary($key, 0)]]]);
+
+$key = $clientEncryption->createDataKey('local');
+
+var_dump($clientEncryption->encrypt('top-secret', ['keyId' => $key, 'algorithm' => MongoDB\Driver\ClientEncryption::AEAD_AES_256_CBC_HMAC_SHA_512_DETERMINISTIC]));
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+object(MongoDB\BSON\Binary)#%d (%d) {
+ ["data"]=>
+ string(82) "%a"
+ ["type"]=>
+ int(6)
+}
+===DONE===
diff --git a/mongodb-1.12.0/tests/command/command-ctor-001.phpt b/mongodb-1.13.0/tests/command/command-ctor-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/command/command-ctor-001.phpt
rename to mongodb-1.13.0/tests/command/command-ctor-001.phpt
diff --git a/mongodb-1.12.0/tests/command/command_error-001.phpt b/mongodb-1.13.0/tests/command/command_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/command/command_error-001.phpt
rename to mongodb-1.13.0/tests/command/command_error-001.phpt
diff --git a/mongodb-1.12.0/tests/command/cursor-batchsize-001.phpt b/mongodb-1.13.0/tests/command/cursor-batchsize-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/command/cursor-batchsize-001.phpt
rename to mongodb-1.13.0/tests/command/cursor-batchsize-001.phpt
diff --git a/mongodb-1.12.0/tests/command/cursor-batchsize-002.phpt b/mongodb-1.13.0/tests/command/cursor-batchsize-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/command/cursor-batchsize-002.phpt
rename to mongodb-1.13.0/tests/command/cursor-batchsize-002.phpt
diff --git a/mongodb-1.13.0/tests/command/cursor-tailable-001.phpt b/mongodb-1.13.0/tests/command/cursor-tailable-001.phpt
new file mode 100644
index 00000000..85864521
--- /dev/null
+++ b/mongodb-1.13.0/tests/command/cursor-tailable-001.phpt
@@ -0,0 +1,71 @@
+--TEST--
+MongoDB\Driver\Command tailable cursor iteration with maxAwaitTimeMS option
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_replica_set(); ?>
+<?php skip_if_not_server_storage_engine('wiredTiger'); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+$manager = create_test_manager();
+
+$manager->executeCommand(DATABASE_NAME, new MongoDB\Driver\Command([
+ 'create' => COLLECTION_NAME,
+ 'capped' => true,
+ 'size' => 1048576,
+]));
+
+$bulkWrite = new MongoDB\Driver\BulkWrite;
+$bulkWrite->insert(['_id' => 1]);
+$manager->executeBulkWrite(NS, $bulkWrite);
+
+$pipeline = [
+ [ '$changeStream' => [ 'fullDocument' => 'updateLookup' ] ]
+];
+
+$command = new MongoDB\Driver\Command([
+ 'aggregate' => COLLECTION_NAME,
+ 'pipeline' => $pipeline,
+ 'cursor' => ['batchSize' => 0],
+], [
+ 'maxAwaitTimeMS' => 500,
+]);
+
+$cursor = $manager->executeCommand(DATABASE_NAME, $command);
+$it = new IteratorIterator($cursor);
+
+$it->rewind();
+$it->next();
+
+$bulkWrite = new MongoDB\Driver\BulkWrite;
+$bulkWrite->insert(['_id' => "new-document"]);
+$manager->executeBulkWrite(NS, $bulkWrite);
+
+$startTime = microtime(true);
+echo "Awaiting results...\n";
+$it->next();
+var_dump($it->current()->operationType, $it->current()->documentKey);
+printf("Waited for %.6f seconds\n", microtime(true) - $startTime);
+
+$startTime = microtime(true);
+echo "Awaiting results...\n";
+$it->next();
+var_dump($it->current()); /* Should be NULL */
+printf("Waited for %.6f seconds\n", microtime(true) - $startTime);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Awaiting results...
+string(6) "insert"
+object(stdClass)#%d (%d) {
+ ["_id"]=>
+ string(12) "new-document"
+}
+Waited for 0.%d seconds
+Awaiting results...
+NULL
+Waited for 0.%r(4|5)\d*%r seconds
+===DONE===
diff --git a/mongodb-1.13.0/tests/command/findAndModify-001.phpt b/mongodb-1.13.0/tests/command/findAndModify-001.phpt
new file mode 100644
index 00000000..e0b19b7b
--- /dev/null
+++ b/mongodb-1.13.0/tests/command/findAndModify-001.phpt
@@ -0,0 +1,83 @@
+--TEST--
+MongoDB\Driver\Command with findAndModify and arrayFilters
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_live(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+
+$bulk = new MongoDB\Driver\BulkWrite();
+
+$bulk->insert([ '_id' => 1, 'grades' => [ 95, 92, 90 ] ]);
+$bulk->insert([ '_id' => 2, 'grades' => [ 98, 100, 102 ] ]);
+$bulk->insert([ '_id' => 3, 'grades' => [ 95, 110, 100 ] ]);
+
+$manager->executeBulkWrite(DATABASE_NAME . '.' . COLLECTION_NAME, $bulk);
+
+$command = new MongoDB\Driver\Command([
+ 'findAndModify' => COLLECTION_NAME,
+ 'query' => ['grades' => [ '$gt' => 100 ] ],
+ 'update' => ['$set' => [ 'grades.$[element]' => 100 ] ],
+ 'arrayFilters' => [ [ 'element' => [ '$gt' => 100 ] ] ],
+]);
+
+// Running this twice, because findAndModify only updates the first document
+// it finds.
+$manager->executeCommand(DATABASE_NAME, $command);
+$manager->executeCommand(DATABASE_NAME, $command);
+
+$cursor = $manager->executeQuery( DATABASE_NAME . '.' . COLLECTION_NAME, new \MongoDB\Driver\Query([]));
+var_dump($cursor->toArray());
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+array(%d) {
+ [0]=>
+ object(stdClass)#%d (%d) {
+ ["_id"]=>
+ int(1)
+ ["grades"]=>
+ array(%d) {
+ [0]=>
+ int(95)
+ [1]=>
+ int(92)
+ [2]=>
+ int(90)
+ }
+ }
+ [1]=>
+ object(stdClass)#%d (%d) {
+ ["_id"]=>
+ int(2)
+ ["grades"]=>
+ array(%d) {
+ [0]=>
+ int(98)
+ [1]=>
+ int(100)
+ [2]=>
+ int(100)
+ }
+ }
+ [2]=>
+ object(stdClass)#%d (%d) {
+ ["_id"]=>
+ int(3)
+ ["grades"]=>
+ array(%d) {
+ [0]=>
+ int(95)
+ [1]=>
+ int(100)
+ [2]=>
+ int(100)
+ }
+ }
+}
+===DONE===
diff --git a/mongodb-1.13.0/tests/command/update-001.phpt b/mongodb-1.13.0/tests/command/update-001.phpt
new file mode 100644
index 00000000..acb6adc8
--- /dev/null
+++ b/mongodb-1.13.0/tests/command/update-001.phpt
@@ -0,0 +1,83 @@
+--TEST--
+MongoDB\Driver\Command with update and arrayFilters
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_live(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+
+$bulk = new MongoDB\Driver\BulkWrite();
+
+$bulk->insert([ '_id' => 1, 'grades' => [ 95, 92, 90 ] ]);
+$bulk->insert([ '_id' => 2, 'grades' => [ 98, 100, 102 ] ]);
+$bulk->insert([ '_id' => 3, 'grades' => [ 95, 110, 100 ] ]);
+
+$manager->executeBulkWrite(DATABASE_NAME . '.' . COLLECTION_NAME, $bulk);
+
+$command = new MongoDB\Driver\Command([
+ 'update' => COLLECTION_NAME,
+ 'updates' => [[
+ 'q' => [ 'grades' => [ '$gte' => 100 ] ],
+ 'u' => [ '$set' => [ 'grades.$[element]' => 100 ] ],
+ 'arrayFilters' => [ [ 'element' => [ '$gte' => 100 ] ] ],
+ 'multi' => true
+ ]],
+]);
+
+$manager->executeCommand(DATABASE_NAME, $command);
+
+$cursor = $manager->executeQuery( DATABASE_NAME . '.' . COLLECTION_NAME, new \MongoDB\Driver\Query([]));
+var_dump($cursor->toArray());
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+array(%d) {
+ [0]=>
+ object(stdClass)#%d (%d) {
+ ["_id"]=>
+ int(1)
+ ["grades"]=>
+ array(%d) {
+ [0]=>
+ int(95)
+ [1]=>
+ int(92)
+ [2]=>
+ int(90)
+ }
+ }
+ [1]=>
+ object(stdClass)#%d (%d) {
+ ["_id"]=>
+ int(2)
+ ["grades"]=>
+ array(%d) {
+ [0]=>
+ int(98)
+ [1]=>
+ int(100)
+ [2]=>
+ int(100)
+ }
+ }
+ [2]=>
+ object(stdClass)#%d (%d) {
+ ["_id"]=>
+ int(3)
+ ["grades"]=>
+ array(%d) {
+ [0]=>
+ int(95)
+ [1]=>
+ int(100)
+ [2]=>
+ int(100)
+ }
+ }
+}
+===DONE===
diff --git a/mongodb-1.13.0/tests/connect/bug0720.phpt b/mongodb-1.13.0/tests/connect/bug0720.phpt
new file mode 100644
index 00000000..95a2ab57
--- /dev/null
+++ b/mongodb-1.13.0/tests/connect/bug0720.phpt
@@ -0,0 +1,38 @@
+--TEST--
+PHPC-720: Do not persist SSL streams to avoid SSL reinitialization errors
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_ssl(); ?>
+<?php skip_if_not_ssl(); ?>
+<?php skip_if_no_ssl_dir(); ?>
+<?php skip_if_not_live(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$driverOptions = [
+ // libmongoc does not allow the hostname to be overridden as "server"
+ 'allow_invalid_hostname' => true,
+ 'ca_file' => SSL_DIR . '/ca.pem',
+];
+
+$manager = create_test_manager(URI, [], $driverOptions);
+$cursor = $manager->executeCommand(DATABASE_NAME, new MongoDB\Driver\Command(['ping' => 1]));
+printf("ping: %d\n", $cursor->toArray()[0]->ok);
+
+unset($manager, $cursor);
+
+$manager = create_test_manager(URI, [], $driverOptions);
+$cursor = $manager->executeCommand(DATABASE_NAME, new MongoDB\Driver\Command(['ping' => 1]));
+printf("ping: %d\n", $cursor->toArray()[0]->ok);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Deprecated: MongoDB\Driver\Manager::__construct(): The "allow_invalid_hostname" driver option is deprecated. Please use the "tlsAllowInvalidHostnames" URI option instead.%s
+
+Deprecated: MongoDB\Driver\Manager::__construct(): The "ca_file" driver option is deprecated. Please use the "tlsCAFile" URI option instead.%s
+ping: 1
+ping: 1
+===DONE===
diff --git a/mongodb-1.12.0/tests/connect/bug1015.phpt b/mongodb-1.13.0/tests/connect/bug1015.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/connect/bug1015.phpt
rename to mongodb-1.13.0/tests/connect/bug1015.phpt
diff --git a/mongodb-1.13.0/tests/connect/bug1045.phpt b/mongodb-1.13.0/tests/connect/bug1045.phpt
new file mode 100644
index 00000000..102386ba
--- /dev/null
+++ b/mongodb-1.13.0/tests/connect/bug1045.phpt
@@ -0,0 +1,22 @@
+--TEST--
+PHPC-1045: Segfault if username is not provided for SCRAM-SHA-1 authMechanism
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+--FILE--
+<?php
+
+require_once __DIR__ . "/../utils/basic.inc";
+
+echo throws(function() {
+ // URI may or may not support auth, but that is not necessary for the test
+ create_test_manager('mongodb://127.0.0.1/', ['authMechanism' => 'SCRAM-SHA-1']);
+}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse URI options: 'SCRAM-SHA-1' authentication mechanism requires username
+===DONE===
diff --git a/mongodb-1.12.0/tests/connect/compression_error-001.phpt b/mongodb-1.13.0/tests/connect/compression_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/connect/compression_error-001.phpt
rename to mongodb-1.13.0/tests/connect/compression_error-001.phpt
diff --git a/mongodb-1.12.0/tests/connect/compression_error-002.phpt b/mongodb-1.13.0/tests/connect/compression_error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/connect/compression_error-002.phpt
rename to mongodb-1.13.0/tests/connect/compression_error-002.phpt
diff --git a/mongodb-1.12.0/tests/connect/replicaset-seedlist-001.phpt b/mongodb-1.13.0/tests/connect/replicaset-seedlist-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/connect/replicaset-seedlist-001.phpt
rename to mongodb-1.13.0/tests/connect/replicaset-seedlist-001.phpt
diff --git a/mongodb-1.12.0/tests/connect/replicaset-seedlist-002.phpt b/mongodb-1.13.0/tests/connect/replicaset-seedlist-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/connect/replicaset-seedlist-002.phpt
rename to mongodb-1.13.0/tests/connect/replicaset-seedlist-002.phpt
diff --git a/mongodb-1.12.0/tests/connect/standalone-auth-001.phpt b/mongodb-1.13.0/tests/connect/standalone-auth-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/connect/standalone-auth-001.phpt
rename to mongodb-1.13.0/tests/connect/standalone-auth-001.phpt
diff --git a/mongodb-1.12.0/tests/connect/standalone-auth_error-001.phpt b/mongodb-1.13.0/tests/connect/standalone-auth_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/connect/standalone-auth_error-001.phpt
rename to mongodb-1.13.0/tests/connect/standalone-auth_error-001.phpt
diff --git a/mongodb-1.12.0/tests/connect/standalone-plain-0001.phpt b/mongodb-1.13.0/tests/connect/standalone-plain-0001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/connect/standalone-plain-0001.phpt
rename to mongodb-1.13.0/tests/connect/standalone-plain-0001.phpt
diff --git a/mongodb-1.12.0/tests/connect/standalone-plain-0002.phpt b/mongodb-1.13.0/tests/connect/standalone-plain-0002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/connect/standalone-plain-0002.phpt
rename to mongodb-1.13.0/tests/connect/standalone-plain-0002.phpt
diff --git a/mongodb-1.13.0/tests/connect/standalone-ssl-no_verify-001.phpt b/mongodb-1.13.0/tests/connect/standalone-ssl-no_verify-001.phpt
new file mode 100644
index 00000000..f1d36502
--- /dev/null
+++ b/mongodb-1.13.0/tests/connect/standalone-ssl-no_verify-001.phpt
@@ -0,0 +1,29 @@
+--TEST--
+Connect to MongoDB with SSL and no host/cert verification (driver options)
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_ssl(); ?>
+<?php skip_if_not_ssl(); ?>
+<?php skip_if_not_live(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$driverOptions = [
+ 'allow_invalid_hostname' => true,
+ "weak_cert_validation" => true,
+];
+
+$manager = create_test_manager(URI, [], $driverOptions);
+$cursor = $manager->executeCommand(DATABASE_NAME, new MongoDB\Driver\Command(['ping' => 1]));
+printf("ping: %d\n", $cursor->toArray()[0]->ok);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Deprecated: MongoDB\Driver\Manager::__construct(): The "allow_invalid_hostname" driver option is deprecated. Please use the "tlsAllowInvalidHostnames" URI option instead.%s
+
+Deprecated: MongoDB\Driver\Manager::__construct(): The "weak_cert_validation" driver option is deprecated. Please use the "tlsAllowInvalidCertificates" URI option instead.%s
+ping: 1
+===DONE===
diff --git a/mongodb-1.13.0/tests/connect/standalone-ssl-no_verify-002.phpt b/mongodb-1.13.0/tests/connect/standalone-ssl-no_verify-002.phpt
new file mode 100644
index 00000000..3a09ff0e
--- /dev/null
+++ b/mongodb-1.13.0/tests/connect/standalone-ssl-no_verify-002.phpt
@@ -0,0 +1,35 @@
+--TEST--
+Connect to MongoDB with SSL and no host/cert verification (context options)
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_ssl(); ?>
+<?php skip_if_not_ssl(); ?>
+<?php skip_if_not_live(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$driverOptions = [
+ 'context' => stream_context_create([
+ 'ssl' => [
+ 'allow_invalid_hostname' => true,
+ 'allow_self_signed' => true, // "weak_cert_validation" alias
+ ],
+ ]),
+];
+
+$manager = create_test_manager(URI, [], $driverOptions);
+$cursor = $manager->executeCommand(DATABASE_NAME, new MongoDB\Driver\Command(['ping' => 1]));
+printf("ping: %d\n", $cursor->toArray()[0]->ok);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Deprecated: MongoDB\Driver\Manager::__construct(): The "context" driver option is deprecated.%s
+
+Deprecated: MongoDB\Driver\Manager::__construct(): The "allow_invalid_hostname" driver option is deprecated. Please use the "tlsAllowInvalidHostnames" URI option instead.%s
+
+Deprecated: MongoDB\Driver\Manager::__construct(): The "allow_self_signed" context driver option is deprecated. Please use the "tlsAllowInvalidCertificates" URI option instead.%s
+ping: 1
+===DONE===
diff --git a/mongodb-1.13.0/tests/connect/standalone-ssl-no_verify-003.phpt b/mongodb-1.13.0/tests/connect/standalone-ssl-no_verify-003.phpt
new file mode 100644
index 00000000..266590c7
--- /dev/null
+++ b/mongodb-1.13.0/tests/connect/standalone-ssl-no_verify-003.phpt
@@ -0,0 +1,26 @@
+--TEST--
+Connect to MongoDB with SSL and no host/cert verification (URI options)
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_ssl(); ?>
+<?php skip_if_not_ssl(); ?>
+<?php skip_if_not_live(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$uriOptions = [
+ 'tlsAllowInvalidHostnames' => true,
+ 'tlsAllowInvalidCertificates' => true,
+];
+
+$manager = create_test_manager(URI, $uriOptions);
+$cursor = $manager->executeCommand(DATABASE_NAME, new MongoDB\Driver\Command(['ping' => 1]));
+printf("ping: %d\n", $cursor->toArray()[0]->ok);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+ping: 1
+===DONE===
diff --git a/mongodb-1.13.0/tests/connect/standalone-ssl-verify_cert-001.phpt b/mongodb-1.13.0/tests/connect/standalone-ssl-verify_cert-001.phpt
new file mode 100644
index 00000000..39f6acd0
--- /dev/null
+++ b/mongodb-1.13.0/tests/connect/standalone-ssl-verify_cert-001.phpt
@@ -0,0 +1,34 @@
+--TEST--
+Connect to MongoDB with SSL and cert verification (driver options)
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_ssl(); ?>
+<?php skip_if_not_ssl(); ?>
+<?php skip_if_no_ssl_dir(); ?>
+<?php skip_if_not_live(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$driverOptions = [
+ // libmongoc does not allow the hostname to be overridden as "server"
+ 'allow_invalid_hostname' => true,
+ 'weak_cert_validation' => false,
+ 'ca_file' => SSL_DIR . '/ca.pem',
+];
+
+$manager = create_test_manager(URI, [], $driverOptions);
+$cursor = $manager->executeCommand(DATABASE_NAME, new MongoDB\Driver\Command(['ping' => 1]));
+printf("ping: %d\n", $cursor->toArray()[0]->ok);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Deprecated: MongoDB\Driver\Manager::__construct(): The "allow_invalid_hostname" driver option is deprecated. Please use the "tlsAllowInvalidHostnames" URI option instead.%s
+
+Deprecated: MongoDB\Driver\Manager::__construct(): The "weak_cert_validation" driver option is deprecated. Please use the "tlsAllowInvalidCertificates" URI option instead.%s
+
+Deprecated: MongoDB\Driver\Manager::__construct(): The "ca_file" driver option is deprecated. Please use the "tlsCAFile" URI option instead.%s
+ping: 1
+===DONE===
diff --git a/mongodb-1.13.0/tests/connect/standalone-ssl-verify_cert-002.phpt b/mongodb-1.13.0/tests/connect/standalone-ssl-verify_cert-002.phpt
new file mode 100644
index 00000000..18807921
--- /dev/null
+++ b/mongodb-1.13.0/tests/connect/standalone-ssl-verify_cert-002.phpt
@@ -0,0 +1,40 @@
+--TEST--
+Connect to MongoDB with SSL and cert verification (context options)
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_ssl(); ?>
+<?php skip_if_not_ssl(); ?>
+<?php skip_if_no_ssl_dir(); ?>
+<?php skip_if_not_live(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$driverOptions = [
+ 'context' => stream_context_create([
+ 'ssl' => [
+ // libmongoc does not allow the hostname to be overridden as "server"
+ 'allow_invalid_hostname' => true,
+ 'allow_self_signed' => false, // "weak_cert_validation" alias
+ 'cafile' => SSL_DIR . '/ca.pem', // "ca_file" alias
+ ],
+ ]),
+];
+
+$manager = create_test_manager(URI, [], $driverOptions);
+$cursor = $manager->executeCommand(DATABASE_NAME, new MongoDB\Driver\Command(['ping' => 1]));
+printf("ping: %d\n", $cursor->toArray()[0]->ok);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Deprecated: MongoDB\Driver\Manager::__construct(): The "context" driver option is deprecated.%s
+
+Deprecated: MongoDB\Driver\Manager::__construct(): The "allow_invalid_hostname" driver option is deprecated. Please use the "tlsAllowInvalidHostnames" URI option instead.%s
+
+Deprecated: MongoDB\Driver\Manager::__construct(): The "allow_self_signed" context driver option is deprecated. Please use the "tlsAllowInvalidCertificates" URI option instead.%s
+
+Deprecated: MongoDB\Driver\Manager::__construct(): The "cafile" context driver option is deprecated. Please use the "tlsCAFile" URI option instead.%s
+ping: 1
+===DONE===
diff --git a/mongodb-1.13.0/tests/connect/standalone-ssl-verify_cert-003.phpt b/mongodb-1.13.0/tests/connect/standalone-ssl-verify_cert-003.phpt
new file mode 100644
index 00000000..c66186a4
--- /dev/null
+++ b/mongodb-1.13.0/tests/connect/standalone-ssl-verify_cert-003.phpt
@@ -0,0 +1,29 @@
+--TEST--
+Connect to MongoDB with SSL and cert verification (URI options)
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_ssl(); ?>
+<?php skip_if_not_ssl(); ?>
+<?php skip_if_no_ssl_dir(); ?>
+<?php skip_if_not_live(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$uriOptions = [
+ // libmongoc does not allow the hostname to be overridden as "server"
+ 'tlsAllowInvalidHostnames' => true,
+ 'tlsAllowInvalidCertificates' => false,
+ 'tlsCAFile' => SSL_DIR . '/ca.pem',
+];
+
+$manager = create_test_manager(URI, $uriOptions);
+$cursor = $manager->executeCommand(DATABASE_NAME, new MongoDB\Driver\Command(['ping' => 1]));
+printf("ping: %d\n", $cursor->toArray()[0]->ok);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+ping: 1
+===DONE===
diff --git a/mongodb-1.13.0/tests/connect/standalone-ssl-verify_cert-error-001.phpt b/mongodb-1.13.0/tests/connect/standalone-ssl-verify_cert-error-001.phpt
new file mode 100644
index 00000000..ea43c76e
--- /dev/null
+++ b/mongodb-1.13.0/tests/connect/standalone-ssl-verify_cert-error-001.phpt
@@ -0,0 +1,32 @@
+--TEST--
+Connect to MongoDB with SSL and cert verification error (driver options)
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_ssl(); ?>
+<?php skip_if_not_ssl(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$driverOptions = [
+ // libmongoc does not allow the hostname to be overridden as "server"
+ 'allow_invalid_hostname' => true,
+ 'weak_cert_validation' => false,
+];
+
+echo throws(function() use ($driverOptions) {
+ $manager = create_test_manager(URI, [], $driverOptions);
+ $cursor = $manager->executeCommand(DATABASE_NAME, new MongoDB\Driver\Command(['ping' => 1]));
+ var_dump($cursor->toArray()[0]);
+}, MongoDB\Driver\Exception\ConnectionException::class, 'executeCommand'), "\n";
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Deprecated: MongoDB\Driver\Manager::__construct(): The "allow_invalid_hostname" driver option is deprecated. Please use the "tlsAllowInvalidHostnames" URI option instead.%s
+
+Deprecated: MongoDB\Driver\Manager::__construct(): The "weak_cert_validation" driver option is deprecated. Please use the "tlsAllowInvalidCertificates" URI option instead.%s
+OK: Got MongoDB\Driver\Exception\ConnectionException thrown from executeCommand
+%sTLS handshake failed%s
+===DONE===
diff --git a/mongodb-1.12.0/tests/connect/standalone-ssl-verify_cert-error-002.phpt b/mongodb-1.13.0/tests/connect/standalone-ssl-verify_cert-error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/connect/standalone-ssl-verify_cert-error-002.phpt
rename to mongodb-1.13.0/tests/connect/standalone-ssl-verify_cert-error-002.phpt
diff --git a/mongodb-1.13.0/tests/connect/standalone-ssl-verify_cert-error-003.phpt b/mongodb-1.13.0/tests/connect/standalone-ssl-verify_cert-error-003.phpt
new file mode 100644
index 00000000..7a51dfcb
--- /dev/null
+++ b/mongodb-1.13.0/tests/connect/standalone-ssl-verify_cert-error-003.phpt
@@ -0,0 +1,29 @@
+--TEST--
+Connect to MongoDB with SSL and cert verification error (URI options)
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_ssl(); ?>
+<?php skip_if_not_ssl(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$uriOptions = [
+ // libmongoc does not allow the hostname to be overridden as "server"
+ 'tlsAllowInvalidHostnames' => true,
+ 'tlsAllowInvalidCertificates' => false,
+];
+
+echo throws(function() use ($uriOptions) {
+ $manager = create_test_manager(URI, $uriOptions);
+ $cursor = $manager->executeCommand(DATABASE_NAME, new MongoDB\Driver\Command(['ping' => 1]));
+ var_dump($cursor->toArray()[0]);
+}, MongoDB\Driver\Exception\ConnectionException::class, 'executeCommand'), "\n";
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+OK: Got MongoDB\Driver\Exception\ConnectionException thrown from executeCommand
+%sTLS handshake failed%s
+===DONE===
diff --git a/mongodb-1.12.0/tests/connect/standalone-x509-auth-001.phpt b/mongodb-1.13.0/tests/connect/standalone-x509-auth-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/connect/standalone-x509-auth-001.phpt
rename to mongodb-1.13.0/tests/connect/standalone-x509-auth-001.phpt
diff --git a/mongodb-1.12.0/tests/connect/standalone-x509-auth-002.phpt b/mongodb-1.13.0/tests/connect/standalone-x509-auth-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/connect/standalone-x509-auth-002.phpt
rename to mongodb-1.13.0/tests/connect/standalone-x509-auth-002.phpt
diff --git a/mongodb-1.12.0/tests/connect/standalone-x509-error-0001.phpt b/mongodb-1.13.0/tests/connect/standalone-x509-error-0001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/connect/standalone-x509-error-0001.phpt
rename to mongodb-1.13.0/tests/connect/standalone-x509-error-0001.phpt
diff --git a/mongodb-1.12.0/tests/connect/standalone-x509-extract_username-001.phpt b/mongodb-1.13.0/tests/connect/standalone-x509-extract_username-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/connect/standalone-x509-extract_username-001.phpt
rename to mongodb-1.13.0/tests/connect/standalone-x509-extract_username-001.phpt
diff --git a/mongodb-1.12.0/tests/connect/standalone-x509-extract_username-002.phpt b/mongodb-1.13.0/tests/connect/standalone-x509-extract_username-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/connect/standalone-x509-extract_username-002.phpt
rename to mongodb-1.13.0/tests/connect/standalone-x509-extract_username-002.phpt
diff --git a/mongodb-1.12.0/tests/cursor/bug0671-001.phpt b/mongodb-1.13.0/tests/cursor/bug0671-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/cursor/bug0671-001.phpt
rename to mongodb-1.13.0/tests/cursor/bug0671-001.phpt
diff --git a/mongodb-1.12.0/tests/cursor/bug0732-001.phpt b/mongodb-1.13.0/tests/cursor/bug0732-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/cursor/bug0732-001.phpt
rename to mongodb-1.13.0/tests/cursor/bug0732-001.phpt
diff --git a/mongodb-1.12.0/tests/cursor/bug0849-001.phpt b/mongodb-1.13.0/tests/cursor/bug0849-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/cursor/bug0849-001.phpt
rename to mongodb-1.13.0/tests/cursor/bug0849-001.phpt
diff --git a/mongodb-1.12.0/tests/cursor/bug0924-001.phpt b/mongodb-1.13.0/tests/cursor/bug0924-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/cursor/bug0924-001.phpt
rename to mongodb-1.13.0/tests/cursor/bug0924-001.phpt
diff --git a/mongodb-1.12.0/tests/cursor/bug0924-002.phpt b/mongodb-1.13.0/tests/cursor/bug0924-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/cursor/bug0924-002.phpt
rename to mongodb-1.13.0/tests/cursor/bug0924-002.phpt
diff --git a/mongodb-1.13.0/tests/cursor/bug1050-001.phpt b/mongodb-1.13.0/tests/cursor/bug1050-001.phpt
new file mode 100644
index 00000000..b64efbbd
--- /dev/null
+++ b/mongodb-1.13.0/tests/cursor/bug1050-001.phpt
@@ -0,0 +1,109 @@
+--TEST--
+PHPC-1050: Command cursor should not invoke getMore at execution
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_replica_set(); ?>
+<?php skip_if_not_server_storage_engine('wiredTiger'); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+class CommandLogger implements MongoDB\Driver\Monitoring\CommandSubscriber
+{
+ public function commandStarted(MongoDB\Driver\Monitoring\CommandStartedEvent $event)
+ {
+ if ($event->getCommandName() !== 'aggregate' && $event->getCommandName() !== 'getMore') {
+ return;
+ }
+
+ printf("Executing command: %s\n", $event->getCommandName());
+ }
+
+ public function commandSucceeded(MongoDB\Driver\Monitoring\CommandSucceededEvent $event)
+ {
+ if ($event->getCommandName() !== 'aggregate' && $event->getCommandName() !== 'getMore') {
+ return;
+ }
+
+ printf("Executing command took %0.6f seconds\n", $event->getDurationMicros() / 1000000);
+ }
+
+ public function commandFailed(MongoDB\Driver\Monitoring\CommandFailedEvent $event)
+ {
+ }
+}
+
+$manager = create_test_manager();
+
+$cmd = new MongoDB\Driver\Command(
+ [
+ 'aggregate' => COLLECTION_NAME,
+ 'pipeline' => [
+ ['$changeStream' => (object) []],
+ ],
+ 'cursor' => (object) [],
+ ],
+ [
+ 'maxAwaitTimeMS' => 500,
+ ]
+);
+
+MongoDB\Driver\Monitoring\addSubscriber(new CommandLogger);
+
+$cursor = $manager->executeReadCommand(DATABASE_NAME, $cmd);
+
+$it = new IteratorIterator($cursor);
+
+printf("Current position is valid: %s\n\n", $it->valid() ? 'yes' : 'no');
+
+echo "Rewinding cursor\n";
+$it->rewind();
+
+printf("Current position is valid: %s\n\n", $it->valid() ? 'yes' : 'no');
+
+$bulk = new MongoDB\Driver\BulkWrite;
+$bulk->insert(['x' => 1]);
+$manager->executeBulkWrite(NS, $bulk);
+
+echo "Advancing cursor\n";
+$it->next();
+
+printf("Current position is valid: %s\n\n", $it->valid() ? 'yes' : 'no');
+
+$document = $it->current();
+
+if (isset($document)) {
+ printf("Operation type: %s\n", $document->operationType);
+ var_dump($document->fullDocument);
+}
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Executing command: aggregate
+Executing command took 0.%d seconds
+Current position is valid: no
+
+Rewinding cursor
+Executing command: getMore
+Executing command took 0.%r(4|5)%r%d seconds
+Current position is valid: no
+
+Advancing cursor
+Executing command: getMore
+Executing command took 0.%d seconds
+Current position is valid: yes
+
+Operation type: insert
+object(stdClass)#%d (%d) {
+ ["_id"]=>
+ object(MongoDB\BSON\ObjectId)#%d (%d) {
+ ["oid"]=>
+ string(24) "%x"
+ }
+ ["x"]=>
+ int(1)
+}
+===DONE===
diff --git a/mongodb-1.13.0/tests/cursor/bug1050-002.phpt b/mongodb-1.13.0/tests/cursor/bug1050-002.phpt
new file mode 100644
index 00000000..42c3bfe6
--- /dev/null
+++ b/mongodb-1.13.0/tests/cursor/bug1050-002.phpt
@@ -0,0 +1,117 @@
+--TEST--
+PHPC-1050: Command cursor should not invoke getMore at execution (rewind omitted)
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_php_version('>', '7.99'); ?>
+<?php skip_if_not_replica_set(); ?>
+<?php skip_if_not_server_storage_engine('wiredTiger'); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+/* Note: this test is skipped on PHP 8 because the InternalIterator class
+ * returned by Cursor::getIterator() has logic to ensure rewind() is always
+ * called. That causes and additional getMore to be observed when starting
+ * iteration with next(), since rewind() and next() both trigger a getMore.
+ * We may be able to resume running this test on PHP 8 if Cursor implements
+ * Iterator directly and allow rewind() to be optional (see: PHPC-1691). */
+
+class CommandLogger implements MongoDB\Driver\Monitoring\CommandSubscriber
+{
+ public function commandStarted(MongoDB\Driver\Monitoring\CommandStartedEvent $event)
+ {
+ if ($event->getCommandName() !== 'aggregate' && $event->getCommandName() !== 'getMore') {
+ return;
+ }
+
+ printf("Executing command: %s\n", $event->getCommandName());
+ }
+
+ public function commandSucceeded(MongoDB\Driver\Monitoring\CommandSucceededEvent $event)
+ {
+ if ($event->getCommandName() !== 'aggregate' && $event->getCommandName() !== 'getMore') {
+ return;
+ }
+
+ printf("Executing command took %0.6f seconds\n", $event->getDurationMicros() / 1000000);
+ }
+
+ public function commandFailed(MongoDB\Driver\Monitoring\CommandFailedEvent $event)
+ {
+ }
+}
+
+$manager = create_test_manager();
+
+$cmd = new MongoDB\Driver\Command(
+ [
+ 'aggregate' => COLLECTION_NAME,
+ 'pipeline' => [
+ ['$changeStream' => (object) []],
+ ],
+ 'cursor' => (object) [],
+ ],
+ [
+ 'maxAwaitTimeMS' => 500,
+ ]
+);
+
+MongoDB\Driver\Monitoring\addSubscriber(new CommandLogger);
+
+$cursor = $manager->executeReadCommand(DATABASE_NAME, $cmd);
+
+$it = new IteratorIterator($cursor);
+
+printf("Current position is valid: %s\n\n", $it->valid() ? 'yes' : 'no');
+
+echo "Advancing cursor\n";
+$it->next();
+
+printf("Current position is valid: %s\n\n", $it->valid() ? 'yes' : 'no');
+
+$bulk = new MongoDB\Driver\BulkWrite;
+$bulk->insert(['x' => 1]);
+$manager->executeBulkWrite(NS, $bulk);
+
+echo "Advancing cursor\n";
+$it->next();
+
+printf("Current position is valid: %s\n\n", $it->valid() ? 'yes' : 'no');
+
+$document = $it->current();
+
+if (isset($document)) {
+ printf("Operation type: %s\n", $document->operationType);
+ var_dump($document->fullDocument);
+}
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Executing command: aggregate
+Executing command took 0.%d seconds
+Current position is valid: no
+
+Advancing cursor
+Executing command: getMore
+Executing command took 0.%r(4|5)%r%d seconds
+Current position is valid: no
+
+Advancing cursor
+Executing command: getMore
+Executing command took 0.%d seconds
+Current position is valid: yes
+
+Operation type: insert
+object(stdClass)#%d (%d) {
+ ["_id"]=>
+ object(MongoDB\BSON\ObjectId)#%d (%d) {
+ ["oid"]=>
+ string(24) "%x"
+ }
+ ["x"]=>
+ int(1)
+}
+===DONE===
diff --git a/mongodb-1.13.0/tests/cursor/bug1151-001.phpt b/mongodb-1.13.0/tests/cursor/bug1151-001.phpt
new file mode 100644
index 00000000..296d5179
--- /dev/null
+++ b/mongodb-1.13.0/tests/cursor/bug1151-001.phpt
@@ -0,0 +1,37 @@
+--TEST--
+PHPC-1151: Segfault if session unset before first getMore (find)
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_not_live(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+
+$bulk = new MongoDB\Driver\BulkWrite;
+$bulk->insert(['_id' => 1]);
+$bulk->insert(['_id' => 2]);
+$bulk->insert(['_id' => 3]);
+$manager->executeBulkWrite(NS, $bulk);
+
+$query = new MongoDB\Driver\Query([], ['batchSize' => 2]);
+$session = $manager->startSession();
+
+$cursor = $manager->executeQuery(NS, $query, ['session' => $session]);
+
+foreach ($cursor as $document) {
+ unset($session);
+ echo $document->_id, "\n";
+}
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+1
+2
+3
+===DONE===
diff --git a/mongodb-1.13.0/tests/cursor/bug1151-002.phpt b/mongodb-1.13.0/tests/cursor/bug1151-002.phpt
new file mode 100644
index 00000000..bd201752
--- /dev/null
+++ b/mongodb-1.13.0/tests/cursor/bug1151-002.phpt
@@ -0,0 +1,41 @@
+--TEST--
+PHPC-1151: Segfault if session unset before first getMore (aggregate)
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_not_live(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+
+$bulk = new MongoDB\Driver\BulkWrite;
+$bulk->insert(['_id' => 1]);
+$bulk->insert(['_id' => 2]);
+$bulk->insert(['_id' => 3]);
+$manager->executeBulkWrite(NS, $bulk);
+
+$command = new MongoDB\Driver\Command([
+ 'aggregate' => COLLECTION_NAME,
+ 'pipeline' => [],
+ 'cursor' => ['batchSize' => 2],
+]);
+$session = $manager->startSession();
+
+$cursor = $manager->executeReadCommand(DATABASE_NAME, $command, ['session' => $session]);
+
+foreach ($cursor as $document) {
+ unset($session);
+ echo $document->_id, "\n";
+}
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+1
+2
+3
+===DONE===
diff --git a/mongodb-1.13.0/tests/cursor/bug1151-003.phpt b/mongodb-1.13.0/tests/cursor/bug1151-003.phpt
new file mode 100644
index 00000000..fde11f65
--- /dev/null
+++ b/mongodb-1.13.0/tests/cursor/bug1151-003.phpt
@@ -0,0 +1,31 @@
+--TEST--
+PHPC-1151: Segfault if session unset before cursor is killed (find)
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_not_live(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+
+$bulk = new MongoDB\Driver\BulkWrite;
+$bulk->insert(['_id' => 1]);
+$bulk->insert(['_id' => 2]);
+$bulk->insert(['_id' => 3]);
+$manager->executeBulkWrite(NS, $bulk);
+
+$query = new MongoDB\Driver\Query([], ['batchSize' => 2]);
+$session = $manager->startSession();
+
+$cursor = $manager->executeQuery(NS, $query, ['session' => $session]);
+unset($session);
+unset($cursor);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+===DONE===
diff --git a/mongodb-1.13.0/tests/cursor/bug1151-004.phpt b/mongodb-1.13.0/tests/cursor/bug1151-004.phpt
new file mode 100644
index 00000000..edfb6c28
--- /dev/null
+++ b/mongodb-1.13.0/tests/cursor/bug1151-004.phpt
@@ -0,0 +1,35 @@
+--TEST--
+PHPC-1151: Segfault if session unset before cursor is killed (aggregate)
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_not_live(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+
+$bulk = new MongoDB\Driver\BulkWrite;
+$bulk->insert(['_id' => 1]);
+$bulk->insert(['_id' => 2]);
+$bulk->insert(['_id' => 3]);
+$manager->executeBulkWrite(NS, $bulk);
+
+$command = new MongoDB\Driver\Command([
+ 'aggregate' => COLLECTION_NAME,
+ 'pipeline' => [],
+ 'cursor' => ['batchSize' => 2],
+]);
+$session = $manager->startSession();
+
+$cursor = $manager->executeReadCommand(DATABASE_NAME, $command, ['session' => $session]);
+unset($session);
+unset($cursor);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+===DONE===
diff --git a/mongodb-1.13.0/tests/cursor/bug1152-001.phpt b/mongodb-1.13.0/tests/cursor/bug1152-001.phpt
new file mode 100644
index 00000000..aefc107c
--- /dev/null
+++ b/mongodb-1.13.0/tests/cursor/bug1152-001.phpt
@@ -0,0 +1,131 @@
+--TEST--
+PHPC-1152: Command cursors should use the same session for getMore and killCursors (implicit)
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_not_live(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+class Test implements MongoDB\Driver\Monitoring\CommandSubscriber
+{
+ private $lsidByCursorId = [];
+ private $lsidByRequestId = [];
+
+ public function executeCommand()
+ {
+ $manager = create_test_manager();
+
+ $bulk = new MongoDB\Driver\BulkWrite;
+ $bulk->insert(['_id' => 1]);
+ $bulk->insert(['_id' => 2]);
+ $bulk->insert(['_id' => 3]);
+ $manager->executeBulkWrite(NS, $bulk);
+
+ $command = new MongoDB\Driver\Command([
+ 'aggregate' => COLLECTION_NAME,
+ 'pipeline' => [['$match' => new stdClass]],
+ 'cursor' => ['batchSize' => 2],
+ ]);
+
+ MongoDB\Driver\Monitoring\addSubscriber($this);
+
+ /* By creating two cursors with the same name, PHP's reference counting
+ * will destroy the first after the second is created. Note that
+ * mongoc_cursor_destroy also destroys implicit sessions and returns
+ * them to the LIFO pool. This sequencing allows us to test that getMore
+ * and killCursors use the session ID corresponding to the original
+ * aggregate command. */
+ $cursor = $manager->executeCommand(DATABASE_NAME, $command);
+ $cursor->toArray();
+
+ $cursor = $manager->executeCommand(DATABASE_NAME, $command);
+ $cursor->toArray();
+
+ $cursor = $manager->executeCommand(DATABASE_NAME, $command);
+ $cursor = $manager->executeCommand(DATABASE_NAME, $command);
+ unset($cursor);
+
+ MongoDB\Driver\Monitoring\removeSubscriber($this);
+
+ /* We should expect two unique session IDs over the course of the test,
+ * since at most two implicit sessions would have been in use at any
+ * given time. */
+ printf("Unique session IDs used: %d\n", count(array_unique($this->lsidByRequestId)));
+ }
+
+ public function commandStarted(MongoDB\Driver\Monitoring\CommandStartedEvent $event)
+ {
+ $requestId = $event->getRequestId();
+ $sessionId = bin2hex((string) $event->getCommand()->lsid->id);
+
+ printf("%s session ID: %s\n", $event->getCommandName(), $sessionId);
+
+ if ($event->getCommandName() === 'aggregate') {
+ if (isset($this->lsidByRequestId[$requestId])) {
+ throw new UnexpectedValueException('Previous command observed for request ID: ' . $requestId);
+ }
+
+ $this->lsidByRequestId[$requestId] = $sessionId;
+ }
+
+ if ($event->getCommandName() === 'getMore') {
+ $cursorId = (string) $event->getCommand()->getMore;
+
+ if ( ! isset($this->lsidByCursorId[$cursorId])) {
+ throw new UnexpectedValueException('No previous command observed for cursor ID: ' . $cursorId);
+ }
+
+ printf("getMore used same session as aggregate: %s\n", $sessionId === $this->lsidByCursorId[$cursorId] ? 'yes' : 'no');
+ }
+
+ if ($event->getCommandName() === 'killCursors') {
+ $cursorId = (string) $event->getCommand()->cursors[0];
+
+ if ( ! isset($this->lsidByCursorId[$cursorId])) {
+ throw new UnexpectedValueException('No previous command observed for cursor ID: ' . $cursorId);
+ }
+
+ printf("killCursors used same session as aggregate: %s\n", $sessionId === $this->lsidByCursorId[$cursorId] ? 'yes' : 'no');
+ }
+ }
+
+ public function commandSucceeded(MongoDB\Driver\Monitoring\CommandSucceededEvent $event)
+ {
+ /* Associate the aggregate's session ID with its cursor ID so it can be
+ * looked up by the subsequent getMore or killCursors */
+ if ($event->getCommandName() === 'aggregate') {
+ $cursorId = (string) $event->getReply()->cursor->id;
+ $requestId = $event->getRequestId();
+
+ $this->lsidByCursorId[$cursorId] = $this->lsidByRequestId[$requestId];
+ }
+ }
+
+ public function commandFailed(MongoDB\Driver\Monitoring\CommandFailedEvent $event)
+ {
+ }
+}
+
+(new Test)->executeCommand();
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+aggregate session ID: %x
+getMore session ID: %x
+getMore used same session as aggregate: yes
+aggregate session ID: %x
+getMore session ID: %x
+getMore used same session as aggregate: yes
+aggregate session ID: %x
+aggregate session ID: %x
+killCursors session ID: %x
+killCursors used same session as aggregate: yes
+killCursors session ID: %x
+killCursors used same session as aggregate: yes
+Unique session IDs used: 2
+===DONE===
diff --git a/mongodb-1.13.0/tests/cursor/bug1152-002.phpt b/mongodb-1.13.0/tests/cursor/bug1152-002.phpt
new file mode 100644
index 00000000..39f7016a
--- /dev/null
+++ b/mongodb-1.13.0/tests/cursor/bug1152-002.phpt
@@ -0,0 +1,129 @@
+--TEST--
+PHPC-1152: Command cursors should use the same session for getMore and killCursors (explicit)
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_not_live(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+class Test implements MongoDB\Driver\Monitoring\CommandSubscriber
+{
+ private $lsidByCursorId = [];
+ private $lsidByRequestId = [];
+
+ public function executeCommand()
+ {
+ $manager = create_test_manager();
+
+ $bulk = new MongoDB\Driver\BulkWrite;
+ $bulk->insert(['_id' => 1]);
+ $bulk->insert(['_id' => 2]);
+ $bulk->insert(['_id' => 3]);
+ $manager->executeBulkWrite(NS, $bulk);
+
+ $command = new MongoDB\Driver\Command([
+ 'aggregate' => COLLECTION_NAME,
+ 'pipeline' => [['$match' => new stdClass]],
+ 'cursor' => ['batchSize' => 2],
+ ]);
+
+ $session = $manager->startSession();
+
+ MongoDB\Driver\Monitoring\addSubscriber($this);
+
+ /* This uses the same sequencing as the implicit session test; however,
+ * we should expect all commands (aggregate, getMore, and killCursors)
+ * to use the same explicit session ID. */
+ $cursor = $manager->executeCommand(DATABASE_NAME, $command, ['session' => $session]);
+ $cursor->toArray();
+
+ $cursor = $manager->executeCommand(DATABASE_NAME, $command, ['session' => $session]);
+ $cursor->toArray();
+
+ $cursor = $manager->executeCommand(DATABASE_NAME, $command, ['session' => $session]);
+ $cursor = $manager->executeCommand(DATABASE_NAME, $command, ['session' => $session]);
+ unset($cursor);
+
+ MongoDB\Driver\Monitoring\removeSubscriber($this);
+
+ /* We should expect one unique session ID over the course of the test,
+ * since all commands used the same explicit session. */
+ printf("Unique session IDs used: %d\n", count(array_unique($this->lsidByRequestId)));
+ }
+
+ public function commandStarted(MongoDB\Driver\Monitoring\CommandStartedEvent $event)
+ {
+ $requestId = $event->getRequestId();
+ $sessionId = bin2hex((string) $event->getCommand()->lsid->id);
+
+ printf("%s session ID: %s\n", $event->getCommandName(), $sessionId);
+
+ if ($event->getCommandName() === 'aggregate') {
+ if (isset($this->lsidByRequestId[$requestId])) {
+ throw new UnexpectedValueException('Previous command observed for request ID: ' . $requestId);
+ }
+
+ $this->lsidByRequestId[$requestId] = $sessionId;
+ }
+
+ if ($event->getCommandName() === 'getMore') {
+ $cursorId = (string) $event->getCommand()->getMore;
+
+ if ( ! isset($this->lsidByCursorId[$cursorId])) {
+ throw new UnexpectedValueException('No previous command observed for cursor ID: ' . $cursorId);
+ }
+
+ printf("getMore used same session as aggregate: %s\n", $sessionId === $this->lsidByCursorId[$cursorId] ? 'yes' : 'no');
+ }
+
+ if ($event->getCommandName() === 'killCursors') {
+ $cursorId = (string) $event->getCommand()->cursors[0];
+
+ if ( ! isset($this->lsidByCursorId[$cursorId])) {
+ throw new UnexpectedValueException('No previous command observed for cursor ID: ' . $cursorId);
+ }
+
+ printf("killCursors used same session as aggregate: %s\n", $sessionId === $this->lsidByCursorId[$cursorId] ? 'yes' : 'no');
+ }
+ }
+
+ public function commandSucceeded(MongoDB\Driver\Monitoring\CommandSucceededEvent $event)
+ {
+ /* Associate the aggregate's session ID with its cursor ID so it can be
+ * looked up by the subsequent getMore or killCursors */
+ if ($event->getCommandName() === 'aggregate') {
+ $cursorId = (string) $event->getReply()->cursor->id;
+ $requestId = $event->getRequestId();
+
+ $this->lsidByCursorId[$cursorId] = $this->lsidByRequestId[$requestId];
+ }
+ }
+
+ public function commandFailed(MongoDB\Driver\Monitoring\CommandFailedEvent $event)
+ {
+ }
+}
+
+(new Test)->executeCommand();
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+aggregate session ID: %x
+getMore session ID: %x
+getMore used same session as aggregate: yes
+aggregate session ID: %x
+getMore session ID: %x
+getMore used same session as aggregate: yes
+aggregate session ID: %x
+aggregate session ID: %x
+killCursors session ID: %x
+killCursors used same session as aggregate: yes
+killCursors session ID: %x
+killCursors used same session as aggregate: yes
+Unique session IDs used: 1
+===DONE===
diff --git a/mongodb-1.12.0/tests/cursor/bug1162-001.phpt b/mongodb-1.13.0/tests/cursor/bug1162-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/cursor/bug1162-001.phpt
rename to mongodb-1.13.0/tests/cursor/bug1162-001.phpt
diff --git a/mongodb-1.12.0/tests/cursor/bug1274-001.phpt b/mongodb-1.13.0/tests/cursor/bug1274-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/cursor/bug1274-001.phpt
rename to mongodb-1.13.0/tests/cursor/bug1274-001.phpt
diff --git a/mongodb-1.13.0/tests/cursor/bug1274-002.phpt b/mongodb-1.13.0/tests/cursor/bug1274-002.phpt
new file mode 100644
index 00000000..fcecddc3
--- /dev/null
+++ b/mongodb-1.13.0/tests/cursor/bug1274-002.phpt
@@ -0,0 +1,104 @@
+--TEST--
+PHPC-1274: Child process can still iterate cursor from parent process
+--SKIPIF--
+<?php if (!function_exists('pcntl_fork')) { die('skip pcntl_fork() not available'); } ?>
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_ssl(); ?>
+<?php skip_if_not_live(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+class CommandLogger implements MongoDB\Driver\Monitoring\CommandSubscriber
+{
+ private $pid;
+
+ public function __construct()
+ {
+ $this->pid = getmypid();
+ }
+
+ public function commandStarted(MongoDB\Driver\Monitoring\CommandStartedEvent $event)
+ {
+ $command = $event->getCommand();
+ $commandName = $event->getCommandName();
+ $process = $this->pid === getmypid() ? 'Parent' : 'Child';
+
+ if ($commandName === 'find' || $commandName === 'getMore') {
+ printf("%s executes %s with batchSize: %d\n", $process, $commandName, $command->batchSize);
+ return;
+ }
+
+ printf("%s executes %s\n", $process, $commandName);
+ }
+
+ public function commandSucceeded(MongoDB\Driver\Monitoring\CommandSucceededEvent $event)
+ {
+ }
+
+ public function commandFailed(MongoDB\Driver\Monitoring\CommandFailedEvent $event)
+ {
+ }
+}
+
+$manager = create_test_manager();
+
+$bulk = new MongoDB\Driver\BulkWrite();
+$bulk->insert(['x' => 1]);
+$bulk->insert(['x' => 2]);
+$bulk->insert(['x' => 3]);
+$manager->executeBulkWrite(NS, $bulk);
+
+$subscriber = new CommandLogger;
+MongoDB\Driver\Monitoring\addSubscriber($subscriber);
+
+$query = new MongoDB\Driver\Query([], ['batchSize' => 2]);
+$cursor = $manager->executeQuery(NS, $query);
+
+$childPid = pcntl_fork();
+
+if ($childPid === 0) {
+ /* This test asserts that mongoc_client_reset() does not prevent child
+ * processes from actively interacting with a parent's cursor. Resetting the
+ * client only prevents a child from inadvertently closing a parent cursor
+ * via its php_phongo_cursor_free_object handler.
+ *
+ * Note: this test excludes SSL environments because we cannot interact with
+ * the socket in a child without affecting the parent (and vice versa) due
+ * to the SSL session. */
+ printf("Child fully iterated cursor for %d documents\n", iterator_count($cursor));
+ echo "Child exits\n";
+ exit;
+}
+
+if ($childPid > 0) {
+ $waitPid = pcntl_waitpid($childPid, $status);
+
+ if ($waitPid === $childPid) {
+ echo "Parent waited for child to exit\n";
+ }
+
+ echo throws(function() use ($cursor) {
+ printf("Parent fully iterated cursor for %d documents\n", iterator_count($cursor));
+ }, 'MongoDB\Driver\Exception\RuntimeException'), "\n";
+}
+
+/* This test doesn't need to assert that libmongoc may call killCursors when
+ * destroying a cursor that previously encountered a CursorNotFound error.
+ * See: https://jira.mongodb.org/browse/CDRIVER-3474 */
+MongoDB\Driver\Monitoring\removeSubscriber($subscriber);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Parent executes find with batchSize: 2
+Child executes getMore with batchSize: 2
+Child fully iterated cursor for 3 documents
+Child exits
+Parent waited for child to exit
+Parent executes getMore with batchSize: 2
+OK: Got MongoDB\Driver\Exception\RuntimeException
+%r(Cursor not found, cursor id: \d+|cursor id \d+ not found|Cursor not found \(.*id: \d+\)\.)%r
+===DONE===
diff --git a/mongodb-1.12.0/tests/cursor/bug1274-003.phpt b/mongodb-1.13.0/tests/cursor/bug1274-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/cursor/bug1274-003.phpt
rename to mongodb-1.13.0/tests/cursor/bug1274-003.phpt
diff --git a/mongodb-1.12.0/tests/cursor/bug1274-004.phpt b/mongodb-1.13.0/tests/cursor/bug1274-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/cursor/bug1274-004.phpt
rename to mongodb-1.13.0/tests/cursor/bug1274-004.phpt
diff --git a/mongodb-1.13.0/tests/cursor/bug1274-005.phpt b/mongodb-1.13.0/tests/cursor/bug1274-005.phpt
new file mode 100644
index 00000000..69a29814
--- /dev/null
+++ b/mongodb-1.13.0/tests/cursor/bug1274-005.phpt
@@ -0,0 +1,104 @@
+--TEST--
+PHPC-1274: Child process can still iterate cursor from parent process (disableClientPersistence=true)
+--SKIPIF--
+<?php if (!function_exists('pcntl_fork')) { die('skip pcntl_fork() not available'); } ?>
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_ssl(); ?>
+<?php skip_if_not_live(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+class CommandLogger implements MongoDB\Driver\Monitoring\CommandSubscriber
+{
+ private $pid;
+
+ public function __construct()
+ {
+ $this->pid = getmypid();
+ }
+
+ public function commandStarted(MongoDB\Driver\Monitoring\CommandStartedEvent $event)
+ {
+ $command = $event->getCommand();
+ $commandName = $event->getCommandName();
+ $process = $this->pid === getmypid() ? 'Parent' : 'Child';
+
+ if ($commandName === 'find' || $commandName === 'getMore') {
+ printf("%s executes %s with batchSize: %d\n", $process, $commandName, $command->batchSize);
+ return;
+ }
+
+ printf("%s executes %s\n", $process, $commandName);
+ }
+
+ public function commandSucceeded(MongoDB\Driver\Monitoring\CommandSucceededEvent $event)
+ {
+ }
+
+ public function commandFailed(MongoDB\Driver\Monitoring\CommandFailedEvent $event)
+ {
+ }
+}
+
+$manager = create_test_manager(URI, [], ['disableClientPersistence' => true]);
+
+$bulk = new MongoDB\Driver\BulkWrite();
+$bulk->insert(['x' => 1]);
+$bulk->insert(['x' => 2]);
+$bulk->insert(['x' => 3]);
+$manager->executeBulkWrite(NS, $bulk);
+
+$subscriber = new CommandLogger;
+MongoDB\Driver\Monitoring\addSubscriber($subscriber);
+
+$query = new MongoDB\Driver\Query([], ['batchSize' => 2]);
+$cursor = $manager->executeQuery(NS, $query);
+
+$childPid = pcntl_fork();
+
+if ($childPid === 0) {
+ /* This test asserts that mongoc_client_reset() does not prevent child
+ * processes from actively interacting with a parent's cursor. Resetting the
+ * client only prevents a child from inadvertently closing a parent cursor
+ * via its php_phongo_cursor_free_object handler.
+ *
+ * Note: this test excludes SSL environments because we cannot interact with
+ * the socket in a child without affecting the parent (and vice versa) due
+ * to the SSL session. */
+ printf("Child fully iterated cursor for %d documents\n", iterator_count($cursor));
+ echo "Child exits\n";
+ exit;
+}
+
+if ($childPid > 0) {
+ $waitPid = pcntl_waitpid($childPid, $status);
+
+ if ($waitPid === $childPid) {
+ echo "Parent waited for child to exit\n";
+ }
+
+ echo throws(function() use ($cursor) {
+ printf("Parent fully iterated cursor for %d documents\n", iterator_count($cursor));
+ }, 'MongoDB\Driver\Exception\RuntimeException'), "\n";
+}
+
+/* This test doesn't need to assert that libmongoc may call killCursors when
+ * destroying a cursor that previously encountered a CursorNotFound error.
+ * See: https://jira.mongodb.org/browse/CDRIVER-3474 */
+MongoDB\Driver\Monitoring\removeSubscriber($subscriber);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Parent executes find with batchSize: 2
+Child executes getMore with batchSize: 2
+Child fully iterated cursor for 3 documents
+Child exits
+Parent waited for child to exit
+Parent executes getMore with batchSize: 2
+OK: Got MongoDB\Driver\Exception\RuntimeException
+%r(Cursor not found, cursor id: \d+|cursor id \d+ not found|Cursor not found \(.*id: \d+\)\.)%r
+===DONE===
diff --git a/mongodb-1.12.0/tests/cursor/bug1274-006.phpt b/mongodb-1.13.0/tests/cursor/bug1274-006.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/cursor/bug1274-006.phpt
rename to mongodb-1.13.0/tests/cursor/bug1274-006.phpt
diff --git a/mongodb-1.12.0/tests/cursor/bug1419-001.phpt b/mongodb-1.13.0/tests/cursor/bug1419-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/cursor/bug1419-001.phpt
rename to mongodb-1.13.0/tests/cursor/bug1419-001.phpt
diff --git a/mongodb-1.13.0/tests/cursor/bug1529-001.phpt b/mongodb-1.13.0/tests/cursor/bug1529-001.phpt
new file mode 100644
index 00000000..e1082546
--- /dev/null
+++ b/mongodb-1.13.0/tests/cursor/bug1529-001.phpt
@@ -0,0 +1,105 @@
+--TEST--
+PHPC-1529: Resetting a client should also reset the keyVaultClient
+--SKIPIF--
+<?php if (!function_exists('pcntl_fork')) { die('skip pcntl_fork() not available'); } ?>
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_live(); ?>
+<?php skip_if_server_version('<', '4.2'); ?>
+<?php skip_if_not_libmongocrypt(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+class CommandLogger implements MongoDB\Driver\Monitoring\CommandSubscriber
+{
+ private $pid;
+
+ public function __construct()
+ {
+ $this->pid = getmypid();
+ }
+
+ public function commandStarted(MongoDB\Driver\Monitoring\CommandStartedEvent $event)
+ {
+ $command = $event->getCommand();
+ $commandName = $event->getCommandName();
+ $process = $this->pid === getmypid() ? 'Parent' : 'Child';
+
+ if ($commandName === 'find' || $commandName === 'getMore') {
+ printf("%s executes %s with batchSize: %d\n", $process, $commandName, $command->batchSize);
+ return;
+ }
+
+ printf("%s executes %s\n", $process, $commandName);
+ }
+
+ public function commandSucceeded(MongoDB\Driver\Monitoring\CommandSucceededEvent $event)
+ {
+ }
+
+ public function commandFailed(MongoDB\Driver\Monitoring\CommandFailedEvent $event)
+ {
+ }
+}
+
+$keyVaultClient = create_test_manager(URI, [], ['disableClientPersistence' => true]);
+$autoEncryptionOpts = [
+ 'keyVaultClient' => $keyVaultClient,
+ 'keyVaultNamespace' => 'default.keys',
+ 'kmsProviders' => ['local' => ['key' => new MongoDB\BSON\Binary(str_repeat('0', 96), 0)]],
+];
+
+$manager = create_test_manager(URI, [], ['autoEncryption' => $autoEncryptionOpts, 'disableClientPersistence' => true]);
+
+$bulk = new MongoDB\Driver\BulkWrite();
+$bulk->insert(['x' => 1]);
+$bulk->insert(['x' => 2]);
+$bulk->insert(['x' => 3]);
+$keyVaultClient->executeBulkWrite(NS, $bulk);
+
+MongoDB\Driver\Monitoring\addSubscriber(new CommandLogger);
+
+$query = new MongoDB\Driver\Query([], ['batchSize' => 2]);
+$cursor = $keyVaultClient->executeQuery(NS, $query);
+
+$childPid = pcntl_fork();
+
+if ($childPid === 0) {
+ /* Executing any operation with the parent's client resets this client as well as
+ * the keyVaultClient. Continuing iteration of the cursor opened on the
+ * keyVaultClient before resetting it should then result in an error due to
+ * the client having been reset. */
+ $manager->executeCommand(DATABASE_NAME, new MongoDB\Driver\Command(['ping' => 1]));
+
+ echo throws(
+ function () use ($cursor) { iterator_count($cursor); },
+ MongoDB\Driver\Exception\RuntimeException::class
+ ), "\n";
+
+ echo "Child exits\n";
+ exit;
+}
+
+if ($childPid > 0) {
+ $waitPid = pcntl_waitpid($childPid, $status);
+
+ if ($waitPid === $childPid) {
+ echo "Parent waited for child to exit\n";
+ }
+
+ unset($cursor);
+}
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+Parent executes find with batchSize: 2
+Child executes ping
+OK: Got MongoDB\Driver\Exception\RuntimeException
+Cannot advance cursor after client reset
+Child exits
+Parent waited for child to exit
+Parent executes killCursors
+===DONE===
diff --git a/mongodb-1.12.0/tests/cursor/bug1713-001.phpt b/mongodb-1.13.0/tests/cursor/bug1713-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/cursor/bug1713-001.phpt
rename to mongodb-1.13.0/tests/cursor/bug1713-001.phpt
diff --git a/mongodb-1.12.0/tests/cursor/cursor-001.phpt b/mongodb-1.13.0/tests/cursor/cursor-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/cursor/cursor-001.phpt
rename to mongodb-1.13.0/tests/cursor/cursor-001.phpt
diff --git a/mongodb-1.12.0/tests/cursor/cursor-IteratorIterator-001.phpt b/mongodb-1.13.0/tests/cursor/cursor-IteratorIterator-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/cursor/cursor-IteratorIterator-001.phpt
rename to mongodb-1.13.0/tests/cursor/cursor-IteratorIterator-001.phpt
diff --git a/mongodb-1.12.0/tests/cursor/cursor-IteratorIterator-002.phpt b/mongodb-1.13.0/tests/cursor/cursor-IteratorIterator-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/cursor/cursor-IteratorIterator-002.phpt
rename to mongodb-1.13.0/tests/cursor/cursor-IteratorIterator-002.phpt
diff --git a/mongodb-1.13.0/tests/cursor/cursor-IteratorIterator-003.phpt b/mongodb-1.13.0/tests/cursor/cursor-IteratorIterator-003.phpt
new file mode 100644
index 00000000..1a81ae21
--- /dev/null
+++ b/mongodb-1.13.0/tests/cursor/cursor-IteratorIterator-003.phpt
@@ -0,0 +1,41 @@
+--TEST--
+MongoDB\Driver\Cursor iteration beyond last document
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_live(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+
+$bulk = new MongoDB\Driver\BulkWrite();
+$bulk->insert(['_id' => 1]);
+$manager->executeBulkWrite(NS, $bulk);
+
+$cursor = $manager->executeQuery(NS, new MongoDB\Driver\Query([]));
+
+$iterator = new IteratorIterator($cursor);
+$iterator->rewind();
+var_dump($iterator->current());
+$iterator->next();
+var_dump($iterator->current());
+
+// libmongoc throws on superfluous iteration of find command cursor (CDRIVER-1234)
+echo throws(function() use ($iterator) {
+ $iterator->next();
+}, 'MongoDB\Driver\Exception\RuntimeException'), "\n";
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+object(stdClass)#%d (%d) {
+ ["_id"]=>
+ int(1)
+}
+NULL
+OK: Got MongoDB\Driver\Exception\RuntimeException
+Cannot advance a completed or failed cursor.
+===DONE===
diff --git a/mongodb-1.12.0/tests/cursor/cursor-NoRewindIterator-001.phpt b/mongodb-1.13.0/tests/cursor/cursor-NoRewindIterator-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/cursor/cursor-NoRewindIterator-001.phpt
rename to mongodb-1.13.0/tests/cursor/cursor-NoRewindIterator-001.phpt
diff --git a/mongodb-1.12.0/tests/cursor/cursor-destruct-001.phpt b/mongodb-1.13.0/tests/cursor/cursor-destruct-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/cursor/cursor-destruct-001.phpt
rename to mongodb-1.13.0/tests/cursor/cursor-destruct-001.phpt
diff --git a/mongodb-1.12.0/tests/cursor/cursor-getmore-001.phpt b/mongodb-1.13.0/tests/cursor/cursor-getmore-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/cursor/cursor-getmore-001.phpt
rename to mongodb-1.13.0/tests/cursor/cursor-getmore-001.phpt
diff --git a/mongodb-1.12.0/tests/cursor/cursor-getmore-002.phpt b/mongodb-1.13.0/tests/cursor/cursor-getmore-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/cursor/cursor-getmore-002.phpt
rename to mongodb-1.13.0/tests/cursor/cursor-getmore-002.phpt
diff --git a/mongodb-1.12.0/tests/cursor/cursor-getmore-003.phpt b/mongodb-1.13.0/tests/cursor/cursor-getmore-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/cursor/cursor-getmore-003.phpt
rename to mongodb-1.13.0/tests/cursor/cursor-getmore-003.phpt
diff --git a/mongodb-1.12.0/tests/cursor/cursor-getmore-004.phpt b/mongodb-1.13.0/tests/cursor/cursor-getmore-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/cursor/cursor-getmore-004.phpt
rename to mongodb-1.13.0/tests/cursor/cursor-getmore-004.phpt
diff --git a/mongodb-1.13.0/tests/cursor/cursor-getmore-005.phpt b/mongodb-1.13.0/tests/cursor/cursor-getmore-005.phpt
new file mode 100644
index 00000000..6b0c181a
--- /dev/null
+++ b/mongodb-1.13.0/tests/cursor/cursor-getmore-005.phpt
@@ -0,0 +1,53 @@
+--TEST--
+MongoDB\Driver\Cursor query result iteration with getmore failure
+--SKIPIF--
+<?php require __DIR__ . "/" ."../utils/basic-skipif.inc"; ?>
+<?php
+/* This test spins up its own mongod instance, so only run this in the most default "standalone, no
+ * auth" configurations. This way, we can test on multiple server versions, but not waste resources
+ * on f.e. Travis. */
+?>
+<?php skip_if_not_live(); ?>
+<?php skip_if_not_standalone(); ?>
+<?php skip_if_no_getmore_failpoint(); ?>
+<?php skip_if_auth(); ?>
+<?php skip_if_no_mongo_orchestration(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$uri = createTemporaryMongoInstance();
+$manager = create_test_manager($uri);
+
+$bulkWrite = new MongoDB\Driver\BulkWrite;
+
+for ($i = 0; $i < 5; $i++) {
+ $bulkWrite->insert(array('_id' => $i));
+}
+
+$writeResult = $manager->executeBulkWrite(NS, $bulkWrite);
+printf("Inserted: %d\n", $writeResult->getInsertedCount());
+
+$query = new MongoDB\Driver\Query([], ['batchSize' => 2]);
+$cursor = $manager->executeQuery(NS, $query);
+
+failGetMore($manager);
+
+throws(function() use ($cursor) {
+ foreach ($cursor as $i => $document) {
+ printf("%d => {_id: %d}\n", $i, $document->_id);
+ }
+}, MongoDB\Driver\Exception\ServerException::class);
+?>
+===DONE===
+<?php destroyTemporaryMongoInstance(); ?>
+<?php exit(0); ?>
+--CLEAN--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php destroyTemporaryMongoInstance(); ?>
+--EXPECT--
+Inserted: 5
+0 => {_id: 0}
+1 => {_id: 1}
+OK: Got MongoDB\Driver\Exception\ServerException
+===DONE===
diff --git a/mongodb-1.13.0/tests/cursor/cursor-getmore-006.phpt b/mongodb-1.13.0/tests/cursor/cursor-getmore-006.phpt
new file mode 100644
index 00000000..aba79f40
--- /dev/null
+++ b/mongodb-1.13.0/tests/cursor/cursor-getmore-006.phpt
@@ -0,0 +1,61 @@
+--TEST--
+MongoDB\Driver\Cursor command result iteration with getmore failure
+--SKIPIF--
+<?php require __DIR__ . "/" ."../utils/basic-skipif.inc"; ?>
+<?php
+/* This test spins up its own mongod instance, so only run this in the most default "standalone, no
+ * auth" configurations. This way, we can test on multiple server versions, but not waste resources
+ * on f.e. Travis. */
+?>
+<?php skip_if_not_live(); ?>
+<?php skip_if_not_standalone(); ?>
+<?php skip_if_no_getmore_failpoint(); ?>
+<?php skip_if_auth(); ?>
+<?php skip_if_no_mongo_orchestration(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$uri = createTemporaryMongoInstance();
+$manager = create_test_manager($uri);
+
+$bulkWrite = new MongoDB\Driver\BulkWrite;
+
+for ($i = 0; $i < 5; $i++) {
+ $bulkWrite->insert(array('_id' => $i));
+}
+
+$writeResult = $manager->executeBulkWrite(NS, $bulkWrite);
+printf("Inserted: %d\n", $writeResult->getInsertedCount());
+
+$command = new MongoDB\Driver\Command([
+ 'aggregate' => COLLECTION_NAME,
+ 'pipeline' => [
+ ['$match' => new stdClass],
+ ],
+ 'cursor' => ['batchSize' => 2],
+]);
+
+$cursor = $manager->executeCommand(DATABASE_NAME, $command);
+
+failGetMore($manager);
+
+throws(function() use ($cursor) {
+ foreach ($cursor as $i => $document) {
+ printf("%d => {_id: %d}\n", $i, $document->_id);
+ }
+}, MongoDB\Driver\Exception\ServerException::class);
+
+?>
+===DONE===
+<?php destroyTemporaryMongoInstance(); ?>
+<?php exit(0); ?>
+--CLEAN--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php destroyTemporaryMongoInstance(); ?>
+--EXPECT--
+Inserted: 5
+0 => {_id: 0}
+1 => {_id: 1}
+OK: Got MongoDB\Driver\Exception\ServerException
+===DONE===
diff --git a/mongodb-1.13.0/tests/cursor/cursor-isDead-001.phpt b/mongodb-1.13.0/tests/cursor/cursor-isDead-001.phpt
new file mode 100644
index 00000000..b28de544
--- /dev/null
+++ b/mongodb-1.13.0/tests/cursor/cursor-isDead-001.phpt
@@ -0,0 +1,35 @@
+--TEST--
+MongoDB\Driver\Cursor::isDead() with basic iteration
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_live(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+
+$bulk = new MongoDB\Driver\BulkWrite();
+$bulk->insert(['_id' => 1]);
+$bulk->insert(['_id' => 2]);
+$bulk->insert(['_id' => 3]);
+$manager->executeBulkWrite(NS, $bulk);
+
+$cursor = $manager->executeQuery(NS, new MongoDB\Driver\Query([], ['batchSize' => 2]));
+
+foreach ($cursor as $_) {
+ var_dump($cursor->isDead());
+}
+
+var_dump($cursor->isDead());
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+bool(false)
+bool(false)
+bool(false)
+bool(true)
+===DONE===
diff --git a/mongodb-1.13.0/tests/cursor/cursor-isDead-002.phpt b/mongodb-1.13.0/tests/cursor/cursor-isDead-002.phpt
new file mode 100644
index 00000000..20d049b5
--- /dev/null
+++ b/mongodb-1.13.0/tests/cursor/cursor-isDead-002.phpt
@@ -0,0 +1,39 @@
+--TEST--
+MongoDB\Driver\Cursor::isDead() with IteratorIterator
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_live(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+
+$bulk = new MongoDB\Driver\BulkWrite();
+$bulk->insert(['_id' => 1]);
+$bulk->insert(['_id' => 2]);
+$bulk->insert(['_id' => 3]);
+$manager->executeBulkWrite(NS, $bulk);
+
+$cursor = $manager->executeQuery(NS, new MongoDB\Driver\Query([], ['batchSize' => 2]));
+
+$iterator = new IteratorIterator($cursor);
+$iterator->rewind();
+
+for ($i = 0; $i < 3; $i++) {
+ var_dump($cursor->isDead());
+ $iterator->next();
+}
+
+var_dump($cursor->isDead());
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+bool(false)
+bool(false)
+bool(false)
+bool(true)
+===DONE===
diff --git a/mongodb-1.12.0/tests/cursor/cursor-iterator-001.phpt b/mongodb-1.13.0/tests/cursor/cursor-iterator-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/cursor/cursor-iterator-001.phpt
rename to mongodb-1.13.0/tests/cursor/cursor-iterator-001.phpt
diff --git a/mongodb-1.12.0/tests/cursor/cursor-iterator-002.phpt b/mongodb-1.13.0/tests/cursor/cursor-iterator-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/cursor/cursor-iterator-002.phpt
rename to mongodb-1.13.0/tests/cursor/cursor-iterator-002.phpt
diff --git a/mongodb-1.12.0/tests/cursor/cursor-iterator-003.phpt b/mongodb-1.13.0/tests/cursor/cursor-iterator-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/cursor/cursor-iterator-003.phpt
rename to mongodb-1.13.0/tests/cursor/cursor-iterator-003.phpt
diff --git a/mongodb-1.12.0/tests/cursor/cursor-iterator_handlers-001.phpt b/mongodb-1.13.0/tests/cursor/cursor-iterator_handlers-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/cursor/cursor-iterator_handlers-001.phpt
rename to mongodb-1.13.0/tests/cursor/cursor-iterator_handlers-001.phpt
diff --git a/mongodb-1.12.0/tests/cursor/cursor-rewind-001.phpt b/mongodb-1.13.0/tests/cursor/cursor-rewind-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/cursor/cursor-rewind-001.phpt
rename to mongodb-1.13.0/tests/cursor/cursor-rewind-001.phpt
diff --git a/mongodb-1.13.0/tests/cursor/cursor-session-001.phpt b/mongodb-1.13.0/tests/cursor/cursor-session-001.phpt
new file mode 100644
index 00000000..ade67b84
--- /dev/null
+++ b/mongodb-1.13.0/tests/cursor/cursor-session-001.phpt
@@ -0,0 +1,62 @@
+--TEST--
+MongoDB\Driver\Cursor debug output for query cursor includes explicit session
+--SKIPIF--
+<?php require __DIR__ . "/" ."../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_not_live(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+
+$bulk = new MongoDB\Driver\BulkWrite;
+$bulk->insert(['_id' => 1]);
+$bulk->insert(['_id' => 2]);
+$bulk->insert(['_id' => 3]);
+$manager->executeBulkWrite(NS, $bulk);
+
+$query = new MongoDB\Driver\Query([], ['batchSize' => 2]);
+$session = $manager->startSession();
+
+$cursor = $manager->executeQuery(NS, $query, ['session' => $session]);
+
+$iterator = new IteratorIterator($cursor);
+$iterator->rewind();
+$iterator->next();
+
+printf("Cursor ID is zero: %s\n", (string) $cursor->getId() === '0' ? 'yes' : 'no');
+var_dump($cursor);
+
+$iterator->next();
+
+/* Per PHPC-1161, the Cursor will free a reference to the Session as soon as it
+ * is exhausted. While this is primarily done to ensure implicit sessions for
+ * command cursors are returned to the pool ASAP, it also applies to explicit
+ * sessions. */
+printf("\nCursor ID is zero: %s\n", (string) $cursor->getId() === '0' ? 'yes' : 'no');
+var_dump($cursor);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Cursor ID is zero: no
+object(MongoDB\Driver\Cursor)#%d (%d) {
+ %a
+ ["session"]=>
+ object(MongoDB\Driver\Session)#%d (%d) {
+ %a
+ }
+ %a
+}
+
+Cursor ID is zero: yes
+object(MongoDB\Driver\Cursor)#%d (%d) {
+ %a
+ ["session"]=>
+ NULL
+ %a
+}
+===DONE===
diff --git a/mongodb-1.13.0/tests/cursor/cursor-session-002.phpt b/mongodb-1.13.0/tests/cursor/cursor-session-002.phpt
new file mode 100644
index 00000000..4332f7c1
--- /dev/null
+++ b/mongodb-1.13.0/tests/cursor/cursor-session-002.phpt
@@ -0,0 +1,58 @@
+--TEST--
+MongoDB\Driver\Cursor debug output for query cursor omits implicit session
+--SKIPIF--
+<?php require __DIR__ . "/" ."../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_not_live(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+
+$bulk = new MongoDB\Driver\BulkWrite;
+$bulk->insert(['_id' => 1]);
+$bulk->insert(['_id' => 2]);
+$bulk->insert(['_id' => 3]);
+$manager->executeBulkWrite(NS, $bulk);
+
+$query = new MongoDB\Driver\Query([], ['batchSize' => 2]);
+
+$cursor = $manager->executeQuery(NS, $query);
+
+$iterator = new IteratorIterator($cursor);
+$iterator->rewind();
+$iterator->next();
+
+/* Implicit sessions for query cursors are never exposed to PHPC, as they are
+ * handled internally by libmongoc. Cursor debug ouput should never report such
+ * sessions. */
+printf("Cursor ID is zero: %s\n", (string) $cursor->getId() === '0' ? 'yes' : 'no');
+var_dump($cursor);
+
+$iterator->next();
+
+printf("\nCursor ID is zero: %s\n", (string) $cursor->getId() === '0' ? 'yes' : 'no');
+var_dump($cursor);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Cursor ID is zero: no
+object(MongoDB\Driver\Cursor)#%d (%d) {
+ %a
+ ["session"]=>
+ NULL
+ %a
+}
+
+Cursor ID is zero: yes
+object(MongoDB\Driver\Cursor)#%d (%d) {
+ %a
+ ["session"]=>
+ NULL
+ %a
+}
+===DONE===
diff --git a/mongodb-1.13.0/tests/cursor/cursor-session-003.phpt b/mongodb-1.13.0/tests/cursor/cursor-session-003.phpt
new file mode 100644
index 00000000..df9f7d46
--- /dev/null
+++ b/mongodb-1.13.0/tests/cursor/cursor-session-003.phpt
@@ -0,0 +1,66 @@
+--TEST--
+MongoDB\Driver\Cursor debug output for command cursor includes explicit session
+--SKIPIF--
+<?php require __DIR__ . "/" ."../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_not_live(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+
+$bulk = new MongoDB\Driver\BulkWrite;
+$bulk->insert(['_id' => 1]);
+$bulk->insert(['_id' => 2]);
+$bulk->insert(['_id' => 3]);
+$manager->executeBulkWrite(NS, $bulk);
+
+$command = new MongoDB\Driver\Command([
+ 'aggregate' => COLLECTION_NAME,
+ 'pipeline' => [['$match' => new stdClass]],
+ 'cursor' => ['batchSize' => 2],
+]);
+$session = $manager->startSession();
+
+$cursor = $manager->executeCommand(DATABASE_NAME, $command, ['session' => $session]);
+
+$iterator = new IteratorIterator($cursor);
+$iterator->rewind();
+$iterator->next();
+
+printf("Cursor ID is zero: %s\n", (string) $cursor->getId() === '0' ? 'yes' : 'no');
+var_dump($cursor);
+
+$iterator->next();
+
+/* Per PHPC-1161, the Cursor will free a reference to the Session as soon as it
+ * is exhausted. While this is primarily done to ensure implicit sessions for
+ * command cursors are returned to the pool ASAP, it also applies to explicit
+ * sessions. */
+printf("\nCursor ID is zero: %s\n", (string) $cursor->getId() === '0' ? 'yes' : 'no');
+var_dump($cursor);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Cursor ID is zero: no
+object(MongoDB\Driver\Cursor)#%d (%d) {
+ %a
+ ["session"]=>
+ object(MongoDB\Driver\Session)#%d (%d) {
+ %a
+ }
+ %a
+}
+
+Cursor ID is zero: yes
+object(MongoDB\Driver\Cursor)#%d (%d) {
+ %a
+ ["session"]=>
+ NULL
+ %a
+}
+===DONE===
diff --git a/mongodb-1.13.0/tests/cursor/cursor-session-004.phpt b/mongodb-1.13.0/tests/cursor/cursor-session-004.phpt
new file mode 100644
index 00000000..b93bbbf0
--- /dev/null
+++ b/mongodb-1.13.0/tests/cursor/cursor-session-004.phpt
@@ -0,0 +1,65 @@
+--TEST--
+MongoDB\Driver\Cursor debug output for command cursor includes implicit session
+--SKIPIF--
+<?php require __DIR__ . "/" ."../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_not_live(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+
+$bulk = new MongoDB\Driver\BulkWrite;
+$bulk->insert(['_id' => 1]);
+$bulk->insert(['_id' => 2]);
+$bulk->insert(['_id' => 3]);
+$manager->executeBulkWrite(NS, $bulk);
+
+$command = new MongoDB\Driver\Command([
+ 'aggregate' => COLLECTION_NAME,
+ 'pipeline' => [['$match' => new stdClass]],
+ 'cursor' => ['batchSize' => 2],
+]);
+
+$cursor = $manager->executeCommand(DATABASE_NAME, $command);
+
+$iterator = new IteratorIterator($cursor);
+$iterator->rewind();
+$iterator->next();
+
+printf("Cursor ID is zero: %s\n", (string) $cursor->getId() === '0' ? 'yes' : 'no');
+var_dump($cursor);
+
+$iterator->next();
+
+/* Unlike implicit sessions for query cursors, which are handled internally by
+ * libmongoc, PHPC-1152 emulates its own implicit sessions for command cursors
+ * in order to ensure that command cursors always share the same session as the
+ * originating command. */
+printf("\nCursor ID is zero: %s\n", (string) $cursor->getId() === '0' ? 'yes' : 'no');
+var_dump($cursor);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Cursor ID is zero: no
+object(MongoDB\Driver\Cursor)#%d (%d) {
+ %a
+ ["session"]=>
+ object(MongoDB\Driver\Session)#%d (%d) {
+ %a
+ }
+ %a
+}
+
+Cursor ID is zero: yes
+object(MongoDB\Driver\Cursor)#%d (%d) {
+ %a
+ ["session"]=>
+ NULL
+ %a
+}
+===DONE===
diff --git a/mongodb-1.12.0/tests/cursor/cursor-setTypeMap_error-001.phpt b/mongodb-1.13.0/tests/cursor/cursor-setTypeMap_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/cursor/cursor-setTypeMap_error-001.phpt
rename to mongodb-1.13.0/tests/cursor/cursor-setTypeMap_error-001.phpt
diff --git a/mongodb-1.12.0/tests/cursor/cursor-setTypeMap_error-002.phpt b/mongodb-1.13.0/tests/cursor/cursor-setTypeMap_error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/cursor/cursor-setTypeMap_error-002.phpt
rename to mongodb-1.13.0/tests/cursor/cursor-setTypeMap_error-002.phpt
diff --git a/mongodb-1.12.0/tests/cursor/cursor-setTypeMap_error-003.phpt b/mongodb-1.13.0/tests/cursor/cursor-setTypeMap_error-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/cursor/cursor-setTypeMap_error-003.phpt
rename to mongodb-1.13.0/tests/cursor/cursor-setTypeMap_error-003.phpt
diff --git a/mongodb-1.12.0/tests/cursor/cursor-setTypeMap_error-004.phpt b/mongodb-1.13.0/tests/cursor/cursor-setTypeMap_error-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/cursor/cursor-setTypeMap_error-004.phpt
rename to mongodb-1.13.0/tests/cursor/cursor-setTypeMap_error-004.phpt
diff --git a/mongodb-1.12.0/tests/cursor/cursor-tailable-001.phpt b/mongodb-1.13.0/tests/cursor/cursor-tailable-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/cursor/cursor-tailable-001.phpt
rename to mongodb-1.13.0/tests/cursor/cursor-tailable-001.phpt
diff --git a/mongodb-1.12.0/tests/cursor/cursor-tailable-002.phpt b/mongodb-1.13.0/tests/cursor/cursor-tailable-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/cursor/cursor-tailable-002.phpt
rename to mongodb-1.13.0/tests/cursor/cursor-tailable-002.phpt
diff --git a/mongodb-1.13.0/tests/cursor/cursor-tailable-003.phpt b/mongodb-1.13.0/tests/cursor/cursor-tailable-003.phpt
new file mode 100644
index 00000000..b8d676a6
--- /dev/null
+++ b/mongodb-1.13.0/tests/cursor/cursor-tailable-003.phpt
@@ -0,0 +1,46 @@
+--TEST--
+MongoDB\Driver\Cursor tailable iteration with awaitData and maxAwaitTimeMS options
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_live(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+
+$manager->executeCommand(DATABASE_NAME, new MongoDB\Driver\Command([
+ 'create' => COLLECTION_NAME,
+ 'capped' => true,
+ 'size' => 1048576,
+]));
+
+$bulkWrite = new MongoDB\Driver\BulkWrite;
+$bulkWrite->insert(['_id' => 1]);
+$manager->executeBulkWrite(NS, $bulkWrite);
+
+$cursor = $manager->executeQuery(NS, new MongoDB\Driver\Query([], [
+ 'tailable' => true,
+ 'awaitData' => true,
+ 'maxAwaitTimeMS' => 10,
+]));
+$it = new IteratorIterator($cursor);
+
+$it->rewind();
+printf("{_id: %d}\n", $it->current()->_id);
+$it->next();
+
+$startTime = microtime(true);
+echo "Awaiting results...\n";
+$it->next();
+printf("Waited for %.6f seconds\n", microtime(true) - $startTime);
+// Sometimes the cursor will wait for 0.0099 seconds and sometimes it will wait for 0.01.
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+{_id: 1}
+Awaiting results...
+Waited for 0.0%d seconds
+===DONE===
diff --git a/mongodb-1.12.0/tests/cursor/cursor-tailable_error-001.phpt b/mongodb-1.13.0/tests/cursor/cursor-tailable_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/cursor/cursor-tailable_error-001.phpt
rename to mongodb-1.13.0/tests/cursor/cursor-tailable_error-001.phpt
diff --git a/mongodb-1.13.0/tests/cursor/cursor-tailable_error-002.phpt b/mongodb-1.13.0/tests/cursor/cursor-tailable_error-002.phpt
new file mode 100644
index 00000000..9157c5e2
--- /dev/null
+++ b/mongodb-1.13.0/tests/cursor/cursor-tailable_error-002.phpt
@@ -0,0 +1,89 @@
+--TEST--
+MongoDB\Driver\Cursor cursor killed during tailable iteration
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_live(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+function insert(MongoDB\Driver\Manager $manager, $from, $to = null)
+{
+ if ($to === null) {
+ $to = $from;
+ }
+
+ $bulkWrite = new MongoDB\Driver\BulkWrite;
+
+ for ($i = $from; $i <= $to; $i++) {
+ $bulkWrite->insert(['_id' => $i]);
+ }
+
+ $writeResult = $manager->executeBulkWrite(NS, $bulkWrite);
+
+ printf("Inserted %d document(s): %s\n", $writeResult->getInsertedCount(), implode(', ', range($from, $to)));
+}
+
+$manager = create_test_manager();
+
+$manager->executeCommand(DATABASE_NAME, new MongoDB\Driver\Command([
+ 'create' => COLLECTION_NAME,
+ 'capped' => true,
+ 'size' => 1048576,
+]));
+
+insert($manager, 1, 3);
+
+echo throws(function() use ($manager) {
+ $cursor = $manager->executeQuery(NS, new MongoDB\Driver\Query([], ['tailable' => true]));
+ $it = new IteratorIterator($cursor);
+
+ $numAwaitAttempts = 0;
+ $maxAwaitAttempts = 7;
+
+ for ($it->rewind(); $numAwaitAttempts < $maxAwaitAttempts; $it->next()) {
+ $document = $it->current();
+
+ if ($document !== null) {
+ printf("{_id: %d}\n", $document->_id);
+ continue;
+ }
+
+ if ($numAwaitAttempts === 2) {
+ insert($manager, 4, 6);
+ }
+
+ if ($numAwaitAttempts === 5) {
+ $cursor->getServer()->executeCommand(DATABASE_NAME, new MongoDB\Driver\Command([
+ 'killCursors' => COLLECTION_NAME,
+ 'cursors' => [ $cursor->getId() ],
+ ]));
+ }
+
+ echo "Awaiting results...\n";
+ $numAwaitAttempts += 1;
+ }
+}, 'MongoDB\Driver\Exception\RuntimeException'), "\n";
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Inserted 3 document(s): 1, 2, 3
+{_id: 1}
+{_id: 2}
+{_id: 3}
+Awaiting results...
+Awaiting results...
+Inserted 3 document(s): 4, 5, 6
+Awaiting results...
+{_id: 4}
+{_id: 5}
+{_id: 6}
+Awaiting results...
+Awaiting results...
+Awaiting results...
+OK: Got MongoDB\Driver\Exception\RuntimeException
+%r(Cursor not found, cursor id: \d+|cursor id \d+ not found|Cursor not found \(.*id: \d+\)\.)%r
+===DONE===
diff --git a/mongodb-1.12.0/tests/cursor/cursor-toArray-001.phpt b/mongodb-1.13.0/tests/cursor/cursor-toArray-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/cursor/cursor-toArray-001.phpt
rename to mongodb-1.13.0/tests/cursor/cursor-toArray-001.phpt
diff --git a/mongodb-1.12.0/tests/cursor/cursor-toArray-002.phpt b/mongodb-1.13.0/tests/cursor/cursor-toArray-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/cursor/cursor-toArray-002.phpt
rename to mongodb-1.13.0/tests/cursor/cursor-toArray-002.phpt
diff --git a/mongodb-1.12.0/tests/cursor/cursor_error-001.phpt b/mongodb-1.13.0/tests/cursor/cursor_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/cursor/cursor_error-001.phpt
rename to mongodb-1.13.0/tests/cursor/cursor_error-001.phpt
diff --git a/mongodb-1.12.0/tests/cursor/cursorinterface-001.phpt b/mongodb-1.13.0/tests/cursor/cursorinterface-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/cursor/cursorinterface-001.phpt
rename to mongodb-1.13.0/tests/cursor/cursorinterface-001.phpt
diff --git a/mongodb-1.12.0/tests/cursor/cursorinterface-002.phpt b/mongodb-1.13.0/tests/cursor/cursorinterface-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/cursor/cursorinterface-002.phpt
rename to mongodb-1.13.0/tests/cursor/cursorinterface-002.phpt
diff --git a/mongodb-1.12.0/tests/cursor/cursorinterface-003.phpt b/mongodb-1.13.0/tests/cursor/cursorinterface-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/cursor/cursorinterface-003.phpt
rename to mongodb-1.13.0/tests/cursor/cursorinterface-003.phpt
diff --git a/mongodb-1.12.0/tests/cursorid/cursorid-001.phpt b/mongodb-1.13.0/tests/cursorid/cursorid-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/cursorid/cursorid-001.phpt
rename to mongodb-1.13.0/tests/cursorid/cursorid-001.phpt
diff --git a/mongodb-1.13.0/tests/cursorid/cursorid-002.phpt b/mongodb-1.13.0/tests/cursorid/cursorid-002.phpt
new file mode 100644
index 00000000..23c05389
--- /dev/null
+++ b/mongodb-1.13.0/tests/cursorid/cursorid-002.phpt
@@ -0,0 +1,43 @@
+--TEST--
+MongoDB\Driver\CursorId BSON serialization for killCursors command
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_live(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+
+// Select a specific server for future operations to avoid mongos switching in sharded clusters
+$server = $manager->selectServer(new \MongoDB\Driver\ReadPreference('primary'));
+
+$bulk = new MongoDB\Driver\BulkWrite();
+$bulk->insert(['_id' => 1]);
+$bulk->insert(['_id' => 2]);
+$bulk->insert(['_id' => 3]);
+$server->executeBulkWrite(NS, $bulk);
+
+$cursor = $server->executeQuery(NS, new MongoDB\Driver\Query([], ['batchSize' => 2]));
+$cursorId = $cursor->getId();
+
+$command = new MongoDB\Driver\Command([
+ 'killCursors' => COLLECTION_NAME,
+ 'cursors' => [ $cursorId ],
+]);
+
+/* Since the killCursors command result includes cursor IDs as 64-bit integers,
+ * unserializing the result document requires a 64-bit platform. */
+$result = $server->executeCommand(DATABASE_NAME, $command)->toArray()[0];
+printf("Killed %d cursor(s)\n", count($result->cursorsKilled));
+printf("Killed expected cursor: %s\n", (string) $cursorId === (string) $result->cursorsKilled[0] ? 'yes' : 'no');
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+Killed 1 cursor(s)
+Killed expected cursor: yes
+===DONE===
diff --git a/mongodb-1.12.0/tests/cursorid/cursorid-debug-001.phpt b/mongodb-1.13.0/tests/cursorid/cursorid-debug-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/cursorid/cursorid-debug-001.phpt
rename to mongodb-1.13.0/tests/cursorid/cursorid-debug-001.phpt
diff --git a/mongodb-1.12.0/tests/cursorid/cursorid-debug-002.phpt b/mongodb-1.13.0/tests/cursorid/cursorid-debug-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/cursorid/cursorid-debug-002.phpt
rename to mongodb-1.13.0/tests/cursorid/cursorid-debug-002.phpt
diff --git a/mongodb-1.12.0/tests/cursorid/cursorid-debug-003.phpt b/mongodb-1.13.0/tests/cursorid/cursorid-debug-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/cursorid/cursorid-debug-003.phpt
rename to mongodb-1.13.0/tests/cursorid/cursorid-debug-003.phpt
diff --git a/mongodb-1.12.0/tests/cursorid/cursorid-serialization-001.phpt b/mongodb-1.13.0/tests/cursorid/cursorid-serialization-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/cursorid/cursorid-serialization-001.phpt
rename to mongodb-1.13.0/tests/cursorid/cursorid-serialization-001.phpt
diff --git a/mongodb-1.12.0/tests/cursorid/cursorid-serialization-002.phpt b/mongodb-1.13.0/tests/cursorid/cursorid-serialization-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/cursorid/cursorid-serialization-002.phpt
rename to mongodb-1.13.0/tests/cursorid/cursorid-serialization-002.phpt
diff --git a/mongodb-1.12.0/tests/cursorid/cursorid-serialization_error-001.phpt b/mongodb-1.13.0/tests/cursorid/cursorid-serialization_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/cursorid/cursorid-serialization_error-001.phpt
rename to mongodb-1.13.0/tests/cursorid/cursorid-serialization_error-001.phpt
diff --git a/mongodb-1.12.0/tests/cursorid/cursorid-serialization_error-002.phpt b/mongodb-1.13.0/tests/cursorid/cursorid-serialization_error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/cursorid/cursorid-serialization_error-002.phpt
rename to mongodb-1.13.0/tests/cursorid/cursorid-serialization_error-002.phpt
diff --git a/mongodb-1.12.0/tests/cursorid/cursorid-set_state-001.phpt b/mongodb-1.13.0/tests/cursorid/cursorid-set_state-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/cursorid/cursorid-set_state-001.phpt
rename to mongodb-1.13.0/tests/cursorid/cursorid-set_state-001.phpt
diff --git a/mongodb-1.12.0/tests/cursorid/cursorid-set_state_error-001.phpt b/mongodb-1.13.0/tests/cursorid/cursorid-set_state_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/cursorid/cursorid-set_state_error-001.phpt
rename to mongodb-1.13.0/tests/cursorid/cursorid-set_state_error-001.phpt
diff --git a/mongodb-1.12.0/tests/cursorid/cursorid-tostring-001.phpt b/mongodb-1.13.0/tests/cursorid/cursorid-tostring-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/cursorid/cursorid-tostring-001.phpt
rename to mongodb-1.13.0/tests/cursorid/cursorid-tostring-001.phpt
diff --git a/mongodb-1.12.0/tests/cursorid/cursorid-var_export-001.phpt b/mongodb-1.13.0/tests/cursorid/cursorid-var_export-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/cursorid/cursorid-var_export-001.phpt
rename to mongodb-1.13.0/tests/cursorid/cursorid-var_export-001.phpt
diff --git a/mongodb-1.12.0/tests/cursorid/cursorid_error-001.phpt b/mongodb-1.13.0/tests/cursorid/cursorid_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/cursorid/cursorid_error-001.phpt
rename to mongodb-1.13.0/tests/cursorid/cursorid_error-001.phpt
diff --git a/mongodb-1.12.0/tests/exception/bulkwriteexception-getwriteresult-001.phpt b/mongodb-1.13.0/tests/exception/bulkwriteexception-getwriteresult-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/exception/bulkwriteexception-getwriteresult-001.phpt
rename to mongodb-1.13.0/tests/exception/bulkwriteexception-getwriteresult-001.phpt
diff --git a/mongodb-1.12.0/tests/exception/bulkwriteexception-haserrorlabel-001.phpt b/mongodb-1.13.0/tests/exception/bulkwriteexception-haserrorlabel-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/exception/bulkwriteexception-haserrorlabel-001.phpt
rename to mongodb-1.13.0/tests/exception/bulkwriteexception-haserrorlabel-001.phpt
diff --git a/mongodb-1.12.0/tests/exception/bulkwriteexception-haserrorlabel-002.phpt b/mongodb-1.13.0/tests/exception/bulkwriteexception-haserrorlabel-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/exception/bulkwriteexception-haserrorlabel-002.phpt
rename to mongodb-1.13.0/tests/exception/bulkwriteexception-haserrorlabel-002.phpt
diff --git a/mongodb-1.12.0/tests/exception/bulkwriteexception-haserrorlabel_error-001.phpt b/mongodb-1.13.0/tests/exception/bulkwriteexception-haserrorlabel_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/exception/bulkwriteexception-haserrorlabel_error-001.phpt
rename to mongodb-1.13.0/tests/exception/bulkwriteexception-haserrorlabel_error-001.phpt
diff --git a/mongodb-1.12.0/tests/exception/commandexception-getresultdocument-001.phpt b/mongodb-1.13.0/tests/exception/commandexception-getresultdocument-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/exception/commandexception-getresultdocument-001.phpt
rename to mongodb-1.13.0/tests/exception/commandexception-getresultdocument-001.phpt
diff --git a/mongodb-1.12.0/tests/exception/commandexception-haserrorlabel-001.phpt b/mongodb-1.13.0/tests/exception/commandexception-haserrorlabel-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/exception/commandexception-haserrorlabel-001.phpt
rename to mongodb-1.13.0/tests/exception/commandexception-haserrorlabel-001.phpt
diff --git a/mongodb-1.12.0/tests/exception/commandexception-haserrorlabel_error-001.phpt b/mongodb-1.13.0/tests/exception/commandexception-haserrorlabel_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/exception/commandexception-haserrorlabel_error-001.phpt
rename to mongodb-1.13.0/tests/exception/commandexception-haserrorlabel_error-001.phpt
diff --git a/mongodb-1.12.0/tests/exception/exception-001.phpt b/mongodb-1.13.0/tests/exception/exception-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/exception/exception-001.phpt
rename to mongodb-1.13.0/tests/exception/exception-001.phpt
diff --git a/mongodb-1.12.0/tests/exception/runtimeexception-haserrorlabel-001.phpt b/mongodb-1.13.0/tests/exception/runtimeexception-haserrorlabel-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/exception/runtimeexception-haserrorlabel-001.phpt
rename to mongodb-1.13.0/tests/exception/runtimeexception-haserrorlabel-001.phpt
diff --git a/mongodb-1.12.0/tests/exception/runtimeexception-haserrorlabel_error-001.phpt b/mongodb-1.13.0/tests/exception/runtimeexception-haserrorlabel_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/exception/runtimeexception-haserrorlabel_error-001.phpt
rename to mongodb-1.13.0/tests/exception/runtimeexception-haserrorlabel_error-001.phpt
diff --git a/mongodb-1.12.0/tests/functional/cursor-001.phpt b/mongodb-1.13.0/tests/functional/cursor-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/functional/cursor-001.phpt
rename to mongodb-1.13.0/tests/functional/cursor-001.phpt
diff --git a/mongodb-1.12.0/tests/functional/cursorid-001.phpt b/mongodb-1.13.0/tests/functional/cursorid-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/functional/cursorid-001.phpt
rename to mongodb-1.13.0/tests/functional/cursorid-001.phpt
diff --git a/mongodb-1.12.0/tests/functional/query-sort-001.phpt b/mongodb-1.13.0/tests/functional/query-sort-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/functional/query-sort-001.phpt
rename to mongodb-1.13.0/tests/functional/query-sort-001.phpt
diff --git a/mongodb-1.12.0/tests/functional/query-sort-002.phpt b/mongodb-1.13.0/tests/functional/query-sort-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/functional/query-sort-002.phpt
rename to mongodb-1.13.0/tests/functional/query-sort-002.phpt
diff --git a/mongodb-1.12.0/tests/functional/query-sort-003.phpt b/mongodb-1.13.0/tests/functional/query-sort-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/functional/query-sort-003.phpt
rename to mongodb-1.13.0/tests/functional/query-sort-003.phpt
diff --git a/mongodb-1.12.0/tests/functional/query-sort-004.phpt b/mongodb-1.13.0/tests/functional/query-sort-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/functional/query-sort-004.phpt
rename to mongodb-1.13.0/tests/functional/query-sort-004.phpt
diff --git a/mongodb-1.12.0/tests/ini/ini-debug-ini_get-001.phpt b/mongodb-1.13.0/tests/ini/ini-debug-ini_get-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/ini/ini-debug-ini_get-001.phpt
rename to mongodb-1.13.0/tests/ini/ini-debug-ini_get-001.phpt
diff --git a/mongodb-1.12.0/tests/ini/ini-debug-ini_get-002.phpt b/mongodb-1.13.0/tests/ini/ini-debug-ini_get-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/ini/ini-debug-ini_get-002.phpt
rename to mongodb-1.13.0/tests/ini/ini-debug-ini_get-002.phpt
diff --git a/mongodb-1.12.0/tests/ini/ini-debug-phpinfo-001.phpt b/mongodb-1.13.0/tests/ini/ini-debug-phpinfo-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/ini/ini-debug-phpinfo-001.phpt
rename to mongodb-1.13.0/tests/ini/ini-debug-phpinfo-001.phpt
diff --git a/mongodb-1.12.0/tests/ini/ini-debug-phpinfo-002.phpt b/mongodb-1.13.0/tests/ini/ini-debug-phpinfo-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/ini/ini-debug-phpinfo-002.phpt
rename to mongodb-1.13.0/tests/ini/ini-debug-phpinfo-002.phpt
diff --git a/mongodb-1.12.0/tests/ini/ini-mock_service_id-ini_get-001.phpt b/mongodb-1.13.0/tests/ini/ini-mock_service_id-ini_get-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/ini/ini-mock_service_id-ini_get-001.phpt
rename to mongodb-1.13.0/tests/ini/ini-mock_service_id-ini_get-001.phpt
diff --git a/mongodb-1.12.0/tests/ini/ini-mock_service_id-ini_get-002.phpt b/mongodb-1.13.0/tests/ini/ini-mock_service_id-ini_get-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/ini/ini-mock_service_id-ini_get-002.phpt
rename to mongodb-1.13.0/tests/ini/ini-mock_service_id-ini_get-002.phpt
diff --git a/mongodb-1.12.0/tests/ini/ini-mock_service_id-phpinfo-001.phpt b/mongodb-1.13.0/tests/ini/ini-mock_service_id-phpinfo-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/ini/ini-mock_service_id-phpinfo-001.phpt
rename to mongodb-1.13.0/tests/ini/ini-mock_service_id-phpinfo-001.phpt
diff --git a/mongodb-1.12.0/tests/ini/ini-mock_service_id-phpinfo-002.phpt b/mongodb-1.13.0/tests/ini/ini-mock_service_id-phpinfo-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/ini/ini-mock_service_id-phpinfo-002.phpt
rename to mongodb-1.13.0/tests/ini/ini-mock_service_id-phpinfo-002.phpt
diff --git a/mongodb-1.13.0/tests/manager/bug0572.phpt b/mongodb-1.13.0/tests/manager/bug0572.phpt
new file mode 100644
index 00000000..0b0c6bf0
--- /dev/null
+++ b/mongodb-1.13.0/tests/manager/bug0572.phpt
@@ -0,0 +1,35 @@
+--TEST--
+PHPC-572: Ensure stream context does not go out of scope before socket init
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_ssl(); ?>
+<?php skip_if_not_ssl(); ?>
+<?php skip_if_not_live(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$closure = function() {
+ $context = stream_context_create([
+ 'ssl' => [
+ 'verify_peer' => false,
+ 'verify_peer_name' => false,
+ 'allow_self_signed' => true,
+ ],
+ ]);
+ return create_test_manager(URI, [], ['context' => $context]);
+};
+
+$manager = $closure();
+$cursor = $manager->executeCommand(DATABASE_NAME, new MongoDB\Driver\Command(['ping' => 1]));
+printf("ping: %d\n", $cursor->toArray()[0]->ok);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Deprecated: MongoDB\Driver\Manager::__construct(): The "context" driver option is deprecated.%s
+
+Deprecated: MongoDB\Driver\Manager::__construct(): The "allow_self_signed" context driver option is deprecated. Please use the "tlsAllowInvalidCertificates" URI option instead.%s
+ping: 1
+===DONE===
diff --git a/mongodb-1.12.0/tests/manager/bug0851-001.phpt b/mongodb-1.13.0/tests/manager/bug0851-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/bug0851-001.phpt
rename to mongodb-1.13.0/tests/manager/bug0851-001.phpt
diff --git a/mongodb-1.12.0/tests/manager/bug0851-002.phpt b/mongodb-1.13.0/tests/manager/bug0851-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/bug0851-002.phpt
rename to mongodb-1.13.0/tests/manager/bug0851-002.phpt
diff --git a/mongodb-1.12.0/tests/manager/bug0912-001.phpt b/mongodb-1.13.0/tests/manager/bug0912-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/bug0912-001.phpt
rename to mongodb-1.13.0/tests/manager/bug0912-001.phpt
diff --git a/mongodb-1.12.0/tests/manager/bug0913-001.phpt b/mongodb-1.13.0/tests/manager/bug0913-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/bug0913-001.phpt
rename to mongodb-1.13.0/tests/manager/bug0913-001.phpt
diff --git a/mongodb-1.12.0/tests/manager/bug0940-001.phpt b/mongodb-1.13.0/tests/manager/bug0940-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/bug0940-001.phpt
rename to mongodb-1.13.0/tests/manager/bug0940-001.phpt
diff --git a/mongodb-1.12.0/tests/manager/bug0940-002.phpt b/mongodb-1.13.0/tests/manager/bug0940-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/bug0940-002.phpt
rename to mongodb-1.13.0/tests/manager/bug0940-002.phpt
diff --git a/mongodb-1.13.0/tests/manager/bug1163-001.phpt b/mongodb-1.13.0/tests/manager/bug1163-001.phpt
new file mode 100644
index 00000000..01accd4c
--- /dev/null
+++ b/mongodb-1.13.0/tests/manager/bug1163-001.phpt
@@ -0,0 +1,82 @@
+--TEST--
+PHPC-1163: Unacknowledged write concern should omit implicit session
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_live(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+class Test implements MongoDB\Driver\Monitoring\CommandSubscriber
+{
+ public function run()
+ {
+ $manager = create_test_manager(URI, ['w' => 0]);
+
+ MongoDB\Driver\Monitoring\addSubscriber($this);
+
+ $bulk = new MongoDB\Driver\BulkWrite;
+ $bulk->insert(['x' => 1]);
+
+ echo "Testing executeBulkWrite\n";
+ $manager->executeBulkWrite(NS, $bulk);
+
+ $command = new MongoDB\Driver\Command([
+ 'insert' => COLLECTION_NAME,
+ 'documents' => [['x' => 1]],
+ ]);
+
+ /* Note: executeCommand() and executeReadCommand() are not tested
+ * because they do not inherit the client-level write concern. */
+
+ echo "\nTesting executeWriteCommand\n";
+ $manager->executeWriteCommand(DATABASE_NAME, $command);
+
+ /* We can safely re-use the insert command with executeReadWriteCommand
+ * because there is no readConcern to inherit. */
+ echo "\nTesting executeReadWriteCommand\n";
+ $manager->executeReadWriteCommand(DATABASE_NAME, $command);
+
+ MongoDB\Driver\Monitoring\removeSubscriber($this);
+ }
+
+ public function commandStarted(MongoDB\Driver\Monitoring\CommandStartedEvent $event)
+ {
+ if ($event->getCommandName() === 'insert') {
+ $command = $event->getCommand();
+ $hasSession = isset($command->lsid);
+ $writeConcern = isset($command->writeConcern) ? $command->writeConcern: null;
+
+ printf("insert command write concern: %s\n", json_encode($writeConcern));
+ printf("insert command has session: %s\n", $hasSession ? 'yes' : 'no');
+ }
+ }
+
+ public function commandSucceeded(MongoDB\Driver\Monitoring\CommandSucceededEvent $event)
+ {
+ }
+
+ public function commandFailed(MongoDB\Driver\Monitoring\CommandFailedEvent $event)
+ {
+ }
+}
+
+(new Test)->run();
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+Testing executeBulkWrite
+insert command write concern: {"w":0}
+insert command has session: no
+
+Testing executeWriteCommand
+insert command write concern: {"w":0}
+insert command has session: no
+
+Testing executeReadWriteCommand
+insert command write concern: {"w":0}
+insert command has session: no
+===DONE===
diff --git a/mongodb-1.12.0/tests/manager/bug1701-001.phpt b/mongodb-1.13.0/tests/manager/bug1701-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/bug1701-001.phpt
rename to mongodb-1.13.0/tests/manager/bug1701-001.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-addSubscriber-001.phpt b/mongodb-1.13.0/tests/manager/manager-addSubscriber-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-addSubscriber-001.phpt
rename to mongodb-1.13.0/tests/manager/manager-addSubscriber-001.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-addSubscriber-002.phpt b/mongodb-1.13.0/tests/manager/manager-addSubscriber-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-addSubscriber-002.phpt
rename to mongodb-1.13.0/tests/manager/manager-addSubscriber-002.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-addSubscriber-003.phpt b/mongodb-1.13.0/tests/manager/manager-addSubscriber-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-addSubscriber-003.phpt
rename to mongodb-1.13.0/tests/manager/manager-addSubscriber-003.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-addSubscriber-004.phpt b/mongodb-1.13.0/tests/manager/manager-addSubscriber-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-addSubscriber-004.phpt
rename to mongodb-1.13.0/tests/manager/manager-addSubscriber-004.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-addSubscriber-005.phpt b/mongodb-1.13.0/tests/manager/manager-addSubscriber-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-addSubscriber-005.phpt
rename to mongodb-1.13.0/tests/manager/manager-addSubscriber-005.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-addSubscriber-006.phpt b/mongodb-1.13.0/tests/manager/manager-addSubscriber-006.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-addSubscriber-006.phpt
rename to mongodb-1.13.0/tests/manager/manager-addSubscriber-006.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-createClientEncryption-001.phpt b/mongodb-1.13.0/tests/manager/manager-createClientEncryption-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-createClientEncryption-001.phpt
rename to mongodb-1.13.0/tests/manager/manager-createClientEncryption-001.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-createClientEncryption-error-001.phpt b/mongodb-1.13.0/tests/manager/manager-createClientEncryption-error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-createClientEncryption-error-001.phpt
rename to mongodb-1.13.0/tests/manager/manager-createClientEncryption-error-001.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-createClientEncryption-error-002.phpt b/mongodb-1.13.0/tests/manager/manager-createClientEncryption-error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-createClientEncryption-error-002.phpt
rename to mongodb-1.13.0/tests/manager/manager-createClientEncryption-error-002.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-001.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-001.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-001.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-002.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-002.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-002.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-003.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-003.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-003.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-004.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-004.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-004.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-005.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-005.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-005.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-006.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-006.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-006.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-006.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-007.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-007.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-007.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-007.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-008.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-008.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-008.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-008.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-appname-001.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-appname-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-appname-001.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-appname-001.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-appname_error-001.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-appname_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-appname_error-001.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-appname_error-001.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-auth_mechanism-001.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-auth_mechanism-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-auth_mechanism-001.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-auth_mechanism-001.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-auth_mechanism-002.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-auth_mechanism-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-auth_mechanism-002.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-auth_mechanism-002.phpt
diff --git a/mongodb-1.13.0/tests/manager/manager-ctor-auth_mechanism-error-001.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-auth_mechanism-error-001.phpt
new file mode 100644
index 00000000..97b9c03b
--- /dev/null
+++ b/mongodb-1.13.0/tests/manager/manager-ctor-auth_mechanism-error-001.phpt
@@ -0,0 +1,54 @@
+--TEST--
+MongoDB\Driver\Manager::__construct(): authentication options are validated
+--FILE--
+<?php
+
+require_once __DIR__ . '/../utils/basic.inc';
+
+echo throws(function() {
+ create_test_manager('mongodb://localhost:27017/?authMechanism=GSSAPI&authSource=admin');
+}, "MongoDB\Driver\Exception\InvalidArgumentException"), "\n";
+
+echo throws(function() {
+ create_test_manager('mongodb://localhost:27017/', ['authMechanism' => 'GSSAPI', 'authSource' => 'admin']);
+}, "MongoDB\Driver\Exception\InvalidArgumentException"), "\n";
+
+echo throws(function() {
+ create_test_manager('mongodb://localhost:27017/?authMechanism=MONGODB-X509&authSource=admin');
+}, "MongoDB\Driver\Exception\InvalidArgumentException"), "\n";
+
+echo throws(function() {
+ create_test_manager('mongodb://localhost:27017/', ['authMechanism' => 'MONGODB-X509', 'authSource' => 'admin']);
+}, "MongoDB\Driver\Exception\InvalidArgumentException"), "\n";
+
+echo throws(function() {
+ create_test_manager('mongodb://@localhost:27017/?authMechanism=SCRAM-SHA-1');
+}, "MongoDB\Driver\Exception\InvalidArgumentException"), "\n";
+
+echo throws(function() {
+ create_test_manager('mongodb://localhost:27017/', ['username' => '', 'authMechanism' => 'SCRAM-SHA-1']);
+}, "MongoDB\Driver\Exception\InvalidArgumentException"), "\n";
+
+echo throws(function() {
+ create_test_manager('mongodb://localhost:27017/', ['password' => 'password', 'authMechanism' => 'MONGODB-X509']);
+}, "MongoDB\Driver\Exception\InvalidArgumentException"), "\n";
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse MongoDB URI: 'mongodb://localhost:27017/?authMechanism=GSSAPI&authSource=admin'. GSSAPI and X509 require "$external" authSource.
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse URI options: GSSAPI and X509 require "$external" authSource
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse MongoDB URI: 'mongodb://localhost:27017/?authMechanism=MONGODB-X509&authSource=admin'. GSSAPI and X509 require "$external" authSource.
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse URI options: GSSAPI and X509 require "$external" authSource
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse MongoDB URI: 'mongodb://@localhost:27017/?authMechanism=SCRAM-SHA-1'. 'SCRAM-SHA-1' authentication mechanism requires username.
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse URI options: 'SCRAM-SHA-1' authentication mechanism requires username
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse URI options: 'MONGODB-X509' authentication mechanism does not accept a password
+===DONE===
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-auth_source-001.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-auth_source-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-auth_source-001.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-auth_source-001.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-auto_encryption-001.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-auto_encryption-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-auto_encryption-001.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-auto_encryption-001.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-auto_encryption-error-001.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-auto_encryption-error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-auto_encryption-error-001.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-auto_encryption-error-001.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-auto_encryption-error-002.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-auto_encryption-error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-auto_encryption-error-002.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-auto_encryption-error-002.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-auto_encryption-error-003.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-auto_encryption-error-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-auto_encryption-error-003.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-auto_encryption-error-003.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-directconnection-001.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-directconnection-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-directconnection-001.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-directconnection-001.phpt
diff --git a/mongodb-1.13.0/tests/manager/manager-ctor-directconnection-error-001.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-directconnection-error-001.phpt
new file mode 100644
index 00000000..67c9490b
--- /dev/null
+++ b/mongodb-1.13.0/tests/manager/manager-ctor-directconnection-error-001.phpt
@@ -0,0 +1,25 @@
+--TEST--
+MongoDB\Driver\Manager::__construct(): directConnection=true conflicts with multiple seeds
+--FILE--
+<?php
+
+require_once __DIR__ . '/../utils/basic.inc';
+
+echo throws(function() {
+ $manager = create_test_manager('mongodb://a.example.com,b.example.com/?directConnection=true');
+}, "MongoDB\Driver\Exception\InvalidArgumentException"), "\n\n";
+
+echo throws(function() {
+ $manager = create_test_manager('mongodb://a.example.com,b.example.com', ['directConnection' => true]);
+}, "MongoDB\Driver\Exception\InvalidArgumentException"), "\n";
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse MongoDB URI: 'mongodb://a.example.com,b.example.com/?directConnection=true'. Multiple seeds not allowed with directConnection option.
+
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse URI options: Multiple seeds not allowed with directConnection option
+===DONE===
diff --git a/mongodb-1.13.0/tests/manager/manager-ctor-directconnection-error-002.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-directconnection-error-002.phpt
new file mode 100644
index 00000000..0f1ae274
--- /dev/null
+++ b/mongodb-1.13.0/tests/manager/manager-ctor-directconnection-error-002.phpt
@@ -0,0 +1,25 @@
+--TEST--
+MongoDB\Driver\Manager::__construct(): directConnection=true conflicts with SRV
+--FILE--
+<?php
+
+require_once __DIR__ . '/../utils/basic.inc';
+
+echo throws(function() {
+ $manager = create_test_manager('mongodb+srv://a.example.com/?directConnection=true');
+}, "MongoDB\Driver\Exception\InvalidArgumentException"), "\n\n";
+
+echo throws(function() {
+ $manager = create_test_manager('mongodb+srv://a.example.com', ['directConnection' => true]);
+}, "MongoDB\Driver\Exception\InvalidArgumentException"), "\n";
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse MongoDB URI: 'mongodb+srv://a.example.com/?directConnection=true'. SRV URI not allowed with directConnection option.
+
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse URI options: SRV URI not allowed with directConnection option
+===DONE===
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-disableClientPersistence-001.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-disableClientPersistence-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-disableClientPersistence-001.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-disableClientPersistence-001.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-disableClientPersistence-002.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-disableClientPersistence-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-disableClientPersistence-002.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-disableClientPersistence-002.phpt
diff --git a/mongodb-1.13.0/tests/manager/manager-ctor-disableClientPersistence-003.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-disableClientPersistence-003.phpt
new file mode 100644
index 00000000..179bed13
--- /dev/null
+++ b/mongodb-1.13.0/tests/manager/manager-ctor-disableClientPersistence-003.phpt
@@ -0,0 +1,39 @@
+--TEST--
+MongoDB\Driver\Manager with disableClientPersistence=true referenced by Session
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_not_live(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+ini_set('mongodb.debug', 'stderr');
+$manager = create_test_manager(URI, [], ['disableClientPersistence' => true]);
+ini_set('mongodb.debug', '');
+
+echo "Creating session\n";
+$session = $manager->startSession();
+
+echo "Unsetting manager\n";
+ini_set('mongodb.debug', 'stderr');
+unset($manager);
+ini_set('mongodb.debug', '');
+
+echo "Unsetting session\n";
+ini_set('mongodb.debug', 'stderr');
+unset($session);
+ini_set('mongodb.debug', '');
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+%A
+[%s] PHONGO: DEBUG > Created client with hash: %s
+[%s] PHONGO: DEBUG > Stored non-persistent client
+Creating session
+Unsetting manager
+Unsetting session%A
+[%s] PHONGO: DEBUG > Destroying non-persistent client for Manager%A
+===DONE===
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-disableClientPersistence-004.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-disableClientPersistence-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-disableClientPersistence-004.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-disableClientPersistence-004.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-disableClientPersistence-005.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-disableClientPersistence-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-disableClientPersistence-005.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-disableClientPersistence-005.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-disableClientPersistence-006.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-disableClientPersistence-006.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-disableClientPersistence-006.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-disableClientPersistence-006.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-disableClientPersistence-007.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-disableClientPersistence-007.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-disableClientPersistence-007.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-disableClientPersistence-007.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-disableClientPersistence-008.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-disableClientPersistence-008.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-disableClientPersistence-008.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-disableClientPersistence-008.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-disableClientPersistence-009.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-disableClientPersistence-009.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-disableClientPersistence-009.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-disableClientPersistence-009.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-disableClientPersistence-010.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-disableClientPersistence-010.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-disableClientPersistence-010.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-disableClientPersistence-010.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-disableClientPersistence-011.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-disableClientPersistence-011.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-disableClientPersistence-011.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-disableClientPersistence-011.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-disableClientPersistence_error-001.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-disableClientPersistence_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-disableClientPersistence_error-001.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-disableClientPersistence_error-001.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-driver-metadata-001.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-driver-metadata-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-driver-metadata-001.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-driver-metadata-001.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-duplicate-option-001.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-duplicate-option-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-duplicate-option-001.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-duplicate-option-001.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-duplicate-option-002.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-duplicate-option-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-duplicate-option-002.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-duplicate-option-002.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-duplicate-option-003.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-duplicate-option-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-duplicate-option-003.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-duplicate-option-003.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-duplicate-option-004.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-duplicate-option-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-duplicate-option-004.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-duplicate-option-004.phpt
diff --git a/mongodb-1.13.0/tests/manager/manager-ctor-loadBalanced_error-001.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-loadBalanced_error-001.phpt
new file mode 100644
index 00000000..e1b34fc9
--- /dev/null
+++ b/mongodb-1.13.0/tests/manager/manager-ctor-loadBalanced_error-001.phpt
@@ -0,0 +1,48 @@
+--TEST--
+MongoDB\Driver\Manager::__construct(): loadBalanced option validation
+--FILE--
+<?php
+
+require_once __DIR__ . '/../utils/basic.inc';
+
+echo throws(function() {
+ create_test_manager('mongodb://localhost:27017,localhost:27018/?loadBalanced=true');
+}, "MongoDB\Driver\Exception\InvalidArgumentException"), "\n";
+
+echo throws(function() {
+ create_test_manager('mongodb://localhost:27017,localhost:27018', ['loadBalanced' => true]);
+}, "MongoDB\Driver\Exception\InvalidArgumentException"), "\n";
+
+echo throws(function() {
+ create_test_manager('mongodb://localhost:27017/?loadBalanced=true&replicaSet=foo');
+}, "MongoDB\Driver\Exception\InvalidArgumentException"), "\n";
+
+echo throws(function() {
+ create_test_manager('mongodb://localhost:27017', ['loadBalanced' => true, 'replicaSet' => 'foo']);
+}, "MongoDB\Driver\Exception\InvalidArgumentException"), "\n";
+
+echo throws(function() {
+ create_test_manager('mongodb://localhost:27017/?loadBalanced=true&directConnection=true');
+}, "MongoDB\Driver\Exception\InvalidArgumentException"), "\n";
+
+echo throws(function() {
+ create_test_manager('mongodb://localhost:27017', ['loadBalanced' => true, 'directConnection' => true]);
+}, "MongoDB\Driver\Exception\InvalidArgumentException"), "\n";
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse MongoDB URI: 'mongodb://localhost:27017,localhost:27018/?loadBalanced=true'. URI with "loadbalanced" enabled must not contain more than one host.
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse URI options: URI with "loadbalanced" enabled must not contain more than one host
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse MongoDB URI: 'mongodb://localhost:27017/?loadBalanced=true&replicaSet=foo'. URI with "loadbalanced" enabled must not contain option "replicaset".
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse URI options: URI with "loadbalanced" enabled must not contain option "replicaset"
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse MongoDB URI: 'mongodb://localhost:27017/?loadBalanced=true&directConnection=true'. URI with "loadbalanced" enabled must not contain option "directconnection" enabled.
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse URI options: URI with "loadbalanced" enabled must not contain option "directconnection" enabled
+===DONE===
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-read_concern-001.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-read_concern-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-read_concern-001.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-read_concern-001.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-read_concern-error-001.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-read_concern-error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-read_concern-error-001.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-read_concern-error-001.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-read_preference-001.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-read_preference-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-read_preference-001.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-read_preference-001.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-read_preference-002.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-read_preference-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-read_preference-002.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-read_preference-002.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-read_preference-error-001.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-read_preference-error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-read_preference-error-001.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-read_preference-error-001.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-read_preference-error-002.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-read_preference-error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-read_preference-error-002.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-read_preference-error-002.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-read_preference-error-004.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-read_preference-error-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-read_preference-error-004.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-read_preference-error-004.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-server.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-server.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-server.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-server.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-serverApi-001.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-serverApi-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-serverApi-001.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-serverApi-001.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-serverApi-error-001.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-serverApi-error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-serverApi-error-001.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-serverApi-error-001.phpt
diff --git a/mongodb-1.13.0/tests/manager/manager-ctor-srvMaxHosts_error-001.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-srvMaxHosts_error-001.phpt
new file mode 100644
index 00000000..83b2b855
--- /dev/null
+++ b/mongodb-1.13.0/tests/manager/manager-ctor-srvMaxHosts_error-001.phpt
@@ -0,0 +1,48 @@
+--TEST--
+MongoDB\Driver\Manager::__construct(): srvMaxHosts option validation
+--FILE--
+<?php
+
+require_once __DIR__ . '/../utils/basic.inc';
+
+echo throws(function() {
+ create_test_manager('mongodb://localhost:27017/?srvMaxHosts=1');
+}, "MongoDB\Driver\Exception\InvalidArgumentException"), "\n";
+
+echo throws(function() {
+ create_test_manager('mongodb://localhost:27017', ['srvMaxHosts' => 1]);
+}, "MongoDB\Driver\Exception\InvalidArgumentException"), "\n";
+
+echo throws(function() {
+ create_test_manager('mongodb+srv://a.example.com/?srvMaxHosts=1&replicaSet=foo');
+}, "MongoDB\Driver\Exception\InvalidArgumentException"), "\n";
+
+echo throws(function() {
+ create_test_manager('mongodb+srv://a.example.com', ['srvMaxHosts' => 1, 'replicaSet' => 'foo']);
+}, "MongoDB\Driver\Exception\InvalidArgumentException"), "\n";
+
+echo throws(function() {
+ create_test_manager('mongodb+srv://a.example.com/?srvMaxHosts=1&loadBalanced=true');
+}, "MongoDB\Driver\Exception\InvalidArgumentException"), "\n";
+
+echo throws(function() {
+ create_test_manager('mongodb+srv://a.example.com', ['srvMaxHosts' => 1, 'loadBalanced' => true]);
+}, "MongoDB\Driver\Exception\InvalidArgumentException"), "\n";
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse MongoDB URI: 'mongodb://localhost:27017/?srvMaxHosts=1'. srvmaxhosts must not be specified with a non-SRV URI.
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse URI options: srvmaxhosts must not be specified with a non-SRV URI
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse MongoDB URI: 'mongodb+srv://a.example.com/?srvMaxHosts=1&replicaSet=foo'. srvmaxhosts must not be specified with replicaset.
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse URI options: srvmaxhosts must not be specified with replicaset
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse MongoDB URI: 'mongodb+srv://a.example.com/?srvMaxHosts=1&loadBalanced=true'. srvmaxhosts must not be specified with loadbalanced=true.
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse URI options: srvmaxhosts must not be specified with loadbalanced=true
+===DONE===
diff --git a/mongodb-1.13.0/tests/manager/manager-ctor-srvServiceName_error-001.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-srvServiceName_error-001.phpt
new file mode 100644
index 00000000..8c726a1f
--- /dev/null
+++ b/mongodb-1.13.0/tests/manager/manager-ctor-srvServiceName_error-001.phpt
@@ -0,0 +1,24 @@
+--TEST--
+MongoDB\Driver\Manager::__construct(): srvServiceName option validation
+--FILE--
+<?php
+
+require_once __DIR__ . '/../utils/basic.inc';
+
+echo throws(function() {
+ create_test_manager('mongodb://localhost:27017/?srvServiceName=foo');
+}, "MongoDB\Driver\Exception\InvalidArgumentException"), "\n";
+
+echo throws(function() {
+ create_test_manager('mongodb://localhost:27017', ['srvServiceName' => 'foo']);
+}, "MongoDB\Driver\Exception\InvalidArgumentException"), "\n";
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse MongoDB URI: 'mongodb://localhost:27017/?srvServiceName=foo'. srvservicename must not be specified with a non-SRV URI.
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse URI options: srvservicename must not be specified with a non-SRV URI
+===DONE===
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-ssl-001.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-ssl-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-ssl-001.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-ssl-001.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-ssl-002.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-ssl-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-ssl-002.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-ssl-002.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-ssl-003.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-ssl-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-ssl-003.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-ssl-003.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-ssl-deprecated-001.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-ssl-deprecated-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-ssl-deprecated-001.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-ssl-deprecated-001.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-ssl-deprecated-002.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-ssl-deprecated-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-ssl-deprecated-002.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-ssl-deprecated-002.phpt
diff --git a/mongodb-1.13.0/tests/manager/manager-ctor-tls-error-001.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-tls-error-001.phpt
new file mode 100644
index 00000000..29695f04
--- /dev/null
+++ b/mongodb-1.13.0/tests/manager/manager-ctor-tls-error-001.phpt
@@ -0,0 +1,152 @@
+--TEST--
+MongoDB\Driver\Manager::__construct(): Test invalid URI option combinations
+--FILE--
+<?php
+
+require_once __DIR__ . '/../utils/basic.inc';
+
+$invalidCombinations = [
+ ['tlsInsecure', 'tlsAllowInvalidHostnames'],
+ ['tlsInsecure', 'tlsAllowInvalidCertificates'],
+ ['tlsInsecure', 'tlsDisableOCSPEndpointCheck'],
+ ['tlsInsecure', 'tlsDisableCertificateRevocationCheck'],
+ ['tlsAllowInvalidCertificates', 'tlsDisableOCSPEndpointCheck'],
+ ['tlsAllowInvalidCertificates', 'tlsDisableCertificateRevocationCheck'],
+];
+
+foreach ($invalidCombinations as list($optionA, $optionB)) {
+ foreach ([false, true] as $valueA) {
+ foreach ([false, true] as $valueB) {
+ echo throws(function() use ($optionA, $valueA, $optionB, $valueB) {
+ create_test_manager(sprintf(
+ 'mongodb://localhost:27017/?%s=%s&%s=%s',
+ $optionA,
+ $valueA ? 'true' : 'false',
+ $optionB,
+ $valueB ? 'true' : 'false'
+ ));
+ }, "MongoDB\Driver\Exception\InvalidArgumentException"), "\n";
+
+ echo throws(function() use ($optionA, $valueA, $optionB, $valueB) {
+ create_test_manager(
+ sprintf(
+ 'mongodb://localhost:27017/?%s=%s',
+ $optionA,
+ $valueA ? 'true' : 'false'
+ ),
+ [ $optionB => $valueB ]
+ );
+ }, "MongoDB\Driver\Exception\InvalidArgumentException"), "\n";
+ }
+ }
+
+ echo "\n";
+}
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse MongoDB URI: 'mongodb://localhost:27017/?tlsInsecure=false&tlsAllowInvalidHostnames=false'. tlsinsecure may not be specified with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck.
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse URI options: tlsinsecure may not be specified with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse MongoDB URI: 'mongodb://localhost:27017/?tlsInsecure=false&tlsAllowInvalidHostnames=true'. tlsinsecure may not be specified with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck.
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse URI options: tlsinsecure may not be specified with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse MongoDB URI: 'mongodb://localhost:27017/?tlsInsecure=true&tlsAllowInvalidHostnames=false'. tlsinsecure may not be specified with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck.
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse URI options: tlsinsecure may not be specified with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse MongoDB URI: 'mongodb://localhost:27017/?tlsInsecure=true&tlsAllowInvalidHostnames=true'. tlsinsecure may not be specified with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck.
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse URI options: tlsinsecure may not be specified with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck
+
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse MongoDB URI: 'mongodb://localhost:27017/?tlsInsecure=false&tlsAllowInvalidCertificates=false'. tlsinsecure may not be specified with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck.
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse URI options: tlsinsecure may not be specified with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse MongoDB URI: 'mongodb://localhost:27017/?tlsInsecure=false&tlsAllowInvalidCertificates=true'. tlsinsecure may not be specified with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck.
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse URI options: tlsinsecure may not be specified with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse MongoDB URI: 'mongodb://localhost:27017/?tlsInsecure=true&tlsAllowInvalidCertificates=false'. tlsinsecure may not be specified with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck.
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse URI options: tlsinsecure may not be specified with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse MongoDB URI: 'mongodb://localhost:27017/?tlsInsecure=true&tlsAllowInvalidCertificates=true'. tlsinsecure may not be specified with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck.
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse URI options: tlsinsecure may not be specified with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck
+
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse MongoDB URI: 'mongodb://localhost:27017/?tlsInsecure=false&tlsDisableOCSPEndpointCheck=false'. tlsinsecure may not be specified with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck.
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse URI options: tlsinsecure may not be specified with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse MongoDB URI: 'mongodb://localhost:27017/?tlsInsecure=false&tlsDisableOCSPEndpointCheck=true'. tlsinsecure may not be specified with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck.
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse URI options: tlsinsecure may not be specified with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse MongoDB URI: 'mongodb://localhost:27017/?tlsInsecure=true&tlsDisableOCSPEndpointCheck=false'. tlsinsecure may not be specified with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck.
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse URI options: tlsinsecure may not be specified with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse MongoDB URI: 'mongodb://localhost:27017/?tlsInsecure=true&tlsDisableOCSPEndpointCheck=true'. tlsinsecure may not be specified with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck.
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse URI options: tlsinsecure may not be specified with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck
+
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse MongoDB URI: 'mongodb://localhost:27017/?tlsInsecure=false&tlsDisableCertificateRevocationCheck=false'. tlsinsecure may not be specified with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck.
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse URI options: tlsinsecure may not be specified with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse MongoDB URI: 'mongodb://localhost:27017/?tlsInsecure=false&tlsDisableCertificateRevocationCheck=true'. tlsinsecure may not be specified with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck.
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse URI options: tlsinsecure may not be specified with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse MongoDB URI: 'mongodb://localhost:27017/?tlsInsecure=true&tlsDisableCertificateRevocationCheck=false'. tlsinsecure may not be specified with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck.
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse URI options: tlsinsecure may not be specified with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse MongoDB URI: 'mongodb://localhost:27017/?tlsInsecure=true&tlsDisableCertificateRevocationCheck=true'. tlsinsecure may not be specified with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck.
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse URI options: tlsinsecure may not be specified with tlsallowinvalidcertificates, tlsallowinvalidhostnames, tlsdisableocspendpointcheck, or tlsdisablecertificaterevocationcheck
+
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse MongoDB URI: 'mongodb://localhost:27017/?tlsAllowInvalidCertificates=false&tlsDisableOCSPEndpointCheck=false'. tlsallowinvalidcertificates may not be specified with tlsdisableocspendpointcheck or tlsdisablecertificaterevocationcheck.
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse URI options: tlsallowinvalidcertificates may not be specified with tlsdisableocspendpointcheck or tlsdisablecertificaterevocationcheck
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse MongoDB URI: 'mongodb://localhost:27017/?tlsAllowInvalidCertificates=false&tlsDisableOCSPEndpointCheck=true'. tlsallowinvalidcertificates may not be specified with tlsdisableocspendpointcheck or tlsdisablecertificaterevocationcheck.
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse URI options: tlsallowinvalidcertificates may not be specified with tlsdisableocspendpointcheck or tlsdisablecertificaterevocationcheck
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse MongoDB URI: 'mongodb://localhost:27017/?tlsAllowInvalidCertificates=true&tlsDisableOCSPEndpointCheck=false'. tlsallowinvalidcertificates may not be specified with tlsdisableocspendpointcheck or tlsdisablecertificaterevocationcheck.
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse URI options: tlsallowinvalidcertificates may not be specified with tlsdisableocspendpointcheck or tlsdisablecertificaterevocationcheck
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse MongoDB URI: 'mongodb://localhost:27017/?tlsAllowInvalidCertificates=true&tlsDisableOCSPEndpointCheck=true'. tlsallowinvalidcertificates may not be specified with tlsdisableocspendpointcheck or tlsdisablecertificaterevocationcheck.
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse URI options: tlsallowinvalidcertificates may not be specified with tlsdisableocspendpointcheck or tlsdisablecertificaterevocationcheck
+
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse MongoDB URI: 'mongodb://localhost:27017/?tlsAllowInvalidCertificates=false&tlsDisableCertificateRevocationCheck=false'. tlsallowinvalidcertificates may not be specified with tlsdisableocspendpointcheck or tlsdisablecertificaterevocationcheck.
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse URI options: tlsallowinvalidcertificates may not be specified with tlsdisableocspendpointcheck or tlsdisablecertificaterevocationcheck
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse MongoDB URI: 'mongodb://localhost:27017/?tlsAllowInvalidCertificates=false&tlsDisableCertificateRevocationCheck=true'. tlsallowinvalidcertificates may not be specified with tlsdisableocspendpointcheck or tlsdisablecertificaterevocationcheck.
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse URI options: tlsallowinvalidcertificates may not be specified with tlsdisableocspendpointcheck or tlsdisablecertificaterevocationcheck
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse MongoDB URI: 'mongodb://localhost:27017/?tlsAllowInvalidCertificates=true&tlsDisableCertificateRevocationCheck=false'. tlsallowinvalidcertificates may not be specified with tlsdisableocspendpointcheck or tlsdisablecertificaterevocationcheck.
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse URI options: tlsallowinvalidcertificates may not be specified with tlsdisableocspendpointcheck or tlsdisablecertificaterevocationcheck
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse MongoDB URI: 'mongodb://localhost:27017/?tlsAllowInvalidCertificates=true&tlsDisableCertificateRevocationCheck=true'. tlsallowinvalidcertificates may not be specified with tlsdisableocspendpointcheck or tlsdisablecertificaterevocationcheck.
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Failed to parse URI options: tlsallowinvalidcertificates may not be specified with tlsdisableocspendpointcheck or tlsdisablecertificaterevocationcheck
+
+===DONE===
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-wireversion.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-wireversion.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-wireversion.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-wireversion.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-write_concern-001.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-write_concern-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-write_concern-001.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-write_concern-001.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-write_concern-002.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-write_concern-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-write_concern-002.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-write_concern-002.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-write_concern-003.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-write_concern-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-write_concern-003.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-write_concern-003.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-write_concern-004.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-write_concern-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-write_concern-004.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-write_concern-004.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-write_concern-005.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-write_concern-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-write_concern-005.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-write_concern-005.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-write_concern-006.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-write_concern-006.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-write_concern-006.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-write_concern-006.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-write_concern-error-001.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-write_concern-error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-write_concern-error-001.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-write_concern-error-001.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-write_concern-error-002.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-write_concern-error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-write_concern-error-002.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-write_concern-error-002.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-write_concern-error-003.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-write_concern-error-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-write_concern-error-003.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-write_concern-error-003.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-write_concern-error-005.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-write_concern-error-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-write_concern-error-005.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-write_concern-error-005.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-write_concern-error-006.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-write_concern-error-006.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-write_concern-error-006.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-write_concern-error-006.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor-write_concern-error-007.phpt b/mongodb-1.13.0/tests/manager/manager-ctor-write_concern-error-007.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor-write_concern-error-007.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor-write_concern-error-007.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor_error-001.phpt b/mongodb-1.13.0/tests/manager/manager-ctor_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor_error-001.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor_error-001.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor_error-002.phpt b/mongodb-1.13.0/tests/manager/manager-ctor_error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor_error-002.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor_error-002.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor_error-003.phpt b/mongodb-1.13.0/tests/manager/manager-ctor_error-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor_error-003.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor_error-003.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor_error-004.phpt b/mongodb-1.13.0/tests/manager/manager-ctor_error-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor_error-004.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor_error-004.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-ctor_error-005.phpt b/mongodb-1.13.0/tests/manager/manager-ctor_error-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-ctor_error-005.phpt
rename to mongodb-1.13.0/tests/manager/manager-ctor_error-005.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-debug-001.phpt b/mongodb-1.13.0/tests/manager/manager-debug-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-debug-001.phpt
rename to mongodb-1.13.0/tests/manager/manager-debug-001.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-debug-002.phpt b/mongodb-1.13.0/tests/manager/manager-debug-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-debug-002.phpt
rename to mongodb-1.13.0/tests/manager/manager-debug-002.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-debug-003.phpt b/mongodb-1.13.0/tests/manager/manager-debug-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-debug-003.phpt
rename to mongodb-1.13.0/tests/manager/manager-debug-003.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-destruct-001.phpt b/mongodb-1.13.0/tests/manager/manager-destruct-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-destruct-001.phpt
rename to mongodb-1.13.0/tests/manager/manager-destruct-001.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-executeBulkWrite-001.phpt b/mongodb-1.13.0/tests/manager/manager-executeBulkWrite-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-executeBulkWrite-001.phpt
rename to mongodb-1.13.0/tests/manager/manager-executeBulkWrite-001.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-executeBulkWrite-002.phpt b/mongodb-1.13.0/tests/manager/manager-executeBulkWrite-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-executeBulkWrite-002.phpt
rename to mongodb-1.13.0/tests/manager/manager-executeBulkWrite-002.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-executeBulkWrite-003.phpt b/mongodb-1.13.0/tests/manager/manager-executeBulkWrite-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-executeBulkWrite-003.phpt
rename to mongodb-1.13.0/tests/manager/manager-executeBulkWrite-003.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-executeBulkWrite-004.phpt b/mongodb-1.13.0/tests/manager/manager-executeBulkWrite-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-executeBulkWrite-004.phpt
rename to mongodb-1.13.0/tests/manager/manager-executeBulkWrite-004.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-executeBulkWrite-005.phpt b/mongodb-1.13.0/tests/manager/manager-executeBulkWrite-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-executeBulkWrite-005.phpt
rename to mongodb-1.13.0/tests/manager/manager-executeBulkWrite-005.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-executeBulkWrite-006.phpt b/mongodb-1.13.0/tests/manager/manager-executeBulkWrite-006.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-executeBulkWrite-006.phpt
rename to mongodb-1.13.0/tests/manager/manager-executeBulkWrite-006.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-executeBulkWrite-007.phpt b/mongodb-1.13.0/tests/manager/manager-executeBulkWrite-007.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-executeBulkWrite-007.phpt
rename to mongodb-1.13.0/tests/manager/manager-executeBulkWrite-007.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-executeBulkWrite-008.phpt b/mongodb-1.13.0/tests/manager/manager-executeBulkWrite-008.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-executeBulkWrite-008.phpt
rename to mongodb-1.13.0/tests/manager/manager-executeBulkWrite-008.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-executeBulkWrite-009.phpt b/mongodb-1.13.0/tests/manager/manager-executeBulkWrite-009.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-executeBulkWrite-009.phpt
rename to mongodb-1.13.0/tests/manager/manager-executeBulkWrite-009.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-executeBulkWrite-010.phpt b/mongodb-1.13.0/tests/manager/manager-executeBulkWrite-010.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-executeBulkWrite-010.phpt
rename to mongodb-1.13.0/tests/manager/manager-executeBulkWrite-010.phpt
diff --git a/mongodb-1.13.0/tests/manager/manager-executeBulkWrite-011.phpt b/mongodb-1.13.0/tests/manager/manager-executeBulkWrite-011.phpt
new file mode 100644
index 00000000..4ae81450
--- /dev/null
+++ b/mongodb-1.13.0/tests/manager/manager-executeBulkWrite-011.phpt
@@ -0,0 +1,84 @@
+--TEST--
+MongoDB\Driver\BulkWrite: bypassDocumentValidation option
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_live(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+
+$command = new MongoDB\Driver\Command([
+ 'create' => COLLECTION_NAME,
+ 'validator' => ['x' => ['$type' => 'number']],
+]);
+$manager->executeCommand(DATABASE_NAME, $command);
+
+$bulk = new MongoDB\Driver\BulkWrite();
+$bulk->insert(['_id' => 1, 'x' => 1]);
+$bulk->insert(['_id' => 2, 'x' => 2]);
+$manager->executeBulkWrite(NS, $bulk);
+
+$bulk = new MongoDB\Driver\BulkWrite(['bypassDocumentValidation' => true]);
+$bulk->update(['_id' => 2], ['$set' => ['x' => 'two']]);
+$manager->executeBulkWrite(NS, $bulk);
+
+$bulk = new MongoDB\Driver\BulkWrite(['bypassDocumentValidation' => true]);
+$bulk->insert(['_id' => 3, 'x' => 'three']);
+$manager->executeBulkWrite(NS, $bulk);
+
+$bulk = new MongoDB\Driver\BulkWrite();
+$bulk->insert(['_id' => 4, 'x' => 'four']);
+
+echo throws(function() use($manager, $bulk) {
+ $manager->executeBulkWrite(NS, $bulk);
+}, "MongoDB\Driver\Exception\BulkWriteException"), "\n";
+
+$bulk = new MongoDB\Driver\BulkWrite();
+$bulk->update(['_id' => 1], ['$set' => ['x' => 'one']]);
+
+echo throws(function() use($manager, $bulk) {
+ $manager->executeBulkWrite(NS, $bulk);
+}, "MongoDB\Driver\Exception\BulkWriteException"), "\n";
+
+$bulk = new MongoDB\Driver\BulkWrite();
+$bulk->update(['_id' => 2], ['$set' => ['x' => 2]]);
+$manager->executeBulkWrite(NS, $bulk);
+
+$cursor = $manager->executeQuery(NS, new MongoDB\Driver\Query([]));
+var_dump(iterator_to_array($cursor));
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+OK: Got MongoDB\Driver\Exception\BulkWriteException
+Document failed validation
+OK: Got MongoDB\Driver\Exception\BulkWriteException
+Document failed validation
+array(3) {
+ [0]=>
+ object(stdClass)#%d (2) {
+ ["_id"]=>
+ int(1)
+ ["x"]=>
+ int(1)
+ }
+ [1]=>
+ object(stdClass)#%d (2) {
+ ["_id"]=>
+ int(2)
+ ["x"]=>
+ int(2)
+ }
+ [2]=>
+ object(stdClass)#%d (2) {
+ ["_id"]=>
+ int(3)
+ ["x"]=>
+ string(5) "three"
+ }
+}
+===DONE===
diff --git a/mongodb-1.12.0/tests/manager/manager-executeBulkWrite-012.phpt b/mongodb-1.13.0/tests/manager/manager-executeBulkWrite-012.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-executeBulkWrite-012.phpt
rename to mongodb-1.13.0/tests/manager/manager-executeBulkWrite-012.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-executeBulkWrite-013.phpt b/mongodb-1.13.0/tests/manager/manager-executeBulkWrite-013.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-executeBulkWrite-013.phpt
rename to mongodb-1.13.0/tests/manager/manager-executeBulkWrite-013.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-executeBulkWrite-014.phpt b/mongodb-1.13.0/tests/manager/manager-executeBulkWrite-014.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-executeBulkWrite-014.phpt
rename to mongodb-1.13.0/tests/manager/manager-executeBulkWrite-014.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-executeBulkWrite_error-001.phpt b/mongodb-1.13.0/tests/manager/manager-executeBulkWrite_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-executeBulkWrite_error-001.phpt
rename to mongodb-1.13.0/tests/manager/manager-executeBulkWrite_error-001.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-executeBulkWrite_error-002.phpt b/mongodb-1.13.0/tests/manager/manager-executeBulkWrite_error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-executeBulkWrite_error-002.phpt
rename to mongodb-1.13.0/tests/manager/manager-executeBulkWrite_error-002.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-executeBulkWrite_error-003.phpt b/mongodb-1.13.0/tests/manager/manager-executeBulkWrite_error-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-executeBulkWrite_error-003.phpt
rename to mongodb-1.13.0/tests/manager/manager-executeBulkWrite_error-003.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-executeBulkWrite_error-004.phpt b/mongodb-1.13.0/tests/manager/manager-executeBulkWrite_error-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-executeBulkWrite_error-004.phpt
rename to mongodb-1.13.0/tests/manager/manager-executeBulkWrite_error-004.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-executeBulkWrite_error-005.phpt b/mongodb-1.13.0/tests/manager/manager-executeBulkWrite_error-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-executeBulkWrite_error-005.phpt
rename to mongodb-1.13.0/tests/manager/manager-executeBulkWrite_error-005.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-executeBulkWrite_error-006.phpt b/mongodb-1.13.0/tests/manager/manager-executeBulkWrite_error-006.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-executeBulkWrite_error-006.phpt
rename to mongodb-1.13.0/tests/manager/manager-executeBulkWrite_error-006.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-executeBulkWrite_error-007.phpt b/mongodb-1.13.0/tests/manager/manager-executeBulkWrite_error-007.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-executeBulkWrite_error-007.phpt
rename to mongodb-1.13.0/tests/manager/manager-executeBulkWrite_error-007.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-executeBulkWrite_error-008.phpt b/mongodb-1.13.0/tests/manager/manager-executeBulkWrite_error-008.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-executeBulkWrite_error-008.phpt
rename to mongodb-1.13.0/tests/manager/manager-executeBulkWrite_error-008.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-executeBulkWrite_error-009.phpt b/mongodb-1.13.0/tests/manager/manager-executeBulkWrite_error-009.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-executeBulkWrite_error-009.phpt
rename to mongodb-1.13.0/tests/manager/manager-executeBulkWrite_error-009.phpt
diff --git a/mongodb-1.13.0/tests/manager/manager-executeBulkWrite_error-010.phpt b/mongodb-1.13.0/tests/manager/manager-executeBulkWrite_error-010.phpt
new file mode 100644
index 00000000..d66f41cb
--- /dev/null
+++ b/mongodb-1.13.0/tests/manager/manager-executeBulkWrite_error-010.phpt
@@ -0,0 +1,42 @@
+--TEST--
+MongoDB\Driver\Manager::executeBulkWrite() cannot combine session with unacknowledged write concern
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_not_live(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+echo throws(function() {
+ $manager = create_test_manager();
+
+ $bulk = new MongoDB\Driver\BulkWrite;
+ $bulk->insert(['x' => 1]);
+
+ $manager->executeBulkWrite(NS, $bulk, [
+ 'session' => $manager->startSession(),
+ 'writeConcern' => new MongoDB\Driver\WriteConcern(0),
+ ]);
+}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
+
+echo throws(function() {
+ $manager = create_test_manager(URI, ['w' => 0]);
+
+ $bulk = new MongoDB\Driver\BulkWrite;
+ $bulk->insert(['x' => 1]);
+
+ $manager->executeBulkWrite(NS, $bulk, [
+ 'session' => $manager->startSession(),
+ ]);
+}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Cannot combine "session" option with an unacknowledged write concern
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Cannot combine "session" option with an unacknowledged write concern
+===DONE===
diff --git a/mongodb-1.12.0/tests/manager/manager-executeBulkWrite_error-011.phpt b/mongodb-1.13.0/tests/manager/manager-executeBulkWrite_error-011.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-executeBulkWrite_error-011.phpt
rename to mongodb-1.13.0/tests/manager/manager-executeBulkWrite_error-011.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-executeCommand-001.phpt b/mongodb-1.13.0/tests/manager/manager-executeCommand-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-executeCommand-001.phpt
rename to mongodb-1.13.0/tests/manager/manager-executeCommand-001.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-executeCommand-002.phpt b/mongodb-1.13.0/tests/manager/manager-executeCommand-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-executeCommand-002.phpt
rename to mongodb-1.13.0/tests/manager/manager-executeCommand-002.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-executeCommand-003.phpt b/mongodb-1.13.0/tests/manager/manager-executeCommand-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-executeCommand-003.phpt
rename to mongodb-1.13.0/tests/manager/manager-executeCommand-003.phpt
diff --git a/mongodb-1.13.0/tests/manager/manager-executeCommand-004.phpt b/mongodb-1.13.0/tests/manager/manager-executeCommand-004.phpt
new file mode 100644
index 00000000..6f53691d
--- /dev/null
+++ b/mongodb-1.13.0/tests/manager/manager-executeCommand-004.phpt
@@ -0,0 +1,50 @@
+--TEST--
+MongoDB\Driver\Manager::executeCommand() options (MONGOC_CMD_RAW)
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_live(); ?>
+<?php skip_if_not_replica_set(); ?>
+<?php skip_if_no_secondary(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+require_once __DIR__ . "/../utils/observer.php";
+
+$manager = create_test_manager();
+
+(new CommandObserver)->observe(
+ function() use ($manager) {
+ $command = new MongoDB\Driver\Command([
+ 'ping' => true,
+ ]);
+
+ try {
+ $manager->executeCommand(
+ DATABASE_NAME,
+ $command,
+ [
+ 'readPreference' => new \MongoDB\Driver\ReadPreference(\MongoDB\Driver\ReadPreference::RP_SECONDARY),
+ 'readConcern' => new \MongoDB\Driver\ReadConcern(\MongoDB\Driver\ReadConcern::LOCAL),
+ 'writeConcern' => new \MongoDB\Driver\WriteConcern(\MongoDB\Driver\WriteConcern::MAJORITY),
+ ]
+ );
+ } catch ( Exception $e ) {
+ // Ignore exception that ping doesn't support writeConcern
+ }
+ },
+ function(stdClass $command) {
+ echo "Read Preference: ", $command->{'$readPreference'}->mode, "\n";
+ echo "Read Concern: ", $command->readConcern->level, "\n";
+ echo "Write Concern: ", $command->writeConcern->w, "\n";
+ }
+);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Read Preference: secondary
+Read Concern: local
+Write Concern: majority
+===DONE===
diff --git a/mongodb-1.12.0/tests/manager/manager-executeCommand-005.phpt b/mongodb-1.13.0/tests/manager/manager-executeCommand-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-executeCommand-005.phpt
rename to mongodb-1.13.0/tests/manager/manager-executeCommand-005.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-executeCommand-006.phpt b/mongodb-1.13.0/tests/manager/manager-executeCommand-006.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-executeCommand-006.phpt
rename to mongodb-1.13.0/tests/manager/manager-executeCommand-006.phpt
diff --git a/mongodb-1.13.0/tests/manager/manager-executeCommand-007.phpt b/mongodb-1.13.0/tests/manager/manager-executeCommand-007.phpt
new file mode 100644
index 00000000..14e06cac
--- /dev/null
+++ b/mongodb-1.13.0/tests/manager/manager-executeCommand-007.phpt
@@ -0,0 +1,46 @@
+--TEST--
+MongoDB\Driver\Manager::executeCommand() does not inherit read or write concern
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_replica_set(); ?>
+<?php skip_if_not_enough_data_nodes(2); /* w:2 */ ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+require_once __DIR__ . "/../utils/observer.php";
+
+$manager = create_test_manager(URI, ['readConcernLevel' => 'local', 'w' => 2, 'wtimeoutms' => 1000]);
+
+$command = new MongoDB\Driver\Command([
+ 'aggregate' => COLLECTION_NAME,
+ 'pipeline' => [
+ ['$group' => ['_id' => 1]],
+ ['$out' => COLLECTION_NAME . '.out'],
+ ],
+ 'cursor' => (object) [],
+]);
+
+(new CommandObserver)->observe(
+ function() use ($manager, $command) {
+ $manager->executeCommand(DATABASE_NAME, $command);
+ $manager->executeCommand(DATABASE_NAME, $command, [
+ 'readConcern' => new MongoDB\Driver\ReadConcern(MongoDB\Driver\ReadConcern::AVAILABLE),
+ 'writeConcern' => new MongoDB\Driver\WriteConcern(1),
+ ]);
+ },
+ function(stdClass $command) {
+ echo json_encode($command->readConcern ?? null), "\n";
+ echo json_encode($command->writeConcern ?? null), "\n";
+ }
+);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+null
+null
+{"level":"available"}
+{"w":1}
+===DONE===
diff --git a/mongodb-1.12.0/tests/manager/manager-executeCommand_error-001.phpt b/mongodb-1.13.0/tests/manager/manager-executeCommand_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-executeCommand_error-001.phpt
rename to mongodb-1.13.0/tests/manager/manager-executeCommand_error-001.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-executeCommand_error-002.phpt b/mongodb-1.13.0/tests/manager/manager-executeCommand_error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-executeCommand_error-002.phpt
rename to mongodb-1.13.0/tests/manager/manager-executeCommand_error-002.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-executeCommand_error-003.phpt b/mongodb-1.13.0/tests/manager/manager-executeCommand_error-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-executeCommand_error-003.phpt
rename to mongodb-1.13.0/tests/manager/manager-executeCommand_error-003.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-executeCommand_error-004.phpt b/mongodb-1.13.0/tests/manager/manager-executeCommand_error-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-executeCommand_error-004.phpt
rename to mongodb-1.13.0/tests/manager/manager-executeCommand_error-004.phpt
diff --git a/mongodb-1.13.0/tests/manager/manager-executeCommand_error-005.phpt b/mongodb-1.13.0/tests/manager/manager-executeCommand_error-005.phpt
new file mode 100644
index 00000000..5ed7fc56
--- /dev/null
+++ b/mongodb-1.13.0/tests/manager/manager-executeCommand_error-005.phpt
@@ -0,0 +1,27 @@
+--TEST--
+MongoDB\Driver\Manager::executeCommand() cannot combine session with unacknowledged write concern
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_not_live(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+echo throws(function() {
+ $manager = create_test_manager();
+ $command = new MongoDB\Driver\Command([
+ 'insert' => COLLECTION_NAME,
+ 'documents' => [['x' => 1]],
+ ]);
+ $manager->executeCommand(DATABASE_NAME, $command, [
+ 'session' => $manager->startSession(),
+ 'writeConcern' => new MongoDB\Driver\WriteConcern(0),
+ ]);
+}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Cannot combine "session" option with an unacknowledged write concern
+===DONE===
diff --git a/mongodb-1.13.0/tests/manager/manager-executeQuery-002.phpt b/mongodb-1.13.0/tests/manager/manager-executeQuery-002.phpt
new file mode 100644
index 00000000..c1f54d3a
--- /dev/null
+++ b/mongodb-1.13.0/tests/manager/manager-executeQuery-002.phpt
@@ -0,0 +1,91 @@
+--TEST--
+MongoDB\Driver\Manager::executeQuery() one document
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_live(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+
+// load fixtures for test
+$bulk = new MongoDB\Driver\BulkWrite();
+$bulk->insert(array('_id' => 1, 'x' => 2, 'y' => 3));
+$bulk->insert(array('_id' => 2, 'x' => 3, 'y' => 4));
+$bulk->insert(array('_id' => 3, 'x' => 4, 'y' => 5));
+$manager->executeBulkWrite(NS, $bulk);
+
+$query = new MongoDB\Driver\Query(array('x' => 3), array('projection' => array('y' => 1)));
+$qr = $manager->executeQuery(NS, $query);
+
+var_dump($qr instanceof MongoDB\Driver\Cursor);
+var_dump($qr);
+
+$server = $qr->getServer();
+
+var_dump($server instanceof MongoDB\Driver\Server);
+var_dump($server->getHost());
+var_dump($server->getPort());
+
+var_dump(iterator_to_array($qr));
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+bool(true)
+object(MongoDB\Driver\Cursor)#%d (%d) {
+ ["database"]=>
+ string(6) "phongo"
+ ["collection"]=>
+ string(32) "manager_manager_executeQuery_002"
+ ["query"]=>
+ object(MongoDB\Driver\Query)#%d (%d) {
+ ["filter"]=>
+ object(stdClass)#%d (%d) {
+ ["x"]=>
+ int(3)
+ }
+ ["options"]=>
+ object(stdClass)#%d (%d) {
+ ["projection"]=>
+ object(stdClass)#%d (%d) {
+ ["y"]=>
+ int(1)
+ }
+ }
+ ["readConcern"]=>
+ NULL
+ }
+ ["command"]=>
+ NULL
+ ["readPreference"]=>
+ NULL
+ ["session"]=>
+ NULL
+ ["isDead"]=>
+ bool(false)
+ ["currentIndex"]=>
+ int(0)
+ ["currentDocument"]=>
+ NULL
+ ["server"]=>
+ object(MongoDB\Driver\Server)#%d (%d) {
+ %a
+ }
+}
+bool(true)
+string(%d) "%s"
+int(%d)
+array(1) {
+ [0]=>
+ object(stdClass)#%d (2) {
+ ["_id"]=>
+ int(2)
+ ["y"]=>
+ int(4)
+ }
+}
+===DONE===
diff --git a/mongodb-1.12.0/tests/manager/manager-executeQuery-003.phpt b/mongodb-1.13.0/tests/manager/manager-executeQuery-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-executeQuery-003.phpt
rename to mongodb-1.13.0/tests/manager/manager-executeQuery-003.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-executeQuery-004.phpt b/mongodb-1.13.0/tests/manager/manager-executeQuery-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-executeQuery-004.phpt
rename to mongodb-1.13.0/tests/manager/manager-executeQuery-004.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-executeQuery-005.phpt b/mongodb-1.13.0/tests/manager/manager-executeQuery-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-executeQuery-005.phpt
rename to mongodb-1.13.0/tests/manager/manager-executeQuery-005.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-executeQuery-006.phpt b/mongodb-1.13.0/tests/manager/manager-executeQuery-006.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-executeQuery-006.phpt
rename to mongodb-1.13.0/tests/manager/manager-executeQuery-006.phpt
diff --git a/mongodb-1.13.0/tests/manager/manager-executeQuery-007.phpt b/mongodb-1.13.0/tests/manager/manager-executeQuery-007.phpt
new file mode 100644
index 00000000..3f3fe43a
--- /dev/null
+++ b/mongodb-1.13.0/tests/manager/manager-executeQuery-007.phpt
@@ -0,0 +1,32 @@
+--TEST--
+MongoDB\Driver\Manager::executeQuery() read concern inheritance
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_replica_set(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+require_once __DIR__ . "/../utils/observer.php";
+
+$manager = create_test_manager(URI, ['readConcernLevel' => 'local']);
+
+(new CommandObserver)->observe(
+ function() use ($manager) {
+ $manager->executeQuery(NS, new MongoDB\Driver\Query([]));
+ $manager->executeQuery(NS, new MongoDB\Driver\Query([], [
+ 'readConcern' => new MongoDB\Driver\ReadConcern(MongoDB\Driver\ReadConcern::AVAILABLE),
+ ]));
+ },
+ function(stdClass $command) {
+ echo json_encode($command->readConcern), "\n";
+ }
+);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+{"level":"local"}
+{"level":"available"}
+===DONE===
diff --git a/mongodb-1.12.0/tests/manager/manager-executeQuery_error-001.phpt b/mongodb-1.13.0/tests/manager/manager-executeQuery_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-executeQuery_error-001.phpt
rename to mongodb-1.13.0/tests/manager/manager-executeQuery_error-001.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-executeQuery_error-002.phpt b/mongodb-1.13.0/tests/manager/manager-executeQuery_error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-executeQuery_error-002.phpt
rename to mongodb-1.13.0/tests/manager/manager-executeQuery_error-002.phpt
diff --git a/mongodb-1.13.0/tests/manager/manager-executeQuery_error-003.phpt b/mongodb-1.13.0/tests/manager/manager-executeQuery_error-003.phpt
new file mode 100644
index 00000000..b79b6b34
--- /dev/null
+++ b/mongodb-1.13.0/tests/manager/manager-executeQuery_error-003.phpt
@@ -0,0 +1,29 @@
+--TEST--
+MongoDB\Driver\Manager::executeQuery() exposes error document via CommandException
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_live(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+$query = new MongoDB\Driver\Query(['field' => ['$unsupportedOperator' => true]]);
+
+try {
+ $manager->executeQuery(NS, $query);
+} catch (\MongoDB\Driver\Exception\CommandException $e) {
+ printf("%s(%d): %s\n", get_class($e), $e->getCode(), $e->getMessage());
+ $doc = $e->getResultDocument();
+ var_dump($doc->errmsg === $e->getMessage());
+ var_dump($doc->code === $e->getCode());
+}
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+MongoDB\Driver\Exception\CommandException(2): unknown operator: $unsupportedOperator
+bool(true)
+bool(true)
+===DONE===
diff --git a/mongodb-1.13.0/tests/manager/manager-executeReadCommand-001.phpt b/mongodb-1.13.0/tests/manager/manager-executeReadCommand-001.phpt
new file mode 100644
index 00000000..d8a506f0
--- /dev/null
+++ b/mongodb-1.13.0/tests/manager/manager-executeReadCommand-001.phpt
@@ -0,0 +1,46 @@
+--TEST--
+MongoDB\Driver\Manager::executeReadCommand()
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_live(); ?>
+<?php skip_if_not_replica_set(); ?>
+<?php skip_if_no_secondary(); ?>
+<?php skip_if_not_server_storage_engine('wiredTiger'); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+require_once __DIR__ . "/../utils/observer.php";
+
+$manager = create_test_manager();
+
+(new CommandObserver)->observe(
+ function() use ($manager) {
+ $command = new MongoDB\Driver\Command( [
+ 'aggregate' => NS,
+ 'pipeline' => [],
+ 'cursor' => new stdClass(),
+ ] );
+ $manager->executeReadCommand(
+ DATABASE_NAME,
+ $command,
+ [
+ 'readPreference' => new \MongoDB\Driver\ReadPreference(\MongoDB\Driver\ReadPreference::RP_SECONDARY),
+ 'readConcern' => new \MongoDB\Driver\ReadConcern(\MongoDB\Driver\ReadConcern::MAJORITY),
+ ]
+ );
+ },
+ function(stdClass $command) {
+ echo "Read Preference: ", $command->{'$readPreference'}->mode, "\n";
+ echo "Read Concern: ", $command->readConcern->level, "\n";
+ }
+);
+
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Read Preference: secondary
+Read Concern: majority
+===DONE===
diff --git a/mongodb-1.12.0/tests/manager/manager-executeReadCommand-002.phpt b/mongodb-1.13.0/tests/manager/manager-executeReadCommand-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-executeReadCommand-002.phpt
rename to mongodb-1.13.0/tests/manager/manager-executeReadCommand-002.phpt
diff --git a/mongodb-1.13.0/tests/manager/manager-executeReadCommand-003.phpt b/mongodb-1.13.0/tests/manager/manager-executeReadCommand-003.phpt
new file mode 100644
index 00000000..168b6a1f
--- /dev/null
+++ b/mongodb-1.13.0/tests/manager/manager-executeReadCommand-003.phpt
@@ -0,0 +1,38 @@
+--TEST--
+MongoDB\Driver\Manager::executeReadCommand() read concern inheritance
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_replica_set(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+require_once __DIR__ . "/../utils/observer.php";
+
+$manager = create_test_manager(URI, ['readConcernLevel' => 'local']);
+
+$command = new MongoDB\Driver\Command([
+ 'aggregate' => COLLECTION_NAME,
+ 'pipeline' => [['$group' => ['_id' => 1]]],
+ 'cursor' => (object) [],
+]);
+
+(new CommandObserver)->observe(
+ function() use ($manager, $command) {
+ $manager->executeReadCommand(DATABASE_NAME, $command);
+ $manager->executeReadCommand(DATABASE_NAME, $command, [
+ 'readConcern' => new MongoDB\Driver\ReadConcern(MongoDB\Driver\ReadConcern::AVAILABLE),
+ ]);
+ },
+ function(stdClass $command) {
+ echo json_encode($command->readConcern), "\n";
+ }
+);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+{"level":"local"}
+{"level":"available"}
+===DONE===
diff --git a/mongodb-1.12.0/tests/manager/manager-executeReadCommand_error-001.phpt b/mongodb-1.13.0/tests/manager/manager-executeReadCommand_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-executeReadCommand_error-001.phpt
rename to mongodb-1.13.0/tests/manager/manager-executeReadCommand_error-001.phpt
diff --git a/mongodb-1.13.0/tests/manager/manager-executeReadWriteCommand-001.phpt b/mongodb-1.13.0/tests/manager/manager-executeReadWriteCommand-001.phpt
new file mode 100644
index 00000000..ca387dcd
--- /dev/null
+++ b/mongodb-1.13.0/tests/manager/manager-executeReadWriteCommand-001.phpt
@@ -0,0 +1,46 @@
+--TEST--
+MongoDB\Driver\Manager::executeReadWriteCommand()
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_live(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+require_once __DIR__ . "/../utils/observer.php";
+
+$manager = create_test_manager();
+
+$command = new MongoDB\Driver\Command([
+ 'aggregate' => COLLECTION_NAME,
+ 'pipeline' => [
+ ['$group' => ['_id' => 1]],
+ ['$out' => COLLECTION_NAME . '.out'],
+ ],
+ 'cursor' => (object) [],
+]);
+
+(new CommandObserver)->observe(
+ function() use ($manager, $command) {
+ $manager->executeReadWriteCommand(
+ DATABASE_NAME,
+ $command,
+ [
+ 'readConcern' => new \MongoDB\Driver\ReadConcern(\MongoDB\Driver\ReadConcern::LOCAL),
+ 'writeConcern' => new \MongoDB\Driver\WriteConcern(\MongoDB\Driver\WriteConcern::MAJORITY),
+ ]
+ );
+ },
+ function(stdClass $command) {
+ echo "Read Concern: ", $command->readConcern->level, "\n";
+ echo "Write Concern: ", $command->writeConcern->w, "\n";
+ }
+);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Read Concern: local
+Write Concern: majority
+===DONE===
diff --git a/mongodb-1.12.0/tests/manager/manager-executeReadWriteCommand-002.phpt b/mongodb-1.13.0/tests/manager/manager-executeReadWriteCommand-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-executeReadWriteCommand-002.phpt
rename to mongodb-1.13.0/tests/manager/manager-executeReadWriteCommand-002.phpt
diff --git a/mongodb-1.13.0/tests/manager/manager-executeReadWriteCommand-003.phpt b/mongodb-1.13.0/tests/manager/manager-executeReadWriteCommand-003.phpt
new file mode 100644
index 00000000..21e8c031
--- /dev/null
+++ b/mongodb-1.13.0/tests/manager/manager-executeReadWriteCommand-003.phpt
@@ -0,0 +1,46 @@
+--TEST--
+MongoDB\Driver\Manager::executeReadWriteCommand() read and write concern inheritance
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_replica_set(); ?>
+<?php skip_if_not_enough_data_nodes(2); /* w:2 */ ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+require_once __DIR__ . "/../utils/observer.php";
+
+$manager = create_test_manager(URI, ['readConcernLevel' => 'local', 'w' => 2, 'wtimeoutms' => 1000]);
+
+$command = new MongoDB\Driver\Command([
+ 'aggregate' => COLLECTION_NAME,
+ 'pipeline' => [
+ ['$group' => ['_id' => 1]],
+ ['$out' => COLLECTION_NAME . '.out'],
+ ],
+ 'cursor' => (object) [],
+]);
+
+(new CommandObserver)->observe(
+ function() use ($manager, $command) {
+ $manager->executeReadWriteCommand(DATABASE_NAME, $command);
+ $manager->executeReadWriteCommand(DATABASE_NAME, $command, [
+ 'readConcern' => new MongoDB\Driver\ReadConcern(MongoDB\Driver\ReadConcern::AVAILABLE),
+ 'writeConcern' => new MongoDB\Driver\WriteConcern(1),
+ ]);
+ },
+ function(stdClass $command) {
+ echo json_encode($command->readConcern), "\n";
+ echo json_encode($command->writeConcern), "\n";
+ }
+);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+{"level":"local"}
+{"w":2,"wtimeout":1000}
+{"level":"available"}
+{"w":1}
+===DONE===
diff --git a/mongodb-1.12.0/tests/manager/manager-executeReadWriteCommand_error-001.phpt b/mongodb-1.13.0/tests/manager/manager-executeReadWriteCommand_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-executeReadWriteCommand_error-001.phpt
rename to mongodb-1.13.0/tests/manager/manager-executeReadWriteCommand_error-001.phpt
diff --git a/mongodb-1.13.0/tests/manager/manager-executeReadWriteCommand_error-002.phpt b/mongodb-1.13.0/tests/manager/manager-executeReadWriteCommand_error-002.phpt
new file mode 100644
index 00000000..465ce383
--- /dev/null
+++ b/mongodb-1.13.0/tests/manager/manager-executeReadWriteCommand_error-002.phpt
@@ -0,0 +1,48 @@
+--TEST--
+MongoDB\Driver\Manager::executeReadWriteCommand() cannot combine session with unacknowledged write concern
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_not_live(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+/* insert should not normally be used with executeReadWriteCommand(), but we are
+ * only testing executeReadWriteCommand()'s option validation. */
+echo throws(function() {
+ $manager = create_test_manager();
+
+ $command = new MongoDB\Driver\Command([
+ 'insert' => COLLECTION_NAME,
+ 'documents' => [['x' => 1]],
+ ]);
+
+ $manager->executeReadWriteCommand(DATABASE_NAME, $command, [
+ 'session' => $manager->startSession(),
+ 'writeConcern' => new MongoDB\Driver\WriteConcern(0),
+ ]);
+}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
+
+echo throws(function() {
+ $manager = create_test_manager(URI, ['w' => 0]);
+
+ $command = new MongoDB\Driver\Command([
+ 'insert' => COLLECTION_NAME,
+ 'documents' => [['x' => 1]],
+ ]);
+
+ $manager->executeReadWriteCommand(DATABASE_NAME, $command, [
+ 'session' => $manager->startSession(),
+ ]);
+}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Cannot combine "session" option with an unacknowledged write concern
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Cannot combine "session" option with an unacknowledged write concern
+===DONE===
diff --git a/mongodb-1.13.0/tests/manager/manager-executeWriteCommand-001.phpt b/mongodb-1.13.0/tests/manager/manager-executeWriteCommand-001.phpt
new file mode 100644
index 00000000..acc71ef3
--- /dev/null
+++ b/mongodb-1.13.0/tests/manager/manager-executeWriteCommand-001.phpt
@@ -0,0 +1,41 @@
+--TEST--
+MongoDB\Driver\Manager::executeWriteCommand()
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_live(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+require_once __DIR__ . "/../utils/observer.php";
+
+$manager = create_test_manager();
+
+$bw = new MongoDB\Driver\BulkWrite();
+$bw->insert(['a' => 1]);
+$manager->executeBulkWrite(NS, $bw);
+
+(new CommandObserver)->observe(
+ function() use ($manager) {
+ $command = new MongoDB\Driver\Command([
+ 'drop' => COLLECTION_NAME,
+ ]);
+ $manager->executeWriteCommand(
+ DATABASE_NAME,
+ $command,
+ [
+ 'writeConcern' => new \MongoDB\Driver\WriteConcern(\MongoDB\Driver\WriteConcern::MAJORITY),
+ ]
+ );
+ },
+ function(stdClass $command) {
+ echo "Write Concern: ", $command->writeConcern->w, "\n";
+ }
+);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Write Concern: majority
+===DONE===
diff --git a/mongodb-1.12.0/tests/manager/manager-executeWriteCommand-002.phpt b/mongodb-1.13.0/tests/manager/manager-executeWriteCommand-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-executeWriteCommand-002.phpt
rename to mongodb-1.13.0/tests/manager/manager-executeWriteCommand-002.phpt
diff --git a/mongodb-1.13.0/tests/manager/manager-executeWriteCommand-003.phpt b/mongodb-1.13.0/tests/manager/manager-executeWriteCommand-003.phpt
new file mode 100644
index 00000000..47e3e116
--- /dev/null
+++ b/mongodb-1.13.0/tests/manager/manager-executeWriteCommand-003.phpt
@@ -0,0 +1,39 @@
+--TEST--
+MongoDB\Driver\Manager::executeWriteCommand() write concern inheritance
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_replica_set(); ?>
+<?php skip_if_not_enough_data_nodes(2); /* w:2 */ ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+require_once __DIR__ . "/../utils/observer.php";
+
+$manager = create_test_manager(URI, ['w' => 2, 'wtimeoutms' => 1000]);
+
+$command = new MongoDB\Driver\Command([
+ 'findAndModify' => COLLECTION_NAME,
+ 'query' => ['x' => 1],
+ 'upsert' => true,
+ 'new' => true,
+ 'update' => ['$inc' => ['x' => 1]],
+]);
+
+(new CommandObserver)->observe(
+ function() use ($manager, $command) {
+ $manager->executeWriteCommand(DATABASE_NAME, $command);
+ $manager->executeWriteCommand(DATABASE_NAME, $command, ['writeConcern' => new MongoDB\Driver\WriteConcern(1)]);
+ },
+ function(stdClass $command) {
+ echo json_encode($command->writeConcern), "\n";
+ }
+);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+{"w":2,"wtimeout":1000}
+{"w":1}
+===DONE===
diff --git a/mongodb-1.12.0/tests/manager/manager-executeWriteCommand_error-001.phpt b/mongodb-1.13.0/tests/manager/manager-executeWriteCommand_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-executeWriteCommand_error-001.phpt
rename to mongodb-1.13.0/tests/manager/manager-executeWriteCommand_error-001.phpt
diff --git a/mongodb-1.13.0/tests/manager/manager-executeWriteCommand_error-002.phpt b/mongodb-1.13.0/tests/manager/manager-executeWriteCommand_error-002.phpt
new file mode 100644
index 00000000..8f839698
--- /dev/null
+++ b/mongodb-1.13.0/tests/manager/manager-executeWriteCommand_error-002.phpt
@@ -0,0 +1,32 @@
+--TEST--
+MongoDB\Driver\Manager::executeWriteCommand() throws CommandException for invalid writeConcern
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_replica_set(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+
+$command = new MongoDB\Driver\Command([
+ 'findAndModify' => COLLECTION_NAME,
+ 'query' => ['_id' => 'foo'],
+ 'update' => ['foo' => ['bar']],
+ 'upsert' => true,
+ 'new' => true,
+]);
+
+try {
+ $manager->executeWriteCommand(DATABASE_NAME, $command, ['writeConcern' => new MongoDB\Driver\WriteConcern("undefined")]);
+} catch (MongoDB\Driver\Exception\CommandException $e) {
+ printf("%s(%d): %s\n", get_class($e), $e->getCode(), $e->getMessage());
+}
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+MongoDB\Driver\Exception\CommandException(79): Write Concern error: No write concern mode named 'undefined' found in replica set configuration
+===DONE===
diff --git a/mongodb-1.13.0/tests/manager/manager-executeWriteCommand_error-003.phpt b/mongodb-1.13.0/tests/manager/manager-executeWriteCommand_error-003.phpt
new file mode 100644
index 00000000..d2af2919
--- /dev/null
+++ b/mongodb-1.13.0/tests/manager/manager-executeWriteCommand_error-003.phpt
@@ -0,0 +1,30 @@
+--TEST--
+MongoDB\Driver\Manager::executeWriteCommand() throws CommandException for unsupported update operator
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_live(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+
+$command = new MongoDB\Driver\Command([
+ 'findAndModify' => COLLECTION_NAME,
+ 'query' => ['_id' => 'foo'],
+ 'upsert' => true,
+ 'new' => true,
+]);
+
+try {
+ $manager->executeWriteCommand(DATABASE_NAME, $command);
+} catch (MongoDB\Driver\Exception\CommandException $e) {
+ printf("%s(%d): %s\n", get_class($e), $e->getCode(), $e->getMessage());
+}
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+MongoDB\Driver\Exception\CommandException(9): Either an update or remove=true must be specified
+===DONE===
diff --git a/mongodb-1.13.0/tests/manager/manager-executeWriteCommand_error-004.phpt b/mongodb-1.13.0/tests/manager/manager-executeWriteCommand_error-004.phpt
new file mode 100644
index 00000000..c998b382
--- /dev/null
+++ b/mongodb-1.13.0/tests/manager/manager-executeWriteCommand_error-004.phpt
@@ -0,0 +1,46 @@
+--TEST--
+MongoDB\Driver\Manager::executeWriteCommand() cannot combine session with unacknowledged write concern
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_not_live(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+echo throws(function() {
+ $manager = create_test_manager();
+
+ $command = new MongoDB\Driver\Command([
+ 'insert' => COLLECTION_NAME,
+ 'documents' => [['x' => 1]],
+ ]);
+
+ $manager->executeWriteCommand(DATABASE_NAME, $command, [
+ 'session' => $manager->startSession(),
+ 'writeConcern' => new MongoDB\Driver\WriteConcern(0),
+ ]);
+}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
+
+echo throws(function() {
+ $manager = create_test_manager(URI, ['w' => 0]);
+
+ $command = new MongoDB\Driver\Command([
+ 'insert' => COLLECTION_NAME,
+ 'documents' => [['x' => 1]],
+ ]);
+
+ $manager->executeWriteCommand(DATABASE_NAME, $command, [
+ 'session' => $manager->startSession(),
+ ]);
+}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Cannot combine "session" option with an unacknowledged write concern
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Cannot combine "session" option with an unacknowledged write concern
+===DONE===
diff --git a/mongodb-1.12.0/tests/manager/manager-getreadconcern-001.phpt b/mongodb-1.13.0/tests/manager/manager-getreadconcern-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-getreadconcern-001.phpt
rename to mongodb-1.13.0/tests/manager/manager-getreadconcern-001.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-getreadpreference-001.phpt b/mongodb-1.13.0/tests/manager/manager-getreadpreference-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-getreadpreference-001.phpt
rename to mongodb-1.13.0/tests/manager/manager-getreadpreference-001.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-getservers-001.phpt b/mongodb-1.13.0/tests/manager/manager-getservers-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-getservers-001.phpt
rename to mongodb-1.13.0/tests/manager/manager-getservers-001.phpt
diff --git a/mongodb-1.13.0/tests/manager/manager-getservers-002.phpt b/mongodb-1.13.0/tests/manager/manager-getservers-002.phpt
new file mode 100644
index 00000000..fa404dbd
--- /dev/null
+++ b/mongodb-1.13.0/tests/manager/manager-getservers-002.phpt
@@ -0,0 +1,56 @@
+--TEST--
+MongoDB\Driver\Manager::getServers() (replica set)
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_replica_set(); ?>
+<?php skip_if_not_enough_nodes(3, 3); ?>
+<?php skip_if_no_arbiter(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+function assertServerType($type) {
+ $rsTypes = array(
+ MongoDB\Driver\Server::TYPE_RS_PRIMARY,
+ MongoDB\Driver\Server::TYPE_RS_SECONDARY,
+ MongoDB\Driver\Server::TYPE_RS_ARBITER,
+ );
+
+ if (in_array($type, $rsTypes, true)) {
+ printf("Found replica set server type: %d\n", $type);
+ } else {
+ printf("Unexpected server type: %d\n", $type);
+ }
+}
+
+$manager = create_test_manager();
+
+$servers = $manager->getServers();
+printf("Known servers: %d\n", count($servers));
+
+echo "Pinging\n";
+$command = new MongoDB\Driver\Command(array('ping' => 1));
+$manager->executeCommand(DATABASE_NAME, $command);
+
+$servers = $manager->getServers();
+printf("Known servers: %d\n", count($servers));
+
+foreach ($servers as $server) {
+ printf("Found server: %s:%d\n", $server->getHost(), $server->getPort());
+ assertServerType($server->getType());
+}
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Known servers: 0
+Pinging
+Known servers: 3
+Found server: %s:%d
+Found replica set server type: %r(4|5|6)%r
+Found server: %s:%d
+Found replica set server type: %r(4|5|6)%r
+Found server: %s:%d
+Found replica set server type: %r(4|5|6)%r
+===DONE===
diff --git a/mongodb-1.12.0/tests/manager/manager-getwriteconcern-001.phpt b/mongodb-1.13.0/tests/manager/manager-getwriteconcern-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-getwriteconcern-001.phpt
rename to mongodb-1.13.0/tests/manager/manager-getwriteconcern-001.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-invalidnamespace.phpt b/mongodb-1.13.0/tests/manager/manager-invalidnamespace.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-invalidnamespace.phpt
rename to mongodb-1.13.0/tests/manager/manager-invalidnamespace.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-removeSubscriber-001.phpt b/mongodb-1.13.0/tests/manager/manager-removeSubscriber-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-removeSubscriber-001.phpt
rename to mongodb-1.13.0/tests/manager/manager-removeSubscriber-001.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-removeSubscriber-002.phpt b/mongodb-1.13.0/tests/manager/manager-removeSubscriber-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-removeSubscriber-002.phpt
rename to mongodb-1.13.0/tests/manager/manager-removeSubscriber-002.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-selectServer-001.phpt b/mongodb-1.13.0/tests/manager/manager-selectServer-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-selectServer-001.phpt
rename to mongodb-1.13.0/tests/manager/manager-selectServer-001.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-selectServer-002.phpt b/mongodb-1.13.0/tests/manager/manager-selectServer-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-selectServer-002.phpt
rename to mongodb-1.13.0/tests/manager/manager-selectServer-002.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-selectserver_error-001.phpt b/mongodb-1.13.0/tests/manager/manager-selectserver_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-selectserver_error-001.phpt
rename to mongodb-1.13.0/tests/manager/manager-selectserver_error-001.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-set-uri-options-001.phpt b/mongodb-1.13.0/tests/manager/manager-set-uri-options-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-set-uri-options-001.phpt
rename to mongodb-1.13.0/tests/manager/manager-set-uri-options-001.phpt
diff --git a/mongodb-1.13.0/tests/manager/manager-set-uri-options-002.phpt b/mongodb-1.13.0/tests/manager/manager-set-uri-options-002.phpt
new file mode 100644
index 00000000..07603593
--- /dev/null
+++ b/mongodb-1.13.0/tests/manager/manager-set-uri-options-002.phpt
@@ -0,0 +1,58 @@
+--TEST--
+MongoDB\Driver\Manager: Connecting to MongoDB using "ssl" from $options
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_ssl(); ?>
+<?php skip_if_not_ssl(); ?>
+<?php skip_if_not_live(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$opts = array(
+ "ssl" => array(
+ "verify_peer" => false,
+ "verify_peer_name" => false,
+ "allow_self_signed" => true,
+ ),
+);
+$context = stream_context_create($opts);
+
+$options = array(
+ "ssl" => false,
+ "serverselectiontimeoutms" => 100,
+);
+/* The server requires SSL */
+$manager = create_test_manager(URI, $options, array("context" => $context));
+
+$bulk = new MongoDB\Driver\BulkWrite;
+$bulk->insert(array("my" => "value"));
+
+throws(function() use ($manager, $bulk) {
+ $inserted = $manager->executeBulkWrite(NS, $bulk)->getInsertedCount();
+ printf("Inserted incorrectly: %d\n", $inserted);
+}, MongoDB\Driver\Exception\ConnectionException::class);
+
+$options = array(
+ "ssl" => true,
+);
+$manager = create_test_manager(URI, $options, array("context" => $context));
+$bulk = new MongoDB\Driver\BulkWrite;
+
+$bulk->insert(array("my" => "value"));
+$inserted = $manager->executeBulkWrite(NS, $bulk)->getInsertedCount();
+printf("Inserted: %d\n", $inserted);
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Deprecated: MongoDB\Driver\Manager::__construct(): The "context" driver option is deprecated.%s
+
+Deprecated: MongoDB\Driver\Manager::__construct(): The "allow_self_signed" context driver option is deprecated. Please use the "tlsAllowInvalidCertificates" URI option instead.%s
+OK: Got MongoDB\Driver\Exception\ConnectionException
+
+Deprecated: MongoDB\Driver\Manager::__construct(): The "context" driver option is deprecated.%s
+
+Deprecated: MongoDB\Driver\Manager::__construct(): The "allow_self_signed" context driver option is deprecated. Please use the "tlsAllowInvalidCertificates" URI option instead.%s
+Inserted: 1
+===DONE===
diff --git a/mongodb-1.12.0/tests/manager/manager-set-uri-options-003.phpt b/mongodb-1.13.0/tests/manager/manager-set-uri-options-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-set-uri-options-003.phpt
rename to mongodb-1.13.0/tests/manager/manager-set-uri-options-003.phpt
diff --git a/mongodb-1.13.0/tests/manager/manager-startSession_error-001.phpt b/mongodb-1.13.0/tests/manager/manager-startSession_error-001.phpt
new file mode 100644
index 00000000..9e6ed1b4
--- /dev/null
+++ b/mongodb-1.13.0/tests/manager/manager-startSession_error-001.phpt
@@ -0,0 +1,92 @@
+--TEST--
+MongoDB\Driver\Manager::startSession() with wrong defaultTransactionOptions
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_not_live(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+
+$options = [
+ [ 'maxCommitTimeMS' => -1 ],
+ [ 'readConcern' => 42 ],
+ [ 'readConcern' => new stdClass ],
+ [ 'readConcern' => new \MongoDB\Driver\WriteConcern( 2 ) ],
+ [ 'readPreference' => 42 ],
+ [ 'readPreference' => new stdClass ],
+ [ 'readPreference' => new \MongoDB\Driver\ReadConcern( \MongoDB\Driver\ReadConcern::LOCAL ) ],
+ [ 'writeConcern' => 42 ],
+ [ 'writeConcern' => new stdClass ],
+ [ 'writeConcern' => new \MongoDB\Driver\ReadPreference( \MongoDB\Driver\ReadPreference::RP_SECONDARY ) ],
+
+ [
+ 'readConcern' => new \MongoDB\Driver\ReadConcern( \MongoDB\Driver\ReadConcern::LOCAL ),
+ 'readPreference' => new \MongoDB\Driver\ReadConcern( \MongoDB\Driver\ReadConcern::LOCAL ),
+ ],
+ [
+ 'readConcern' => new \MongoDB\Driver\ReadConcern( \MongoDB\Driver\ReadConcern::LOCAL ),
+ 'writeConcern' => new \MongoDB\Driver\ReadPreference( \MongoDB\Driver\ReadPreference::RP_SECONDARY ),
+ ],
+ [
+ 'readPreference' => new \MongoDB\Driver\ReadPreference( \MongoDB\Driver\ReadPreference::RP_SECONDARY ),
+ 'writeConcern' => new \MongoDB\Driver\ReadPreference( \MongoDB\Driver\ReadPreference::RP_SECONDARY ),
+ ],
+
+ 42,
+ new stdClass,
+];
+
+foreach ($options as $txnOptions) {
+ echo throws(function() use ($manager, $txnOptions) {
+ $manager->startSession([
+ 'defaultTransactionOptions' => $txnOptions
+ ]);
+ }, MongoDB\Driver\Exception\InvalidArgumentException::class), "\n";
+}
+
+echo raises(function() use ($manager) {
+ $manager->startSession([
+ 'defaultTransactionOptions' => [ 'maxCommitTimeMS' => new stdClass ]
+ ]);
+}, E_NOTICE | E_WARNING), "\n";
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Expected "maxCommitTimeMS" option to be >= 0, -1 given
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Expected "readConcern" option to be MongoDB\Driver\ReadConcern, int%S given
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Expected "readConcern" option to be MongoDB\Driver\ReadConcern, stdClass given
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Expected "readConcern" option to be MongoDB\Driver\ReadConcern, MongoDB\Driver\WriteConcern given
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Expected "readPreference" option to be MongoDB\Driver\ReadPreference, int%S given
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Expected "readPreference" option to be MongoDB\Driver\ReadPreference, stdClass given
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Expected "readPreference" option to be MongoDB\Driver\ReadPreference, MongoDB\Driver\ReadConcern given
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Expected "writeConcern" option to be MongoDB\Driver\WriteConcern, int%S given
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Expected "writeConcern" option to be MongoDB\Driver\WriteConcern, stdClass given
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Expected "writeConcern" option to be MongoDB\Driver\WriteConcern, MongoDB\Driver\ReadPreference given
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Expected "readPreference" option to be MongoDB\Driver\ReadPreference, MongoDB\Driver\ReadConcern given
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Expected "writeConcern" option to be MongoDB\Driver\WriteConcern, MongoDB\Driver\ReadPreference given
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Expected "writeConcern" option to be MongoDB\Driver\WriteConcern, MongoDB\Driver\ReadPreference given
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Expected "defaultTransactionOptions" option to be an array, int%S given
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Expected "defaultTransactionOptions" option to be an array, stdClass given
+OK: Got %r(E_NOTICE|E_WARNING)%r
+Object of class stdClass could not be converted to int
+===DONE===
diff --git a/mongodb-1.13.0/tests/manager/manager-startSession_error-002.phpt b/mongodb-1.13.0/tests/manager/manager-startSession_error-002.phpt
new file mode 100644
index 00000000..bf5844b0
--- /dev/null
+++ b/mongodb-1.13.0/tests/manager/manager-startSession_error-002.phpt
@@ -0,0 +1,29 @@
+--TEST--
+MongoDB\Driver\Manager::startSession() snapshot and causalConsistency cannot both be true
+--DESCRIPTION--
+Session spec prose test #1
+https://github.com/mongodb/specifications/blob/master/source/sessions/tests/README.rst#prose-tests
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_not_live(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+
+echo throws(function() use ($manager) {
+ $manager->startSession([
+ 'causalConsistency' => true,
+ 'snapshot' => true,
+ ]);
+}, MongoDB\Driver\Exception\InvalidArgumentException::class), "\n";
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Only one of "causalConsistency" and "snapshot" can be enabled
+===DONE===
diff --git a/mongodb-1.12.0/tests/manager/manager-var-dump-001.phpt b/mongodb-1.13.0/tests/manager/manager-var-dump-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-var-dump-001.phpt
rename to mongodb-1.13.0/tests/manager/manager-var-dump-001.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager-wakeup.phpt b/mongodb-1.13.0/tests/manager/manager-wakeup.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager-wakeup.phpt
rename to mongodb-1.13.0/tests/manager/manager-wakeup.phpt
diff --git a/mongodb-1.12.0/tests/manager/manager_error-001.phpt b/mongodb-1.13.0/tests/manager/manager_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/manager/manager_error-001.phpt
rename to mongodb-1.13.0/tests/manager/manager_error-001.phpt
diff --git a/mongodb-1.12.0/tests/query/bug0430-001.phpt b/mongodb-1.13.0/tests/query/bug0430-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/query/bug0430-001.phpt
rename to mongodb-1.13.0/tests/query/bug0430-001.phpt
diff --git a/mongodb-1.12.0/tests/query/bug0430-002.phpt b/mongodb-1.13.0/tests/query/bug0430-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/query/bug0430-002.phpt
rename to mongodb-1.13.0/tests/query/bug0430-002.phpt
diff --git a/mongodb-1.12.0/tests/query/bug0430-003.phpt b/mongodb-1.13.0/tests/query/bug0430-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/query/bug0430-003.phpt
rename to mongodb-1.13.0/tests/query/bug0430-003.phpt
diff --git a/mongodb-1.12.0/tests/query/query-ctor-001.phpt b/mongodb-1.13.0/tests/query/query-ctor-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/query/query-ctor-001.phpt
rename to mongodb-1.13.0/tests/query/query-ctor-001.phpt
diff --git a/mongodb-1.12.0/tests/query/query-ctor-002.phpt b/mongodb-1.13.0/tests/query/query-ctor-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/query/query-ctor-002.phpt
rename to mongodb-1.13.0/tests/query/query-ctor-002.phpt
diff --git a/mongodb-1.12.0/tests/query/query-ctor-003.phpt b/mongodb-1.13.0/tests/query/query-ctor-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/query/query-ctor-003.phpt
rename to mongodb-1.13.0/tests/query/query-ctor-003.phpt
diff --git a/mongodb-1.12.0/tests/query/query-ctor-004.phpt b/mongodb-1.13.0/tests/query/query-ctor-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/query/query-ctor-004.phpt
rename to mongodb-1.13.0/tests/query/query-ctor-004.phpt
diff --git a/mongodb-1.12.0/tests/query/query-ctor-005.phpt b/mongodb-1.13.0/tests/query/query-ctor-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/query/query-ctor-005.phpt
rename to mongodb-1.13.0/tests/query/query-ctor-005.phpt
diff --git a/mongodb-1.12.0/tests/query/query-ctor-006.phpt b/mongodb-1.13.0/tests/query/query-ctor-006.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/query/query-ctor-006.phpt
rename to mongodb-1.13.0/tests/query/query-ctor-006.phpt
diff --git a/mongodb-1.12.0/tests/query/query-ctor_error-001.phpt b/mongodb-1.13.0/tests/query/query-ctor_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/query/query-ctor_error-001.phpt
rename to mongodb-1.13.0/tests/query/query-ctor_error-001.phpt
diff --git a/mongodb-1.12.0/tests/query/query-ctor_error-002.phpt b/mongodb-1.13.0/tests/query/query-ctor_error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/query/query-ctor_error-002.phpt
rename to mongodb-1.13.0/tests/query/query-ctor_error-002.phpt
diff --git a/mongodb-1.12.0/tests/query/query-ctor_error-003.phpt b/mongodb-1.13.0/tests/query/query-ctor_error-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/query/query-ctor_error-003.phpt
rename to mongodb-1.13.0/tests/query/query-ctor_error-003.phpt
diff --git a/mongodb-1.12.0/tests/query/query-ctor_error-004.phpt b/mongodb-1.13.0/tests/query/query-ctor_error-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/query/query-ctor_error-004.phpt
rename to mongodb-1.13.0/tests/query/query-ctor_error-004.phpt
diff --git a/mongodb-1.12.0/tests/query/query-ctor_error-005.phpt b/mongodb-1.13.0/tests/query/query-ctor_error-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/query/query-ctor_error-005.phpt
rename to mongodb-1.13.0/tests/query/query-ctor_error-005.phpt
diff --git a/mongodb-1.12.0/tests/query/query-ctor_error-006.phpt b/mongodb-1.13.0/tests/query/query-ctor_error-006.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/query/query-ctor_error-006.phpt
rename to mongodb-1.13.0/tests/query/query-ctor_error-006.phpt
diff --git a/mongodb-1.12.0/tests/query/query-debug-001.phpt b/mongodb-1.13.0/tests/query/query-debug-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/query/query-debug-001.phpt
rename to mongodb-1.13.0/tests/query/query-debug-001.phpt
diff --git a/mongodb-1.12.0/tests/query/query_error-001.phpt b/mongodb-1.13.0/tests/query/query_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/query/query_error-001.phpt
rename to mongodb-1.13.0/tests/query/query_error-001.phpt
diff --git a/mongodb-1.12.0/tests/readConcern/bug1598-001.phpt b/mongodb-1.13.0/tests/readConcern/bug1598-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/readConcern/bug1598-001.phpt
rename to mongodb-1.13.0/tests/readConcern/bug1598-001.phpt
diff --git a/mongodb-1.12.0/tests/readConcern/bug1598-002.phpt b/mongodb-1.13.0/tests/readConcern/bug1598-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/readConcern/bug1598-002.phpt
rename to mongodb-1.13.0/tests/readConcern/bug1598-002.phpt
diff --git a/mongodb-1.12.0/tests/readConcern/readconcern-bsonserialize-001.phpt b/mongodb-1.13.0/tests/readConcern/readconcern-bsonserialize-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/readConcern/readconcern-bsonserialize-001.phpt
rename to mongodb-1.13.0/tests/readConcern/readconcern-bsonserialize-001.phpt
diff --git a/mongodb-1.12.0/tests/readConcern/readconcern-bsonserialize-002.phpt b/mongodb-1.13.0/tests/readConcern/readconcern-bsonserialize-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/readConcern/readconcern-bsonserialize-002.phpt
rename to mongodb-1.13.0/tests/readConcern/readconcern-bsonserialize-002.phpt
diff --git a/mongodb-1.12.0/tests/readConcern/readconcern-constants.phpt b/mongodb-1.13.0/tests/readConcern/readconcern-constants.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/readConcern/readconcern-constants.phpt
rename to mongodb-1.13.0/tests/readConcern/readconcern-constants.phpt
diff --git a/mongodb-1.12.0/tests/readConcern/readconcern-ctor-001.phpt b/mongodb-1.13.0/tests/readConcern/readconcern-ctor-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/readConcern/readconcern-ctor-001.phpt
rename to mongodb-1.13.0/tests/readConcern/readconcern-ctor-001.phpt
diff --git a/mongodb-1.12.0/tests/readConcern/readconcern-ctor_error-001.phpt b/mongodb-1.13.0/tests/readConcern/readconcern-ctor_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/readConcern/readconcern-ctor_error-001.phpt
rename to mongodb-1.13.0/tests/readConcern/readconcern-ctor_error-001.phpt
diff --git a/mongodb-1.12.0/tests/readConcern/readconcern-ctor_error-002.phpt b/mongodb-1.13.0/tests/readConcern/readconcern-ctor_error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/readConcern/readconcern-ctor_error-002.phpt
rename to mongodb-1.13.0/tests/readConcern/readconcern-ctor_error-002.phpt
diff --git a/mongodb-1.12.0/tests/readConcern/readconcern-debug-001.phpt b/mongodb-1.13.0/tests/readConcern/readconcern-debug-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/readConcern/readconcern-debug-001.phpt
rename to mongodb-1.13.0/tests/readConcern/readconcern-debug-001.phpt
diff --git a/mongodb-1.12.0/tests/readConcern/readconcern-getlevel-001.phpt b/mongodb-1.13.0/tests/readConcern/readconcern-getlevel-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/readConcern/readconcern-getlevel-001.phpt
rename to mongodb-1.13.0/tests/readConcern/readconcern-getlevel-001.phpt
diff --git a/mongodb-1.12.0/tests/readConcern/readconcern-isdefault-001.phpt b/mongodb-1.13.0/tests/readConcern/readconcern-isdefault-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/readConcern/readconcern-isdefault-001.phpt
rename to mongodb-1.13.0/tests/readConcern/readconcern-isdefault-001.phpt
diff --git a/mongodb-1.12.0/tests/readConcern/readconcern-serialization-001.phpt b/mongodb-1.13.0/tests/readConcern/readconcern-serialization-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/readConcern/readconcern-serialization-001.phpt
rename to mongodb-1.13.0/tests/readConcern/readconcern-serialization-001.phpt
diff --git a/mongodb-1.12.0/tests/readConcern/readconcern-serialization-002.phpt b/mongodb-1.13.0/tests/readConcern/readconcern-serialization-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/readConcern/readconcern-serialization-002.phpt
rename to mongodb-1.13.0/tests/readConcern/readconcern-serialization-002.phpt
diff --git a/mongodb-1.12.0/tests/readConcern/readconcern-serialization_error-001.phpt b/mongodb-1.13.0/tests/readConcern/readconcern-serialization_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/readConcern/readconcern-serialization_error-001.phpt
rename to mongodb-1.13.0/tests/readConcern/readconcern-serialization_error-001.phpt
diff --git a/mongodb-1.12.0/tests/readConcern/readconcern-serialization_error-002.phpt b/mongodb-1.13.0/tests/readConcern/readconcern-serialization_error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/readConcern/readconcern-serialization_error-002.phpt
rename to mongodb-1.13.0/tests/readConcern/readconcern-serialization_error-002.phpt
diff --git a/mongodb-1.12.0/tests/readConcern/readconcern-set_state-001.phpt b/mongodb-1.13.0/tests/readConcern/readconcern-set_state-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/readConcern/readconcern-set_state-001.phpt
rename to mongodb-1.13.0/tests/readConcern/readconcern-set_state-001.phpt
diff --git a/mongodb-1.12.0/tests/readConcern/readconcern-set_state_error-001.phpt b/mongodb-1.13.0/tests/readConcern/readconcern-set_state_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/readConcern/readconcern-set_state_error-001.phpt
rename to mongodb-1.13.0/tests/readConcern/readconcern-set_state_error-001.phpt
diff --git a/mongodb-1.12.0/tests/readConcern/readconcern-var_export-001.phpt b/mongodb-1.13.0/tests/readConcern/readconcern-var_export-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/readConcern/readconcern-var_export-001.phpt
rename to mongodb-1.13.0/tests/readConcern/readconcern-var_export-001.phpt
diff --git a/mongodb-1.12.0/tests/readConcern/readconcern_error-001.phpt b/mongodb-1.13.0/tests/readConcern/readconcern_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/readConcern/readconcern_error-001.phpt
rename to mongodb-1.13.0/tests/readConcern/readconcern_error-001.phpt
diff --git a/mongodb-1.13.0/tests/readPreference/bug0146-001.phpt b/mongodb-1.13.0/tests/readPreference/bug0146-001.phpt
new file mode 100644
index 00000000..1f24a575
--- /dev/null
+++ b/mongodb-1.13.0/tests/readPreference/bug0146-001.phpt
@@ -0,0 +1,227 @@
+--TEST--
+PHPC-146: ReadPreference primaryPreferred and secondary swapped
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_live(); ?>
+<?php skip_if_not_replica_set(); ?>
+<?php skip_if_no_secondary(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+
+$bulk = new MongoDB\Driver\BulkWrite();
+$bulk->insert(array('my' => 'document'));
+$manager->executeBulkWrite(NS, $bulk);
+
+$rps = array(
+ MongoDB\Driver\ReadPreference::RP_PRIMARY,
+ MongoDB\Driver\ReadPreference::RP_PRIMARY_PREFERRED,
+ MongoDB\Driver\ReadPreference::RP_SECONDARY,
+ MongoDB\Driver\ReadPreference::RP_SECONDARY_PREFERRED,
+ MongoDB\Driver\ReadPreference::RP_NEAREST,
+);
+
+foreach($rps as $r) {
+ $rp = new MongoDB\Driver\ReadPreference($r);
+ $cursor = $manager->executeQuery(NS, new MongoDB\Driver\Query(array("my" => "query")), $rp);
+ var_dump($cursor);
+}
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+object(MongoDB\Driver\Cursor)#%d (%d) {
+ ["database"]=>
+ string(6) "phongo"
+ ["collection"]=>
+ string(26) "readPreference_bug0146_001"
+ ["query"]=>
+ object(MongoDB\Driver\Query)#%d (%d) {
+ ["filter"]=>
+ object(stdClass)#%d (%d) {
+ ["my"]=>
+ string(5) "query"
+ }
+ ["options"]=>
+ object(stdClass)#%d (%d) {
+ }
+ ["readConcern"]=>
+ NULL
+ }
+ ["command"]=>
+ NULL
+ ["readPreference"]=>
+ object(MongoDB\Driver\ReadPreference)#%d (%d) {
+ ["mode"]=>
+ string(7) "primary"
+ }
+ ["session"]=>
+ NULL
+ ["isDead"]=>
+ bool(true)
+ ["currentIndex"]=>
+ int(0)
+ ["currentDocument"]=>
+ NULL
+ ["server"]=>
+ object(MongoDB\Driver\Server)#%d (%d) {
+ %a
+ }
+}
+object(MongoDB\Driver\Cursor)#%d (%d) {
+ ["database"]=>
+ string(6) "phongo"
+ ["collection"]=>
+ string(26) "readPreference_bug0146_001"
+ ["query"]=>
+ object(MongoDB\Driver\Query)#%d (%d) {
+ ["filter"]=>
+ object(stdClass)#%d (%d) {
+ ["my"]=>
+ string(5) "query"
+ }
+ ["options"]=>
+ object(stdClass)#%d (%d) {
+ }
+ ["readConcern"]=>
+ NULL
+ }
+ ["command"]=>
+ NULL
+ ["readPreference"]=>
+ object(MongoDB\Driver\ReadPreference)#%d (%d) {
+ ["mode"]=>
+ string(16) "primaryPreferred"
+ }
+ ["session"]=>
+ NULL
+ ["isDead"]=>
+ bool(true)
+ ["currentIndex"]=>
+ int(0)
+ ["currentDocument"]=>
+ NULL
+ ["server"]=>
+ object(MongoDB\Driver\Server)#%d (%d) {
+ %a
+ }
+}
+object(MongoDB\Driver\Cursor)#%d (%d) {
+ ["database"]=>
+ string(6) "phongo"
+ ["collection"]=>
+ string(26) "readPreference_bug0146_001"
+ ["query"]=>
+ object(MongoDB\Driver\Query)#%d (%d) {
+ ["filter"]=>
+ object(stdClass)#%d (%d) {
+ ["my"]=>
+ string(5) "query"
+ }
+ ["options"]=>
+ object(stdClass)#%d (%d) {
+ }
+ ["readConcern"]=>
+ NULL
+ }
+ ["command"]=>
+ NULL
+ ["readPreference"]=>
+ object(MongoDB\Driver\ReadPreference)#%d (%d) {
+ ["mode"]=>
+ string(9) "secondary"
+ }
+ ["session"]=>
+ NULL
+ ["isDead"]=>
+ bool(true)
+ ["currentIndex"]=>
+ int(0)
+ ["currentDocument"]=>
+ NULL
+ ["server"]=>
+ object(MongoDB\Driver\Server)#%d (%d) {
+ %a
+ }
+}
+object(MongoDB\Driver\Cursor)#%d (%d) {
+ ["database"]=>
+ string(6) "phongo"
+ ["collection"]=>
+ string(26) "readPreference_bug0146_001"
+ ["query"]=>
+ object(MongoDB\Driver\Query)#%d (%d) {
+ ["filter"]=>
+ object(stdClass)#%d (%d) {
+ ["my"]=>
+ string(5) "query"
+ }
+ ["options"]=>
+ object(stdClass)#%d (%d) {
+ }
+ ["readConcern"]=>
+ NULL
+ }
+ ["command"]=>
+ NULL
+ ["readPreference"]=>
+ object(MongoDB\Driver\ReadPreference)#%d (%d) {
+ ["mode"]=>
+ string(18) "secondaryPreferred"
+ }
+ ["session"]=>
+ NULL
+ ["isDead"]=>
+ bool(true)
+ ["currentIndex"]=>
+ int(0)
+ ["currentDocument"]=>
+ NULL
+ ["server"]=>
+ object(MongoDB\Driver\Server)#%d (%d) {
+ %a
+ }
+}
+object(MongoDB\Driver\Cursor)#%d (%d) {
+ ["database"]=>
+ string(6) "phongo"
+ ["collection"]=>
+ string(26) "readPreference_bug0146_001"
+ ["query"]=>
+ object(MongoDB\Driver\Query)#%d (%d) {
+ ["filter"]=>
+ object(stdClass)#%d (%d) {
+ ["my"]=>
+ string(5) "query"
+ }
+ ["options"]=>
+ object(stdClass)#%d (%d) {
+ }
+ ["readConcern"]=>
+ NULL
+ }
+ ["command"]=>
+ NULL
+ ["readPreference"]=>
+ object(MongoDB\Driver\ReadPreference)#%d (%d) {
+ ["mode"]=>
+ string(7) "nearest"
+ }
+ ["session"]=>
+ NULL
+ ["isDead"]=>
+ bool(true)
+ ["currentIndex"]=>
+ int(0)
+ ["currentDocument"]=>
+ NULL
+ ["server"]=>
+ object(MongoDB\Driver\Server)#%d (%d) {
+ %a
+ }
+}
+===DONE===
diff --git a/mongodb-1.12.0/tests/readPreference/bug0851-001.phpt b/mongodb-1.13.0/tests/readPreference/bug0851-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/readPreference/bug0851-001.phpt
rename to mongodb-1.13.0/tests/readPreference/bug0851-001.phpt
diff --git a/mongodb-1.12.0/tests/readPreference/bug1598-001.phpt b/mongodb-1.13.0/tests/readPreference/bug1598-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/readPreference/bug1598-001.phpt
rename to mongodb-1.13.0/tests/readPreference/bug1598-001.phpt
diff --git a/mongodb-1.12.0/tests/readPreference/bug1598-002.phpt b/mongodb-1.13.0/tests/readPreference/bug1598-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/readPreference/bug1598-002.phpt
rename to mongodb-1.13.0/tests/readPreference/bug1598-002.phpt
diff --git a/mongodb-1.12.0/tests/readPreference/bug1698-001.phpt b/mongodb-1.13.0/tests/readPreference/bug1698-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/readPreference/bug1698-001.phpt
rename to mongodb-1.13.0/tests/readPreference/bug1698-001.phpt
diff --git a/mongodb-1.12.0/tests/readPreference/readpreference-bsonserialize-001.phpt b/mongodb-1.13.0/tests/readPreference/readpreference-bsonserialize-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/readPreference/readpreference-bsonserialize-001.phpt
rename to mongodb-1.13.0/tests/readPreference/readpreference-bsonserialize-001.phpt
diff --git a/mongodb-1.12.0/tests/readPreference/readpreference-bsonserialize-002.phpt b/mongodb-1.13.0/tests/readPreference/readpreference-bsonserialize-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/readPreference/readpreference-bsonserialize-002.phpt
rename to mongodb-1.13.0/tests/readPreference/readpreference-bsonserialize-002.phpt
diff --git a/mongodb-1.12.0/tests/readPreference/readpreference-constants.phpt b/mongodb-1.13.0/tests/readPreference/readpreference-constants.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/readPreference/readpreference-constants.phpt
rename to mongodb-1.13.0/tests/readPreference/readpreference-constants.phpt
diff --git a/mongodb-1.12.0/tests/readPreference/readpreference-ctor-001.phpt b/mongodb-1.13.0/tests/readPreference/readpreference-ctor-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/readPreference/readpreference-ctor-001.phpt
rename to mongodb-1.13.0/tests/readPreference/readpreference-ctor-001.phpt
diff --git a/mongodb-1.12.0/tests/readPreference/readpreference-ctor-002.phpt b/mongodb-1.13.0/tests/readPreference/readpreference-ctor-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/readPreference/readpreference-ctor-002.phpt
rename to mongodb-1.13.0/tests/readPreference/readpreference-ctor-002.phpt
diff --git a/mongodb-1.12.0/tests/readPreference/readpreference-ctor_error-001.phpt b/mongodb-1.13.0/tests/readPreference/readpreference-ctor_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/readPreference/readpreference-ctor_error-001.phpt
rename to mongodb-1.13.0/tests/readPreference/readpreference-ctor_error-001.phpt
diff --git a/mongodb-1.12.0/tests/readPreference/readpreference-ctor_error-002.phpt b/mongodb-1.13.0/tests/readPreference/readpreference-ctor_error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/readPreference/readpreference-ctor_error-002.phpt
rename to mongodb-1.13.0/tests/readPreference/readpreference-ctor_error-002.phpt
diff --git a/mongodb-1.12.0/tests/readPreference/readpreference-ctor_error-003.phpt b/mongodb-1.13.0/tests/readPreference/readpreference-ctor_error-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/readPreference/readpreference-ctor_error-003.phpt
rename to mongodb-1.13.0/tests/readPreference/readpreference-ctor_error-003.phpt
diff --git a/mongodb-1.12.0/tests/readPreference/readpreference-ctor_error-004.phpt b/mongodb-1.13.0/tests/readPreference/readpreference-ctor_error-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/readPreference/readpreference-ctor_error-004.phpt
rename to mongodb-1.13.0/tests/readPreference/readpreference-ctor_error-004.phpt
diff --git a/mongodb-1.12.0/tests/readPreference/readpreference-ctor_error-005.phpt b/mongodb-1.13.0/tests/readPreference/readpreference-ctor_error-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/readPreference/readpreference-ctor_error-005.phpt
rename to mongodb-1.13.0/tests/readPreference/readpreference-ctor_error-005.phpt
diff --git a/mongodb-1.12.0/tests/readPreference/readpreference-ctor_error-006.phpt b/mongodb-1.13.0/tests/readPreference/readpreference-ctor_error-006.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/readPreference/readpreference-ctor_error-006.phpt
rename to mongodb-1.13.0/tests/readPreference/readpreference-ctor_error-006.phpt
diff --git a/mongodb-1.12.0/tests/readPreference/readpreference-ctor_error-007.phpt b/mongodb-1.13.0/tests/readPreference/readpreference-ctor_error-007.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/readPreference/readpreference-ctor_error-007.phpt
rename to mongodb-1.13.0/tests/readPreference/readpreference-ctor_error-007.phpt
diff --git a/mongodb-1.12.0/tests/readPreference/readpreference-debug-001.phpt b/mongodb-1.13.0/tests/readPreference/readpreference-debug-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/readPreference/readpreference-debug-001.phpt
rename to mongodb-1.13.0/tests/readPreference/readpreference-debug-001.phpt
diff --git a/mongodb-1.12.0/tests/readPreference/readpreference-getHedge-001.phpt b/mongodb-1.13.0/tests/readPreference/readpreference-getHedge-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/readPreference/readpreference-getHedge-001.phpt
rename to mongodb-1.13.0/tests/readPreference/readpreference-getHedge-001.phpt
diff --git a/mongodb-1.12.0/tests/readPreference/readpreference-getMaxStalenessMS-001.phpt b/mongodb-1.13.0/tests/readPreference/readpreference-getMaxStalenessMS-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/readPreference/readpreference-getMaxStalenessMS-001.phpt
rename to mongodb-1.13.0/tests/readPreference/readpreference-getMaxStalenessMS-001.phpt
diff --git a/mongodb-1.12.0/tests/readPreference/readpreference-getMaxStalenessMS-002.phpt b/mongodb-1.13.0/tests/readPreference/readpreference-getMaxStalenessMS-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/readPreference/readpreference-getMaxStalenessMS-002.phpt
rename to mongodb-1.13.0/tests/readPreference/readpreference-getMaxStalenessMS-002.phpt
diff --git a/mongodb-1.12.0/tests/readPreference/readpreference-getMode-001.phpt b/mongodb-1.13.0/tests/readPreference/readpreference-getMode-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/readPreference/readpreference-getMode-001.phpt
rename to mongodb-1.13.0/tests/readPreference/readpreference-getMode-001.phpt
diff --git a/mongodb-1.12.0/tests/readPreference/readpreference-getModeString-001.phpt b/mongodb-1.13.0/tests/readPreference/readpreference-getModeString-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/readPreference/readpreference-getModeString-001.phpt
rename to mongodb-1.13.0/tests/readPreference/readpreference-getModeString-001.phpt
diff --git a/mongodb-1.12.0/tests/readPreference/readpreference-getTagSets-001.phpt b/mongodb-1.13.0/tests/readPreference/readpreference-getTagSets-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/readPreference/readpreference-getTagSets-001.phpt
rename to mongodb-1.13.0/tests/readPreference/readpreference-getTagSets-001.phpt
diff --git a/mongodb-1.12.0/tests/readPreference/readpreference-getTagSets-002.phpt b/mongodb-1.13.0/tests/readPreference/readpreference-getTagSets-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/readPreference/readpreference-getTagSets-002.phpt
rename to mongodb-1.13.0/tests/readPreference/readpreference-getTagSets-002.phpt
diff --git a/mongodb-1.12.0/tests/readPreference/readpreference-serialization-001.phpt b/mongodb-1.13.0/tests/readPreference/readpreference-serialization-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/readPreference/readpreference-serialization-001.phpt
rename to mongodb-1.13.0/tests/readPreference/readpreference-serialization-001.phpt
diff --git a/mongodb-1.12.0/tests/readPreference/readpreference-serialization-002.phpt b/mongodb-1.13.0/tests/readPreference/readpreference-serialization-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/readPreference/readpreference-serialization-002.phpt
rename to mongodb-1.13.0/tests/readPreference/readpreference-serialization-002.phpt
diff --git a/mongodb-1.12.0/tests/readPreference/readpreference-serialization_error-001.phpt b/mongodb-1.13.0/tests/readPreference/readpreference-serialization_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/readPreference/readpreference-serialization_error-001.phpt
rename to mongodb-1.13.0/tests/readPreference/readpreference-serialization_error-001.phpt
diff --git a/mongodb-1.12.0/tests/readPreference/readpreference-serialization_error-002.phpt b/mongodb-1.13.0/tests/readPreference/readpreference-serialization_error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/readPreference/readpreference-serialization_error-002.phpt
rename to mongodb-1.13.0/tests/readPreference/readpreference-serialization_error-002.phpt
diff --git a/mongodb-1.12.0/tests/readPreference/readpreference-set_state-001.phpt b/mongodb-1.13.0/tests/readPreference/readpreference-set_state-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/readPreference/readpreference-set_state-001.phpt
rename to mongodb-1.13.0/tests/readPreference/readpreference-set_state-001.phpt
diff --git a/mongodb-1.12.0/tests/readPreference/readpreference-set_state_error-001.phpt b/mongodb-1.13.0/tests/readPreference/readpreference-set_state_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/readPreference/readpreference-set_state_error-001.phpt
rename to mongodb-1.13.0/tests/readPreference/readpreference-set_state_error-001.phpt
diff --git a/mongodb-1.12.0/tests/readPreference/readpreference-set_state_error-002.phpt b/mongodb-1.13.0/tests/readPreference/readpreference-set_state_error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/readPreference/readpreference-set_state_error-002.phpt
rename to mongodb-1.13.0/tests/readPreference/readpreference-set_state_error-002.phpt
diff --git a/mongodb-1.12.0/tests/readPreference/readpreference-var_export-001.phpt b/mongodb-1.13.0/tests/readPreference/readpreference-var_export-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/readPreference/readpreference-var_export-001.phpt
rename to mongodb-1.13.0/tests/readPreference/readpreference-var_export-001.phpt
diff --git a/mongodb-1.12.0/tests/readPreference/readpreference_error-001.phpt b/mongodb-1.13.0/tests/readPreference/readpreference_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/readPreference/readpreference_error-001.phpt
rename to mongodb-1.13.0/tests/readPreference/readpreference_error-001.phpt
diff --git a/mongodb-1.12.0/tests/replicaset/bug0155.phpt b/mongodb-1.13.0/tests/replicaset/bug0155.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/replicaset/bug0155.phpt
rename to mongodb-1.13.0/tests/replicaset/bug0155.phpt
diff --git a/mongodb-1.13.0/tests/replicaset/bug0898-001.phpt b/mongodb-1.13.0/tests/replicaset/bug0898-001.phpt
new file mode 100644
index 00000000..ebda8f61
--- /dev/null
+++ b/mongodb-1.13.0/tests/replicaset/bug0898-001.phpt
@@ -0,0 +1,45 @@
+--TEST--
+PHPC-898: readConcern option should not be included in getMore commands (URI option)
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_replica_set(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager(URI, ['readConcernLevel' => 'local']);
+
+$bulk = new MongoDB\Driver\BulkWrite();
+$bulk->insert(['_id' => 1]);
+$bulk->insert(['_id' => 2]);
+$bulk->insert(['_id' => 3]);
+
+$result = $manager->executeBulkWrite(NS, $bulk);
+printf("Inserted %d document(s)\n", $result->getInsertedCount());
+
+$query = new MongoDB\Driver\Query([], ['batchSize' => 2]);
+$cursor = $manager->executeQuery(NS, $query);
+
+foreach ($cursor as $document) {
+ var_dump($document);
+}
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Inserted 3 document(s)
+object(stdClass)#%d (1) {
+ ["_id"]=>
+ int(1)
+}
+object(stdClass)#%d (1) {
+ ["_id"]=>
+ int(2)
+}
+object(stdClass)#%d (1) {
+ ["_id"]=>
+ int(3)
+}
+===DONE===
diff --git a/mongodb-1.13.0/tests/replicaset/bug0898-002.phpt b/mongodb-1.13.0/tests/replicaset/bug0898-002.phpt
new file mode 100644
index 00000000..d3505248
--- /dev/null
+++ b/mongodb-1.13.0/tests/replicaset/bug0898-002.phpt
@@ -0,0 +1,46 @@
+--TEST--
+PHPC-898: readConcern option should not be included in getMore commands (query option)
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_replica_set(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+
+$bulk = new MongoDB\Driver\BulkWrite();
+$bulk->insert(['_id' => 1]);
+$bulk->insert(['_id' => 2]);
+$bulk->insert(['_id' => 3]);
+
+$result = $manager->executeBulkWrite(NS, $bulk);
+printf("Inserted %d document(s)\n", $result->getInsertedCount());
+
+$rc = new MongoDB\Driver\ReadConcern(MongoDB\Driver\ReadConcern::LOCAL);
+$query = new MongoDB\Driver\Query([], ['batchSize' => 2, 'readConcern' => $rc]);
+$cursor = $manager->executeQuery(NS, $query);
+
+foreach ($cursor as $document) {
+ var_dump($document);
+}
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Inserted 3 document(s)
+object(stdClass)#%d (1) {
+ ["_id"]=>
+ int(1)
+}
+object(stdClass)#%d (1) {
+ ["_id"]=>
+ int(2)
+}
+object(stdClass)#%d (1) {
+ ["_id"]=>
+ int(3)
+}
+===DONE===
diff --git a/mongodb-1.12.0/tests/replicaset/manager-selectserver-001.phpt b/mongodb-1.13.0/tests/replicaset/manager-selectserver-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/replicaset/manager-selectserver-001.phpt
rename to mongodb-1.13.0/tests/replicaset/manager-selectserver-001.phpt
diff --git a/mongodb-1.13.0/tests/replicaset/readconcern-001.phpt b/mongodb-1.13.0/tests/replicaset/readconcern-001.phpt
new file mode 100644
index 00000000..2c699d1e
--- /dev/null
+++ b/mongodb-1.13.0/tests/replicaset/readconcern-001.phpt
@@ -0,0 +1,54 @@
+--TEST--
+ReadConcern: MongoDB\Driver\Manager::executeQuery() with readConcern option
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_replica_set(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+
+$wc = new MongoDB\Driver\WriteConcern(MongoDB\Driver\WriteConcern::MAJORITY);
+
+$bulk = new MongoDB\Driver\BulkWrite();
+$bulk->insert(['_id' => 1, 'x' => 1]);
+$bulk->insert(['_id' => 2, 'x' => 2]);
+$manager->executeBulkWrite(NS, $bulk, $wc);
+
+$rc = new MongoDB\Driver\ReadConcern(MongoDB\Driver\ReadConcern::LOCAL);
+$query = new MongoDB\Driver\Query(['x' => 2], ['readConcern' => $rc]);
+$cursor = $manager->executeQuery(NS, $query);
+
+var_dump(iterator_to_array($cursor));
+
+$rc = new MongoDB\Driver\ReadConcern(MongoDB\Driver\ReadConcern::MAJORITY);
+$query = new MongoDB\Driver\Query(['x' => 2], ['readConcern' => $rc]);
+$cursor = $manager->executeQuery(NS, $query);
+
+var_dump(iterator_to_array($cursor));
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+array(1) {
+ [0]=>
+ object(stdClass)#%d (%d) {
+ ["_id"]=>
+ int(2)
+ ["x"]=>
+ int(2)
+ }
+}
+array(1) {
+ [0]=>
+ object(stdClass)#%d (%d) {
+ ["_id"]=>
+ int(2)
+ ["x"]=>
+ int(2)
+ }
+}
+===DONE===
diff --git a/mongodb-1.12.0/tests/replicaset/writeconcernerror-001.phpt b/mongodb-1.13.0/tests/replicaset/writeconcernerror-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/replicaset/writeconcernerror-001.phpt
rename to mongodb-1.13.0/tests/replicaset/writeconcernerror-001.phpt
diff --git a/mongodb-1.12.0/tests/replicaset/writeconcernerror-002.phpt b/mongodb-1.13.0/tests/replicaset/writeconcernerror-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/replicaset/writeconcernerror-002.phpt
rename to mongodb-1.13.0/tests/replicaset/writeconcernerror-002.phpt
diff --git a/mongodb-1.12.0/tests/replicaset/writeresult-getserver-001.phpt b/mongodb-1.13.0/tests/replicaset/writeresult-getserver-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/replicaset/writeresult-getserver-001.phpt
rename to mongodb-1.13.0/tests/replicaset/writeresult-getserver-001.phpt
diff --git a/mongodb-1.13.0/tests/replicaset/writeresult-getserver-002.phpt b/mongodb-1.13.0/tests/replicaset/writeresult-getserver-002.phpt
new file mode 100644
index 00000000..5ffdc322
--- /dev/null
+++ b/mongodb-1.13.0/tests/replicaset/writeresult-getserver-002.phpt
@@ -0,0 +1,98 @@
+--TEST--
+MongoDB\Driver\Server: Manager->getServer() returning correct server
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_replica_set(); ?>
+<?php skip_if_no_secondary(); ?>
+<?php skip_if_not_clean(); ?>
+<?php skip_if_not_clean('local', COLLECTION_NAME); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+// Disable retryWrites since the test writes to the unreplicated "local" database
+// Explicitly use w:1 to work around MongoDB 5.0 applying w:majority (SERVER-61790)
+$manager = create_test_manager(URI, ['retryWrites' => false, 'w' => 1]);
+
+$doc = array("example" => "document");
+$bulk = new \MongoDB\Driver\BulkWrite();
+$bulk->insert($doc);
+$wresult = $manager->executeBulkWrite(NS, $bulk);
+
+$bulk = new \MongoDB\Driver\BulkWrite();
+$bulk->insert($doc);
+
+/* writes go to the primary */
+$server = $wresult->getServer();
+/* This is the same server */
+$server2 = $server->executeBulkWrite(NS, $bulk)->getServer();
+
+/* Both are the primary, e.g. the same server */
+var_dump($server == $server2);
+
+
+$rp = new MongoDB\Driver\ReadPreference(MongoDB\Driver\ReadPreference::RP_SECONDARY);
+/* Fetch a secondary */
+$server3 = $manager->executeQuery(NS, new MongoDB\Driver\Query(array()), $rp)->getServer();
+
+var_dump($server == $server3);
+var_dump($server->getPort(), $server3->getPort());
+
+
+$bulk = new \MongoDB\Driver\BulkWrite();
+$bulk->insert($doc);
+
+$result = $server3->executeBulkWrite('local.' . COLLECTION_NAME, $bulk);
+var_dump($result, $result->getServer()->getHost(), $result->getServer()->getPort());
+$result = $server3->executeQuery('local.' . COLLECTION_NAME, new MongoDB\Driver\Query(array()));
+foreach($result as $document) {
+ var_dump($document);
+}
+$cmd = new MongoDB\Driver\Command(['drop' => COLLECTION_NAME]);
+$server3->executeCommand("local", $cmd);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+bool(true)
+bool(false)
+int(%d)
+int(%d)
+object(MongoDB\Driver\WriteResult)#%d (%d) {
+ ["nInserted"]=>
+ int(1)
+ ["nMatched"]=>
+ int(0)
+ ["nModified"]=>
+ int(0)
+ ["nRemoved"]=>
+ int(0)
+ ["nUpserted"]=>
+ int(0)
+ ["upsertedIds"]=>
+ array(0) {
+ }
+ ["writeErrors"]=>
+ array(0) {
+ }
+ ["writeConcernError"]=>
+ NULL
+ ["writeConcern"]=>
+ object(MongoDB\Driver\WriteConcern)#%d (%d) {
+ ["w"]=>
+ int(1)
+ }
+}
+string(%d) "%s"
+int(%d)
+object(stdClass)#%d (2) {
+ ["_id"]=>
+ object(%s\ObjectId)#%d (1) {
+ ["oid"]=>
+ string(24) "%s"
+ }
+ ["example"]=>
+ string(8) "document"
+}
+===DONE===
diff --git a/mongodb-1.12.0/tests/retryable-reads/retryable-reads-001.phpt b/mongodb-1.13.0/tests/retryable-reads/retryable-reads-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/retryable-reads/retryable-reads-001.phpt
rename to mongodb-1.13.0/tests/retryable-reads/retryable-reads-001.phpt
diff --git a/mongodb-1.12.0/tests/retryable-reads/retryable-reads-002.phpt b/mongodb-1.13.0/tests/retryable-reads/retryable-reads-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/retryable-reads/retryable-reads-002.phpt
rename to mongodb-1.13.0/tests/retryable-reads/retryable-reads-002.phpt
diff --git a/mongodb-1.12.0/tests/retryable-reads/retryable-reads_error-001.phpt b/mongodb-1.13.0/tests/retryable-reads/retryable-reads_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/retryable-reads/retryable-reads_error-001.phpt
rename to mongodb-1.13.0/tests/retryable-reads/retryable-reads_error-001.phpt
diff --git a/mongodb-1.12.0/tests/retryable-reads/retryable-reads_error-002.phpt b/mongodb-1.13.0/tests/retryable-reads/retryable-reads_error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/retryable-reads/retryable-reads_error-002.phpt
rename to mongodb-1.13.0/tests/retryable-reads/retryable-reads_error-002.phpt
diff --git a/mongodb-1.13.0/tests/retryable-writes/retryable-writes-001.phpt b/mongodb-1.13.0/tests/retryable-writes/retryable-writes-001.phpt
new file mode 100644
index 00000000..edb0d95d
--- /dev/null
+++ b/mongodb-1.13.0/tests/retryable-writes/retryable-writes-001.phpt
@@ -0,0 +1,84 @@
+--TEST--
+Retryable writes: supported single-statement operations include transaction IDs
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_not_replica_set_or_sharded_cluster_with_replica_set(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+class TransactionIdObserver implements MongoDB\Driver\Monitoring\CommandSubscriber
+{
+ public function commandStarted(MongoDB\Driver\Monitoring\CommandStartedEvent $event)
+ {
+ $command = $event->getCommand();
+ $hasTransactionId = isset($command->lsid) && isset($command->txnNumber);
+
+ printf("%s command includes transaction ID: %s\n", $event->getCommandName(), $hasTransactionId ? 'yes' : 'no');
+ }
+
+ public function commandSucceeded(MongoDB\Driver\Monitoring\CommandSucceededEvent $event)
+ {
+ }
+
+ public function commandFailed(MongoDB\Driver\Monitoring\CommandFailedEvent $event)
+ {
+ }
+}
+
+$observer = new TransactionIdObserver;
+MongoDB\Driver\Monitoring\addSubscriber($observer);
+
+$manager = create_test_manager();
+
+echo "Testing deleteOne\n";
+$bulk = new MongoDB\Driver\BulkWrite;
+$bulk->delete(['x' => 1], ['limit' => 1]);
+$manager->executeBulkWrite(NS, $bulk);
+
+echo "\nTesting insertOne\n";
+$bulk = new MongoDB\Driver\BulkWrite;
+$bulk->insert(['x' => 1]);
+$manager->executeBulkWrite(NS, $bulk);
+
+echo "\nTesting replaceOne\n";
+$bulk = new MongoDB\Driver\BulkWrite;
+$bulk->update(['x' => 1], ['x' => 2]);
+$manager->executeBulkWrite(NS, $bulk);
+
+echo "\nTesting updateOne\n";
+$bulk = new MongoDB\Driver\BulkWrite;
+$bulk->update(['x' => 1], ['$inc' => ['x' => 1]]);
+$manager->executeBulkWrite(NS, $bulk);
+
+echo "\nTesting findAndModify\n";
+$command = new MongoDB\Driver\Command([
+ 'findAndModify' => COLLECTION_NAME,
+ 'query' => ['x' => 1],
+ 'update' => ['$inc' => ['x' => 1]],
+]);
+$manager->executeReadWriteCommand(DATABASE_NAME, $command);
+
+MongoDB\Driver\Monitoring\removeSubscriber($observer);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+Testing deleteOne
+delete command includes transaction ID: yes
+
+Testing insertOne
+insert command includes transaction ID: yes
+
+Testing replaceOne
+update command includes transaction ID: yes
+
+Testing updateOne
+update command includes transaction ID: yes
+
+Testing findAndModify
+findAndModify command includes transaction ID: yes
+===DONE===
diff --git a/mongodb-1.13.0/tests/retryable-writes/retryable-writes-002.phpt b/mongodb-1.13.0/tests/retryable-writes/retryable-writes-002.phpt
new file mode 100644
index 00000000..8ac1d21d
--- /dev/null
+++ b/mongodb-1.13.0/tests/retryable-writes/retryable-writes-002.phpt
@@ -0,0 +1,85 @@
+--TEST--
+Retryable writes: supported multi-statement operations include transaction IDs
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_not_replica_set_or_sharded_cluster_with_replica_set(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+class TransactionIdObserver implements MongoDB\Driver\Monitoring\CommandSubscriber
+{
+ public function commandStarted(MongoDB\Driver\Monitoring\CommandStartedEvent $event)
+ {
+ $command = $event->getCommand();
+ $hasTransactionId = isset($command->lsid) && isset($command->txnNumber);
+
+ printf("%s command includes transaction ID: %s\n", $event->getCommandName(), $hasTransactionId ? 'yes' : 'no');
+ }
+
+ public function commandSucceeded(MongoDB\Driver\Monitoring\CommandSucceededEvent $event)
+ {
+ }
+
+ public function commandFailed(MongoDB\Driver\Monitoring\CommandFailedEvent $event)
+ {
+ }
+}
+
+$observer = new TransactionIdObserver;
+MongoDB\Driver\Monitoring\addSubscriber($observer);
+
+$manager = create_test_manager();
+
+echo "Testing multi-statement bulk write (ordered=true)\n";
+$bulk = new MongoDB\Driver\BulkWrite(['ordered' => true]);
+$bulk->delete(['x' => 1], ['limit' => 1]);
+$bulk->insert(['x' => 1]);
+$bulk->update(['x' => 1], ['$inc' => ['x' => 1]]);
+$bulk->update(['x' => 1], ['x' => 2]);
+$manager->executeBulkWrite(NS, $bulk);
+
+echo "\nTesting multi-statement bulk write (ordered=false)\n";
+$bulk = new MongoDB\Driver\BulkWrite(['ordered' => false]);
+$bulk->delete(['x' => 1], ['limit' => 1]);
+$bulk->insert(['x' => 1]);
+$bulk->update(['x' => 1], ['$inc' => ['x' => 1]]);
+$bulk->update(['x' => 1], ['x' => 2]);
+$manager->executeBulkWrite(NS, $bulk);
+
+echo "\nTesting insertMany (ordered=true)\n";
+$bulk = new MongoDB\Driver\BulkWrite(['ordered' => true]);
+$bulk->insert(['x' => 1]);
+$bulk->insert(['x' => 2]);
+$manager->executeBulkWrite(NS, $bulk);
+
+echo "\nTesting insertMany (ordered=false)\n";
+$bulk = new MongoDB\Driver\BulkWrite(['ordered' => false]);
+$bulk->insert(['x' => 1]);
+$bulk->insert(['x' => 2]);
+$manager->executeBulkWrite(NS, $bulk);
+
+MongoDB\Driver\Monitoring\removeSubscriber($observer);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+Testing multi-statement bulk write (ordered=true)
+delete command includes transaction ID: yes
+insert command includes transaction ID: yes
+update command includes transaction ID: yes
+
+Testing multi-statement bulk write (ordered=false)
+delete command includes transaction ID: yes
+insert command includes transaction ID: yes
+update command includes transaction ID: yes
+
+Testing insertMany (ordered=true)
+insert command includes transaction ID: yes
+
+Testing insertMany (ordered=false)
+insert command includes transaction ID: yes
+===DONE===
diff --git a/mongodb-1.13.0/tests/retryable-writes/retryable-writes-003.phpt b/mongodb-1.13.0/tests/retryable-writes/retryable-writes-003.phpt
new file mode 100644
index 00000000..f8d5fc7a
--- /dev/null
+++ b/mongodb-1.13.0/tests/retryable-writes/retryable-writes-003.phpt
@@ -0,0 +1,99 @@
+--TEST--
+Retryable writes: unsupported operations do not include transaction IDs
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_not_replica_set_or_sharded_cluster_with_replica_set(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+class TransactionIdObserver implements MongoDB\Driver\Monitoring\CommandSubscriber
+{
+ public function commandStarted(MongoDB\Driver\Monitoring\CommandStartedEvent $event)
+ {
+ $command = $event->getCommand();
+ $hasTransactionId = isset($command->lsid) && isset($command->txnNumber);
+
+ printf("%s command includes transaction ID: %s\n", $event->getCommandName(), $hasTransactionId ? 'yes' : 'no');
+ }
+
+ public function commandSucceeded(MongoDB\Driver\Monitoring\CommandSucceededEvent $event)
+ {
+ }
+
+ public function commandFailed(MongoDB\Driver\Monitoring\CommandFailedEvent $event)
+ {
+ }
+}
+
+$observer = new TransactionIdObserver;
+MongoDB\Driver\Monitoring\addSubscriber($observer);
+
+$manager = create_test_manager();
+
+echo "Testing deleteMany\n";
+$bulk = new MongoDB\Driver\BulkWrite;
+$bulk->delete(['x' => 1], ['limit' => 0]);
+$manager->executeBulkWrite(NS, $bulk);
+
+echo "\nTesting updateMany\n";
+$bulk = new MongoDB\Driver\BulkWrite;
+$bulk->update(['x' => 1], ['$inc' => ['x' => 1]], ['multi' => true]);
+$manager->executeBulkWrite(NS, $bulk);
+
+echo "\nTesting multi-statement bulk write with one unsupported operation (ordered=true)\n";
+$bulk = new MongoDB\Driver\BulkWrite(['ordered' => true]);
+$bulk->delete(['x' => 1], ['limit' => 1]);
+$bulk->insert(['x' => 1]);
+$bulk->update(['x' => 1], ['$inc' => ['x' => 1]]);
+$bulk->update(['x' => 1], ['x' => 2]);
+$bulk->update(['x' => 1], ['$inc' => ['x' => 1]], ['multi' => true]);
+$manager->executeBulkWrite(NS, $bulk);
+
+echo "\nTesting multi-statement bulk write with one unsupported operation (ordered=false)\n";
+$bulk = new MongoDB\Driver\BulkWrite(['ordered' => false]);
+$bulk->delete(['x' => 1], ['limit' => 1]);
+$bulk->insert(['x' => 1]);
+$bulk->update(['x' => 1], ['$inc' => ['x' => 1]]);
+$bulk->update(['x' => 1], ['x' => 2]);
+$bulk->update(['x' => 1], ['$inc' => ['x' => 1]], ['multi' => true]);
+$manager->executeBulkWrite(NS, $bulk);
+
+echo "\nTesting aggregate\n";
+$command = new MongoDB\Driver\Command([
+ 'aggregate' => COLLECTION_NAME,
+ 'pipeline' => [
+ ['$match' => ['x' => 1]],
+ ['$out' => COLLECTION_NAME . '.out'],
+ ],
+ 'cursor' => new stdClass,
+]);
+$manager->executeReadWriteCommand(DATABASE_NAME, $command);
+
+MongoDB\Driver\Monitoring\removeSubscriber($observer);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+Testing deleteMany
+delete command includes transaction ID: no
+
+Testing updateMany
+update command includes transaction ID: no
+
+Testing multi-statement bulk write with one unsupported operation (ordered=true)
+delete command includes transaction ID: yes
+insert command includes transaction ID: yes
+update command includes transaction ID: no
+
+Testing multi-statement bulk write with one unsupported operation (ordered=false)
+delete command includes transaction ID: yes
+insert command includes transaction ID: yes
+update command includes transaction ID: no
+
+Testing aggregate
+aggregate command includes transaction ID: no
+===DONE===
diff --git a/mongodb-1.13.0/tests/retryable-writes/retryable-writes-004.phpt b/mongodb-1.13.0/tests/retryable-writes/retryable-writes-004.phpt
new file mode 100644
index 00000000..295ca8ec
--- /dev/null
+++ b/mongodb-1.13.0/tests/retryable-writes/retryable-writes-004.phpt
@@ -0,0 +1,88 @@
+--TEST--
+Retryable writes: unacknowledged write operations do not include transaction IDs
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_not_replica_set_or_sharded_cluster_with_replica_set(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+class TransactionIdObserver implements MongoDB\Driver\Monitoring\CommandSubscriber
+{
+ public function commandStarted(MongoDB\Driver\Monitoring\CommandStartedEvent $event)
+ {
+ $command = $event->getCommand();
+ $hasTransactionId = isset($command->lsid) && isset($command->txnNumber);
+
+ printf("%s command includes transaction ID: %s\n", $event->getCommandName(), $hasTransactionId ? 'yes' : 'no');
+ }
+
+ public function commandSucceeded(MongoDB\Driver\Monitoring\CommandSucceededEvent $event)
+ {
+ }
+
+ public function commandFailed(MongoDB\Driver\Monitoring\CommandFailedEvent $event)
+ {
+ }
+}
+
+$observer = new TransactionIdObserver;
+MongoDB\Driver\Monitoring\addSubscriber($observer);
+
+$manager = create_test_manager();
+$writeConcern = new MongoDB\Driver\WriteConcern(0);
+
+echo "Testing unacknowledged deleteOne\n";
+$bulk = new MongoDB\Driver\BulkWrite;
+$bulk->delete(['x' => 1], ['limit' => 1]);
+$manager->executeBulkWrite(NS, $bulk, ['writeConcern' => $writeConcern]);
+
+echo "\nTesting unacknowledged insertOne\n";
+$bulk = new MongoDB\Driver\BulkWrite;
+$bulk->insert(['x' => 1]);
+$manager->executeBulkWrite(NS, $bulk, ['writeConcern' => $writeConcern]);
+
+echo "\nTesting unacknowledged replaceOne\n";
+$bulk = new MongoDB\Driver\BulkWrite;
+$bulk->update(['x' => 1], ['x' => 2]);
+$manager->executeBulkWrite(NS, $bulk, ['writeConcern' => $writeConcern]);
+
+echo "\nTesting unacknowledged updateOne\n";
+$bulk = new MongoDB\Driver\BulkWrite;
+$bulk->update(['x' => 1], ['$inc' => ['x' => 1]]);
+$manager->executeBulkWrite(NS, $bulk, ['writeConcern' => $writeConcern]);
+
+/* Note: the server does not actually support unacknowledged write concerns for
+ * findAndModify. This is just testing that mongoc_cmd_parts_set_write_concern()
+ * in libmongoc detects w:0 and refrains from adding a transaction ID. */
+echo "\nTesting unacknowledged findAndModify\n";
+$command = new MongoDB\Driver\Command([
+ 'findAndModify' => COLLECTION_NAME,
+ 'query' => ['x' => 1],
+ 'update' => ['$inc' => ['x' => 1]],
+]);
+$manager->executeReadWriteCommand(DATABASE_NAME, $command, ['writeConcern' => $writeConcern]);
+
+MongoDB\Driver\Monitoring\removeSubscriber($observer);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+Testing unacknowledged deleteOne
+delete command includes transaction ID: no
+
+Testing unacknowledged insertOne
+insert command includes transaction ID: no
+
+Testing unacknowledged replaceOne
+update command includes transaction ID: no
+
+Testing unacknowledged updateOne
+update command includes transaction ID: no
+
+Testing unacknowledged findAndModify
+findAndModify command includes transaction ID: no
+===DONE===
diff --git a/mongodb-1.13.0/tests/retryable-writes/retryable-writes-005.phpt b/mongodb-1.13.0/tests/retryable-writes/retryable-writes-005.phpt
new file mode 100644
index 00000000..7bda7ab5
--- /dev/null
+++ b/mongodb-1.13.0/tests/retryable-writes/retryable-writes-005.phpt
@@ -0,0 +1,70 @@
+--TEST--
+Retryable writes: non-write command methods do not include transaction IDs
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_not_replica_set_or_sharded_cluster_with_replica_set(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+class TransactionIdObserver implements MongoDB\Driver\Monitoring\CommandSubscriber
+{
+ public function commandStarted(MongoDB\Driver\Monitoring\CommandStartedEvent $event)
+ {
+ $command = $event->getCommand();
+ $hasTransactionId = isset($command->lsid) && isset($command->txnNumber);
+
+ printf("%s command includes transaction ID: %s\n", $event->getCommandName(), $hasTransactionId ? 'yes' : 'no');
+ }
+
+ public function commandSucceeded(MongoDB\Driver\Monitoring\CommandSucceededEvent $event)
+ {
+ }
+
+ public function commandFailed(MongoDB\Driver\Monitoring\CommandFailedEvent $event)
+ {
+ }
+}
+
+$observer = new TransactionIdObserver;
+MongoDB\Driver\Monitoring\addSubscriber($observer);
+
+$manager = create_test_manager();
+$command = new MongoDB\Driver\Command([
+ 'findAndModify' => COLLECTION_NAME,
+ 'query' => ['x' => 1],
+ 'update' => ['$inc' => ['x' => 1]],
+]);
+
+echo "Testing Manager::executeCommand()\n";
+$manager->executeCommand(DATABASE_NAME, $command);
+
+echo "\nTesting Manager::executeReadCommand()\n";
+$manager->executeReadCommand(DATABASE_NAME, $command);
+
+echo "\nTesting Manager::executeReadWriteCommand()\n";
+$manager->executeReadWriteCommand(DATABASE_NAME, $command);
+
+echo "\nTesting Manager::executeWriteCommand()\n";
+$manager->executeWriteCommand(DATABASE_NAME, $command);
+
+MongoDB\Driver\Monitoring\removeSubscriber($observer);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+Testing Manager::executeCommand()
+findAndModify command includes transaction ID: no
+
+Testing Manager::executeReadCommand()
+findAndModify command includes transaction ID: no
+
+Testing Manager::executeReadWriteCommand()
+findAndModify command includes transaction ID: yes
+
+Testing Manager::executeWriteCommand()
+findAndModify command includes transaction ID: yes
+===DONE===
diff --git a/mongodb-1.13.0/tests/retryable-writes/retryable-writes_error-001.phpt b/mongodb-1.13.0/tests/retryable-writes/retryable-writes_error-001.phpt
new file mode 100644
index 00000000..210dd12f
--- /dev/null
+++ b/mongodb-1.13.0/tests/retryable-writes/retryable-writes_error-001.phpt
@@ -0,0 +1,35 @@
+--TEST--
+Retryable writes: actionable error message when using retryable writes on unsupported storage engines
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_not_server_storage_engine('mmapv1'); ?>
+<?php skip_if_not_replica_set_or_sharded_cluster_with_replica_set(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+$session = $manager->startSession();
+
+echo throws(
+ function() use ($manager, $session) {
+ $command = new MongoDB\Driver\Command([
+ 'findAndModify' => COLLECTION_NAME,
+ 'query' => ['x' => 1],
+ 'update' => ['$inc' => ['x' => 1]],
+ ]);
+ $manager->executeReadWriteCommand(DATABASE_NAME, $command, ['session' => $session]);
+ },
+ \MongoDB\Driver\Exception\CommandException::class
+);
+echo "\n";
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+OK: Got MongoDB\Driver\Exception\CommandException
+This MongoDB deployment does not support retryable writes. Please add retryWrites=false to your connection string.
+===DONE===
diff --git a/mongodb-1.12.0/tests/server/bug0671-002.phpt b/mongodb-1.13.0/tests/server/bug0671-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/server/bug0671-002.phpt
rename to mongodb-1.13.0/tests/server/bug0671-002.phpt
diff --git a/mongodb-1.12.0/tests/server/server-constants.phpt b/mongodb-1.13.0/tests/server/server-constants.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/server/server-constants.phpt
rename to mongodb-1.13.0/tests/server/server-constants.phpt
diff --git a/mongodb-1.13.0/tests/server/server-construct-001.phpt b/mongodb-1.13.0/tests/server/server-construct-001.phpt
new file mode 100644
index 00000000..5c726c67
--- /dev/null
+++ b/mongodb-1.13.0/tests/server/server-construct-001.phpt
@@ -0,0 +1,33 @@
+--TEST--
+MongoDB\Driver\Server::__construct()
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_live(); ?>
+<?php skip_if_multiple_mongos(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+/* For replica sets we need to do some extra work to get the primary */
+$uri = is_replica_set(URI) ? get_primary_server(URI)->getInfo()['me'] : URI;
+$parsed = parse_url($uri);
+
+$manager = create_test_manager();
+
+$bulk = new \MongoDB\Driver\BulkWrite();
+$bulk->insert(array('foo' => 'bar'));
+$server = $manager->executeBulkWrite(NS, $bulk)->getServer();
+
+$expectedHost = $parsed['host'];
+$expectedPort = (integer) (isset($parsed['port']) ? $parsed['port'] : 27017);
+
+var_dump($server->getHost() == $expectedHost);
+var_dump($server->getPort() == $expectedPort);
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+bool(true)
+bool(true)
+===DONE===
diff --git a/mongodb-1.12.0/tests/server/server-debug.phpt b/mongodb-1.13.0/tests/server/server-debug.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/server/server-debug.phpt
rename to mongodb-1.13.0/tests/server/server-debug.phpt
diff --git a/mongodb-1.12.0/tests/server/server-errors.phpt b/mongodb-1.13.0/tests/server/server-errors.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/server/server-errors.phpt
rename to mongodb-1.13.0/tests/server/server-errors.phpt
diff --git a/mongodb-1.12.0/tests/server/server-executeBulkWrite-001.phpt b/mongodb-1.13.0/tests/server/server-executeBulkWrite-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/server/server-executeBulkWrite-001.phpt
rename to mongodb-1.13.0/tests/server/server-executeBulkWrite-001.phpt
diff --git a/mongodb-1.12.0/tests/server/server-executeBulkWrite-002.phpt b/mongodb-1.13.0/tests/server/server-executeBulkWrite-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/server/server-executeBulkWrite-002.phpt
rename to mongodb-1.13.0/tests/server/server-executeBulkWrite-002.phpt
diff --git a/mongodb-1.12.0/tests/server/server-executeBulkWrite-003.phpt b/mongodb-1.13.0/tests/server/server-executeBulkWrite-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/server/server-executeBulkWrite-003.phpt
rename to mongodb-1.13.0/tests/server/server-executeBulkWrite-003.phpt
diff --git a/mongodb-1.12.0/tests/server/server-executeBulkWrite-004.phpt b/mongodb-1.13.0/tests/server/server-executeBulkWrite-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/server/server-executeBulkWrite-004.phpt
rename to mongodb-1.13.0/tests/server/server-executeBulkWrite-004.phpt
diff --git a/mongodb-1.12.0/tests/server/server-executeBulkWrite-005.phpt b/mongodb-1.13.0/tests/server/server-executeBulkWrite-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/server/server-executeBulkWrite-005.phpt
rename to mongodb-1.13.0/tests/server/server-executeBulkWrite-005.phpt
diff --git a/mongodb-1.12.0/tests/server/server-executeBulkWrite-006.phpt b/mongodb-1.13.0/tests/server/server-executeBulkWrite-006.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/server/server-executeBulkWrite-006.phpt
rename to mongodb-1.13.0/tests/server/server-executeBulkWrite-006.phpt
diff --git a/mongodb-1.12.0/tests/server/server-executeBulkWrite-007.phpt b/mongodb-1.13.0/tests/server/server-executeBulkWrite-007.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/server/server-executeBulkWrite-007.phpt
rename to mongodb-1.13.0/tests/server/server-executeBulkWrite-007.phpt
diff --git a/mongodb-1.12.0/tests/server/server-executeBulkWrite-008.phpt b/mongodb-1.13.0/tests/server/server-executeBulkWrite-008.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/server/server-executeBulkWrite-008.phpt
rename to mongodb-1.13.0/tests/server/server-executeBulkWrite-008.phpt
diff --git a/mongodb-1.12.0/tests/server/server-executeBulkWrite-009.phpt b/mongodb-1.13.0/tests/server/server-executeBulkWrite-009.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/server/server-executeBulkWrite-009.phpt
rename to mongodb-1.13.0/tests/server/server-executeBulkWrite-009.phpt
diff --git a/mongodb-1.12.0/tests/server/server-executeBulkWrite_error-001.phpt b/mongodb-1.13.0/tests/server/server-executeBulkWrite_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/server/server-executeBulkWrite_error-001.phpt
rename to mongodb-1.13.0/tests/server/server-executeBulkWrite_error-001.phpt
diff --git a/mongodb-1.12.0/tests/server/server-executeBulkWrite_error-002.phpt b/mongodb-1.13.0/tests/server/server-executeBulkWrite_error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/server/server-executeBulkWrite_error-002.phpt
rename to mongodb-1.13.0/tests/server/server-executeBulkWrite_error-002.phpt
diff --git a/mongodb-1.12.0/tests/server/server-executeCommand-001.phpt b/mongodb-1.13.0/tests/server/server-executeCommand-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/server/server-executeCommand-001.phpt
rename to mongodb-1.13.0/tests/server/server-executeCommand-001.phpt
diff --git a/mongodb-1.13.0/tests/server/server-executeCommand-002.phpt b/mongodb-1.13.0/tests/server/server-executeCommand-002.phpt
new file mode 100644
index 00000000..ae444c29
--- /dev/null
+++ b/mongodb-1.13.0/tests/server/server-executeCommand-002.phpt
@@ -0,0 +1,75 @@
+--TEST--
+MongoDB\Driver\Server::executeCommand() takes a read preference
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_replica_set(); ?>
+<?php skip_if_no_secondary(); ?>
+<?php skip_if_not_clean(DATABASE_NAME, 'system.profile'); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+
+$rp = new MongoDB\Driver\ReadPreference(MongoDB\Driver\ReadPreference::RP_SECONDARY);
+$secondary = $manager->selectServer($rp);
+
+$command = new MongoDB\Driver\Command(array('profile' => 2));
+$cursor = $secondary->executeCommand(DATABASE_NAME, $command);
+$result = current($cursor->toArray());
+
+printf("Set profile level to 2 successfully: %s\n", (empty($result->ok) ? 'no' : 'yes'));
+
+$command = new MongoDB\Driver\Command([
+ 'aggregate' => COLLECTION_NAME,
+ 'pipeline' => [ [ '$match' => [ 'x' => 1 ] ] ],
+ 'cursor' => (object) [],
+]);
+$secondary->executeCommand(DATABASE_NAME, $command, $rp);
+
+$query = new MongoDB\Driver\Query(
+ array(
+ 'op' => 'command',
+ 'ns' => DATABASE_NAME . '.' . COLLECTION_NAME,
+ ),
+ array(
+ 'sort' => array('ts' => -1),
+ 'limit' => 1,
+ )
+);
+$cursor = $secondary->executeQuery(DATABASE_NAME . '.system.profile', $query, $rp);
+$profileEntry = current($cursor->toArray());
+
+var_dump($profileEntry->command);
+
+$command = new MongoDB\Driver\Command(array('profile' => 0));
+$cursor = $secondary->executeCommand(DATABASE_NAME, $command);
+$result = current($cursor->toArray());
+
+printf("Set profile level to 0 successfully: %s\n", (empty($result->ok) ? 'no' : 'yes'));
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Set profile level to 2 successfully: yes
+object(stdClass)#%d (%d) {
+ ["aggregate"]=>
+ string(32) "server_server_executeCommand_002"
+ ["pipeline"]=>
+ array(1) {
+ [0]=>
+ object(stdClass)#%d (%d) {
+ ["$match"]=>
+ object(stdClass)#%d (%d) {
+ ["x"]=>
+ int(1)
+ }
+ }
+ }
+ ["cursor"]=>
+ object(stdClass)#%d (%d) {
+ }%A
+}
+Set profile level to 0 successfully: yes
+===DONE===
diff --git a/mongodb-1.12.0/tests/server/server-executeCommand-003.phpt b/mongodb-1.13.0/tests/server/server-executeCommand-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/server/server-executeCommand-003.phpt
rename to mongodb-1.13.0/tests/server/server-executeCommand-003.phpt
diff --git a/mongodb-1.12.0/tests/server/server-executeCommand-004.phpt b/mongodb-1.13.0/tests/server/server-executeCommand-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/server/server-executeCommand-004.phpt
rename to mongodb-1.13.0/tests/server/server-executeCommand-004.phpt
diff --git a/mongodb-1.12.0/tests/server/server-executeCommand-005.phpt b/mongodb-1.13.0/tests/server/server-executeCommand-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/server/server-executeCommand-005.phpt
rename to mongodb-1.13.0/tests/server/server-executeCommand-005.phpt
diff --git a/mongodb-1.13.0/tests/server/server-executeCommand-006.phpt b/mongodb-1.13.0/tests/server/server-executeCommand-006.phpt
new file mode 100644
index 00000000..afed4e4f
--- /dev/null
+++ b/mongodb-1.13.0/tests/server/server-executeCommand-006.phpt
@@ -0,0 +1,50 @@
+--TEST--
+MongoDB\Driver\Server::executeCommand() options (MONGO_CMD_RAW)
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_live(); ?>
+<?php skip_if_standalone(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+require_once __DIR__ . "/../utils/observer.php";
+
+$manager = create_test_manager();
+$server = $manager->selectServer(new MongoDB\Driver\ReadPreference(MongoDB\Driver\ReadPreference::RP_PRIMARY));
+
+(new CommandObserver)->observe(
+ function() use ($server) {
+ $command = new MongoDB\Driver\Command([
+ 'ping' => true,
+ ]);
+
+ try {
+ $server->executeCommand(
+ DATABASE_NAME,
+ $command,
+ [
+ 'readPreference' => new \MongoDB\Driver\ReadPreference(\MongoDB\Driver\ReadPreference::RP_SECONDARY),
+ 'readConcern' => new \MongoDB\Driver\ReadConcern(\MongoDB\Driver\ReadConcern::LOCAL),
+ 'writeConcern' => new \MongoDB\Driver\WriteConcern(\MongoDB\Driver\WriteConcern::MAJORITY),
+ ]
+ );
+ } catch ( Exception $e ) {
+ // Ignore exception that ping doesn't support writeConcern
+ }
+ },
+ function(stdClass $command) {
+ echo "Read Preference: ", $command->{'$readPreference'}->mode, "\n";
+ echo "Read Concern: ", $command->readConcern->level, "\n";
+ echo "Write Concern: ", $command->writeConcern->w, "\n";
+ }
+);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Read Preference: secondary
+Read Concern: local
+Write Concern: majority
+===DONE===
diff --git a/mongodb-1.12.0/tests/server/server-executeCommand-007.phpt b/mongodb-1.13.0/tests/server/server-executeCommand-007.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/server/server-executeCommand-007.phpt
rename to mongodb-1.13.0/tests/server/server-executeCommand-007.phpt
diff --git a/mongodb-1.13.0/tests/server/server-executeCommand-008.phpt b/mongodb-1.13.0/tests/server/server-executeCommand-008.phpt
new file mode 100644
index 00000000..b72c9961
--- /dev/null
+++ b/mongodb-1.13.0/tests/server/server-executeCommand-008.phpt
@@ -0,0 +1,50 @@
+--TEST--
+MongoDB\Driver\Server::executeCommand() does not send read preference to standalone
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_live(); ?>
+<?php skip_if_not_standalone(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+require_once __DIR__ . "/../utils/observer.php";
+
+$manager = create_test_manager();
+$server = $manager->selectServer(new MongoDB\Driver\ReadPreference(MongoDB\Driver\ReadPreference::RP_PRIMARY));
+
+(new CommandObserver)->observe(
+ function() use ($server) {
+ $command = new MongoDB\Driver\Command([
+ 'ping' => true,
+ ]);
+
+ try {
+ $server->executeCommand(
+ DATABASE_NAME,
+ $command,
+ [
+ 'readPreference' => new \MongoDB\Driver\ReadPreference(\MongoDB\Driver\ReadPreference::RP_SECONDARY),
+ 'readConcern' => new \MongoDB\Driver\ReadConcern(\MongoDB\Driver\ReadConcern::LOCAL),
+ 'writeConcern' => new \MongoDB\Driver\WriteConcern(\MongoDB\Driver\WriteConcern::MAJORITY),
+ ]
+ );
+ } catch ( Exception $e ) {
+ // Ignore exception that ping doesn't support writeConcern
+ }
+ },
+ function(stdClass $command) {
+ echo isset($command->{'$readPreference'}) ? 'Read preference set' : 'No read preference set', "\n";
+ echo "Read Concern: ", $command->readConcern->level, "\n";
+ echo "Write Concern: ", $command->writeConcern->w, "\n";
+ }
+);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+No read preference set
+Read Concern: local
+Write Concern: majority
+===DONE===
diff --git a/mongodb-1.12.0/tests/server/server-executeCommand-009.phpt b/mongodb-1.13.0/tests/server/server-executeCommand-009.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/server/server-executeCommand-009.phpt
rename to mongodb-1.13.0/tests/server/server-executeCommand-009.phpt
diff --git a/mongodb-1.13.0/tests/server/server-executeCommand-010.phpt b/mongodb-1.13.0/tests/server/server-executeCommand-010.phpt
new file mode 100644
index 00000000..f0b4a72d
--- /dev/null
+++ b/mongodb-1.13.0/tests/server/server-executeCommand-010.phpt
@@ -0,0 +1,47 @@
+--TEST--
+MongoDB\Driver\Server::executeCommand() does not inherit read or write concern
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_replica_set(); ?>
+<?php skip_if_not_enough_data_nodes(2); /* w:2 */ ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+require_once __DIR__ . "/../utils/observer.php";
+
+$manager = create_test_manager(URI, ['readConcernLevel' => 'local', 'w' => 2, 'wtimeoutms' => 1000]);
+$server = $manager->selectServer(new MongoDB\Driver\ReadPreference('primary'));
+
+$command = new MongoDB\Driver\Command([
+ 'aggregate' => COLLECTION_NAME,
+ 'pipeline' => [
+ ['$group' => ['_id' => 1]],
+ ['$out' => COLLECTION_NAME . '.out'],
+ ],
+ 'cursor' => (object) [],
+]);
+
+(new CommandObserver)->observe(
+ function() use ($server, $command) {
+ $server->executeCommand(DATABASE_NAME, $command);
+ $server->executeCommand(DATABASE_NAME, $command, [
+ 'readConcern' => new MongoDB\Driver\ReadConcern(MongoDB\Driver\ReadConcern::AVAILABLE),
+ 'writeConcern' => new MongoDB\Driver\WriteConcern(1),
+ ]);
+ },
+ function(stdClass $command) {
+ echo json_encode($command->readConcern ?? null), "\n";
+ echo json_encode($command->writeConcern ?? null), "\n";
+ }
+);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+null
+null
+{"level":"available"}
+{"w":1}
+===DONE===
diff --git a/mongodb-1.12.0/tests/server/server-executeCommand_error-001.phpt b/mongodb-1.13.0/tests/server/server-executeCommand_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/server/server-executeCommand_error-001.phpt
rename to mongodb-1.13.0/tests/server/server-executeCommand_error-001.phpt
diff --git a/mongodb-1.12.0/tests/server/server-executeQuery-001.phpt b/mongodb-1.13.0/tests/server/server-executeQuery-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/server/server-executeQuery-001.phpt
rename to mongodb-1.13.0/tests/server/server-executeQuery-001.phpt
diff --git a/mongodb-1.12.0/tests/server/server-executeQuery-002.phpt b/mongodb-1.13.0/tests/server/server-executeQuery-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/server/server-executeQuery-002.phpt
rename to mongodb-1.13.0/tests/server/server-executeQuery-002.phpt
diff --git a/mongodb-1.12.0/tests/server/server-executeQuery-003.phpt b/mongodb-1.13.0/tests/server/server-executeQuery-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/server/server-executeQuery-003.phpt
rename to mongodb-1.13.0/tests/server/server-executeQuery-003.phpt
diff --git a/mongodb-1.12.0/tests/server/server-executeQuery-004.phpt b/mongodb-1.13.0/tests/server/server-executeQuery-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/server/server-executeQuery-004.phpt
rename to mongodb-1.13.0/tests/server/server-executeQuery-004.phpt
diff --git a/mongodb-1.13.0/tests/server/server-executeQuery-006.phpt b/mongodb-1.13.0/tests/server/server-executeQuery-006.phpt
new file mode 100644
index 00000000..73ebfa8a
--- /dev/null
+++ b/mongodb-1.13.0/tests/server/server-executeQuery-006.phpt
@@ -0,0 +1,65 @@
+--TEST--
+MongoDB\Driver\Server::executeQuery() takes a read preference
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_replica_set(); ?>
+<?php skip_if_no_secondary(); ?>
+<?php skip_if_not_clean(DATABASE_NAME, 'system.profile'); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+
+$rp = new MongoDB\Driver\ReadPreference(MongoDB\Driver\ReadPreference::RP_SECONDARY);
+$secondary = $manager->selectServer($rp);
+
+$command = new MongoDB\Driver\Command(array('profile' => 2));
+$cursor = $secondary->executeCommand(DATABASE_NAME, $command);
+$result = current($cursor->toArray());
+
+printf("Set profile level to 2 successfully: %s\n", (empty($result->ok) ? 'no' : 'yes'));
+
+if (empty($result->ok)) {
+ exit("Could not set profile level\n");
+}
+
+$secondary->executeQuery(NS, new MongoDB\Driver\Query(array("x" => 1)), $rp);
+
+$query = new MongoDB\Driver\Query(
+ array(
+ 'op' => 'query',
+ 'ns' => NS,
+ ),
+ array(
+ 'sort' => array('ts' => -1),
+ 'limit' => 1,
+ )
+);
+$cursor = $secondary->executeQuery(DATABASE_NAME . '.system.profile', $query, $rp);
+$profileEntry = current($cursor->toArray());
+
+if (! isset( $profileEntry->command )) {
+ var_dump($profileEntry);
+}
+var_dump($profileEntry->command->find);
+var_dump($profileEntry->command->filter);
+
+$command = new MongoDB\Driver\Command(array('profile' => 0));
+$cursor = $secondary->executeCommand(DATABASE_NAME, $command);
+$result = current($cursor->toArray());
+
+printf("Set profile level to 0 successfully: %s\n", (empty($result->ok) ? 'no' : 'yes'));
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Set profile level to 2 successfully: yes
+string(%d) "%s"
+object(stdClass)#%d (1) {
+ ["x"]=>
+ int(1)
+}
+Set profile level to 0 successfully: yes
+===DONE===
diff --git a/mongodb-1.12.0/tests/server/server-executeQuery-007.phpt b/mongodb-1.13.0/tests/server/server-executeQuery-007.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/server/server-executeQuery-007.phpt
rename to mongodb-1.13.0/tests/server/server-executeQuery-007.phpt
diff --git a/mongodb-1.12.0/tests/server/server-executeQuery-008.phpt b/mongodb-1.13.0/tests/server/server-executeQuery-008.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/server/server-executeQuery-008.phpt
rename to mongodb-1.13.0/tests/server/server-executeQuery-008.phpt
diff --git a/mongodb-1.12.0/tests/server/server-executeQuery-009.phpt b/mongodb-1.13.0/tests/server/server-executeQuery-009.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/server/server-executeQuery-009.phpt
rename to mongodb-1.13.0/tests/server/server-executeQuery-009.phpt
diff --git a/mongodb-1.12.0/tests/server/server-executeQuery-010.phpt b/mongodb-1.13.0/tests/server/server-executeQuery-010.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/server/server-executeQuery-010.phpt
rename to mongodb-1.13.0/tests/server/server-executeQuery-010.phpt
diff --git a/mongodb-1.12.0/tests/server/server-executeQuery-011.phpt b/mongodb-1.13.0/tests/server/server-executeQuery-011.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/server/server-executeQuery-011.phpt
rename to mongodb-1.13.0/tests/server/server-executeQuery-011.phpt
diff --git a/mongodb-1.13.0/tests/server/server-executeQuery-012.phpt b/mongodb-1.13.0/tests/server/server-executeQuery-012.phpt
new file mode 100644
index 00000000..f67a0633
--- /dev/null
+++ b/mongodb-1.13.0/tests/server/server-executeQuery-012.phpt
@@ -0,0 +1,70 @@
+--TEST--
+MongoDB\Driver\Server::executeQuery() pins transaction to server
+--XFAIL--
+_mongoc_cursor_fetch_stream segfault (CDRIVER-4290)
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_mongos(); ?>
+<?php skip_if_no_transactions(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+
+/* Create collections as that can't be (automatically) done in a transaction */
+$manager->executeCommand(
+ DATABASE_NAME,
+ new \MongoDB\Driver\Command([ 'create' => COLLECTION_NAME ]),
+ [ 'writeConcern' => new \MongoDB\Driver\WriteConcern( \MongoDB\Driver\WriteConcern::MAJORITY ) ]
+);
+
+$servers = $manager->getServers();
+$selectedServer = array_pop($servers);
+$wrongServer = array_pop($servers);
+var_dump($selectedServer != $wrongServer);
+
+$session = $manager->startSession();
+var_dump($session->getServer() instanceof \MongoDB\Driver\Server);
+
+$session->startTransaction();
+var_dump($session->getServer() instanceof \MongoDB\Driver\Server);
+
+$query = new MongoDB\Driver\Query([]);
+$selectedServer->executeQuery(NS, $query, ['session' => $session]);
+
+var_dump($session->getServer() == $selectedServer);
+
+$bulk = new MongoDB\Driver\BulkWrite();
+$bulk->insert(['x' => 1]);
+$selectedServer->executeBulkWrite(NS, $bulk, ['session' => $session]);
+
+echo throws(function () use ($wrongServer, $session) {
+ $query = new MongoDB\Driver\Query([]);
+ $wrongServer->executeQuery(NS, $query, ['session' => $session]);
+}, \MongoDB\Driver\Exception\RuntimeException::class), "\n";
+
+$session->commitTransaction();
+
+var_dump($session->getServer() == $selectedServer);
+
+$bulk = new MongoDB\Driver\BulkWrite();
+$bulk->insert(['x' => 1]);
+$selectedServer->executeBulkWrite(NS, $bulk, ['session' => $session]);
+
+var_dump($session->getServer() instanceof \MongoDB\Driver\Server);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+bool(true)
+bool(false)
+bool(false)
+bool(true)
+OK: Got MongoDB\Driver\Exception\RuntimeException
+Requested server id does not matched pinned server id
+bool(true)
+bool(false)
+===DONE===
diff --git a/mongodb-1.13.0/tests/server/server-executeQuery-013.phpt b/mongodb-1.13.0/tests/server/server-executeQuery-013.phpt
new file mode 100644
index 00000000..5b593e6e
--- /dev/null
+++ b/mongodb-1.13.0/tests/server/server-executeQuery-013.phpt
@@ -0,0 +1,33 @@
+--TEST--
+MongoDB\Driver\Server::executeQuery() read concern inheritance
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_replica_set(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+require_once __DIR__ . "/../utils/observer.php";
+
+$manager = create_test_manager(URI, ['readConcernLevel' => 'local']);
+$server = $manager->selectServer(new MongoDB\Driver\ReadPreference('primary'));
+
+(new CommandObserver)->observe(
+ function() use ($server) {
+ $server->executeQuery(NS, new MongoDB\Driver\Query([]));
+ $server->executeQuery(NS, new MongoDB\Driver\Query([], [
+ 'readConcern' => new MongoDB\Driver\ReadConcern(MongoDB\Driver\ReadConcern::AVAILABLE),
+ ]));
+ },
+ function(stdClass $command) {
+ echo json_encode($command->readConcern), "\n";
+ }
+);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+{"level":"local"}
+{"level":"available"}
+===DONE===
diff --git a/mongodb-1.12.0/tests/server/server-executeQuery_error-001.phpt b/mongodb-1.13.0/tests/server/server-executeQuery_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/server/server-executeQuery_error-001.phpt
rename to mongodb-1.13.0/tests/server/server-executeQuery_error-001.phpt
diff --git a/mongodb-1.13.0/tests/server/server-executeReadCommand-001.phpt b/mongodb-1.13.0/tests/server/server-executeReadCommand-001.phpt
new file mode 100644
index 00000000..b673e391
--- /dev/null
+++ b/mongodb-1.13.0/tests/server/server-executeReadCommand-001.phpt
@@ -0,0 +1,47 @@
+--TEST--
+MongoDB\Driver\Server::executeReadCommand()
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_live(); ?>
+<?php skip_if_not_replica_set(); ?>
+<?php skip_if_no_secondary(); ?>
+<?php skip_if_not_server_storage_engine('wiredTiger'); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+require_once __DIR__ . "/../utils/observer.php";
+
+$manager = create_test_manager();
+$server = $manager->selectServer(new MongoDB\Driver\ReadPreference(MongoDB\Driver\ReadPreference::RP_SECONDARY));
+
+(new CommandObserver)->observe(
+ function() use ($server) {
+ $command = new MongoDB\Driver\Command( [
+ 'aggregate' => NS,
+ 'pipeline' => [],
+ 'cursor' => new stdClass(),
+ ] );
+ $server->executeReadCommand(
+ DATABASE_NAME,
+ $command,
+ [
+ 'readPreference' => new \MongoDB\Driver\ReadPreference(\MongoDB\Driver\ReadPreference::RP_SECONDARY),
+ 'readConcern' => new \MongoDB\Driver\ReadConcern(\MongoDB\Driver\ReadConcern::MAJORITY),
+ ]
+ );
+ },
+ function(stdClass $command) {
+ echo "Read Preference: ", $command->{'$readPreference'}->mode, "\n";
+ echo "Read Concern: ", $command->readConcern->level, "\n";
+ }
+);
+
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Read Preference: secondary
+Read Concern: majority
+===DONE===
diff --git a/mongodb-1.12.0/tests/server/server-executeReadCommand-002.phpt b/mongodb-1.13.0/tests/server/server-executeReadCommand-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/server/server-executeReadCommand-002.phpt
rename to mongodb-1.13.0/tests/server/server-executeReadCommand-002.phpt
diff --git a/mongodb-1.13.0/tests/server/server-executeReadCommand-003.phpt b/mongodb-1.13.0/tests/server/server-executeReadCommand-003.phpt
new file mode 100644
index 00000000..fdf79a31
--- /dev/null
+++ b/mongodb-1.13.0/tests/server/server-executeReadCommand-003.phpt
@@ -0,0 +1,39 @@
+--TEST--
+MongoDB\Driver\Server::executeReadCommand() read concern inheritance
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_replica_set(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+require_once __DIR__ . "/../utils/observer.php";
+
+$manager = create_test_manager(URI, ['readConcernLevel' => 'local']);
+$server = $manager->selectServer(new MongoDB\Driver\ReadPreference('primary'));
+
+$command = new MongoDB\Driver\Command([
+ 'aggregate' => COLLECTION_NAME,
+ 'pipeline' => [['$group' => ['_id' => 1]]],
+ 'cursor' => (object) [],
+]);
+
+(new CommandObserver)->observe(
+ function() use ($server, $command) {
+ $server->executeReadCommand(DATABASE_NAME, $command);
+ $server->executeReadCommand(DATABASE_NAME, $command, [
+ 'readConcern' => new MongoDB\Driver\ReadConcern(MongoDB\Driver\ReadConcern::AVAILABLE),
+ ]);
+ },
+ function(stdClass $command) {
+ echo json_encode($command->readConcern), "\n";
+ }
+);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+{"level":"local"}
+{"level":"available"}
+===DONE===
diff --git a/mongodb-1.12.0/tests/server/server-executeReadCommand_error-001.phpt b/mongodb-1.13.0/tests/server/server-executeReadCommand_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/server/server-executeReadCommand_error-001.phpt
rename to mongodb-1.13.0/tests/server/server-executeReadCommand_error-001.phpt
diff --git a/mongodb-1.13.0/tests/server/server-executeReadWriteCommand-001.phpt b/mongodb-1.13.0/tests/server/server-executeReadWriteCommand-001.phpt
new file mode 100644
index 00000000..9b3b6a96
--- /dev/null
+++ b/mongodb-1.13.0/tests/server/server-executeReadWriteCommand-001.phpt
@@ -0,0 +1,42 @@
+--TEST--
+MongoDB\Driver\Server::executeReadWriteCommand()
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_live(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+require_once __DIR__ . "/../utils/observer.php";
+
+$manager = create_test_manager();
+$server = $manager->selectServer(new MongoDB\Driver\ReadPreference(MongoDB\Driver\ReadPreference::RP_PRIMARY));
+
+(new CommandObserver)->observe(
+ function() use ($server) {
+ $command = new MongoDB\Driver\Command( [
+ 'findAndModify' => NS,
+ 'update' => [ '$set' => [ 'foo' => 'bar' ] ],
+ ] );
+ $server->executeReadWriteCommand(
+ DATABASE_NAME,
+ $command,
+ [
+ 'readConcern' => new \MongoDB\Driver\ReadConcern(\MongoDB\Driver\ReadConcern::LOCAL),
+ 'writeConcern' => new \MongoDB\Driver\WriteConcern(\MongoDB\Driver\WriteConcern::MAJORITY),
+ ]
+ );
+ },
+ function(stdClass $command) {
+ echo "Read Concern: ", $command->readConcern->level, "\n";
+ echo "Write Concern: ", $command->writeConcern->w, "\n";
+ }
+);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Read Concern: local
+Write Concern: majority
+===DONE===
diff --git a/mongodb-1.12.0/tests/server/server-executeReadWriteCommand-002.phpt b/mongodb-1.13.0/tests/server/server-executeReadWriteCommand-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/server/server-executeReadWriteCommand-002.phpt
rename to mongodb-1.13.0/tests/server/server-executeReadWriteCommand-002.phpt
diff --git a/mongodb-1.13.0/tests/server/server-executeReadWriteCommand-003.phpt b/mongodb-1.13.0/tests/server/server-executeReadWriteCommand-003.phpt
new file mode 100644
index 00000000..a750b368
--- /dev/null
+++ b/mongodb-1.13.0/tests/server/server-executeReadWriteCommand-003.phpt
@@ -0,0 +1,47 @@
+--TEST--
+MongoDB\Driver\Server::executeReadWriteCommand() read and write concern inheritance
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_replica_set(); ?>
+<?php skip_if_not_enough_data_nodes(2); /* w:2 */ ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+require_once __DIR__ . "/../utils/observer.php";
+
+$manager = create_test_manager(URI, ['readConcernLevel' => 'local', 'w' => 2, 'wtimeoutms' => 1000]);
+$server = $manager->selectServer(new MongoDB\Driver\ReadPreference('primary'));
+
+$command = new MongoDB\Driver\Command([
+ 'aggregate' => COLLECTION_NAME,
+ 'pipeline' => [
+ ['$group' => ['_id' => 1]],
+ ['$out' => COLLECTION_NAME . '.out'],
+ ],
+ 'cursor' => (object) [],
+]);
+
+(new CommandObserver)->observe(
+ function() use ($server, $command) {
+ $server->executeReadWriteCommand(DATABASE_NAME, $command);
+ $server->executeReadWriteCommand(DATABASE_NAME, $command, [
+ 'readConcern' => new MongoDB\Driver\ReadConcern(MongoDB\Driver\ReadConcern::AVAILABLE),
+ 'writeConcern' => new MongoDB\Driver\WriteConcern(1),
+ ]);
+ },
+ function(stdClass $command) {
+ echo json_encode($command->readConcern), "\n";
+ echo json_encode($command->writeConcern), "\n";
+ }
+);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+{"level":"local"}
+{"w":2,"wtimeout":1000}
+{"level":"available"}
+{"w":1}
+===DONE===
diff --git a/mongodb-1.12.0/tests/server/server-executeReadWriteCommand_error-001.phpt b/mongodb-1.13.0/tests/server/server-executeReadWriteCommand_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/server/server-executeReadWriteCommand_error-001.phpt
rename to mongodb-1.13.0/tests/server/server-executeReadWriteCommand_error-001.phpt
diff --git a/mongodb-1.13.0/tests/server/server-executeWriteCommand-001.phpt b/mongodb-1.13.0/tests/server/server-executeWriteCommand-001.phpt
new file mode 100644
index 00000000..44c34e54
--- /dev/null
+++ b/mongodb-1.13.0/tests/server/server-executeWriteCommand-001.phpt
@@ -0,0 +1,42 @@
+--TEST--
+MongoDB\Driver\Server::executeWriteCommand()
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_live(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+require_once __DIR__ . "/../utils/observer.php";
+
+$manager = create_test_manager();
+$server = $manager->selectServer(new MongoDB\Driver\ReadPreference(MongoDB\Driver\ReadPreference::RP_PRIMARY));
+
+$bw = new MongoDB\Driver\BulkWrite();
+$bw->insert(['a' => 1]);
+$manager->executeBulkWrite(NS, $bw);
+
+(new CommandObserver)->observe(
+ function() use ($server) {
+ $command = new MongoDB\Driver\Command([
+ 'drop' => COLLECTION_NAME,
+ ]);
+ $server->executeWriteCommand(
+ DATABASE_NAME,
+ $command,
+ [
+ 'writeConcern' => new \MongoDB\Driver\WriteConcern(\MongoDB\Driver\WriteConcern::MAJORITY),
+ ]
+ );
+ },
+ function(stdClass $command) {
+ echo "Write Concern: ", $command->writeConcern->w, "\n";
+ }
+);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Write Concern: majority
+===DONE===
diff --git a/mongodb-1.12.0/tests/server/server-executeWriteCommand-002.phpt b/mongodb-1.13.0/tests/server/server-executeWriteCommand-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/server/server-executeWriteCommand-002.phpt
rename to mongodb-1.13.0/tests/server/server-executeWriteCommand-002.phpt
diff --git a/mongodb-1.13.0/tests/server/server-executeWriteCommand-003.phpt b/mongodb-1.13.0/tests/server/server-executeWriteCommand-003.phpt
new file mode 100644
index 00000000..21b63173
--- /dev/null
+++ b/mongodb-1.13.0/tests/server/server-executeWriteCommand-003.phpt
@@ -0,0 +1,40 @@
+--TEST--
+MongoDB\Driver\Server::executeWriteCommand() write concern inheritance
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_replica_set(); ?>
+<?php skip_if_not_enough_data_nodes(2); /* w:2 */ ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+require_once __DIR__ . "/../utils/observer.php";
+
+$manager = create_test_manager(URI, ['w' => 2, 'wtimeoutms' => 1000]);
+$server = $manager->selectServer(new MongoDB\Driver\ReadPreference('primary'));
+
+$command = new MongoDB\Driver\Command([
+ 'findAndModify' => COLLECTION_NAME,
+ 'query' => ['x' => 1],
+ 'upsert' => true,
+ 'new' => true,
+ 'update' => ['$inc' => ['x' => 1]],
+]);
+
+(new CommandObserver)->observe(
+ function() use ($server, $command) {
+ $server->executeWriteCommand(DATABASE_NAME, $command);
+ $server->executeWriteCommand(DATABASE_NAME, $command, ['writeConcern' => new MongoDB\Driver\WriteConcern(1)]);
+ },
+ function(stdClass $command) {
+ echo json_encode($command->writeConcern), "\n";
+ }
+);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+{"w":2,"wtimeout":1000}
+{"w":1}
+===DONE===
diff --git a/mongodb-1.12.0/tests/server/server-executeWriteCommand_error-001.phpt b/mongodb-1.13.0/tests/server/server-executeWriteCommand_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/server/server-executeWriteCommand_error-001.phpt
rename to mongodb-1.13.0/tests/server/server-executeWriteCommand_error-001.phpt
diff --git a/mongodb-1.12.0/tests/server/server-getInfo-001.phpt b/mongodb-1.13.0/tests/server/server-getInfo-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/server/server-getInfo-001.phpt
rename to mongodb-1.13.0/tests/server/server-getInfo-001.phpt
diff --git a/mongodb-1.12.0/tests/server/server-getLatency-001.phpt b/mongodb-1.13.0/tests/server/server-getLatency-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/server/server-getLatency-001.phpt
rename to mongodb-1.13.0/tests/server/server-getLatency-001.phpt
diff --git a/mongodb-1.13.0/tests/server/server-getLatency-002.phpt b/mongodb-1.13.0/tests/server/server-getLatency-002.phpt
new file mode 100644
index 00000000..5530c0b3
--- /dev/null
+++ b/mongodb-1.13.0/tests/server/server-getLatency-002.phpt
@@ -0,0 +1,19 @@
+--TEST--
+MongoDB\Driver\Server::getLatency() returns null when unset (e.g. load balancer)
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_load_balanced(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+$server = $manager->selectServer(new MongoDB\Driver\ReadPreference('primary'));
+var_dump($server->getLatency());
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+NULL
+===DONE===
diff --git a/mongodb-1.13.0/tests/server/server-getServerDescription-001.phpt b/mongodb-1.13.0/tests/server/server-getServerDescription-001.phpt
new file mode 100644
index 00000000..392555df
--- /dev/null
+++ b/mongodb-1.13.0/tests/server/server-getServerDescription-001.phpt
@@ -0,0 +1,19 @@
+--TEST--
+MongoDB\Driver\Server::getServerDescription()
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_live(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+$server = $manager->selectServer(new MongoDB\Driver\ReadPreference('primary'));
+var_dump($server->getServerDescription() instanceof MongoDB\Driver\ServerDescription);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+bool(true)
+===DONE===
diff --git a/mongodb-1.12.0/tests/server/server-getTags-001.phpt b/mongodb-1.13.0/tests/server/server-getTags-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/server/server-getTags-001.phpt
rename to mongodb-1.13.0/tests/server/server-getTags-001.phpt
diff --git a/mongodb-1.12.0/tests/server/server-getTags-002.phpt b/mongodb-1.13.0/tests/server/server-getTags-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/server/server-getTags-002.phpt
rename to mongodb-1.13.0/tests/server/server-getTags-002.phpt
diff --git a/mongodb-1.12.0/tests/server/server_error-001.phpt b/mongodb-1.13.0/tests/server/server_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/server/server_error-001.phpt
rename to mongodb-1.13.0/tests/server/server_error-001.phpt
diff --git a/mongodb-1.12.0/tests/serverApi/serverApi-bsonserialize-001.phpt b/mongodb-1.13.0/tests/serverApi/serverApi-bsonserialize-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/serverApi/serverApi-bsonserialize-001.phpt
rename to mongodb-1.13.0/tests/serverApi/serverApi-bsonserialize-001.phpt
diff --git a/mongodb-1.12.0/tests/serverApi/serverApi-bsonserialize-002.phpt b/mongodb-1.13.0/tests/serverApi/serverApi-bsonserialize-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/serverApi/serverApi-bsonserialize-002.phpt
rename to mongodb-1.13.0/tests/serverApi/serverApi-bsonserialize-002.phpt
diff --git a/mongodb-1.12.0/tests/serverApi/serverApi-construct-001.phpt b/mongodb-1.13.0/tests/serverApi/serverApi-construct-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/serverApi/serverApi-construct-001.phpt
rename to mongodb-1.13.0/tests/serverApi/serverApi-construct-001.phpt
diff --git a/mongodb-1.12.0/tests/serverApi/serverApi-debug.phpt b/mongodb-1.13.0/tests/serverApi/serverApi-debug.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/serverApi/serverApi-debug.phpt
rename to mongodb-1.13.0/tests/serverApi/serverApi-debug.phpt
diff --git a/mongodb-1.12.0/tests/serverApi/serverApi-serialization-001.phpt b/mongodb-1.13.0/tests/serverApi/serverApi-serialization-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/serverApi/serverApi-serialization-001.phpt
rename to mongodb-1.13.0/tests/serverApi/serverApi-serialization-001.phpt
diff --git a/mongodb-1.12.0/tests/serverApi/serverApi-serialization-002.phpt b/mongodb-1.13.0/tests/serverApi/serverApi-serialization-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/serverApi/serverApi-serialization-002.phpt
rename to mongodb-1.13.0/tests/serverApi/serverApi-serialization-002.phpt
diff --git a/mongodb-1.12.0/tests/serverApi/serverApi-serialization_error-001.phpt b/mongodb-1.13.0/tests/serverApi/serverApi-serialization_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/serverApi/serverApi-serialization_error-001.phpt
rename to mongodb-1.13.0/tests/serverApi/serverApi-serialization_error-001.phpt
diff --git a/mongodb-1.12.0/tests/serverApi/serverApi-serialization_error-002.phpt b/mongodb-1.13.0/tests/serverApi/serverApi-serialization_error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/serverApi/serverApi-serialization_error-002.phpt
rename to mongodb-1.13.0/tests/serverApi/serverApi-serialization_error-002.phpt
diff --git a/mongodb-1.12.0/tests/serverApi/serverApi-set_state-001.phpt b/mongodb-1.13.0/tests/serverApi/serverApi-set_state-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/serverApi/serverApi-set_state-001.phpt
rename to mongodb-1.13.0/tests/serverApi/serverApi-set_state-001.phpt
diff --git a/mongodb-1.12.0/tests/serverApi/serverApi-set_state_error-001.phpt b/mongodb-1.13.0/tests/serverApi/serverApi-set_state_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/serverApi/serverApi-set_state_error-001.phpt
rename to mongodb-1.13.0/tests/serverApi/serverApi-set_state_error-001.phpt
diff --git a/mongodb-1.12.0/tests/serverApi/serverApi-var_export-001.phpt b/mongodb-1.13.0/tests/serverApi/serverApi-var_export-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/serverApi/serverApi-var_export-001.phpt
rename to mongodb-1.13.0/tests/serverApi/serverApi-var_export-001.phpt
diff --git a/mongodb-1.13.0/tests/serverDescription/serverDescription-constants.phpt b/mongodb-1.13.0/tests/serverDescription/serverDescription-constants.phpt
new file mode 100644
index 00000000..1d0e8162
--- /dev/null
+++ b/mongodb-1.13.0/tests/serverDescription/serverDescription-constants.phpt
@@ -0,0 +1,31 @@
+--TEST--
+MongoDB\Driver\ServerDescription constants
+--FILE--
+<?php
+
+var_dump(MongoDB\Driver\ServerDescription::TYPE_UNKNOWN);
+var_dump(MongoDB\Driver\ServerDescription::TYPE_STANDALONE);
+var_dump(MongoDB\Driver\ServerDescription::TYPE_MONGOS);
+var_dump(MongoDB\Driver\ServerDescription::TYPE_POSSIBLE_PRIMARY);
+var_dump(MongoDB\Driver\ServerDescription::TYPE_RS_PRIMARY);
+var_dump(MongoDB\Driver\ServerDescription::TYPE_RS_SECONDARY);
+var_dump(MongoDB\Driver\ServerDescription::TYPE_RS_ARBITER);
+var_dump(MongoDB\Driver\ServerDescription::TYPE_RS_OTHER);
+var_dump(MongoDB\Driver\ServerDescription::TYPE_RS_GHOST);
+var_dump(MongoDB\Driver\ServerDescription::TYPE_LOAD_BALANCER);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+string(7) "Unknown"
+string(10) "Standalone"
+string(6) "Mongos"
+string(15) "PossiblePrimary"
+string(9) "RSPrimary"
+string(11) "RSSecondary"
+string(9) "RSArbiter"
+string(7) "RSOther"
+string(7) "RSGhost"
+string(12) "LoadBalancer"
+===DONE===
diff --git a/mongodb-1.13.0/tests/serverDescription/serverDescription-debug-001.phpt b/mongodb-1.13.0/tests/serverDescription/serverDescription-debug-001.phpt
new file mode 100644
index 00000000..489c73d1
--- /dev/null
+++ b/mongodb-1.13.0/tests/serverDescription/serverDescription-debug-001.phpt
@@ -0,0 +1,33 @@
+--TEST--
+MongoDB\Driver\ServerDescription debug output
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_live(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+$server = $manager->selectServer(new MongoDB\Driver\ReadPreference('primary'));
+var_dump($server->getServerDescription());
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+object(MongoDB\Driver\ServerDescription)#%d (%d) {
+ ["host"]=>
+ string(%d) "%s"
+ ["port"]=>
+ int(%d)
+ ["type"]=>
+ string(%d) "%r(Standalone|Mongos|RSPrimary|LoadBalancer)%r"
+ ["hello_response"]=>
+ array(%d) {%A
+ }
+ ["last_update_time"]=>
+ %r(string\(\d+\) "\d+"|int\(\d+\))%r
+ ["round_trip_time"]=>
+ %r(NULL|int\(\d+\))%r
+}
+===DONE===
diff --git a/mongodb-1.13.0/tests/serverDescription/serverDescription-getHelloResponse-001.phpt b/mongodb-1.13.0/tests/serverDescription/serverDescription-getHelloResponse-001.phpt
new file mode 100644
index 00000000..139df71e
--- /dev/null
+++ b/mongodb-1.13.0/tests/serverDescription/serverDescription-getHelloResponse-001.phpt
@@ -0,0 +1,21 @@
+--TEST--
+MongoDB\Driver\ServerDescription::getHelloResponse()
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_live(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+$server = $manager->selectServer(new MongoDB\Driver\ReadPreference('primary'));
+
+var_dump($server->getServerDescription()->getHelloResponse());
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+array(%d) {%A
+}
+===DONE===
diff --git a/mongodb-1.13.0/tests/serverDescription/serverDescription-getHost-001.phpt b/mongodb-1.13.0/tests/serverDescription/serverDescription-getHost-001.phpt
new file mode 100644
index 00000000..25ed7d19
--- /dev/null
+++ b/mongodb-1.13.0/tests/serverDescription/serverDescription-getHost-001.phpt
@@ -0,0 +1,20 @@
+--TEST--
+MongoDB\Driver\ServerDescription::getHost()
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_live(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+$server = $manager->selectServer(new MongoDB\Driver\ReadPreference('primary'));
+
+var_dump($server->getServerDescription()->getHost());
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+string(%s) %s
+===DONE===
diff --git a/mongodb-1.13.0/tests/serverDescription/serverDescription-getLastUpdateTime-001.phpt b/mongodb-1.13.0/tests/serverDescription/serverDescription-getLastUpdateTime-001.phpt
new file mode 100644
index 00000000..bb769a93
--- /dev/null
+++ b/mongodb-1.13.0/tests/serverDescription/serverDescription-getLastUpdateTime-001.phpt
@@ -0,0 +1,21 @@
+--TEST--
+MongoDB\Driver\ServerDescription::getLastUpdateTime()
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php if (8 !== PHP_INT_SIZE) { die('skip Only for 64-bit platform'); } ?>
+<?php skip_if_not_live(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+$server = $manager->selectServer(new MongoDB\Driver\ReadPreference('primary'));
+
+var_dump($server->getServerDescription()->getLastUpdateTime());
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+int(%d)
+===DONE===
diff --git a/mongodb-1.13.0/tests/serverDescription/serverDescription-getLastUpdateTime-002.phpt b/mongodb-1.13.0/tests/serverDescription/serverDescription-getLastUpdateTime-002.phpt
new file mode 100644
index 00000000..191af0e5
--- /dev/null
+++ b/mongodb-1.13.0/tests/serverDescription/serverDescription-getLastUpdateTime-002.phpt
@@ -0,0 +1,26 @@
+--TEST--
+MongoDB\Driver\ServerDescription::getLastUpdateTime() emits warning on truncation of 64-bit value
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php if (4 !== PHP_INT_SIZE) { die('skip Only for 32-bit platform'); } ?>
+<?php skip_if_not_live(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+$server = $manager->selectServer(new MongoDB\Driver\ReadPreference('primary'));
+
+/* The return value of mongoc_server_description_last_update_time() originates
+ * from bson_get_monotonic_time(), which has an unspecified starting point and
+ * may or may not exceed the range of a 32-bit integer. As such, EXPECTF allows
+ * for a possible warning message. Depending on how the value is truncated, it
+ * may also be reported as negative. */
+var_dump($server->getServerDescription()->getLastUpdateTime());
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+%r(Warning: Truncating 64-bit value for lastUpdateTime in .+ on line \d+\R)?%rint(%r(-?\d+)%r)
+===DONE===
diff --git a/mongodb-1.13.0/tests/serverDescription/serverDescription-getPort-001.phpt b/mongodb-1.13.0/tests/serverDescription/serverDescription-getPort-001.phpt
new file mode 100644
index 00000000..837bfc05
--- /dev/null
+++ b/mongodb-1.13.0/tests/serverDescription/serverDescription-getPort-001.phpt
@@ -0,0 +1,20 @@
+--TEST--
+MongoDB\Driver\ServerDescription::getPort()
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_live(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+$server = $manager->selectServer(new MongoDB\Driver\ReadPreference('primary'));
+
+var_dump($server->getServerDescription()->getPort());
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+int(%d)
+===DONE===
diff --git a/mongodb-1.13.0/tests/serverDescription/serverDescription-getRoundTripTime-001.phpt b/mongodb-1.13.0/tests/serverDescription/serverDescription-getRoundTripTime-001.phpt
new file mode 100644
index 00000000..4da70df9
--- /dev/null
+++ b/mongodb-1.13.0/tests/serverDescription/serverDescription-getRoundTripTime-001.phpt
@@ -0,0 +1,20 @@
+--TEST--
+MongoDB\Driver\ServerDescription::getRoundTripTime()
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_live(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+$server = $manager->selectServer(new MongoDB\Driver\ReadPreference('primary'));
+
+var_dump($server->getServerDescription()->getRoundTripTime());
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+%r(NULL|int\(\d+\))%r
+===DONE===
diff --git a/mongodb-1.13.0/tests/serverDescription/serverDescription-getType-001.phpt b/mongodb-1.13.0/tests/serverDescription/serverDescription-getType-001.phpt
new file mode 100644
index 00000000..d3b0d590
--- /dev/null
+++ b/mongodb-1.13.0/tests/serverDescription/serverDescription-getType-001.phpt
@@ -0,0 +1,20 @@
+--TEST--
+MongoDB\Driver\ServerDescription::getType()
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_live(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+$server = $manager->selectServer(new MongoDB\Driver\ReadPreference('primary'));
+
+var_dump($server->getServerDescription()->getType());
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+string(%d) "%r(Standalone|Mongos|RSPrimary|LoadBalancer)%r"
+===DONE===
diff --git a/mongodb-1.13.0/tests/serverDescription/serverDescription-var_export-001.phpt b/mongodb-1.13.0/tests/serverDescription/serverDescription-var_export-001.phpt
new file mode 100644
index 00000000..3ce79b89
--- /dev/null
+++ b/mongodb-1.13.0/tests/serverDescription/serverDescription-var_export-001.phpt
@@ -0,0 +1,30 @@
+--TEST--
+MongoDB\Driver\ServerDescription: var_export()
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_live(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+$server = $manager->selectServer(new MongoDB\Driver\ReadPreference('primary'));
+
+echo var_export($server->getServerDescription(), true), "\n";
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+MongoDB\Driver\ServerDescription::__set_state(array(
+ 'host' => '%s',
+ 'port' => %d,
+ 'type' => '%r(Standalone|Mongos|RSPrimary|LoadBalancer)%r',
+ 'hello_response' =>
+ array (%A
+ ),
+ 'last_update_time' => %r('\d+'|\d+)%r,
+ 'round_trip_time' => %r(NULL|\d+)%r,
+))
+===DONE===
diff --git a/mongodb-1.12.0/tests/session/bug1274-001.phpt b/mongodb-1.13.0/tests/session/bug1274-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/session/bug1274-001.phpt
rename to mongodb-1.13.0/tests/session/bug1274-001.phpt
diff --git a/mongodb-1.13.0/tests/session/bug1274-002.phpt b/mongodb-1.13.0/tests/session/bug1274-002.phpt
new file mode 100644
index 00000000..f5886865
--- /dev/null
+++ b/mongodb-1.13.0/tests/session/bug1274-002.phpt
@@ -0,0 +1,106 @@
+--TEST--
+PHPC-1274: Session destruct should not end session from parent process
+--SKIPIF--
+<?php if (!function_exists('pcntl_fork')) { die('skip pcntl_fork() not available'); } ?>
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_not_replica_set(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+class CommandLogger implements MongoDB\Driver\Monitoring\CommandSubscriber
+{
+ private $pid;
+
+ public function __construct()
+ {
+ $this->pid = getmypid();
+ }
+
+ public function commandStarted(MongoDB\Driver\Monitoring\CommandStartedEvent $event)
+ {
+ $command = $event->getCommand();
+ $commandName = $event->getCommandName();
+ $process = $this->pid === getmypid() ? 'Parent' : 'Child';
+
+ if ($commandName === 'find' || $commandName === 'getMore') {
+ printf("%s executes %s with batchSize: %d\n", $process, $commandName, $command->batchSize);
+ return;
+ }
+
+ printf("%s executes %s\n", $process, $commandName);
+ }
+
+ public function commandSucceeded(MongoDB\Driver\Monitoring\CommandSucceededEvent $event)
+ {
+ }
+
+ public function commandFailed(MongoDB\Driver\Monitoring\CommandFailedEvent $event)
+ {
+ }
+}
+
+$manager = create_test_manager();
+$session = $manager->startSession();
+
+$bulk = new MongoDB\Driver\BulkWrite();
+$bulk->insert(['x' => 1]);
+$bulk->insert(['x' => 2]);
+$bulk->insert(['x' => 3]);
+$manager->executeBulkWrite(NS, $bulk, ['session' => $session]);
+
+MongoDB\Driver\Monitoring\addSubscriber(new CommandLogger);
+
+$query = new MongoDB\Driver\Query([], ['batchSize' => 2]);
+$cursor = $manager->executeQuery(NS, $query, ['session' => $session]);
+
+$childPid = pcntl_fork();
+
+if ($childPid === 0) {
+ echo "Child exits\n";
+ exit;
+}
+
+function isSessionOnServer($manager, $session) {
+ /* Note: use $listLocalSessions since sessions are only synced to the config
+ * database's system.sessions collection every 30 minutes. Alternatively, we
+ * could run the refreshLogicalSessionCacheNow command on the primary. */
+ $command = new MongoDB\Driver\Command([
+ 'aggregate' => 1,
+ 'pipeline' => [
+ ['$listLocalSessions' => new stdClass],
+ ['$match' => ['_id.id' => $session->getLogicalSessionId()->id]],
+ ],
+ 'cursor' => new stdClass,
+ ]);
+ $cursor = $manager->executeReadCommand(DATABASE_NAME, $command);
+
+ return iterator_count($cursor) > 0;
+}
+
+if ($childPid > 0) {
+ $waitPid = pcntl_waitpid($childPid, $status);
+
+ if ($waitPid === $childPid) {
+ echo "Parent waited for child to exit\n";
+ }
+
+ printf("Session is on server: %s\n", isSessionOnServer($manager, $session) ? 'yes' : 'no');
+
+ printf("Parent fully iterated cursor for %d documents\n", iterator_count($cursor));
+}
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+Parent executes find with batchSize: 2
+Child exits
+Parent waited for child to exit
+Parent executes aggregate
+Session is on server: yes
+Parent executes getMore with batchSize: 2
+Parent fully iterated cursor for 3 documents
+===DONE===
diff --git a/mongodb-1.13.0/tests/session/bug1274-003.phpt b/mongodb-1.13.0/tests/session/bug1274-003.phpt
new file mode 100644
index 00000000..802d6f7f
--- /dev/null
+++ b/mongodb-1.13.0/tests/session/bug1274-003.phpt
@@ -0,0 +1,120 @@
+--TEST--
+PHPC-1274: Implicit sessions are not reused from parent process
+--SKIPIF--
+<?php if (!function_exists('pcntl_fork')) { die('skip pcntl_fork() not available'); } ?>
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_not_replica_set(); ?>
+<?php skip_if_not_clean(); ?>
+<?php skip_if_not_clean(DATABASE_NAME, COLLECTION_NAME . '_sessions'); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+class SessionLogger implements MongoDB\Driver\Monitoring\CommandSubscriber
+{
+ private $lsids = [];
+ private $logNamespace;
+ private $manager;
+ private $pid;
+
+ public function __construct(MongoDB\Driver\Manager $manager, $logNamespace)
+ {
+ $this->logNamespace = $logNamespace;
+ $this->manager = $manager;
+ $this->pid = getmypid();
+ }
+
+ public function executeAndLogSessions(callable $callable)
+ {
+ $this->lsids = [];
+
+ MongoDB\Driver\Monitoring\addSubscriber($this);
+ call_user_func($callable);
+ MongoDB\Driver\Monitoring\removeSubscriber($this);
+
+ if (empty($this->lsids)) {
+ return;
+ }
+
+ $bulk = new MongoDB\Driver\BulkWrite();
+
+ foreach ($this->lsids as $lsid) {
+ $bulk->update(['lsid' => $lsid], ['$inc' => ['count' => 1]], ['upsert' => true]);
+ }
+
+ $this->manager->executeBulkWrite($this->logNamespace, $bulk);
+ }
+
+ public function commandStarted(MongoDB\Driver\Monitoring\CommandStartedEvent $event)
+ {
+ $command = $event->getCommand();
+
+ if (isset($command->lsid)) {
+ $this->lsids[] = $command->lsid;
+ }
+
+ $commandName = $event->getCommandName();
+ $process = $this->pid === getmypid() ? 'Parent' : 'Child';
+
+ printf("%s executes %s\n", $process, $commandName);
+ }
+
+ public function commandSucceeded(MongoDB\Driver\Monitoring\CommandSucceededEvent $event)
+ {
+ }
+
+ public function commandFailed(MongoDB\Driver\Monitoring\CommandFailedEvent $event)
+ {
+ }
+}
+
+$manager = create_test_manager();
+$logNamespace = NS . '_sessions';
+$sessionLogger = new SessionLogger($manager, $logNamespace);
+
+/* This test uses executeBulkWrite() as it's the only execute method that does
+ * not create a cursor. The original patch for PHPC-1274 covered those methods
+ * that return a cursor but omitted executeBulkWrite(). */
+$sessionLogger->executeAndLogSessions(function() use ($manager) {
+ $bulk = new MongoDB\Driver\BulkWrite();
+ $bulk->insert(['x' => 1]);
+ $manager->executeBulkWrite(NS, $bulk);
+});
+
+$childPid = pcntl_fork();
+
+if ($childPid === 0) {
+ $sessionLogger->executeAndLogSessions(function() use ($manager) {
+ $bulk = new MongoDB\Driver\BulkWrite();
+ $bulk->insert(['x' => 2]);
+ $manager->executeBulkWrite(NS, $bulk);
+ });
+
+ echo "Child exits\n";
+ exit;
+}
+
+if ($childPid > 0) {
+ $waitPid = pcntl_waitpid($childPid, $status);
+
+ if ($waitPid === $childPid) {
+ echo "Parent waited for child to exit\n";
+ }
+
+ $query = new MongoDB\Driver\Query([]);
+ $cursor = $manager->executeQuery($logNamespace, $query);
+
+ printf("Sessions used: %d\n", iterator_count($cursor));
+}
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+Parent executes insert
+Child executes insert
+Child exits
+Parent waited for child to exit
+Sessions used: 2
+===DONE===
diff --git a/mongodb-1.12.0/tests/session/bug1274-004.phpt b/mongodb-1.13.0/tests/session/bug1274-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/session/bug1274-004.phpt
rename to mongodb-1.13.0/tests/session/bug1274-004.phpt
diff --git a/mongodb-1.13.0/tests/session/bug1274-005.phpt b/mongodb-1.13.0/tests/session/bug1274-005.phpt
new file mode 100644
index 00000000..b9df3082
--- /dev/null
+++ b/mongodb-1.13.0/tests/session/bug1274-005.phpt
@@ -0,0 +1,106 @@
+--TEST--
+PHPC-1274: Session destruct should not end session from parent process (disableClientPersistence=true)
+--SKIPIF--
+<?php if (!function_exists('pcntl_fork')) { die('skip pcntl_fork() not available'); } ?>
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_not_replica_set(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+class CommandLogger implements MongoDB\Driver\Monitoring\CommandSubscriber
+{
+ private $pid;
+
+ public function __construct()
+ {
+ $this->pid = getmypid();
+ }
+
+ public function commandStarted(MongoDB\Driver\Monitoring\CommandStartedEvent $event)
+ {
+ $command = $event->getCommand();
+ $commandName = $event->getCommandName();
+ $process = $this->pid === getmypid() ? 'Parent' : 'Child';
+
+ if ($commandName === 'find' || $commandName === 'getMore') {
+ printf("%s executes %s with batchSize: %d\n", $process, $commandName, $command->batchSize);
+ return;
+ }
+
+ printf("%s executes %s\n", $process, $commandName);
+ }
+
+ public function commandSucceeded(MongoDB\Driver\Monitoring\CommandSucceededEvent $event)
+ {
+ }
+
+ public function commandFailed(MongoDB\Driver\Monitoring\CommandFailedEvent $event)
+ {
+ }
+}
+
+$manager = create_test_manager(URI, [], ['disableClientPersistence' => true]);
+$session = $manager->startSession();
+
+$bulk = new MongoDB\Driver\BulkWrite();
+$bulk->insert(['x' => 1]);
+$bulk->insert(['x' => 2]);
+$bulk->insert(['x' => 3]);
+$manager->executeBulkWrite(NS, $bulk, ['session' => $session]);
+
+MongoDB\Driver\Monitoring\addSubscriber(new CommandLogger);
+
+$query = new MongoDB\Driver\Query([], ['batchSize' => 2]);
+$cursor = $manager->executeQuery(NS, $query, ['session' => $session]);
+
+$childPid = pcntl_fork();
+
+if ($childPid === 0) {
+ echo "Child exits\n";
+ exit;
+}
+
+function isSessionOnServer($manager, $session) {
+ /* Note: use $listLocalSessions since sessions are only synced to the config
+ * database's system.sessions collection every 30 minutes. Alternatively, we
+ * could run the refreshLogicalSessionCacheNow command on the primary. */
+ $command = new MongoDB\Driver\Command([
+ 'aggregate' => 1,
+ 'pipeline' => [
+ ['$listLocalSessions' => new stdClass],
+ ['$match' => ['_id.id' => $session->getLogicalSessionId()->id]],
+ ],
+ 'cursor' => new stdClass,
+ ]);
+ $cursor = $manager->executeReadCommand(DATABASE_NAME, $command);
+
+ return iterator_count($cursor) > 0;
+}
+
+if ($childPid > 0) {
+ $waitPid = pcntl_waitpid($childPid, $status);
+
+ if ($waitPid === $childPid) {
+ echo "Parent waited for child to exit\n";
+ }
+
+ printf("Session is on server: %s\n", isSessionOnServer($manager, $session) ? 'yes' : 'no');
+
+ printf("Parent fully iterated cursor for %d documents\n", iterator_count($cursor));
+}
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+Parent executes find with batchSize: 2
+Child exits
+Parent waited for child to exit
+Parent executes aggregate
+Session is on server: yes
+Parent executes getMore with batchSize: 2
+Parent fully iterated cursor for 3 documents
+===DONE===
diff --git a/mongodb-1.13.0/tests/session/bug1274-006.phpt b/mongodb-1.13.0/tests/session/bug1274-006.phpt
new file mode 100644
index 00000000..642a934a
--- /dev/null
+++ b/mongodb-1.13.0/tests/session/bug1274-006.phpt
@@ -0,0 +1,120 @@
+--TEST--
+PHPC-1274: Implicit sessions are not reused from parent process (disableClientPersistence=true)
+--SKIPIF--
+<?php if (!function_exists('pcntl_fork')) { die('skip pcntl_fork() not available'); } ?>
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_not_replica_set(); ?>
+<?php skip_if_not_clean(); ?>
+<?php skip_if_not_clean(DATABASE_NAME, COLLECTION_NAME . '_sessions'); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+class SessionLogger implements MongoDB\Driver\Monitoring\CommandSubscriber
+{
+ private $lsids = [];
+ private $logNamespace;
+ private $manager;
+ private $pid;
+
+ public function __construct(MongoDB\Driver\Manager $manager, $logNamespace)
+ {
+ $this->logNamespace = $logNamespace;
+ $this->manager = $manager;
+ $this->pid = getmypid();
+ }
+
+ public function executeAndLogSessions(callable $callable)
+ {
+ $this->lsids = [];
+
+ MongoDB\Driver\Monitoring\addSubscriber($this);
+ call_user_func($callable);
+ MongoDB\Driver\Monitoring\removeSubscriber($this);
+
+ if (empty($this->lsids)) {
+ return;
+ }
+
+ $bulk = new MongoDB\Driver\BulkWrite();
+
+ foreach ($this->lsids as $lsid) {
+ $bulk->update(['lsid' => $lsid], ['$inc' => ['count' => 1]], ['upsert' => true]);
+ }
+
+ $this->manager->executeBulkWrite($this->logNamespace, $bulk);
+ }
+
+ public function commandStarted(MongoDB\Driver\Monitoring\CommandStartedEvent $event)
+ {
+ $command = $event->getCommand();
+
+ if (isset($command->lsid)) {
+ $this->lsids[] = $command->lsid;
+ }
+
+ $commandName = $event->getCommandName();
+ $process = $this->pid === getmypid() ? 'Parent' : 'Child';
+
+ printf("%s executes %s\n", $process, $commandName);
+ }
+
+ public function commandSucceeded(MongoDB\Driver\Monitoring\CommandSucceededEvent $event)
+ {
+ }
+
+ public function commandFailed(MongoDB\Driver\Monitoring\CommandFailedEvent $event)
+ {
+ }
+}
+
+$manager = create_test_manager(URI, [], ['disableClientPersistence' => true]);
+$logNamespace = NS . '_sessions';
+$sessionLogger = new SessionLogger($manager, $logNamespace);
+
+/* This test uses executeBulkWrite() as it's the only execute method that does
+ * not create a cursor. The original patch for PHPC-1274 covered those methods
+ * that return a cursor but omitted executeBulkWrite(). */
+$sessionLogger->executeAndLogSessions(function() use ($manager) {
+ $bulk = new MongoDB\Driver\BulkWrite();
+ $bulk->insert(['x' => 1]);
+ $manager->executeBulkWrite(NS, $bulk);
+});
+
+$childPid = pcntl_fork();
+
+if ($childPid === 0) {
+ $sessionLogger->executeAndLogSessions(function() use ($manager) {
+ $bulk = new MongoDB\Driver\BulkWrite();
+ $bulk->insert(['x' => 2]);
+ $manager->executeBulkWrite(NS, $bulk);
+ });
+
+ echo "Child exits\n";
+ exit;
+}
+
+if ($childPid > 0) {
+ $waitPid = pcntl_waitpid($childPid, $status);
+
+ if ($waitPid === $childPid) {
+ echo "Parent waited for child to exit\n";
+ }
+
+ $query = new MongoDB\Driver\Query([]);
+ $cursor = $manager->executeQuery($logNamespace, $query);
+
+ printf("Sessions used: %d\n", iterator_count($cursor));
+}
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+Parent executes insert
+Child executes insert
+Child exits
+Parent waited for child to exit
+Sessions used: 2
+===DONE===
diff --git a/mongodb-1.13.0/tests/session/session-001.phpt b/mongodb-1.13.0/tests/session/session-001.phpt
new file mode 100644
index 00000000..849278a0
--- /dev/null
+++ b/mongodb-1.13.0/tests/session/session-001.phpt
@@ -0,0 +1,33 @@
+--TEST--
+MongoDB\Driver\Session spec test: Pool is LIFO
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_not_live(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+
+$firstSession = $manager->startSession();
+$firstSessionId = $firstSession->getLogicalSessionId();
+
+/* libmongoc does not pool unused sessions (CDRIVER-3322), so we must use this
+ * session with a command to ensure it enters the pool. */
+$command = new MongoDB\Driver\Command(['ping' => 1]);
+$manager->executeCommand(DATABASE_NAME, $command, ['session' => $firstSession]);
+
+unset($firstSession);
+
+$secondSession = $manager->startSession();
+$secondSessionId = $secondSession->getLogicalSessionId();
+
+var_dump($firstSessionId == $secondSessionId);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+bool(true)
+===DONE===
diff --git a/mongodb-1.13.0/tests/session/session-002.phpt b/mongodb-1.13.0/tests/session/session-002.phpt
new file mode 100644
index 00000000..a83b3d53
--- /dev/null
+++ b/mongodb-1.13.0/tests/session/session-002.phpt
@@ -0,0 +1,173 @@
+--TEST--
+MongoDB\Driver\Session spec test: $clusterTime in commands
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_load_balanced(); /* TODO: CDRIVER-4174 */ ?>
+<?php skip_if_not_replica_set_or_sharded_cluster_with_replica_set(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+class Test implements MongoDB\Driver\Monitoring\CommandSubscriber
+{
+ private $lastSeenClusterTime;
+
+ public function aggregate()
+ {
+ $this->lastSeenClusterTime = null;
+
+ MongoDB\Driver\Monitoring\addSubscriber($this);
+
+ $manager = create_test_manager();
+ $session = $manager->startSession();
+
+ $command = new MongoDB\Driver\Command([
+ 'aggregate' => COLLECTION_NAME,
+ 'pipeline' => [],
+ 'cursor' => new stdClass(),
+ ]);
+ $manager->executeReadWriteCommand(DATABASE_NAME, $command, ['session' => $session]);
+ $manager->executeReadWriteCommand(DATABASE_NAME, $command, ['session' => $session]);
+
+ printf("Session reports last seen \$clusterTime: %s\n", ($session->getClusterTime() == $this->lastSeenClusterTime) ? 'yes' : 'no');
+
+ MongoDB\Driver\Monitoring\removeSubscriber($this);
+ }
+
+ public function find()
+ {
+ $this->lastSeenClusterTime = null;
+
+ MongoDB\Driver\Monitoring\addSubscriber($this);
+
+ $manager = create_test_manager();
+ $session = $manager->startSession();
+
+ $query = new MongoDB\Driver\Query([]);
+ $manager->executeQuery(NS, $query, ['session' => $session]);
+ $manager->executeQuery(NS, $query, ['session' => $session]);
+
+ printf("Session reports last seen \$clusterTime: %s\n", ($session->getClusterTime() == $this->lastSeenClusterTime) ? 'yes' : 'no');
+
+ MongoDB\Driver\Monitoring\removeSubscriber($this);
+ }
+
+ public function insert()
+ {
+ $this->lastSeenClusterTime = null;
+
+ MongoDB\Driver\Monitoring\addSubscriber($this);
+
+ $manager = create_test_manager();
+ $session = $manager->startSession();
+
+ $bulk = new MongoDB\Driver\BulkWrite();
+ $bulk->insert(['x' => 1]);
+ $manager->executeBulkWrite(NS, $bulk, ['session' => $session]);
+
+ $bulk = new MongoDB\Driver\BulkWrite();
+ $bulk->insert(['x' => 2]);
+ $manager->executeBulkWrite(NS, $bulk, ['session' => $session]);
+
+ printf("Session reports last seen \$clusterTime: %s\n", ($session->getClusterTime() == $this->lastSeenClusterTime) ? 'yes' : 'no');
+
+ MongoDB\Driver\Monitoring\removeSubscriber($this);
+ }
+
+ public function ping()
+ {
+ $this->lastSeenClusterTime = null;
+
+ MongoDB\Driver\Monitoring\addSubscriber($this);
+
+ $manager = create_test_manager();
+ $session = $manager->startSession();
+
+ $command = new MongoDB\Driver\Command(['ping' => 1]);
+ $manager->executeCommand(DATABASE_NAME, $command, ['session' => $session]);
+ $manager->executeCommand(DATABASE_NAME, $command, ['session' => $session]);
+
+ printf("Session reports last seen \$clusterTime: %s\n", ($session->getClusterTime() == $this->lastSeenClusterTime) ? 'yes' : 'no');
+
+ MongoDB\Driver\Monitoring\removeSubscriber($this);
+ }
+
+ public function commandStarted(MongoDB\Driver\Monitoring\CommandStartedEvent $event)
+ {
+ $command = $event->getCommand();
+ $hasClusterTime = isset($command->{'$clusterTime'});
+
+ printf("%s command includes \$clusterTime: %s\n", $event->getCommandName(), $hasClusterTime ? 'yes' : 'no');
+
+ if ($hasClusterTime && $this->lastSeenClusterTime !== null) {
+ printf("%s command uses last seen \$clusterTime: %s\n", $event->getCommandName(), ($command->{'$clusterTime'} == $this->lastSeenClusterTime) ? 'yes' : 'no');
+ }
+ }
+
+ public function commandSucceeded(MongoDB\Driver\Monitoring\CommandSucceededEvent $event)
+ {
+ $reply = $event->getReply();
+ $hasClusterTime = isset($reply->{'$clusterTime'});
+
+ printf("%s command reply includes \$clusterTime: %s\n", $event->getCommandName(), $hasClusterTime ? 'yes' : 'no');
+
+ if ($hasClusterTime) {
+ $this->lastSeenClusterTime = $reply->{'$clusterTime'};
+ }
+ }
+
+ public function commandFailed(MongoDB\Driver\Monitoring\CommandFailedEvent $event)
+ {
+ }
+}
+
+echo "\nTesting aggregate command\n";
+(new Test)->aggregate();
+
+echo "\nTesting find command\n";
+(new Test)->find();
+
+echo "\nTesting insert command\n";
+(new Test)->insert();
+
+echo "\nTesting ping command\n";
+(new Test)->ping();
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+Testing aggregate command
+aggregate command includes $clusterTime: yes
+aggregate command reply includes $clusterTime: yes
+aggregate command includes $clusterTime: yes
+aggregate command uses last seen $clusterTime: yes
+aggregate command reply includes $clusterTime: yes
+Session reports last seen $clusterTime: yes
+
+Testing find command
+find command includes $clusterTime: yes
+find command reply includes $clusterTime: yes
+find command includes $clusterTime: yes
+find command uses last seen $clusterTime: yes
+find command reply includes $clusterTime: yes
+Session reports last seen $clusterTime: yes
+
+Testing insert command
+insert command includes $clusterTime: yes
+insert command reply includes $clusterTime: yes
+insert command includes $clusterTime: yes
+insert command uses last seen $clusterTime: yes
+insert command reply includes $clusterTime: yes
+Session reports last seen $clusterTime: yes
+
+Testing ping command
+ping command includes $clusterTime: yes
+ping command reply includes $clusterTime: yes
+ping command includes $clusterTime: yes
+ping command uses last seen $clusterTime: yes
+ping command reply includes $clusterTime: yes
+Session reports last seen $clusterTime: yes
+===DONE===
diff --git a/mongodb-1.13.0/tests/session/session-003.phpt b/mongodb-1.13.0/tests/session/session-003.phpt
new file mode 100644
index 00000000..baedb445
--- /dev/null
+++ b/mongodb-1.13.0/tests/session/session-003.phpt
@@ -0,0 +1,52 @@
+--TEST--
+MongoDB\Driver\Session spec test: session cannot be used for different clients
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_not_live(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+// Vary heartbeatFrequencyMS to ensure each Manager gets a different client
+$manager = create_test_manager(URI, ['heartbeatFrequencyMS' => 60000]);
+$otherManager = create_test_manager(URI, ['heartbeatFrequencyMS' => 90000]);
+
+// Create a session with the second Manager (associated with different client)
+$session = $otherManager->startSession();
+
+echo "\nTesting executeBulkWrite()\n";
+echo throws(function() use ($manager, $session) {
+ $bulk = new MongoDB\Driver\BulkWrite();
+ $bulk->insert(['x' => 1]);
+ $manager->executeBulkWrite(NS, $bulk, ['session' => $session]);
+}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
+
+echo "\nTesting executeCommand()\n";
+echo throws(function() use ($manager, $session) {
+ $command = new MongoDB\Driver\Command(['ping' => 1]);
+ $manager->executeCommand(DATABASE_NAME, $command, ['session' => $session]);
+}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
+
+echo "\nTesting executeQuery()\n";
+echo throws(function() use ($manager, $session) {
+ $query = new MongoDB\Driver\Query([]);
+ $manager->executeQuery(NS, $query, ['session' => $session]);
+}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+Testing executeBulkWrite()
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Cannot use Session started from a different Manager
+
+Testing executeCommand()
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Cannot use Session started from a different Manager
+
+Testing executeQuery()
+OK: Got MongoDB\Driver\Exception\InvalidArgumentException
+Cannot use Session started from a different Manager
+===DONE===
diff --git a/mongodb-1.12.0/tests/session/session-004.phpt b/mongodb-1.13.0/tests/session/session-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/session/session-004.phpt
rename to mongodb-1.13.0/tests/session/session-004.phpt
diff --git a/mongodb-1.13.0/tests/session/session-005.phpt b/mongodb-1.13.0/tests/session/session-005.phpt
new file mode 100644
index 00000000..1f2da9c9
--- /dev/null
+++ b/mongodb-1.13.0/tests/session/session-005.phpt
@@ -0,0 +1,53 @@
+--TEST--
+MongoDB\Driver\Session spec test: snapshot option requires MongoDB 5.0+
+--DESCRIPTION--
+PHPC-1876: Raise client error for snapshot sessions on <5.0 servers
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_not_live(); ?>
+<?php skip_if_server_version('>=', '5.0'); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+$session = $manager->startSession(['snapshot' => true]);
+
+/* Note: executeBulkWrite() always throws a BulkWriteException. Any previous
+ * exception's message will be included in the BulkWriteException message. */
+echo "\nTesting executeBulkWrite()\n";
+echo throws(function() use ($manager, $session) {
+ $bulk = new MongoDB\Driver\BulkWrite();
+ $bulk->insert(['x' => 1]);
+ $manager->executeBulkWrite(NS, $bulk, ['session' => $session]);
+}, MongoDB\Driver\Exception\BulkWriteException::class), "\n";
+
+echo "\nTesting executeCommand()\n";
+echo throws(function() use ($manager, $session) {
+ $command = new MongoDB\Driver\Command(['ping' => 1]);
+ $manager->executeCommand(DATABASE_NAME, $command, ['session' => $session]);
+}, MongoDB\Driver\Exception\RuntimeException::class), "\n";
+
+echo "\nTesting executeQuery()\n";
+echo throws(function() use ($manager, $session) {
+ $query = new MongoDB\Driver\Query([]);
+ $manager->executeQuery(NS, $query, ['session' => $session]);
+}, MongoDB\Driver\Exception\RuntimeException::class), "\n";
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+Testing executeBulkWrite()
+OK: Got MongoDB\Driver\Exception\BulkWriteException
+Bulk write failed due to previous MongoDB\Driver\Exception\RuntimeException: Snapshot reads require MongoDB 5.0 or later
+
+Testing executeCommand()
+OK: Got MongoDB\Driver\Exception\RuntimeException
+Snapshot reads require MongoDB 5.0 or later
+
+Testing executeQuery()
+OK: Got MongoDB\Driver\Exception\RuntimeException
+Snapshot reads require MongoDB 5.0 or later
+===DONE===
diff --git a/mongodb-1.13.0/tests/session/session-advanceClusterTime-001.phpt b/mongodb-1.13.0/tests/session/session-advanceClusterTime-001.phpt
new file mode 100644
index 00000000..7e8fe663
--- /dev/null
+++ b/mongodb-1.13.0/tests/session/session-advanceClusterTime-001.phpt
@@ -0,0 +1,51 @@
+--TEST--
+MongoDB\Driver\Session::advanceClusterTime()
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_not_replica_set_or_sharded_cluster_with_replica_set(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+$sessionA = $manager->startSession();
+$sessionB = $manager->startSession();
+
+$command = new MongoDB\Driver\Command(['ping' => 1]);
+$manager->executeCommand(DATABASE_NAME, $command, ['session' => $sessionA]);
+
+echo "Initial cluster time of session B:\n";
+var_dump($sessionB->getClusterTime());
+
+$sessionB->advanceClusterTime($sessionA->getClusterTime());
+
+echo "\nCluster time after advancing session B:\n";
+var_dump($sessionB->getClusterTime());
+
+echo "\nSessions A and B have equivalent cluster times:\n";
+var_dump($sessionA->getClusterTime() == $sessionB->getClusterTime());
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Initial cluster time of session B:
+NULL
+
+Cluster time after advancing session B:
+object(stdClass)#%d (%d) {
+ ["clusterTime"]=>
+ object(MongoDB\BSON\Timestamp)#%d (%d) {
+ ["increment"]=>
+ string(%d) "%d"
+ ["timestamp"]=>
+ string(%d) "%d"
+ }
+ ["signature"]=>
+ %a
+}
+
+Sessions A and B have equivalent cluster times:
+bool(true)
+===DONE===
diff --git a/mongodb-1.13.0/tests/session/session-advanceOperationTime-001.phpt b/mongodb-1.13.0/tests/session/session-advanceOperationTime-001.phpt
new file mode 100644
index 00000000..37f83b4f
--- /dev/null
+++ b/mongodb-1.13.0/tests/session/session-advanceOperationTime-001.phpt
@@ -0,0 +1,46 @@
+--TEST--
+MongoDB\Driver\Session::advanceOperationTime()
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_not_replica_set_or_sharded_cluster_with_replica_set(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+$sessionA = $manager->startSession();
+$sessionB = $manager->startSession();
+
+$command = new MongoDB\Driver\Command(['ping' => 1]);
+$manager->executeCommand(DATABASE_NAME, $command, ['session' => $sessionA]);
+
+echo "Initial operation time of session B:\n";
+var_dump($sessionB->getOperationTime());
+
+$sessionB->advanceOperationTime($sessionA->getOperationTime());
+
+echo "\nOperation time after advancing session B:\n";
+var_dump($sessionB->getOperationTime());
+
+echo "\nSessions A and B have equivalent operation times:\n";
+var_dump($sessionA->getOperationTime() == $sessionB->getOperationTime());
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Initial operation time of session B:
+NULL
+
+Operation time after advancing session B:
+object(MongoDB\BSON\Timestamp)#%d (%d) {
+ ["increment"]=>
+ string(%d) "%d"
+ ["timestamp"]=>
+ string(%d) "%d"
+}
+
+Sessions A and B have equivalent operation times:
+bool(true)
+===DONE===
diff --git a/mongodb-1.13.0/tests/session/session-advanceOperationTime-002.phpt b/mongodb-1.13.0/tests/session/session-advanceOperationTime-002.phpt
new file mode 100644
index 00000000..a00e07be
--- /dev/null
+++ b/mongodb-1.13.0/tests/session/session-advanceOperationTime-002.phpt
@@ -0,0 +1,36 @@
+--TEST--
+MongoDB\Driver\Session::advanceOperationTime() with Timestamp
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_not_replica_set_or_sharded_cluster_with_replica_set(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+$session = $manager->startSession();
+
+echo "Initial operation time of session:\n";
+var_dump($session->getOperationTime());
+
+$session->advanceOperationTime(new MongoDB\BSON\Timestamp(5678, 1234));
+
+echo "\nOperation time after advancing session:\n";
+var_dump($session->getOperationTime());
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Initial operation time of session:
+NULL
+
+Operation time after advancing session:
+object(MongoDB\BSON\Timestamp)#%d (%d) {
+ ["increment"]=>
+ string(4) "5678"
+ ["timestamp"]=>
+ string(4) "1234"
+}
+===DONE===
diff --git a/mongodb-1.13.0/tests/session/session-advanceOperationTime-003.phpt b/mongodb-1.13.0/tests/session/session-advanceOperationTime-003.phpt
new file mode 100644
index 00000000..3c51346d
--- /dev/null
+++ b/mongodb-1.13.0/tests/session/session-advanceOperationTime-003.phpt
@@ -0,0 +1,54 @@
+--TEST--
+MongoDB\Driver\Session::advanceOperationTime() with TimestampInterface
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_not_replica_set_or_sharded_cluster_with_replica_set(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+class MyTimestamp implements MongoDB\BSON\TimestampInterface
+{
+ public function getIncrement()
+ {
+ return 5678;
+ }
+
+ public function getTimestamp()
+ {
+ return 1234;
+ }
+
+ public function __toString()
+ {
+ return sprintf('[%d:%d]', $this->getIncrement(), $this->getTimestamp());
+ }
+}
+
+$manager = create_test_manager();
+$session = $manager->startSession();
+
+echo "Initial operation time of session:\n";
+var_dump($session->getOperationTime());
+
+$session->advanceOperationTime(new MyTimestamp);
+
+echo "\nOperation time after advancing session:\n";
+var_dump($session->getOperationTime());
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Initial operation time of session:
+NULL
+
+Operation time after advancing session:
+object(MongoDB\BSON\Timestamp)#%d (%d) {
+ ["increment"]=>
+ string(4) "5678"
+ ["timestamp"]=>
+ string(4) "1234"
+}
+===DONE===
diff --git a/mongodb-1.13.0/tests/session/session-advanceOperationTime_error-001.phpt b/mongodb-1.13.0/tests/session/session-advanceOperationTime_error-001.phpt
new file mode 100644
index 00000000..8192bfbf
--- /dev/null
+++ b/mongodb-1.13.0/tests/session/session-advanceOperationTime_error-001.phpt
@@ -0,0 +1,91 @@
+--TEST--
+MongoDB\Driver\Session::advanceOperationTime() with TimestampInterface exceptions
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_not_replica_set_or_sharded_cluster_with_replica_set(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+class MyTimestamp implements MongoDB\BSON\TimestampInterface
+{
+ private $failIncrement;
+ private $failTimestamp;
+
+ public function __construct($failIncrement, $failTimestamp)
+ {
+ $this->failIncrement = $failIncrement;
+ $this->failTimestamp = $failTimestamp;
+ }
+
+ public function getIncrement()
+ {
+ if ($this->failIncrement) {
+ throw new Exception('getIncrement() failed');
+ }
+
+ return 5678;
+ }
+
+ public function getTimestamp()
+ {
+ if ($this->failTimestamp) {
+ throw new Exception('getTimestamp() failed');
+ }
+
+ return 1234;
+ }
+
+ public function __toString()
+ {
+ return sprintf('[%d:%d]', $this->getIncrement(), $this->getTimestamp());
+ }
+}
+
+$manager = create_test_manager();
+$session = $manager->startSession();
+
+echo "Initial operation time of session:\n";
+var_dump($session->getOperationTime());
+
+$timestamps = [
+ new MyTimestamp(true, false),
+ new MyTimestamp(false, true),
+ new MyTimestamp(true, true),
+];
+
+foreach ($timestamps as $timestamp) {
+ echo "\n", throws(function() use ($session, $timestamp) {
+ $session->advanceOperationTime($timestamp);
+ }, 'Exception'), "\n";
+
+ echo "\nOperation time after advancing session fails:\n";
+ var_dump($session->getOperationTime());
+}
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+Initial operation time of session:
+NULL
+
+OK: Got Exception
+getIncrement() failed
+
+Operation time after advancing session fails:
+NULL
+
+OK: Got Exception
+getTimestamp() failed
+
+Operation time after advancing session fails:
+NULL
+
+OK: Got Exception
+getTimestamp() failed
+
+Operation time after advancing session fails:
+NULL
+===DONE===
diff --git a/mongodb-1.12.0/tests/session/session-commitTransaction-001.phpt b/mongodb-1.13.0/tests/session/session-commitTransaction-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/session/session-commitTransaction-001.phpt
rename to mongodb-1.13.0/tests/session/session-commitTransaction-001.phpt
diff --git a/mongodb-1.12.0/tests/session/session-constants.phpt b/mongodb-1.13.0/tests/session/session-constants.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/session/session-constants.phpt
rename to mongodb-1.13.0/tests/session/session-constants.phpt
diff --git a/mongodb-1.13.0/tests/session/session-debug-001.phpt b/mongodb-1.13.0/tests/session/session-debug-001.phpt
new file mode 100644
index 00000000..7480fbcf
--- /dev/null
+++ b/mongodb-1.13.0/tests/session/session-debug-001.phpt
@@ -0,0 +1,50 @@
+--TEST--
+MongoDB\Driver\Session debug output (before an operation)
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_not_live(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+$session = $manager->startSession();
+
+var_dump($session);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+object(MongoDB\Driver\Session)#%d (%d) {
+ ["logicalSessionId"]=>
+ array(1) {
+ ["id"]=>
+ object(MongoDB\BSON\Binary)#%d (%d) {
+ ["data"]=>
+ string(16) "%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c"
+ ["type"]=>
+ int(4)
+ }
+ }
+ ["clusterTime"]=>
+ NULL
+ ["causalConsistency"]=>
+ bool(true)
+ ["snapshot"]=>
+ bool(false)
+ ["operationTime"]=>
+ NULL
+ ["server"]=>
+ NULL
+ ["dirty"]=>
+ bool(false)
+ ["inTransaction"]=>
+ bool(false)
+ ["transactionState"]=>
+ string(4) "none"
+ ["transactionOptions"]=>
+ NULL
+}
+===DONE===
diff --git a/mongodb-1.13.0/tests/session/session-debug-002.phpt b/mongodb-1.13.0/tests/session/session-debug-002.phpt
new file mode 100644
index 00000000..46badb9b
--- /dev/null
+++ b/mongodb-1.13.0/tests/session/session-debug-002.phpt
@@ -0,0 +1,68 @@
+--TEST--
+MongoDB\Driver\Session debug output (after an operation)
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_not_replica_set_or_sharded_cluster_with_replica_set(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+$session = $manager->startSession();
+
+$command = new MongoDB\Driver\Command(['ping' => 1]);
+$manager->executeCommand(DATABASE_NAME, $command, ['session' => $session]);
+
+var_dump($session);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+object(MongoDB\Driver\Session)#%d (%d) {
+ ["logicalSessionId"]=>
+ array(1) {
+ ["id"]=>
+ object(MongoDB\BSON\Binary)#%d (%d) {
+ ["data"]=>
+ string(16) "%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c"
+ ["type"]=>
+ int(4)
+ }
+ }
+ ["clusterTime"]=>
+ array(2) {
+ ["clusterTime"]=>
+ object(MongoDB\BSON\Timestamp)#%d (%d) {
+ ["increment"]=>
+ string(%d) "%d"
+ ["timestamp"]=>
+ string(%d) "%d"
+ }
+ ["signature"]=>
+ %a
+ }
+ ["causalConsistency"]=>
+ bool(true)
+ ["snapshot"]=>
+ bool(false)
+ ["operationTime"]=>
+ object(MongoDB\BSON\Timestamp)#%d (%d) {
+ ["increment"]=>
+ string(%d) "%d"
+ ["timestamp"]=>
+ string(%d) "%d"
+ }
+ ["server"]=>
+ NULL
+ ["dirty"]=>
+ bool(false)
+ ["inTransaction"]=>
+ bool(false)
+ ["transactionState"]=>
+ string(4) "none"
+ ["transactionOptions"]=>
+ NULL
+}
+===DONE===
diff --git a/mongodb-1.13.0/tests/session/session-debug-003.phpt b/mongodb-1.13.0/tests/session/session-debug-003.phpt
new file mode 100644
index 00000000..57a3cce9
--- /dev/null
+++ b/mongodb-1.13.0/tests/session/session-debug-003.phpt
@@ -0,0 +1,50 @@
+--TEST--
+MongoDB\Driver\Session debug output (causalConsistency=false)
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_not_live(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+$session = $manager->startSession(['causalConsistency' => false]);
+
+var_dump($session);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+object(MongoDB\Driver\Session)#%d (%d) {
+ ["logicalSessionId"]=>
+ array(1) {
+ ["id"]=>
+ object(MongoDB\BSON\Binary)#%d (%d) {
+ ["data"]=>
+ string(16) "%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c"
+ ["type"]=>
+ int(4)
+ }
+ }
+ ["clusterTime"]=>
+ NULL
+ ["causalConsistency"]=>
+ bool(false)
+ ["snapshot"]=>
+ bool(false)
+ ["operationTime"]=>
+ NULL
+ ["server"]=>
+ NULL
+ ["dirty"]=>
+ bool(false)
+ ["inTransaction"]=>
+ bool(false)
+ ["transactionState"]=>
+ string(4) "none"
+ ["transactionOptions"]=>
+ NULL
+}
+===DONE===
diff --git a/mongodb-1.13.0/tests/session/session-debug-004.phpt b/mongodb-1.13.0/tests/session/session-debug-004.phpt
new file mode 100644
index 00000000..d884e3c2
--- /dev/null
+++ b/mongodb-1.13.0/tests/session/session-debug-004.phpt
@@ -0,0 +1,29 @@
+--TEST--
+MongoDB\Driver\Session debug output (after ending session)
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_not_live(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+$session = $manager->startSession();
+
+$command = new MongoDB\Driver\Command(['ping' => 1]);
+$manager->executeCommand(DATABASE_NAME, $command, ['session' => $session]);
+
+$session->endSession();
+
+var_dump($session);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+object(MongoDB\Driver\Session)#%d (%d) {
+ ["ended"]=>
+ bool(true)
+}
+===DONE===
diff --git a/mongodb-1.13.0/tests/session/session-debug-005.phpt b/mongodb-1.13.0/tests/session/session-debug-005.phpt
new file mode 100644
index 00000000..98607d40
--- /dev/null
+++ b/mongodb-1.13.0/tests/session/session-debug-005.phpt
@@ -0,0 +1,84 @@
+--TEST--
+MongoDB\Driver\Session debug output (during a pinned transaction)
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_not_mongos(); ?>
+<?php skip_if_no_transactions(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+$server = $manager->selectServer(new \MongoDB\Driver\ReadPreference('primary'));
+
+$session = $manager->startSession();
+$session->startTransaction();
+
+$query = new MongoDB\Driver\Query([]);
+$server->executeQuery(NS, $query, ['session' => $session]);
+
+var_dump($session);
+
+$session->abortTransaction();
+$session->endSession();
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+object(MongoDB\Driver\Session)#%d (%d) {
+ ["logicalSessionId"]=>
+ array(1) {
+ ["id"]=>
+ object(MongoDB\BSON\Binary)#%d (%d) {
+ ["data"]=>
+ string(16) "%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c"
+ ["type"]=>
+ int(4)
+ }
+ }
+ ["clusterTime"]=>
+ array(2) {
+ ["clusterTime"]=>
+ object(MongoDB\BSON\Timestamp)#%d (%d) {
+ ["increment"]=>
+ string(%d) "%d"
+ ["timestamp"]=>
+ string(%d) "%d"
+ }
+ ["signature"]=>
+ %a
+ }
+ ["causalConsistency"]=>
+ bool(true)
+ ["snapshot"]=>
+ bool(false)
+ ["operationTime"]=>
+ object(MongoDB\BSON\Timestamp)#%d (%d) {
+ ["increment"]=>
+ string(%d) "%d"
+ ["timestamp"]=>
+ string(%d) "%d"
+ }
+ ["server"]=>
+ object(MongoDB\Driver\Server)#%d (%d) {
+ %a
+ }
+ ["dirty"]=>
+ bool(false)
+ ["inTransaction"]=>
+ bool(true)
+ ["transactionState"]=>
+ string(11) "in_progress"
+ ["transactionOptions"]=>
+ array(1) {
+ ["readPreference"]=>
+ object(MongoDB\Driver\ReadPreference)#%d (%d) {
+ ["mode"]=>
+ string(7) "primary"
+ }
+ }
+}
+===DONE===
diff --git a/mongodb-1.13.0/tests/session/session-debug-006.phpt b/mongodb-1.13.0/tests/session/session-debug-006.phpt
new file mode 100644
index 00000000..b0cc7b3f
--- /dev/null
+++ b/mongodb-1.13.0/tests/session/session-debug-006.phpt
@@ -0,0 +1,77 @@
+--TEST--
+MongoDB\Driver\Session debug output (with transaction options)
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_no_transactions(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+$session = $manager->startSession();
+
+$options = [
+ 'maxCommitTimeMS' => 1,
+ 'readConcern' => new \MongoDB\Driver\ReadConcern('majority'),
+ 'readPreference' => new \MongoDB\Driver\ReadPreference('primaryPreferred'),
+ 'writeConcern' => new \MongoDB\Driver\WriteConcern('majority'),
+];
+
+$session->startTransaction($options);
+
+var_dump($session);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+object(MongoDB\Driver\Session)#%d (%d) {
+ ["logicalSessionId"]=>
+ array(1) {
+ ["id"]=>
+ object(MongoDB\BSON\Binary)#%d (%d) {
+ ["data"]=>
+ string(16) "%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c"
+ ["type"]=>
+ int(4)
+ }
+ }
+ ["clusterTime"]=>
+ NULL
+ ["causalConsistency"]=>
+ bool(true)
+ ["snapshot"]=>
+ bool(false)
+ ["operationTime"]=>
+ NULL
+ ["server"]=>
+ NULL
+ ["dirty"]=>
+ bool(false)
+ ["inTransaction"]=>
+ bool(true)
+ ["transactionState"]=>
+ string(8) "starting"
+ ["transactionOptions"]=>
+ array(4) {
+ ["maxCommitTimeMS"]=>
+ int(1)
+ ["readConcern"]=>
+ object(MongoDB\Driver\ReadConcern)#%d (%d) {
+ ["level"]=>
+ string(8) "majority"
+ }
+ ["readPreference"]=>
+ object(MongoDB\Driver\ReadPreference)#%d (%d) {
+ ["mode"]=>
+ string(16) "primaryPreferred"
+ }
+ ["writeConcern"]=>
+ object(MongoDB\Driver\WriteConcern)#%d (%d) {
+ ["w"]=>
+ string(8) "majority"
+ }
+ }
+}
+===DONE===
diff --git a/mongodb-1.13.0/tests/session/session-debug-007.phpt b/mongodb-1.13.0/tests/session/session-debug-007.phpt
new file mode 100644
index 00000000..38d4509b
--- /dev/null
+++ b/mongodb-1.13.0/tests/session/session-debug-007.phpt
@@ -0,0 +1,50 @@
+--TEST--
+MongoDB\Driver\Session debug output (snapshot=true)
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_not_live(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+$session = $manager->startSession(['snapshot' => true]);
+
+var_dump($session);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+object(MongoDB\Driver\Session)#%d (%d) {
+ ["logicalSessionId"]=>
+ array(1) {
+ ["id"]=>
+ object(MongoDB\BSON\Binary)#%d (%d) {
+ ["data"]=>
+ string(16) "%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c"
+ ["type"]=>
+ int(4)
+ }
+ }
+ ["clusterTime"]=>
+ NULL
+ ["causalConsistency"]=>
+ bool(false)
+ ["snapshot"]=>
+ bool(true)
+ ["operationTime"]=>
+ NULL
+ ["server"]=>
+ NULL
+ ["dirty"]=>
+ bool(false)
+ ["inTransaction"]=>
+ bool(false)
+ ["transactionState"]=>
+ string(4) "none"
+ ["transactionOptions"]=>
+ NULL
+}
+===DONE===
diff --git a/mongodb-1.12.0/tests/session/session-endSession-001.phpt b/mongodb-1.13.0/tests/session/session-endSession-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/session/session-endSession-001.phpt
rename to mongodb-1.13.0/tests/session/session-endSession-001.phpt
diff --git a/mongodb-1.13.0/tests/session/session-endSession-002.phpt b/mongodb-1.13.0/tests/session/session-endSession-002.phpt
new file mode 100644
index 00000000..2263acad
--- /dev/null
+++ b/mongodb-1.13.0/tests/session/session-endSession-002.phpt
@@ -0,0 +1,21 @@
+--TEST--
+MongoDB\Driver\Session::endSession() Calling method multiple times
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_not_live(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+
+$sessionA = $manager->startSession();
+$sessionA->endSession();
+$sessionA->endSession();
+$sessionA->endSession();
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+===DONE===
diff --git a/mongodb-1.13.0/tests/session/session-getClusterTime-001.phpt b/mongodb-1.13.0/tests/session/session-getClusterTime-001.phpt
new file mode 100644
index 00000000..9b68098a
--- /dev/null
+++ b/mongodb-1.13.0/tests/session/session-getClusterTime-001.phpt
@@ -0,0 +1,42 @@
+--TEST--
+MongoDB\Driver\Session::getClusterTime()
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_not_replica_set_or_sharded_cluster_with_replica_set(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+$session = $manager->startSession();
+
+echo "Initial cluster time:\n";
+var_dump($session->getClusterTime());
+
+$command = new MongoDB\Driver\Command(['ping' => 1]);
+$manager->executeCommand(DATABASE_NAME, $command, ['session' => $session]);
+
+echo "\nCluster time after command:\n";
+var_dump($session->getClusterTime());
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Initial cluster time:
+NULL
+
+Cluster time after command:
+object(stdClass)#%d (%d) {
+ ["clusterTime"]=>
+ object(MongoDB\BSON\Timestamp)#%d (%d) {
+ ["increment"]=>
+ string(%d) "%d"
+ ["timestamp"]=>
+ string(%d) "%d"
+ }
+ ["signature"]=>
+ %a
+}
+===DONE===
diff --git a/mongodb-1.13.0/tests/session/session-getLogicalSessionId-001.phpt b/mongodb-1.13.0/tests/session/session-getLogicalSessionId-001.phpt
new file mode 100644
index 00000000..5c610308
--- /dev/null
+++ b/mongodb-1.13.0/tests/session/session-getLogicalSessionId-001.phpt
@@ -0,0 +1,29 @@
+--TEST--
+MongoDB\Driver\Session::getLogicalSessionId()
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_not_live(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+$session = $manager->startSession();
+
+$lsid = $session->getLogicalSessionId();
+
+/* Note: we avoid dumping the Binary object as it may contain bytes that
+ * intefere with the test suite's ability to compare expected output. */
+var_dump($lsid instanceof stdClass);
+var_dump($lsid->id instanceof MongoDB\BSON\Binary);
+var_dump($lsid->id->getType() === MongoDB\BSON\Binary::TYPE_UUID);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+bool(true)
+bool(true)
+bool(true)
+===DONE===
diff --git a/mongodb-1.13.0/tests/session/session-getOperationTime-001.phpt b/mongodb-1.13.0/tests/session/session-getOperationTime-001.phpt
new file mode 100644
index 00000000..eac2ecbe
--- /dev/null
+++ b/mongodb-1.13.0/tests/session/session-getOperationTime-001.phpt
@@ -0,0 +1,37 @@
+--TEST--
+MongoDB\Driver\Session::getOperationTime()
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto(); ?>
+<?php skip_if_not_replica_set_or_sharded_cluster_with_replica_set(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+$session = $manager->startSession();
+
+echo "Initial operation time:\n";
+var_dump($session->getOperationTime());
+
+$command = new MongoDB\Driver\Command(['ping' => 1]);
+$manager->executeCommand(DATABASE_NAME, $command, ['session' => $session]);
+
+echo "\nOperation time after command:\n";
+var_dump($session->getOperationTime());
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Initial operation time:
+NULL
+
+Operation time after command:
+object(MongoDB\BSON\Timestamp)#%d (%d) {
+ ["increment"]=>
+ string(%d) "%d"
+ ["timestamp"]=>
+ string(%d) "%d"
+}
+===DONE===
diff --git a/mongodb-1.12.0/tests/session/session-getTransactionOptions-001.phpt b/mongodb-1.13.0/tests/session/session-getTransactionOptions-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/session/session-getTransactionOptions-001.phpt
rename to mongodb-1.13.0/tests/session/session-getTransactionOptions-001.phpt
diff --git a/mongodb-1.12.0/tests/session/session-getTransactionState-001.phpt b/mongodb-1.13.0/tests/session/session-getTransactionState-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/session/session-getTransactionState-001.phpt
rename to mongodb-1.13.0/tests/session/session-getTransactionState-001.phpt
diff --git a/mongodb-1.13.0/tests/session/session-isDirty-001.phpt b/mongodb-1.13.0/tests/session/session-isDirty-001.phpt
new file mode 100644
index 00000000..52a5eb15
--- /dev/null
+++ b/mongodb-1.13.0/tests/session/session-isDirty-001.phpt
@@ -0,0 +1,41 @@
+--TEST--
+MongoDB\Driver\Session::isDirty()
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto() ?>
+<?php skip_if_no_failcommand_failpoint(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+$server = $manager->selectServer();
+$session = $manager->startSession();
+
+printf("New session is dirty: %s\n", $session->isDirty() ? 'yes' : 'no');
+
+$command = new MongoDB\Driver\Command(['ping' => 1]);
+$server->executeCommand(DATABASE_NAME, $command, ['session' => $session]);
+
+printf("Session after successful command is dirty: %s\n", $session->isDirty() ? 'yes' : 'no');
+
+configureTargetedFailPoint($server, 'failCommand', [ 'times' => 1 ], [
+ 'failCommands' => ['ping'],
+ 'closeConnection' => true
+]);
+
+throws(function() use ($server, $command, $session) {
+ $server->executeCommand(DATABASE_NAME, $command, ['session' => $session]);
+}, MongoDB\Driver\Exception\ConnectionTimeoutException::class);
+
+printf("Session after network error is dirty: %s\n", $session->isDirty() ? 'yes' : 'no');
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+New session is dirty: no
+Session after successful command is dirty: no
+OK: Got MongoDB\Driver\Exception\ConnectionTimeoutException
+Session after network error is dirty: yes
+===DONE===
diff --git a/mongodb-1.12.0/tests/session/session-isInTransaction-001.phpt b/mongodb-1.13.0/tests/session/session-isInTransaction-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/session/session-isInTransaction-001.phpt
rename to mongodb-1.13.0/tests/session/session-isInTransaction-001.phpt
diff --git a/mongodb-1.12.0/tests/session/session-startTransaction-001.phpt b/mongodb-1.13.0/tests/session/session-startTransaction-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/session/session-startTransaction-001.phpt
rename to mongodb-1.13.0/tests/session/session-startTransaction-001.phpt
diff --git a/mongodb-1.12.0/tests/session/session-startTransaction_error-001.phpt b/mongodb-1.13.0/tests/session/session-startTransaction_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/session/session-startTransaction_error-001.phpt
rename to mongodb-1.13.0/tests/session/session-startTransaction_error-001.phpt
diff --git a/mongodb-1.12.0/tests/session/session-startTransaction_error-002.phpt b/mongodb-1.13.0/tests/session/session-startTransaction_error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/session/session-startTransaction_error-002.phpt
rename to mongodb-1.13.0/tests/session/session-startTransaction_error-002.phpt
diff --git a/mongodb-1.12.0/tests/session/session-startTransaction_error-004.phpt b/mongodb-1.13.0/tests/session/session-startTransaction_error-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/session/session-startTransaction_error-004.phpt
rename to mongodb-1.13.0/tests/session/session-startTransaction_error-004.phpt
diff --git a/mongodb-1.12.0/tests/session/session-startTransaction_error-005.phpt b/mongodb-1.13.0/tests/session/session-startTransaction_error-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/session/session-startTransaction_error-005.phpt
rename to mongodb-1.13.0/tests/session/session-startTransaction_error-005.phpt
diff --git a/mongodb-1.13.0/tests/session/session-startTransaction_error-006.phpt b/mongodb-1.13.0/tests/session/session-startTransaction_error-006.phpt
new file mode 100644
index 00000000..9c05b7cf
--- /dev/null
+++ b/mongodb-1.13.0/tests/session/session-startTransaction_error-006.phpt
@@ -0,0 +1,25 @@
+--TEST--
+MongoDB\Driver\Session::startTransaction() throws an error on replicasets < 4.0
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto() ?>
+<?php skip_if_not_replica_set(); ?>
+<?php skip_if_server_version('>=', '4.0'); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+$session = $manager->startSession();
+
+echo throws(function () use ($session) {
+ $session->startTransaction();
+}, MongoDB\Driver\Exception\RuntimeException::class), "\n";
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+OK: Got MongoDB\Driver\Exception\RuntimeException
+Multi-document transactions are not supported by this server version
+===DONE===
diff --git a/mongodb-1.13.0/tests/session/session-startTransaction_error-007.phpt b/mongodb-1.13.0/tests/session/session-startTransaction_error-007.phpt
new file mode 100644
index 00000000..a64bedf7
--- /dev/null
+++ b/mongodb-1.13.0/tests/session/session-startTransaction_error-007.phpt
@@ -0,0 +1,25 @@
+--TEST--
+MongoDB\Driver\Session::startTransaction() throws an error on sharded clusters < 4.2
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_libmongoc_crypto() ?>
+<?php skip_if_not_sharded_cluster_with_replica_set(); ?>
+<?php skip_if_server_version('>=', '4.2'); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+$session = $manager->startSession();
+
+echo throws(function () use ($session) {
+ $session->startTransaction();
+}, MongoDB\Driver\Exception\RuntimeException::class), "\n";
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+OK: Got MongoDB\Driver\Exception\RuntimeException
+Multi-document transactions are not supported by this server version
+===DONE===
diff --git a/mongodb-1.12.0/tests/session/transaction-integration-001.phpt b/mongodb-1.13.0/tests/session/transaction-integration-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/session/transaction-integration-001.phpt
rename to mongodb-1.13.0/tests/session/transaction-integration-001.phpt
diff --git a/mongodb-1.12.0/tests/session/transaction-integration-002.phpt b/mongodb-1.13.0/tests/session/transaction-integration-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/session/transaction-integration-002.phpt
rename to mongodb-1.13.0/tests/session/transaction-integration-002.phpt
diff --git a/mongodb-1.12.0/tests/session/transaction-integration-003.phpt b/mongodb-1.13.0/tests/session/transaction-integration-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/session/transaction-integration-003.phpt
rename to mongodb-1.13.0/tests/session/transaction-integration-003.phpt
diff --git a/mongodb-1.12.0/tests/session/transaction-integration_error-001.phpt b/mongodb-1.13.0/tests/session/transaction-integration_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/session/transaction-integration_error-001.phpt
rename to mongodb-1.13.0/tests/session/transaction-integration_error-001.phpt
diff --git a/mongodb-1.12.0/tests/session/transaction-integration_error-002.phpt b/mongodb-1.13.0/tests/session/transaction-integration_error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/session/transaction-integration_error-002.phpt
rename to mongodb-1.13.0/tests/session/transaction-integration_error-002.phpt
diff --git a/mongodb-1.12.0/tests/session/transaction-integration_error-003.phpt b/mongodb-1.13.0/tests/session/transaction-integration_error-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/session/transaction-integration_error-003.phpt
rename to mongodb-1.13.0/tests/session/transaction-integration_error-003.phpt
diff --git a/mongodb-1.12.0/tests/session/transaction-integration_error-004.phpt b/mongodb-1.13.0/tests/session/transaction-integration_error-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/session/transaction-integration_error-004.phpt
rename to mongodb-1.13.0/tests/session/transaction-integration_error-004.phpt
diff --git a/mongodb-1.12.0/tests/standalone/bug0166.phpt b/mongodb-1.13.0/tests/standalone/bug0166.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/standalone/bug0166.phpt
rename to mongodb-1.13.0/tests/standalone/bug0166.phpt
diff --git a/mongodb-1.12.0/tests/standalone/bug0231.phpt b/mongodb-1.13.0/tests/standalone/bug0231.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/standalone/bug0231.phpt
rename to mongodb-1.13.0/tests/standalone/bug0231.phpt
diff --git a/mongodb-1.12.0/tests/standalone/bug0357.phpt b/mongodb-1.13.0/tests/standalone/bug0357.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/standalone/bug0357.phpt
rename to mongodb-1.13.0/tests/standalone/bug0357.phpt
diff --git a/mongodb-1.12.0/tests/standalone/bug0545.phpt b/mongodb-1.13.0/tests/standalone/bug0545.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/standalone/bug0545.phpt
rename to mongodb-1.13.0/tests/standalone/bug0545.phpt
diff --git a/mongodb-1.12.0/tests/standalone/bug0655.phpt b/mongodb-1.13.0/tests/standalone/bug0655.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/standalone/bug0655.phpt
rename to mongodb-1.13.0/tests/standalone/bug0655.phpt
diff --git a/mongodb-1.12.0/tests/standalone/command-aggregate-001.phpt b/mongodb-1.13.0/tests/standalone/command-aggregate-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/standalone/command-aggregate-001.phpt
rename to mongodb-1.13.0/tests/standalone/command-aggregate-001.phpt
diff --git a/mongodb-1.12.0/tests/standalone/connectiontimeoutexception-001.phpt b/mongodb-1.13.0/tests/standalone/connectiontimeoutexception-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/standalone/connectiontimeoutexception-001.phpt
rename to mongodb-1.13.0/tests/standalone/connectiontimeoutexception-001.phpt
diff --git a/mongodb-1.13.0/tests/standalone/executiontimeoutexception-001.phpt b/mongodb-1.13.0/tests/standalone/executiontimeoutexception-001.phpt
new file mode 100644
index 00000000..8c35546d
--- /dev/null
+++ b/mongodb-1.13.0/tests/standalone/executiontimeoutexception-001.phpt
@@ -0,0 +1,34 @@
+--TEST--
+ExecutionTimeoutException: exceeding $maxTimeMS (queries)
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_test_commands_disabled(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+
+// Select a specific server for future operations to avoid mongos switching in sharded clusters
+$server = $manager->selectServer(new \MongoDB\Driver\ReadPreference('primary'));
+
+$query = new MongoDB\Driver\Query(array("company" => "Smith, Carter and Buckridge"), array(
+ 'projection' => array('_id' => 0, 'username' => 1),
+ 'sort' => array('phoneNumber' => 1),
+ 'modifiers' => array(
+ '$maxTimeMS' => 1,
+ ),
+));
+
+failMaxTimeMS($server);
+throws(function() use ($server, $query) {
+ $result = $server->executeQuery(NS, $query);
+}, "MongoDB\Driver\Exception\ExecutionTimeoutException");
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+OK: Got MongoDB\Driver\Exception\ExecutionTimeoutException
+===DONE===
diff --git a/mongodb-1.13.0/tests/standalone/executiontimeoutexception-002.phpt b/mongodb-1.13.0/tests/standalone/executiontimeoutexception-002.phpt
new file mode 100644
index 00000000..3ec35d24
--- /dev/null
+++ b/mongodb-1.13.0/tests/standalone/executiontimeoutexception-002.phpt
@@ -0,0 +1,34 @@
+--TEST--
+ExecutionTimeoutException: exceeding maxTimeMS (commands)
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_live(); ?>
+<?php skip_if_test_commands_disabled(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+
+// Select a specific server for future operations to avoid mongos switching in sharded clusters
+$server = $manager->selectServer(new \MongoDB\Driver\ReadPreference('primary'));
+
+$cmd = array(
+ "count" => "collection",
+ "query" => array("a" => 1),
+ "maxTimeMS" => 100,
+);
+$command = new MongoDB\Driver\Command($cmd);
+
+failMaxTimeMS($server);
+throws(function() use ($server, $command) {
+ $result = $server->executeCommand(DATABASE_NAME, $command);
+}, "MongoDB\Driver\Exception\ExecutionTimeoutException");
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+OK: Got MongoDB\Driver\Exception\ExecutionTimeoutException
+===DONE===
diff --git a/mongodb-1.12.0/tests/standalone/manager-as-singleton.phpt b/mongodb-1.13.0/tests/standalone/manager-as-singleton.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/standalone/manager-as-singleton.phpt
rename to mongodb-1.13.0/tests/standalone/manager-as-singleton.phpt
diff --git a/mongodb-1.12.0/tests/standalone/query-errors.phpt b/mongodb-1.13.0/tests/standalone/query-errors.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/standalone/query-errors.phpt
rename to mongodb-1.13.0/tests/standalone/query-errors.phpt
diff --git a/mongodb-1.12.0/tests/standalone/update-multi-001.phpt b/mongodb-1.13.0/tests/standalone/update-multi-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/standalone/update-multi-001.phpt
rename to mongodb-1.13.0/tests/standalone/update-multi-001.phpt
diff --git a/mongodb-1.12.0/tests/standalone/write-error-001.phpt b/mongodb-1.13.0/tests/standalone/write-error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/standalone/write-error-001.phpt
rename to mongodb-1.13.0/tests/standalone/write-error-001.phpt
diff --git a/mongodb-1.12.0/tests/standalone/writeresult-isacknowledged-001.phpt b/mongodb-1.13.0/tests/standalone/writeresult-isacknowledged-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/standalone/writeresult-isacknowledged-001.phpt
rename to mongodb-1.13.0/tests/standalone/writeresult-isacknowledged-001.phpt
diff --git a/mongodb-1.12.0/tests/standalone/writeresult-isacknowledged-002.phpt b/mongodb-1.13.0/tests/standalone/writeresult-isacknowledged-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/standalone/writeresult-isacknowledged-002.phpt
rename to mongodb-1.13.0/tests/standalone/writeresult-isacknowledged-002.phpt
diff --git a/mongodb-1.12.0/tests/standalone/writeresult-isacknowledged-003.phpt b/mongodb-1.13.0/tests/standalone/writeresult-isacknowledged-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/standalone/writeresult-isacknowledged-003.phpt
rename to mongodb-1.13.0/tests/standalone/writeresult-isacknowledged-003.phpt
diff --git a/mongodb-1.13.0/tests/topologyDescription/topologyDescription-constants.phpt b/mongodb-1.13.0/tests/topologyDescription/topologyDescription-constants.phpt
new file mode 100644
index 00000000..16979090
--- /dev/null
+++ b/mongodb-1.13.0/tests/topologyDescription/topologyDescription-constants.phpt
@@ -0,0 +1,23 @@
+--TEST--
+MongoDB\Driver\TopologyDescription constants
+--FILE--
+<?php
+
+var_dump(MongoDB\Driver\TopologyDescription::TYPE_UNKNOWN);
+var_dump(MongoDB\Driver\TopologyDescription::TYPE_SINGLE);
+var_dump(MongoDB\Driver\TopologyDescription::TYPE_SHARDED);
+var_dump(MongoDB\Driver\TopologyDescription::TYPE_REPLICA_SET_NO_PRIMARY);
+var_dump(MongoDB\Driver\TopologyDescription::TYPE_REPLICA_SET_WITH_PRIMARY);
+var_dump(MongoDB\Driver\TopologyDescription::TYPE_LOAD_BALANCED);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+string(7) "Unknown"
+string(6) "Single"
+string(7) "Sharded"
+string(19) "ReplicaSetNoPrimary"
+string(21) "ReplicaSetWithPrimary"
+string(12) "LoadBalanced"
+===DONE===
diff --git a/mongodb-1.13.0/tests/topologyDescription/topologyDescription-debug-001.phpt b/mongodb-1.13.0/tests/topologyDescription/topologyDescription-debug-001.phpt
new file mode 100644
index 00000000..e96ebefc
--- /dev/null
+++ b/mongodb-1.13.0/tests/topologyDescription/topologyDescription-debug-001.phpt
@@ -0,0 +1,64 @@
+--TEST--
+MongoDB\Driver\TopologyDescription debug output
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_live(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+class TopologyDescriptionProvider implements MongoDB\Driver\Monitoring\SDAMSubscriber
+{
+ private $topologyDescription;
+
+ public function serverChanged(MongoDB\Driver\Monitoring\ServerChangedEvent $event) {}
+
+ public function serverClosed(MongoDB\Driver\Monitoring\ServerClosedEvent $event) {}
+
+ public function serverHeartbeatFailed(MongoDB\Driver\Monitoring\ServerHeartbeatFailedEvent $event) {}
+
+ public function serverHeartbeatStarted(MongoDB\Driver\Monitoring\ServerHeartbeatStartedEvent $event) {}
+
+ public function serverHeartbeatSucceeded(MongoDB\Driver\Monitoring\ServerHeartbeatSucceededEvent $event) {}
+
+ public function serverOpening(MongoDB\Driver\Monitoring\ServerOpeningEvent $event) {}
+
+ public function topologyChanged(MongoDB\Driver\Monitoring\TopologyChangedEvent $event)
+ {
+ $this->topologyDescription = $event->getNewDescription();
+ }
+
+ public function topologyClosed(MongoDB\Driver\Monitoring\TopologyClosedEvent $event) {}
+
+ public function topologyOpening(MongoDB\Driver\Monitoring\TopologyOpeningEvent $event) {}
+
+ public function getTopologyDescription()
+ {
+ $manager = create_test_manager();
+ $manager->addSubscriber($this);
+ $manager->executeCommand(DATABASE_NAME, new MongoDB\Driver\Command(['ping' => 1]));
+ $manager->removeSubscriber($this);
+
+ return $this->topologyDescription;
+ }
+}
+
+$subscriber = new TopologyDescriptionProvider;
+$topologyDescription = $subscriber->getTopologyDescription();
+var_dump($topologyDescription);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+object(MongoDB\Driver\TopologyDescription)#%d (%d) {
+ ["servers"]=>
+ array(%d) {
+ [0]=>
+ object(MongoDB\Driver\ServerDescription)#%d (%d) {%A
+ }%A
+ }
+ ["type"]=>
+ string(%d) "%r(Single|Sharded|ReplicaSetWithPrimary|LoadBalanced)%r"
+}
+===DONE===
diff --git a/mongodb-1.13.0/tests/topologyDescription/topologyDescription-getServers-001.phpt b/mongodb-1.13.0/tests/topologyDescription/topologyDescription-getServers-001.phpt
new file mode 100644
index 00000000..1ca2ccd7
--- /dev/null
+++ b/mongodb-1.13.0/tests/topologyDescription/topologyDescription-getServers-001.phpt
@@ -0,0 +1,71 @@
+--TEST--
+MongoDB\Driver\TopologyDescription::getServers()
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_live(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+class TopologyDescriptionProvider implements MongoDB\Driver\Monitoring\SDAMSubscriber
+{
+ private $topologyDescription;
+
+ public function serverChanged(MongoDB\Driver\Monitoring\ServerChangedEvent $event) {}
+
+ public function serverClosed(MongoDB\Driver\Monitoring\ServerClosedEvent $event) {}
+
+ public function serverHeartbeatFailed(MongoDB\Driver\Monitoring\ServerHeartbeatFailedEvent $event) {}
+
+ public function serverHeartbeatStarted(MongoDB\Driver\Monitoring\ServerHeartbeatStartedEvent $event) {}
+
+ public function serverHeartbeatSucceeded(MongoDB\Driver\Monitoring\ServerHeartbeatSucceededEvent $event) {}
+
+ public function serverOpening(MongoDB\Driver\Monitoring\ServerOpeningEvent $event) {}
+
+ public function topologyChanged(MongoDB\Driver\Monitoring\TopologyChangedEvent $event)
+ {
+ $this->topologyDescription = $event->getNewDescription();
+ }
+
+ public function topologyClosed(MongoDB\Driver\Monitoring\TopologyClosedEvent $event) {}
+
+ public function topologyOpening(MongoDB\Driver\Monitoring\TopologyOpeningEvent $event) {}
+
+ public function getTopologyDescription()
+ {
+ $manager = create_test_manager();
+ $manager->addSubscriber($this);
+ $manager->executeCommand(DATABASE_NAME, new MongoDB\Driver\Command(['ping' => 1]));
+ $manager->removeSubscriber($this);
+
+ return $this->topologyDescription;
+ }
+}
+
+function isArrayOfServerDescriptions(array $sds) {
+ if (count($sds) < 1) {
+ return false;
+ }
+
+ foreach ($sds as $sd) {
+ if (! $sd instanceof MongoDB\Driver\ServerDescription) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+$subscriber = new TopologyDescriptionProvider;
+$topologyDescription = $subscriber->getTopologyDescription();
+$serverDescriptions = $topologyDescription->getServers();
+
+var_dump(isArrayOfServerDescriptions($serverDescriptions));
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+bool(true)
+===DONE===
diff --git a/mongodb-1.13.0/tests/topologyDescription/topologyDescription-getType-001.phpt b/mongodb-1.13.0/tests/topologyDescription/topologyDescription-getType-001.phpt
new file mode 100644
index 00000000..64a6e3b0
--- /dev/null
+++ b/mongodb-1.13.0/tests/topologyDescription/topologyDescription-getType-001.phpt
@@ -0,0 +1,55 @@
+--TEST--
+MongoDB\Driver\TopologyDescription::getType()
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_live(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+class TopologyDescriptionProvider implements MongoDB\Driver\Monitoring\SDAMSubscriber
+{
+ private $topologyDescription;
+
+ public function serverChanged(MongoDB\Driver\Monitoring\ServerChangedEvent $event) {}
+
+ public function serverClosed(MongoDB\Driver\Monitoring\ServerClosedEvent $event) {}
+
+ public function serverHeartbeatFailed(MongoDB\Driver\Monitoring\ServerHeartbeatFailedEvent $event) {}
+
+ public function serverHeartbeatStarted(MongoDB\Driver\Monitoring\ServerHeartbeatStartedEvent $event) {}
+
+ public function serverHeartbeatSucceeded(MongoDB\Driver\Monitoring\ServerHeartbeatSucceededEvent $event) {}
+
+ public function serverOpening(MongoDB\Driver\Monitoring\ServerOpeningEvent $event) {}
+
+ public function topologyChanged(MongoDB\Driver\Monitoring\TopologyChangedEvent $event)
+ {
+ $this->topologyDescription = $event->getNewDescription();
+ }
+
+ public function topologyClosed(MongoDB\Driver\Monitoring\TopologyClosedEvent $event) {}
+
+ public function topologyOpening(MongoDB\Driver\Monitoring\TopologyOpeningEvent $event) {}
+
+ public function getTopologyDescription()
+ {
+ $manager = create_test_manager();
+ $manager->addSubscriber($this);
+ $manager->executeCommand(DATABASE_NAME, new MongoDB\Driver\Command(['ping' => 1]));
+ $manager->removeSubscriber($this);
+
+ return $this->topologyDescription;
+ }
+}
+
+$subscriber = new TopologyDescriptionProvider;
+$topologyDescription = $subscriber->getTopologyDescription();
+var_dump($topologyDescription->getType());
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+string(%d) "%r(Single|Sharded|ReplicaSetWithPrimary|LoadBalanced)%r"
+===DONE===
diff --git a/mongodb-1.13.0/tests/topologyDescription/topologyDescription-hasReadableServer-001.phpt b/mongodb-1.13.0/tests/topologyDescription/topologyDescription-hasReadableServer-001.phpt
new file mode 100644
index 00000000..1f7c2d29
--- /dev/null
+++ b/mongodb-1.13.0/tests/topologyDescription/topologyDescription-hasReadableServer-001.phpt
@@ -0,0 +1,55 @@
+--TEST--
+MongoDB\Driver\TopologyDescription::hasReadableServer()
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_live(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+class TopologyDescriptionProvider implements MongoDB\Driver\Monitoring\SDAMSubscriber
+{
+ private $topologyDescription;
+
+ public function serverChanged(MongoDB\Driver\Monitoring\ServerChangedEvent $event) {}
+
+ public function serverClosed(MongoDB\Driver\Monitoring\ServerClosedEvent $event) {}
+
+ public function serverHeartbeatFailed(MongoDB\Driver\Monitoring\ServerHeartbeatFailedEvent $event) {}
+
+ public function serverHeartbeatStarted(MongoDB\Driver\Monitoring\ServerHeartbeatStartedEvent $event) {}
+
+ public function serverHeartbeatSucceeded(MongoDB\Driver\Monitoring\ServerHeartbeatSucceededEvent $event) {}
+
+ public function serverOpening(MongoDB\Driver\Monitoring\ServerOpeningEvent $event) {}
+
+ public function topologyChanged(MongoDB\Driver\Monitoring\TopologyChangedEvent $event)
+ {
+ $this->topologyDescription = $event->getNewDescription();
+ }
+
+ public function topologyClosed(MongoDB\Driver\Monitoring\TopologyClosedEvent $event) {}
+
+ public function topologyOpening(MongoDB\Driver\Monitoring\TopologyOpeningEvent $event) {}
+
+ public function getTopologyDescription()
+ {
+ $manager = create_test_manager();
+ $manager->addSubscriber($this);
+ $manager->executeCommand(DATABASE_NAME, new MongoDB\Driver\Command(['ping' => 1]));
+ $manager->removeSubscriber($this);
+
+ return $this->topologyDescription;
+ }
+}
+
+$subscriber = new TopologyDescriptionProvider;
+$topologyDescription = $subscriber->getTopologyDescription();
+var_dump($topologyDescription->hasReadableServer());
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+bool(true)
+===DONE===
diff --git a/mongodb-1.13.0/tests/topologyDescription/topologyDescription-hasReadableServer-002.phpt b/mongodb-1.13.0/tests/topologyDescription/topologyDescription-hasReadableServer-002.phpt
new file mode 100644
index 00000000..c0234ff3
--- /dev/null
+++ b/mongodb-1.13.0/tests/topologyDescription/topologyDescription-hasReadableServer-002.phpt
@@ -0,0 +1,56 @@
+--TEST--
+MongoDB\Driver\TopologyDescription::hasReadableServer() with ReadPreference argument
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_live(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+class TopologyDescriptionProvider implements MongoDB\Driver\Monitoring\SDAMSubscriber
+{
+ private $topologyDescription;
+
+ public function serverChanged(MongoDB\Driver\Monitoring\ServerChangedEvent $event) {}
+
+ public function serverClosed(MongoDB\Driver\Monitoring\ServerClosedEvent $event) {}
+
+ public function serverHeartbeatFailed(MongoDB\Driver\Monitoring\ServerHeartbeatFailedEvent $event) {}
+
+ public function serverHeartbeatStarted(MongoDB\Driver\Monitoring\ServerHeartbeatStartedEvent $event) {}
+
+ public function serverHeartbeatSucceeded(MongoDB\Driver\Monitoring\ServerHeartbeatSucceededEvent $event) {}
+
+ public function serverOpening(MongoDB\Driver\Monitoring\ServerOpeningEvent $event) {}
+
+ public function topologyChanged(MongoDB\Driver\Monitoring\TopologyChangedEvent $event)
+ {
+ $this->topologyDescription = $event->getNewDescription();
+ }
+
+ public function topologyClosed(MongoDB\Driver\Monitoring\TopologyClosedEvent $event) {}
+
+ public function topologyOpening(MongoDB\Driver\Monitoring\TopologyOpeningEvent $event) {}
+
+ public function getTopologyDescription()
+ {
+ $manager = create_test_manager();
+ $manager->addSubscriber($this);
+ $manager->executeCommand(DATABASE_NAME, new MongoDB\Driver\Command(['ping' => 1]));
+ $manager->removeSubscriber($this);
+
+ return $this->topologyDescription;
+ }
+}
+
+$subscriber = new TopologyDescriptionProvider;
+$topologyDescription = $subscriber->getTopologyDescription();
+$rp = new MongoDB\Driver\ReadPreference('primary');
+var_dump($topologyDescription->hasReadableServer($rp));
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+bool(true)
+===DONE===
diff --git a/mongodb-1.13.0/tests/topologyDescription/topologyDescription-hasReadableServer_error-001.phpt b/mongodb-1.13.0/tests/topologyDescription/topologyDescription-hasReadableServer_error-001.phpt
new file mode 100644
index 00000000..e6fc8e1f
--- /dev/null
+++ b/mongodb-1.13.0/tests/topologyDescription/topologyDescription-hasReadableServer_error-001.phpt
@@ -0,0 +1,68 @@
+--TEST--
+MongoDB\Driver\TopologyDescription::hasReadableServer() (argument with bad type)
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_live(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+class TopologyDescriptionProvider implements MongoDB\Driver\Monitoring\SDAMSubscriber
+{
+ private $topologyDescription;
+
+ public function serverChanged(MongoDB\Driver\Monitoring\ServerChangedEvent $event) {}
+
+ public function serverClosed(MongoDB\Driver\Monitoring\ServerClosedEvent $event) {}
+
+ public function serverHeartbeatFailed(MongoDB\Driver\Monitoring\ServerHeartbeatFailedEvent $event) {}
+
+ public function serverHeartbeatStarted(MongoDB\Driver\Monitoring\ServerHeartbeatStartedEvent $event) {}
+
+ public function serverHeartbeatSucceeded(MongoDB\Driver\Monitoring\ServerHeartbeatSucceededEvent $event) {}
+
+ public function serverOpening(MongoDB\Driver\Monitoring\ServerOpeningEvent $event) {}
+
+ public function topologyChanged(MongoDB\Driver\Monitoring\TopologyChangedEvent $event)
+ {
+ $this->topologyDescription = $event->getNewDescription();
+ }
+
+ public function topologyClosed(MongoDB\Driver\Monitoring\TopologyClosedEvent $event) {}
+
+ public function topologyOpening(MongoDB\Driver\Monitoring\TopologyOpeningEvent $event) {}
+
+ public function getTopologyDescription()
+ {
+ $manager = create_test_manager();
+ $manager->addSubscriber($this);
+ $manager->executeCommand(DATABASE_NAME, new MongoDB\Driver\Command(['ping' => 1]));
+ $manager->removeSubscriber($this);
+
+ return $this->topologyDescription;
+ }
+}
+
+$tests = [
+ null,
+ 1,
+ [],
+];
+
+$subscriber = new TopologyDescriptionProvider;
+$topologyDescription = $subscriber->getTopologyDescription();
+
+foreach ($tests as $test) {
+ throws(function() use ($topologyDescription, $test) {
+ $topologyDescription->hasReadableServer($test);
+ }, TypeError::class);
+}
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+OK: Got TypeError
+OK: Got TypeError
+OK: Got TypeError
+===DONE===
diff --git a/mongodb-1.13.0/tests/topologyDescription/topologyDescription-hasWritableServer-001.phpt b/mongodb-1.13.0/tests/topologyDescription/topologyDescription-hasWritableServer-001.phpt
new file mode 100644
index 00000000..17be4fb7
--- /dev/null
+++ b/mongodb-1.13.0/tests/topologyDescription/topologyDescription-hasWritableServer-001.phpt
@@ -0,0 +1,55 @@
+--TEST--
+MongoDB\Driver\TopologyDescription::hasWritableServer()
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_live(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+class TopologyDescriptionProvider implements MongoDB\Driver\Monitoring\SDAMSubscriber
+{
+ private $topologyDescription;
+
+ public function serverChanged(MongoDB\Driver\Monitoring\ServerChangedEvent $event) {}
+
+ public function serverClosed(MongoDB\Driver\Monitoring\ServerClosedEvent $event) {}
+
+ public function serverHeartbeatFailed(MongoDB\Driver\Monitoring\ServerHeartbeatFailedEvent $event) {}
+
+ public function serverHeartbeatStarted(MongoDB\Driver\Monitoring\ServerHeartbeatStartedEvent $event) {}
+
+ public function serverHeartbeatSucceeded(MongoDB\Driver\Monitoring\ServerHeartbeatSucceededEvent $event) {}
+
+ public function serverOpening(MongoDB\Driver\Monitoring\ServerOpeningEvent $event) {}
+
+ public function topologyChanged(MongoDB\Driver\Monitoring\TopologyChangedEvent $event)
+ {
+ $this->topologyDescription = $event->getNewDescription();
+ }
+
+ public function topologyClosed(MongoDB\Driver\Monitoring\TopologyClosedEvent $event) {}
+
+ public function topologyOpening(MongoDB\Driver\Monitoring\TopologyOpeningEvent $event) {}
+
+ public function getTopologyDescription()
+ {
+ $manager = create_test_manager();
+ $manager->addSubscriber($this);
+ $manager->executeCommand(DATABASE_NAME, new MongoDB\Driver\Command(['ping' => 1]));
+ $manager->removeSubscriber($this);
+
+ return $this->topologyDescription;
+ }
+}
+
+$subscriber = new TopologyDescriptionProvider;
+$topologyDescription = $subscriber->getTopologyDescription();
+var_dump($topologyDescription->hasWritableServer());
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+bool(true)
+===DONE===
diff --git a/mongodb-1.12.0/tests/utils/PHONGO-FIXTURES.json.gz b/mongodb-1.13.0/tests/utils/PHONGO-FIXTURES.json.gz
similarity index 100%
rename from mongodb-1.12.0/tests/utils/PHONGO-FIXTURES.json.gz
rename to mongodb-1.13.0/tests/utils/PHONGO-FIXTURES.json.gz
diff --git a/mongodb-1.12.0/tests/utils/basic-skipif.inc b/mongodb-1.13.0/tests/utils/basic-skipif.inc
similarity index 100%
rename from mongodb-1.12.0/tests/utils/basic-skipif.inc
rename to mongodb-1.13.0/tests/utils/basic-skipif.inc
diff --git a/mongodb-1.12.0/tests/utils/basic.inc b/mongodb-1.13.0/tests/utils/basic.inc
similarity index 100%
rename from mongodb-1.12.0/tests/utils/basic.inc
rename to mongodb-1.13.0/tests/utils/basic.inc
diff --git a/mongodb-1.12.0/tests/utils/classes.inc b/mongodb-1.13.0/tests/utils/classes.inc
similarity index 100%
rename from mongodb-1.12.0/tests/utils/classes.inc
rename to mongodb-1.13.0/tests/utils/classes.inc
diff --git a/mongodb-1.12.0/tests/utils/observer.php b/mongodb-1.13.0/tests/utils/observer.php
similarity index 100%
rename from mongodb-1.12.0/tests/utils/observer.php
rename to mongodb-1.13.0/tests/utils/observer.php
diff --git a/mongodb-1.13.0/tests/utils/skipif.php b/mongodb-1.13.0/tests/utils/skipif.php
new file mode 100644
index 00000000..f4848f8b
--- /dev/null
+++ b/mongodb-1.13.0/tests/utils/skipif.php
@@ -0,0 +1,481 @@
+<?php
+
+use MongoDB\Driver\Command;
+use MongoDB\Driver\Manager;
+use MongoDB\Driver\ReadPreference;
+use MongoDB\Driver\Server;
+use MongoDB\Driver\Exception\ConnectionException;
+use MongoDB\Driver\Exception\RuntimeException;
+
+require_once __DIR__ . '/basic.inc';
+require_once __DIR__ . '/tools.php';
+
+/**
+ * Disables SKIPIF caching (PHP 8.1+).
+ */
+function disable_skipif_caching()
+{
+ if (PHP_VERSION_ID < 80100) {
+ return;
+ }
+
+ echo "nocache\n";
+}
+
+/**
+ * Skips the test if the topology is load balanced.
+ */
+function skip_if_load_balanced()
+{
+ is_load_balanced(URI) and exit('skip topology is load balanced');
+}
+
+/**
+ * Skips the test if the topology is not load balanced.
+ */
+function skip_if_not_load_balanced()
+{
+ is_load_balanced(URI) or exit('skip topology is not load balanced');
+}
+
+/**
+ * Skips the test if the topology is a sharded cluster.
+ */
+function skip_if_mongos()
+{
+ is_mongos(URI) and exit('skip topology is a sharded cluster');
+}
+
+/**
+ * Skips the test if the topology contains multiple mongos nodes.
+ *
+ * This is particularly useful for tests that rely on configureFailPoint, since
+ * randomized server selection can interfere with testing.
+ */
+function skip_if_multiple_mongos()
+{
+ $manager = create_test_manager();
+
+ // Ensure SDAM is initialized before calling Manager::getServers()
+ $manager->selectServer(new ReadPreference('nearest'));
+
+ $mongosNodes = array_filter($manager->getServers(), function(Server $server) {
+ return $server->getType() === Server::TYPE_MONGOS;
+ });
+
+ if (count($mongosNodes) > 1) {
+ exit('skip topology contains multiple mongos nodes');
+ }
+}
+
+/**
+ * Skips the test if the topology is not a shard cluster.
+ */
+function skip_if_not_mongos()
+{
+ is_mongos(URI) or exit('skip topology is not a sharded cluster');
+}
+
+function skip_if_not_sharded_cluster_with_replica_set()
+{
+ is_sharded_cluster_with_replica_set(URI) or exit('skip topology is not a sharded cluster with replica set');
+}
+
+/**
+ * Skips the test if the topology is a replica set.
+ */
+function skip_if_replica_set()
+{
+ is_replica_set(URI) and exit('skip topology is a replica set');
+}
+
+/**
+ * Skips the test if the topology is not a replica set.
+ */
+function skip_if_not_replica_set()
+{
+ is_replica_set(URI) or exit('skip topology is not a replica set');
+}
+
+/**
+ * Skips the test if the topology is not a replica set or sharded cluster backed by replica sets
+ */
+function skip_if_not_replica_set_or_sharded_cluster_with_replica_set()
+{
+ is_replica_set(URI) or is_sharded_cluster_with_replica_set(URI) or exit('skip topology is not a replica set or sharded cluster with replica set');
+}
+
+function skip_if_no_transactions()
+{
+ if (is_sharded_cluster_with_replica_set(URI)) {
+ skip_if_server_version('<', '4.2');
+ } elseif (is_replica_set(URI)) {
+ skip_if_server_version('<', '4.0');
+ } else {
+ exit('skip topology does not support transactions');
+ }
+}
+
+/**
+ * Skips the test if the topology has no arbiter.
+ */
+function skip_if_no_arbiter()
+{
+ try {
+ $primary = get_primary_server(URI);
+ } catch (ConnectionException $e) {
+ exit('skip primary server is not accessible: ' . $e->getMessage());
+ }
+ $info = $primary->getInfo();
+
+ if (!isset($info['arbiters']) || count($info['arbiters']) < 1) {
+ exit('skip no arbiters available');
+ }
+}
+
+/**
+ * Skips the test if the topology has no secondary.
+ */
+function skip_if_no_secondary()
+{
+ try {
+ $primary = get_primary_server(URI);
+ } catch (ConnectionException $e) {
+ exit('skip primary server is not accessible: ' . $e->getMessage());
+ }
+ $info = $primary->getInfo();
+
+ if (!isset($info['hosts']) || count($info['hosts']) < 2) {
+ exit('skip no secondaries available');
+ }
+}
+
+/**
+ * Skips the test if the topology does not have enough data carrying nodes
+ */
+function skip_if_not_enough_data_nodes($requiredNodes, $maxNodeCount = null)
+{
+ try {
+ $primary = get_primary_server(URI);
+ } catch (ConnectionException $e) {
+ exit('skip primary server is not accessible: ' . $e->getMessage());
+ }
+ $info = $primary->getInfo();
+
+ $dataNodeCount = isset($info['hosts']) ? count($info['hosts']) : 0;
+
+ if ($dataNodeCount < $requiredNodes) {
+ exit("skip not enough nodes available (wanted: {$requiredNodes}, available: " . count($info['hosts']) . ')');
+ }
+ if ($maxNodeCount !== null && $dataNodeCount > $requiredNodes) {
+ exit("skip too many nodes available (wanted: {$requiredNodes}, available: " . count($info['hosts']) . ')');
+ }
+}
+
+/**
+ * Skips the test if the topology does not have enough nodes
+ */
+function skip_if_not_enough_nodes($requiredNodes, $maxNodeCount = null)
+{
+ try {
+ $primary = get_primary_server(URI);
+ } catch (ConnectionException $e) {
+ exit('skip primary server is not accessible: ' . $e->getMessage());
+ }
+ $info = $primary->getInfo();
+
+ $nodeCount =
+ (isset($info['hosts']) ? count($info['hosts']) : 0) +
+ (isset($info['arbiters']) ? count($info['arbiters']) : 0);
+
+ if ($nodeCount < $requiredNodes) {
+ exit("skip not enough nodes available (wanted: {$requiredNodes}, available: " . count($info['hosts']) . ')');
+ }
+ if ($maxNodeCount !== null && $nodeCount > $requiredNodes) {
+ exit("skip too many nodes available (wanted: {$requiredNodes}, available: " . count($info['hosts']) . ')');
+ }
+}
+
+/**
+ * Skips the test if the topology is a standalone.
+ */
+function skip_if_standalone()
+{
+ is_standalone(URI) and exit('skip topology is a standalone');
+}
+
+/**
+ * Skips the test if the topology is not a standalone.
+ */
+function skip_if_not_standalone()
+{
+ is_standalone(URI) or exit('skip topology is not a standalone');
+}
+
+/**
+ * Skips the test if the connection string uses SSL.
+ */
+function skip_if_ssl()
+{
+ is_ssl(URI) and exit('skip URI is using SSL');
+}
+
+/**
+ * Skips the test if the connection string uses SSL.
+ */
+function skip_if_not_ssl()
+{
+ is_ssl(URI) or exit('skip URI is not using SSL');
+}
+
+/**
+ * Skips the test if no SSL directory has been defined.
+ */
+function skip_if_no_ssl_dir()
+{
+ $sslDir = getenv('SSL_DIR');
+ $sslDir !== false or exit('skip SSL_DIR environment variable not set');
+
+ $sslDir = realpath($sslDir);
+ ($sslDir !== false && is_dir($sslDir)) or exit('skip SSL_DIR is not a valid directory');
+}
+
+/**
+ * Skips the test if the connection string is using auth.
+ */
+function skip_if_auth()
+{
+ is_auth(URI) and exit('skip URI is using auth');
+}
+
+/**
+ * Skips the test if the connection string is not using auth.
+ */
+function skip_if_not_auth()
+{
+ is_auth(URI) or exit('skip URI is not using auth');
+}
+
+/**
+ * Skips the test if the connection string is not using a particular
+ * authMechanism.
+ *
+ * @param string $authMechanism
+ */
+function skip_if_not_auth_mechanism($authMechanism)
+{
+ $uriAuthMechanism = get_uri_option(URI, 'authMechanism');
+
+ if ($uriAuthMechanism === null && $authMechanism !== null) {
+ exit('skip URI is not using authMechanism');
+ }
+
+ if ($uriAuthMechanism !== $authMechanism) {
+ exit("skip URI authMechanism is '$uriAuthMechanism' (needed: '$authMechanism')");
+ }
+}
+
+/**
+ * Skips the test if the server is not accessible.
+ */
+function skip_if_not_live()
+{
+ try {
+ get_primary_server(URI);
+ } catch (ConnectionException $e) {
+ exit('skip server is not accessible: ' . $e->getMessage());
+ }
+}
+
+/**
+ * Skips the test if the server version satisfies a comparison.
+ *
+ * @see http://php.net/version_compare
+ * @param string $operator Comparison operator
+ * @param string $version Version to compare against
+ */
+function skip_if_server_version($operator, $version)
+{
+ $serverVersion = get_server_version(URI);
+
+ if (version_compare($serverVersion, $version, $operator)) {
+ exit("skip Server version '$serverVersion' $operator '$version'");
+ }
+}
+
+/**
+ * Skips the test if the PHP version satisfies a comparison.
+ *
+ * @see http://php.net/version_compare
+ * @param string $operator Comparison operator
+ * @param string $version Version to compare against
+ */
+function skip_if_php_version($operator, $version)
+{
+ if (version_compare(PHP_VERSION, $version, $operator)) {
+ exit("skip PHP version '" . PHP_VERSION . "' $operator '$version'");
+ }
+}
+
+/**
+ * Skips the test if the server not using a particular storage engine.
+ *
+ * @param string $storageEngine Storage engine name
+ */
+function skip_if_not_server_storage_engine($storageEngine)
+{
+ $serverStorageEngine = get_server_storage_engine(URI);
+
+ if ($serverStorageEngine !== $storageEngine) {
+ exit("skip Server storage engine is '$serverStorageEngine' (needed '$storageEngine')");
+ }
+}
+
+/**
+ * Skips the test if the server does not support the sleep command.
+ */
+function skip_if_sleep_command_unavailable()
+{
+ if (!command_works(URI, ['sleep' => 1, 'secs' => 1, 'w' => false])) {
+ exit('skip sleep command not available');
+ }
+}
+
+/**
+ * Skips the test if the server does not support test commands.
+ */
+function skip_if_test_commands_disabled()
+{
+ if (!get_server_parameter(URI, 'enableTestCommands')) {
+ exit('skip test commands are disabled');
+ }
+}
+
+/**
+ * Skips the test if libmongoc does not support crypto.
+ *
+ * If one or more libaries are provided, additionally check that the reported
+ * library is in that array. Possible values are "libcrypto", "Common Crypto",
+ * and "CNG".
+ *
+ * @param array $libs Optional list of crypto libraries to require
+ */
+function skip_if_not_libmongoc_crypto(array $libs = [])
+{
+ $lib = get_module_info('libmongoc crypto library');
+
+ if ($lib === null) {
+ exit('skip libmongoc crypto is not enabled');
+ }
+
+ if (!empty($libs) && !in_array($lib, $libs)) {
+ exit('skip Needs libmongoc crypto library ' . implode(', ', $libs) . ', but found ' . $lib);
+ }
+}
+
+/**
+ * Skips the test if libmongoc does not support SSL.
+ *
+ * If one or more libaries are provided, additionally check that the reported
+ * library is in that array. Possible values are "OpenSSL", "LibreSSL",
+ * "Secure Transport", and "Secure Channel".
+ *
+ * @param array $libs Optional list of SSL libraries to require
+ */
+function skip_if_not_libmongoc_ssl(array $libs = [])
+{
+ $lib = get_module_info('libmongoc SSL library');
+
+ if ($lib === null) {
+ exit('skip libmongoc SSL is not enabled');
+ }
+
+ if (!empty($libs) && !in_array($lib, $libs)) {
+ exit('skip Needs libmongoc SSL library ' . implode(', ', $libs) . ', but found ' . $lib);
+ }
+}
+
+/**
+ * Skips the test if the driver was not compiled with support for FLE
+ */
+function skip_if_not_libmongocrypt()
+{
+ $lib = get_module_info('libmongocrypt');
+
+ if ($lib === 'disabled') {
+ exit('skip libmongocrypt is not enabled');
+ }
+}
+
+/**
+ * Skips the test if the driver was compiled with support for FLE
+ */
+function skip_if_libmongocrypt()
+{
+ $lib = get_module_info('libmongocrypt');
+
+ if ($lib !== 'disabled') {
+ exit('skip libmongocrypt is enabled');
+ }
+}
+
+/**
+ * Skips the test if the collection cannot be dropped.
+ *
+ * @param string $databaseName Database name
+ * @param string $collectionName Collection name
+ */
+function skip_if_not_clean($databaseName = DATABASE_NAME, $collectionName = COLLECTION_NAME)
+{
+ try {
+ drop_collection(URI, $databaseName, $collectionName);
+ } catch (RuntimeException $e) {
+ exit("skip Could not drop '$databaseName.$collectionName': " . $e->getMessage());
+ }
+
+ /* Since this function modifies the state of the database, we need it to run
+ * each time before a test. */
+ disable_skipif_caching();
+}
+
+function skip_if_no_getmore_failpoint()
+{
+ $serverVersion = get_server_version(URI);
+
+ if (version_compare($serverVersion, '4.0', '<')) {
+ exit("skip Server version '$serverVersion' does not support a getMore failpoint'");
+ }
+}
+
+function skip_if_no_failcommand_failpoint()
+{
+ skip_if_test_commands_disabled();
+
+ $serverVersion = get_server_version(URI);
+
+ if (is_mongos(URI) && version_compare($serverVersion, '4.1.8', '<')) {
+ exit("skip mongos version '$serverVersion' does not support 'failCommand' failpoint'");
+ } elseif (version_compare($serverVersion, '4.0', '<')) {
+ exit("skip mongod version '$serverVersion' does not support 'failCommand' failpoint'");
+ }
+}
+
+function skip_if_no_mongo_orchestration()
+{
+ $ctx = stream_context_create(['http' => ['timeout' => 0.5]]);
+ $result = @file_get_contents(MONGO_ORCHESTRATION_URI, false, $ctx);
+
+ /* Note: file_get_contents emits an E_WARNING on failure, which will be
+ * caught by the error handler in basic-skipif.inc. In that case, this may
+ * never be reached. */
+ if ($result === false) {
+ exit("skip mongo-orchestration is not accessible: '" . MONGO_ORCHESTRATION_URI . "'");
+ }
+}
+
+function skip_if_appveyor()
+{
+ if (getenv('APPVEYOR')) {
+ exit('skip Test cannot be run on AppVeyor');
+ }
+}
diff --git a/mongodb-1.13.0/tests/utils/tools.php b/mongodb-1.13.0/tests/utils/tools.php
new file mode 100644
index 00000000..bf7184e3
--- /dev/null
+++ b/mongodb-1.13.0/tests/utils/tools.php
@@ -0,0 +1,847 @@
+<?php
+
+use MongoDB\Driver\BulkWrite;
+use MongoDB\Driver\Command;
+use MongoDB\Driver\Manager;
+use MongoDB\Driver\ReadPreference;
+use MongoDB\Driver\Server;
+use MongoDB\Driver\ServerApi;
+use MongoDB\Driver\WriteConcern;
+use MongoDB\Driver\WriteConcernError;
+use MongoDB\Driver\WriteError;
+use MongoDB\Driver\WriteResult;
+use MongoDB\Driver\Exception\ConnectionException;
+use MongoDB\Driver\Exception\RuntimeException;
+
+/**
+ * Appends an option to a URI string and returns a new URI.
+ *
+ * @param string $uri
+ * @param string $option
+ * @param string $value
+ * @return string
+ */
+function append_uri_option($uri, $option)
+{
+ // Append to existing query string
+ if (strpos($uri, '?') !== false) {
+ return $uri . '&' . $option;
+ }
+
+ // Terminate host list and append new query string
+ if (parse_url($uri, PHP_URL_PATH) === null) {
+ return $uri . '/?' . $option;
+ }
+
+ // Append query string after terminated host list and possible auth database
+ return $uri . '?' . $option;
+}
+
+/**
+ * Drops a collection on the primary server.
+ *
+ * @param string $uri Connection string
+ * @param string $databaseName Database name
+ * @param string $collectionName Collection name
+ * @throws RuntimeException
+ */
+function drop_collection($uri, $databaseName, $collectionName)
+{
+ $server = get_primary_server($uri);
+ $command = new Command(['drop' => $collectionName]);
+
+ try {
+ /* Unless we are dropping a collection within the "local" database,
+ * which does not support a write concern, we need to use w:majority due
+ * to the issue explained in SERVER-35613: "drop" uses a two phase
+ * commit, and due to that, it is possible that a lock can't be acquired
+ * for a transaction that gets quickly started as the "drop" reaper
+ * hasn't completed yet. */
+ $wc = $databaseName === 'local' ? new WriteConcern(1) : new WriteConcern(WriteConcern::MAJORITY);
+
+ $server->executeCommand(
+ $databaseName,
+ $command,
+ ['writeConcern' => $wc]
+ );
+ } catch (RuntimeException $e) {
+ if ($e->getMessage() !== 'ns not found') {
+ throw $e;
+ }
+ }
+}
+
+/**
+ * Returns the value of a module row from phpinfo(), or null if it's not found.
+ *
+ * @param string $row
+ * @return string|null
+ */
+function get_module_info($row)
+{
+ ob_start();
+ phpinfo(INFO_MODULES);
+ $info = ob_get_clean();
+
+ $pattern = sprintf('/^%s([\w ]+)$/m', preg_quote($row . ' => '));
+
+ if (preg_match($pattern, $info, $matches) !== 1) {
+ return null;
+ }
+
+ return $matches[1];
+}
+
+function create_test_manager(string $uri = null, array $options = [], array $driverOptions = [])
+{
+ if (getenv('API_VERSION') && ! isset($driverOptions['serverApi'])) {
+ $driverOptions['serverApi'] = new ServerApi(getenv('API_VERSION'));
+ }
+
+ return new Manager($uri ?? URI, $options, $driverOptions);
+}
+
+/**
+ * Returns the primary server.
+ *
+ * @param string $uri Connection string
+ * @return Server
+ * @throws ConnectionException
+ */
+function get_primary_server($uri)
+{
+ return create_test_manager($uri)->selectServer(new ReadPreference('primary'));
+}
+
+/**
+ * Returns a secondary server.
+ *
+ * @param string $uri Connection string
+ * @return Server
+ * @throws ConnectionException
+ */
+function get_secondary_server($uri)
+{
+ return create_test_manager($uri)->selectServer(new ReadPreference('secondary'));
+}
+
+/**
+ * Runs a command and returns whether an exception was thrown or not
+ *
+ * @param string $uri Connection string
+ * @param array|object $commandSpec
+ * @return bool
+ * @throws RuntimeException
+ */
+function command_works($uri, $commandSpec)
+{
+ $command = new Command($commandSpec);
+ $server = get_primary_server($uri);
+ try {
+ $cursor = $server->executeCommand('admin', $command);
+ return true;
+ } catch (Exception $e) {
+ return false;
+ }
+}
+
+/**
+ * Returns a parameter of the primary server.
+ *
+ * @param string $uri Connection string
+ * @return mixed
+ * @throws RuntimeException
+ */
+function get_server_parameter($uri, $parameter)
+{
+ $server = get_primary_server($uri);
+ $command = new Command(['getParameter' => 1, $parameter => 1]);
+ $cursor = $server->executeCommand('admin', $command);
+
+ return current($cursor->toArray())->$parameter;
+}
+
+/**
+ * Returns the storage engine of the primary server.
+ *
+ * @param string $uri Connection string
+ * @return string
+ * @throws RuntimeException
+ */
+function get_server_storage_engine($uri)
+{
+ $server = get_primary_server($uri);
+ $command = new Command(['serverStatus' => 1]);
+ $cursor = $server->executeCommand('admin', $command);
+
+ return current($cursor->toArray())->storageEngine->name;
+}
+
+/**
+ * Helper to return the version of a specific server.
+ *
+ * @param Server $server
+ * @return string
+ * @throws RuntimeException
+ */
+function get_server_version_from_server(Server $server)
+{
+ $command = new Command(['buildInfo' => 1]);
+ $cursor = $server->executeCommand('admin', $command);
+
+ return current($cursor->toArray())->version;
+}
+
+/**
+ * Returns the version of the primary server.
+ *
+ * @param string $uri Connection string
+ * @return string
+ * @throws RuntimeException
+ */
+function get_server_version($uri)
+{
+ $server = get_primary_server($uri);
+ return get_server_version_from_server($server);
+}
+
+/**
+ * Returns the value of a URI option, or null if it's not found.
+ *
+ * @param string $uri
+ * @return string|null
+ */
+function get_uri_option($uri, $option)
+{
+ $pattern = sprintf('/[?&]%s=([^&]+)/i', preg_quote($option));
+
+ if (preg_match($pattern, $uri, $matches) !== 1) {
+ return null;
+ }
+
+ return $matches[1];
+}
+
+/**
+ * Checks that the topology is load balanced.
+ *
+ * @param string $uri
+ * @return boolean
+ */
+function is_load_balanced($uri)
+{
+ return get_primary_server($uri)->getType() === Server::TYPE_LOAD_BALANCER;
+}
+
+/**
+ * Checks that the topology is a sharded cluster.
+ *
+ * @param string $uri
+ * @return boolean
+ */
+function is_mongos($uri)
+{
+ return get_primary_server($uri)->getType() === Server::TYPE_MONGOS;
+}
+
+/**
+ * Checks that the topology is a sharded cluster using a replica set.
+ *
+ * Note: only the first shard is checked.
+ */
+function is_sharded_cluster_with_replica_set($uri)
+{
+ $server = get_primary_server($uri);
+
+ if ($server->getType() !== Server::TYPE_MONGOS && $server->getType() !== Server::TYPE_LOAD_BALANCER) {
+ return false;
+ }
+
+ $cursor = $server->executeQuery('config.shards', new \MongoDB\Driver\Query([], ['limit' => 1]));
+ $cursor->setTypeMap(['root' => 'array', 'document' => 'array']);
+ $document = current($cursor->toArray());
+
+ if (! $document) {
+ return false;
+ }
+
+ /**
+ * Use regular expression to distinguish between standalone or replicaset:
+ * Without a replicaset: "host" : "localhost:4100"
+ * With a replicaset: "host" : "dec6d8a7-9bc1-4c0e-960c-615f860b956f/localhost:4400,localhost:4401"
+ */
+ return preg_match('@^.*/.*:\d+@', $document['host']);
+}
+
+/**
+ * Checks that the topology is a replica set.
+ *
+ * @param string $uri
+ * @return boolean
+ */
+function is_replica_set($uri)
+{
+ if (get_primary_server($uri)->getType() !== Server::TYPE_RS_PRIMARY) {
+ return false;
+ }
+
+ /* Note: this may return a false negative if replicaSet is specified through
+ * a TXT record for a mongodb+srv connection string. */
+ if (get_uri_option($uri, 'replicaSet') === NULL) {
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * Checks if the connection string uses authentication.
+ *
+ * @param string $uri
+ * @return boolean
+ */
+function is_auth($uri)
+{
+ if (stripos($uri, 'authmechanism=') !== false) {
+ return true;
+ }
+
+ if (strpos($uri, ':') !== false && strpos($uri, '@') !== false) {
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * Checks if the connection string uses SSL.
+ *
+ * @param string $uri
+ * @return boolean
+ */
+function is_ssl($uri)
+{
+ return stripos($uri, 'ssl=true') !== false || stripos($uri, 'tls=true') !== false;
+}
+
+/**
+ * Checks that the topology is a standalone.
+ *
+ * @param string $uri
+ * @return boolean
+ */
+function is_standalone($uri)
+{
+ return get_primary_server($uri)->getType() === Server::TYPE_STANDALONE;
+}
+
+/**
+ * Converts the server type constant to a string.
+ *
+ * @see http://php.net/manual/en/class.mongodb-driver-server.php
+ * @param integer $type
+ * @return string
+ */
+function server_type_as_string($type)
+{
+ switch ($type) {
+ case Server::TYPE_STANDALONE:
+ return 'Standalone';
+ case Server::TYPE_MONGOS:
+ return 'Mongos';
+ case Server::TYPE_POSSIBLE_PRIMARY:
+ return 'PossiblePrimary';
+ case Server::TYPE_RS_PRIMARY:
+ return 'RSPrimary';
+ case Server::TYPE_RS_SECONDARY:
+ return 'RSSecondary';
+ case Server::TYPE_RS_ARBITER:
+ return 'RSArbiter';
+ case Server::TYPE_RS_OTHER:
+ return 'RSOther';
+ case Server::TYPE_RS_GHOST:
+ return 'RSGhost';
+ default:
+ return 'Unknown';
+ }
+}
+
+/**
+ * Converts an errno number to a string.
+ *
+ * @see http://php.net/manual/en/errorfunc.constants.php
+ * @param integer $errno
+ * @param string
+ */
+function errno_as_string($errno)
+{
+ $errors = [
+ 'E_ERROR',
+ 'E_WARNING',
+ 'E_PARSE',
+ 'E_NOTICE',
+ 'E_CORE_ERROR',
+ 'E_CORE_WARNING',
+ 'E_COMPILE_ERROR',
+ 'E_COMPILE_WARNING',
+ 'E_USER_ERROR',
+ 'E_USER_WARNING',
+ 'E_USER_NOTICE',
+ 'E_STRICT',
+ 'E_RECOVERABLE_ERROR',
+ 'E_DEPRECATED',
+ 'E_USER_DEPRECATED',
+ 'E_ALL',
+ ];
+
+ foreach ($errors as $error) {
+ if ($errno === constant($error)) {
+ return $error;
+ }
+ }
+
+ return 'Unknown';
+}
+
+/**
+ * Prints a traditional hex dump of byte values and printable characters.
+ *
+ * @see http://stackoverflow.com/a/4225813/162228
+ * @param string $data Binary data
+ * @param integer $width Bytes displayed per line
+ */
+function hex_dump($data, $width = 16)
+{
+ static $pad = '.'; // Placeholder for non-printable characters
+ static $from = '';
+ static $to = '';
+
+ if ($from === '') {
+ for ($i = 0; $i <= 0xFF; $i++) {
+ $from .= chr($i);
+ $to .= ($i >= 0x20 && $i <= 0x7E) ? chr($i) : $pad;
+ }
+ }
+
+ $hex = str_split(bin2hex($data), $width * 2);
+ $chars = str_split(strtr($data, $from, $to), $width);
+
+ $offset = 0;
+ $length = $width * 3;
+
+ foreach ($hex as $i => $line) {
+ printf("%6X : %-{$length}s [%s]\n", $offset, implode(' ', str_split($line, 2)), $chars[$i]);
+ $offset += $width;
+ }
+}
+
+/**
+ * Canonicalizes a JSON string.
+ *
+ * @param string $json
+ * @return string
+ */
+function json_canonicalize($json)
+{
+ $json = json_encode(json_decode($json));
+
+ /* Versions of PHP before 7.1 replace empty JSON keys with "_empty_" when
+ * decoding to a stdClass (see: https://bugs.php.net/bug.php?id=46600). Work
+ * around this by replacing "_empty_" keys before returning.
+ */
+ $json = str_replace('"_empty_":', '"":', $json);
+
+ /* Canonicalize string values for $numberDouble to ensure they are converted
+ * the same as number literals in legacy and relaxed output. This is needed
+ * because the printf format in _bson_as_json_visit_double uses a high level
+ * of precision and may not produce the exponent notation expected by the
+ * BSON corpus tests. */
+ $json = preg_replace_callback(
+ '/{"\$numberDouble":"(-?\d+(\.\d+([eE]\+\d+)?)?)"}/',
+ function ($matches) {
+ return '{"$numberDouble":"' . json_encode(json_decode($matches[1])) . '"}';
+ },
+ $json
+ );
+
+ return $json;
+}
+
+/**
+ * Return a collection name to use for the test file.
+ *
+ * The filename will be stripped of the base path to the test suite (prefix) as
+ * well as the PHP file extension (suffix). Special characters (including hyphen
+ * for shell compatibility) will be replaced with underscores.
+ *
+ * @param string $filename
+ * @return string
+ */
+function makeCollectionNameFromFilename($filename)
+{
+ $filename = realpath($filename);
+ $prefix = realpath(dirname(__FILE__) . '/..') . DIRECTORY_SEPARATOR;
+
+ $replacements = array(
+ // Strip test path prefix
+ sprintf('/^%s/', preg_quote($prefix, '/')) => '',
+ // Strip file extension suffix
+ '/\.php$/' => '',
+ // SKIPIFs add ".skip" between base name and extension
+ '/\.skip$/' => '',
+ // Replace special characters with underscores
+ sprintf('/[%s]/', preg_quote('-$/\\', '/')) => '_',
+ );
+
+ return preg_replace(array_keys($replacements), array_values($replacements), $filename);
+}
+
+function NEEDS($configuration) {
+ if (!constant($configuration)) {
+ exit("skip -- need '$configuration' defined");
+ }
+}
+function SLOW() {
+ if (getenv("SKIP_SLOW_TESTS")) {
+ exit("skip SKIP_SLOW_TESTS");
+ }
+}
+
+function loadFixtures(Manager $manager, $dbname = DATABASE_NAME, $collname = COLLECTION_NAME, $filename = null)
+{
+ if (!$filename) {
+ $filename = "compress.zlib://" . __DIR__ . "/" . "PHONGO-FIXTURES.json.gz";
+ }
+
+ $bulk = new BulkWrite(['ordered' => false]);
+
+ $server = $manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY));
+
+ $data = file_get_contents($filename);
+ $array = json_decode($data);
+
+ foreach($array as $document) {
+ $bulk->insert($document);
+ }
+
+ $retval = $server->executeBulkWrite("$dbname.$collname", $bulk);
+
+ if ($retval->getInsertedCount() !== count($array)) {
+ exit(sprintf('skip Fixtures were not loaded (expected: %d, actual: %d)', $total, $retval->getInsertedCount()));
+ }
+}
+
+function createTemporaryMongoInstance(array $options = [])
+{
+ $id = 'mo_' . COLLECTION_NAME;
+ $options += [
+ "name" => "mongod",
+ "id" => $id,
+ 'procParams' => [
+ 'logpath' => "/tmp/MO/phongo/{$id}.log",
+ 'ipv6' => true,
+ 'setParameter' => [ 'enableTestCommands' => 1 ],
+ ],
+ ];
+ $opts = array(
+ "http" => array(
+ "timeout" => 60,
+ "method" => "PUT",
+ "header" => "Accept: application/json\r\n" .
+ "Content-type: application/x-www-form-urlencoded",
+ "content" => json_encode($options),
+ "ignore_errors" => true,
+ ),
+ );
+ $ctx = stream_context_create($opts);
+ $json = file_get_contents(MONGO_ORCHESTRATION_URI . "/servers/$id", false, $ctx);
+ $result = json_decode($json, true);
+
+ /* Failed -- or was already started */
+ if (!isset($result["mongodb_uri"])) {
+ destroyTemporaryMongoInstance($id);
+ throw new Exception("Could not start temporary server instance\n");
+ } else {
+ return $result['mongodb_uri'];
+ }
+}
+
+function destroyTemporaryMongoInstance($id = NULL)
+{
+ if ($id == NULL) {
+ $id = 'mo_' . COLLECTION_NAME;
+ }
+
+ $opts = array(
+ "http" => array(
+ "timeout" => 60,
+ "method" => "DELETE",
+ "header" => "Accept: application/json\r\n",
+ "ignore_errors" => true,
+ ),
+ );
+ $ctx = stream_context_create($opts);
+ $json = file_get_contents(MONGO_ORCHESTRATION_URI . "/servers/$id", false, $ctx);
+}
+
+/**
+ * Converts an error level (constant or bitmask) to a string description.
+ */
+function severityToString(int $severity): string {
+ static $constants = [
+ 'E_ERROR' => E_ERROR,
+ 'E_WARNING' => E_WARNING,
+ 'E_PARSE' => E_PARSE,
+ 'E_NOTICE' => E_NOTICE,
+ 'E_CORE_ERROR' => E_CORE_ERROR,
+ 'E_CORE_WARNING' => E_CORE_WARNING,
+ 'E_COMPILE_ERROR' => E_COMPILE_ERROR,
+ 'E_COMPILE_WARNING' => E_COMPILE_WARNING,
+ 'E_USER_ERROR' => E_USER_ERROR,
+ 'E_USER_WARNING' => E_USER_WARNING,
+ 'E_USER_NOTICE' => E_USER_NOTICE,
+ 'E_STRICT' => E_STRICT,
+ 'E_RECOVERABLE_ERROR' => E_RECOVERABLE_ERROR,
+ 'E_DEPRECATED' => E_DEPRECATED,
+ 'E_USER_DEPRECATED' => E_USER_DEPRECATED,
+ // E_ALL is handled separately
+ ];
+
+ if ($severity === E_ALL) {
+ return 'E_ALL';
+ }
+
+ foreach ($constants as $constant => $value) {
+ if ($severity & $value) {
+ $matches[] = $constant;
+ }
+ }
+
+ return empty($matches) ? 'UNKNOWN' : implode('|', $matches);
+}
+
+/**
+ * Expects the callable to raise an error matching the expected severity, which
+ * may be a constant or bitmask. May optionally expect the error to be raised
+ * from a particular function. Returns the message from the raised error or
+ * exception, or an empty string if neither was thrown.
+ */
+function raises(callable $callable, int $expectedSeverity, string $expectedFromFunction = null): string
+{
+ set_error_handler(function(int $severity, string $message, string $file, int $line) {
+ throw new ErrorException($message, 0, $severity, $file, $line);
+ });
+
+ try {
+ call_user_func($callable);
+ } catch (ErrorException $e) {
+ if (!($e->getSeverity() & $expectedSeverity)) {
+ printf("ALMOST: Got %s - expected %s\n", severityToString($e->getSeverity()), severityToString($expectedSeverity));
+ return $e->getMessage();
+ }
+
+ if ($expectedFromFunction === null) {
+ printf("OK: Got %s\n", severityToString($e->getSeverity()));
+ return $e->getMessage();
+ }
+
+ $fromFunction = $e->getTrace()[0]['function'];
+
+ if (strcasecmp($fromFunction, $expectedFromFunction) !== 0) {
+ printf("ALMOST: Got %s - but was raised from %s, not %s\n", errorLevelToString($e->getSeverity()), $fromFunction, $expectedFromFunction);
+ return $e->getMessage();
+ }
+
+ printf("OK: Got %s raised from %s\n", severityToString($e->getSeverity()), $fromFunction);
+ return $e->getMessage();
+ } catch (Throwable $e) {
+ printf("ALMOST: Got %s - expected %s\n", get_class($e), ErrorException::class);
+ return $e->getMessage();
+ } finally {
+ restore_error_handler();
+ }
+
+ printf("FAILED: Expected %s, but no error raised!\n", ErrorException::class);
+ return '';
+}
+
+/**
+ * Expects the callable to throw an expected exception. May optionally expect
+ * the exception to be thrown from a particular function. Returns the message
+ * from the thrown exception, or an empty string if one was not thrown.
+ */
+function throws(callable $callable, string $expectedException, string $expectedFromFunction = null): string
+{
+ try {
+ call_user_func($callable);
+ } catch (Throwable $e) {
+ if (!($e instanceof $expectedException)) {
+ printf("ALMOST: Got %s - expected %s\n", get_class($e), $expectedException);
+ return $e->getMessage();
+ }
+
+ if ($expectedFromFunction === null) {
+ printf("OK: Got %s\n", $expectedException);
+ return $e->getMessage();
+ }
+
+ $fromFunction = $e->getTrace()[0]['function'];
+
+ if (strcasecmp($fromFunction, $expectedFromFunction) !== 0) {
+ printf("ALMOST: Got %s - but was thrown from %s, not %s\n", $expectedException, $fromFunction, $expectedFromFunction);
+ return $e->getMessage();
+ }
+
+ printf("OK: Got %s thrown from %s\n", $expectedException, $fromFunction);
+ return $e->getMessage();
+ }
+
+ printf("FAILED: Expected %s, but no exception thrown!\n", $expectedException);
+ return '';
+}
+
+function printServer(Server $server)
+{
+ printf("server: %s:%d\n", $server->getHost(), $server->getPort());
+}
+
+function printWriteResult(WriteResult $result, $details = true)
+{
+ printServer($result->getServer());
+
+ printf("insertedCount: %d\n", $result->getInsertedCount());
+ printf("matchedCount: %d\n", $result->getMatchedCount());
+ printf("modifiedCount: %d\n", $result->getModifiedCount());
+ printf("upsertedCount: %d\n", $result->getUpsertedCount());
+ printf("deletedCount: %d\n", $result->getDeletedCount());
+
+ foreach ($result->getUpsertedIds() as $index => $id) {
+ printf("upsertedId[%d]: ", $index);
+ var_dump($id);
+ }
+
+ $writeConcernError = $result->getWriteConcernError();
+ printWriteConcernError($writeConcernError ? $writeConcernError : null, $details);
+
+ foreach ($result->getWriteErrors() as $writeError) {
+ printWriteError($writeError);
+ }
+}
+
+function printWriteConcernError(WriteConcernError $error = null, $details)
+{
+ if ($error) {
+ /* This stuff is generated by the server, no need for us to test it */
+ if (!$details) {
+ printf("writeConcernError: %s (%d)\n", $error->getMessage(), $error->getCode());
+ return;
+ }
+ var_dump($error);
+ printf("writeConcernError.message: %s\n", $error->getMessage());
+ printf("writeConcernError.code: %d\n", $error->getCode());
+ printf("writeConcernError.info: ");
+ var_dump($error->getInfo());
+ }
+}
+
+function printWriteError(WriteError $error)
+{
+ var_dump($error);
+ printf("writeError[%d].message: %s\n", $error->getIndex(), $error->getMessage());
+ printf("writeError[%d].code: %d\n", $error->getIndex(), $error->getCode());
+}
+
+function getInsertCount($retval) {
+ return $retval->getInsertedCount();
+}
+function getModifiedCount($retval) {
+ return $retval->getModifiedCount();
+}
+function getDeletedCount($retval) {
+ return $retval->getDeletedCount();
+}
+function getUpsertedCount($retval) {
+ return $retval->getUpsertedCount();
+}
+function getWriteErrors($retval) {
+ return (array)$retval->getWriteErrors();
+}
+
+function def($arr) {
+ foreach($arr as $const => $value) {
+ define($const, getenv("PHONGO_TEST_$const") ?: $value);
+ }
+}
+
+function configureFailPoint(Manager $manager, $failPoint, $mode, array $data = [])
+{
+ $doc = [
+ 'configureFailPoint' => $failPoint,
+ 'mode' => $mode,
+ ];
+ if ($data) {
+ $doc['data'] = $data;
+ }
+
+ $cmd = new Command($doc);
+ $manager->executeCommand('admin', $cmd);
+}
+
+function configureTargetedFailPoint(Server $server, $failPoint, $mode, array $data = [])
+{
+ $doc = array(
+ 'configureFailPoint' => $failPoint,
+ 'mode' => $mode,
+ );
+ if ($data) {
+ $doc['data'] = $data;
+ }
+
+ $cmd = new Command($doc);
+ $server->executeCommand('admin', $cmd);
+}
+
+function failMaxTimeMS(Server $server)
+{
+ configureTargetedFailPoint($server, 'maxTimeAlwaysTimeOut', [ 'times' => 1 ]);
+}
+
+function toPHP($var, $typemap = array()) {
+ return MongoDB\BSON\toPHP($var, $typemap);
+}
+function fromPHP($var) {
+ return MongoDB\BSON\fromPHP($var);
+}
+function toJSON($var) {
+ return MongoDB\BSON\toJSON($var);
+}
+function toCanonicalExtendedJSON($var) {
+ return MongoDB\BSON\toCanonicalExtendedJSON($var);
+}
+function toRelaxedExtendedJSON($var) {
+ return MongoDB\BSON\toRelaxedExtendedJSON($var);
+}
+function fromJSON($var) {
+ return MongoDB\BSON\fromJSON($var);
+}
+
+/* Note: this fail point may terminate the mongod process, so you may want to
+ * use this in conjunction with a throwaway server. */
+function failGetMore(Manager $manager)
+{
+ /* We need to do version detection here */
+ $primary = $manager->selectServer(new ReadPreference('primary'));
+ $version = get_server_version_from_server($primary);
+
+ if (version_compare($version, "4.0", ">=")) {
+ /* We use 237 here, as that's the same original code that MongoD would
+ * throw if a cursor had already gone by the time we call getMore. This
+ * allows us to make things consistent with the getMore OP behaviour
+ * from previous mongod versions. An errorCode is required here for the
+ * failPoint to work. */
+ configureFailPoint($manager, 'failCommand', 'alwaysOn', [ 'errorCode' => 237, 'failCommands' => ['getMore'] ]);
+ return;
+ }
+
+ throw new Exception("Trying to configure a getMore fail point for a server version ($version) that doesn't support it");
+}
diff --git a/mongodb-1.12.0/tests/writeConcern/bug1598-001.phpt b/mongodb-1.13.0/tests/writeConcern/bug1598-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeConcern/bug1598-001.phpt
rename to mongodb-1.13.0/tests/writeConcern/bug1598-001.phpt
diff --git a/mongodb-1.12.0/tests/writeConcern/bug1598-002.phpt b/mongodb-1.13.0/tests/writeConcern/bug1598-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeConcern/bug1598-002.phpt
rename to mongodb-1.13.0/tests/writeConcern/bug1598-002.phpt
diff --git a/mongodb-1.12.0/tests/writeConcern/writeconcern-bsonserialize-001.phpt b/mongodb-1.13.0/tests/writeConcern/writeconcern-bsonserialize-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeConcern/writeconcern-bsonserialize-001.phpt
rename to mongodb-1.13.0/tests/writeConcern/writeconcern-bsonserialize-001.phpt
diff --git a/mongodb-1.12.0/tests/writeConcern/writeconcern-bsonserialize-002.phpt b/mongodb-1.13.0/tests/writeConcern/writeconcern-bsonserialize-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeConcern/writeconcern-bsonserialize-002.phpt
rename to mongodb-1.13.0/tests/writeConcern/writeconcern-bsonserialize-002.phpt
diff --git a/mongodb-1.12.0/tests/writeConcern/writeconcern-bsonserialize-003.phpt b/mongodb-1.13.0/tests/writeConcern/writeconcern-bsonserialize-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeConcern/writeconcern-bsonserialize-003.phpt
rename to mongodb-1.13.0/tests/writeConcern/writeconcern-bsonserialize-003.phpt
diff --git a/mongodb-1.12.0/tests/writeConcern/writeconcern-bsonserialize-004.phpt b/mongodb-1.13.0/tests/writeConcern/writeconcern-bsonserialize-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeConcern/writeconcern-bsonserialize-004.phpt
rename to mongodb-1.13.0/tests/writeConcern/writeconcern-bsonserialize-004.phpt
diff --git a/mongodb-1.12.0/tests/writeConcern/writeconcern-constants.phpt b/mongodb-1.13.0/tests/writeConcern/writeconcern-constants.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeConcern/writeconcern-constants.phpt
rename to mongodb-1.13.0/tests/writeConcern/writeconcern-constants.phpt
diff --git a/mongodb-1.12.0/tests/writeConcern/writeconcern-ctor-001.phpt b/mongodb-1.13.0/tests/writeConcern/writeconcern-ctor-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeConcern/writeconcern-ctor-001.phpt
rename to mongodb-1.13.0/tests/writeConcern/writeconcern-ctor-001.phpt
diff --git a/mongodb-1.12.0/tests/writeConcern/writeconcern-ctor-002.phpt b/mongodb-1.13.0/tests/writeConcern/writeconcern-ctor-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeConcern/writeconcern-ctor-002.phpt
rename to mongodb-1.13.0/tests/writeConcern/writeconcern-ctor-002.phpt
diff --git a/mongodb-1.12.0/tests/writeConcern/writeconcern-ctor_error-001.phpt b/mongodb-1.13.0/tests/writeConcern/writeconcern-ctor_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeConcern/writeconcern-ctor_error-001.phpt
rename to mongodb-1.13.0/tests/writeConcern/writeconcern-ctor_error-001.phpt
diff --git a/mongodb-1.12.0/tests/writeConcern/writeconcern-ctor_error-002.phpt b/mongodb-1.13.0/tests/writeConcern/writeconcern-ctor_error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeConcern/writeconcern-ctor_error-002.phpt
rename to mongodb-1.13.0/tests/writeConcern/writeconcern-ctor_error-002.phpt
diff --git a/mongodb-1.12.0/tests/writeConcern/writeconcern-ctor_error-003.phpt b/mongodb-1.13.0/tests/writeConcern/writeconcern-ctor_error-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeConcern/writeconcern-ctor_error-003.phpt
rename to mongodb-1.13.0/tests/writeConcern/writeconcern-ctor_error-003.phpt
diff --git a/mongodb-1.12.0/tests/writeConcern/writeconcern-ctor_error-004.phpt b/mongodb-1.13.0/tests/writeConcern/writeconcern-ctor_error-004.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeConcern/writeconcern-ctor_error-004.phpt
rename to mongodb-1.13.0/tests/writeConcern/writeconcern-ctor_error-004.phpt
diff --git a/mongodb-1.12.0/tests/writeConcern/writeconcern-ctor_error-005.phpt b/mongodb-1.13.0/tests/writeConcern/writeconcern-ctor_error-005.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeConcern/writeconcern-ctor_error-005.phpt
rename to mongodb-1.13.0/tests/writeConcern/writeconcern-ctor_error-005.phpt
diff --git a/mongodb-1.12.0/tests/writeConcern/writeconcern-debug-001.phpt b/mongodb-1.13.0/tests/writeConcern/writeconcern-debug-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeConcern/writeconcern-debug-001.phpt
rename to mongodb-1.13.0/tests/writeConcern/writeconcern-debug-001.phpt
diff --git a/mongodb-1.12.0/tests/writeConcern/writeconcern-debug-002.phpt b/mongodb-1.13.0/tests/writeConcern/writeconcern-debug-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeConcern/writeconcern-debug-002.phpt
rename to mongodb-1.13.0/tests/writeConcern/writeconcern-debug-002.phpt
diff --git a/mongodb-1.12.0/tests/writeConcern/writeconcern-debug-003.phpt b/mongodb-1.13.0/tests/writeConcern/writeconcern-debug-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeConcern/writeconcern-debug-003.phpt
rename to mongodb-1.13.0/tests/writeConcern/writeconcern-debug-003.phpt
diff --git a/mongodb-1.12.0/tests/writeConcern/writeconcern-getjournal-001.phpt b/mongodb-1.13.0/tests/writeConcern/writeconcern-getjournal-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeConcern/writeconcern-getjournal-001.phpt
rename to mongodb-1.13.0/tests/writeConcern/writeconcern-getjournal-001.phpt
diff --git a/mongodb-1.12.0/tests/writeConcern/writeconcern-getw-001.phpt b/mongodb-1.13.0/tests/writeConcern/writeconcern-getw-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeConcern/writeconcern-getw-001.phpt
rename to mongodb-1.13.0/tests/writeConcern/writeconcern-getw-001.phpt
diff --git a/mongodb-1.12.0/tests/writeConcern/writeconcern-getwtimeout-001.phpt b/mongodb-1.13.0/tests/writeConcern/writeconcern-getwtimeout-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeConcern/writeconcern-getwtimeout-001.phpt
rename to mongodb-1.13.0/tests/writeConcern/writeconcern-getwtimeout-001.phpt
diff --git a/mongodb-1.12.0/tests/writeConcern/writeconcern-getwtimeout-002.phpt b/mongodb-1.13.0/tests/writeConcern/writeconcern-getwtimeout-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeConcern/writeconcern-getwtimeout-002.phpt
rename to mongodb-1.13.0/tests/writeConcern/writeconcern-getwtimeout-002.phpt
diff --git a/mongodb-1.12.0/tests/writeConcern/writeconcern-isdefault-001.phpt b/mongodb-1.13.0/tests/writeConcern/writeconcern-isdefault-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeConcern/writeconcern-isdefault-001.phpt
rename to mongodb-1.13.0/tests/writeConcern/writeconcern-isdefault-001.phpt
diff --git a/mongodb-1.12.0/tests/writeConcern/writeconcern-serialization-001.phpt b/mongodb-1.13.0/tests/writeConcern/writeconcern-serialization-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeConcern/writeconcern-serialization-001.phpt
rename to mongodb-1.13.0/tests/writeConcern/writeconcern-serialization-001.phpt
diff --git a/mongodb-1.12.0/tests/writeConcern/writeconcern-serialization-002.phpt b/mongodb-1.13.0/tests/writeConcern/writeconcern-serialization-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeConcern/writeconcern-serialization-002.phpt
rename to mongodb-1.13.0/tests/writeConcern/writeconcern-serialization-002.phpt
diff --git a/mongodb-1.12.0/tests/writeConcern/writeconcern-serialization_error-001.phpt b/mongodb-1.13.0/tests/writeConcern/writeconcern-serialization_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeConcern/writeconcern-serialization_error-001.phpt
rename to mongodb-1.13.0/tests/writeConcern/writeconcern-serialization_error-001.phpt
diff --git a/mongodb-1.12.0/tests/writeConcern/writeconcern-serialization_error-002.phpt b/mongodb-1.13.0/tests/writeConcern/writeconcern-serialization_error-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeConcern/writeconcern-serialization_error-002.phpt
rename to mongodb-1.13.0/tests/writeConcern/writeconcern-serialization_error-002.phpt
diff --git a/mongodb-1.12.0/tests/writeConcern/writeconcern-set_state-001.phpt b/mongodb-1.13.0/tests/writeConcern/writeconcern-set_state-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeConcern/writeconcern-set_state-001.phpt
rename to mongodb-1.13.0/tests/writeConcern/writeconcern-set_state-001.phpt
diff --git a/mongodb-1.12.0/tests/writeConcern/writeconcern-set_state_error-001.phpt b/mongodb-1.13.0/tests/writeConcern/writeconcern-set_state_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeConcern/writeconcern-set_state_error-001.phpt
rename to mongodb-1.13.0/tests/writeConcern/writeconcern-set_state_error-001.phpt
diff --git a/mongodb-1.12.0/tests/writeConcern/writeconcern-var_export-001.phpt b/mongodb-1.13.0/tests/writeConcern/writeconcern-var_export-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeConcern/writeconcern-var_export-001.phpt
rename to mongodb-1.13.0/tests/writeConcern/writeconcern-var_export-001.phpt
diff --git a/mongodb-1.12.0/tests/writeConcern/writeconcern_error-001.phpt b/mongodb-1.13.0/tests/writeConcern/writeconcern_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeConcern/writeconcern_error-001.phpt
rename to mongodb-1.13.0/tests/writeConcern/writeconcern_error-001.phpt
diff --git a/mongodb-1.13.0/tests/writeConcernError/writeconcernerror-debug-001.phpt b/mongodb-1.13.0/tests/writeConcernError/writeconcernerror-debug-001.phpt
new file mode 100644
index 00000000..a164aa8d
--- /dev/null
+++ b/mongodb-1.13.0/tests/writeConcernError/writeconcernerror-debug-001.phpt
@@ -0,0 +1,35 @@
+--TEST--
+MongoDB\Driver\WriteConcernError debug output
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_replica_set(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+
+$bulk = new MongoDB\Driver\BulkWrite;
+$bulk->insert(['x' => 1]);
+
+try {
+ /* We assume that the replica set does not have 12 nodes */
+ $manager->executeBulkWrite(NS, $bulk, new MongoDB\Driver\WriteConcern(12));
+} catch(MongoDB\Driver\Exception\BulkWriteException $e) {
+ var_dump($e->getWriteResult()->getWriteConcernError());
+}
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+object(MongoDB\Driver\WriteConcernError)#%d (%d) {
+ ["message"]=>
+ string(29) "Not enough data-bearing nodes"
+ ["code"]=>
+ int(100)
+ ["info"]=>
+ %A
+}
+===DONE===
diff --git a/mongodb-1.13.0/tests/writeConcernError/writeconcernerror-getcode-001.phpt b/mongodb-1.13.0/tests/writeConcernError/writeconcernerror-getcode-001.phpt
new file mode 100644
index 00000000..e34dc95a
--- /dev/null
+++ b/mongodb-1.13.0/tests/writeConcernError/writeconcernerror-getcode-001.phpt
@@ -0,0 +1,28 @@
+--TEST--
+MongoDB\Driver\WriteConcernError::getCode()
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_replica_set(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+
+$bulk = new MongoDB\Driver\BulkWrite;
+$bulk->insert(['x' => 1]);
+
+try {
+ /* We assume that the replica set does not have 12 nodes */
+ $manager->executeBulkWrite(NS, $bulk, new MongoDB\Driver\WriteConcern(12));
+} catch(MongoDB\Driver\Exception\BulkWriteException $e) {
+ var_dump($e->getWriteResult()->getWriteConcernError()->getCode());
+}
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+int(100)
+===DONE===
diff --git a/mongodb-1.13.0/tests/writeConcernError/writeconcernerror-getinfo-001.phpt b/mongodb-1.13.0/tests/writeConcernError/writeconcernerror-getinfo-001.phpt
new file mode 100644
index 00000000..4abf46a4
--- /dev/null
+++ b/mongodb-1.13.0/tests/writeConcernError/writeconcernerror-getinfo-001.phpt
@@ -0,0 +1,64 @@
+--TEST--
+MongoDB\Driver\WriteConcernError::getInfo() exposes writeConcernError.errInfo
+--DESCRIPTION--
+CRUD spec prose test #1
+https://github.com/mongodb/specifications/blob/master/source/crud/tests/README.rst#writeconcernerror-details-exposes-writeconcernerror-errinfo
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_replica_set(); ?>
+<?php skip_if_no_failcommand_failpoint(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+
+// Select a specific server for future operations to avoid mongos switching in sharded clusters
+$server = $manager->selectServer(new MongoDB\Driver\ReadPreference('primary'));
+
+configureTargetedFailPoint(
+ $server,
+ 'failCommand',
+ [ 'times' => 1],
+ [
+ 'failCommands' => ['insert'],
+ 'writeConcernError' => [
+ 'code' => 100,
+ 'codeName' => 'UnsatisfiableWriteConcern',
+ 'errmsg' => 'Not enough data-bearing nodes',
+ 'errInfo' => [
+ 'writeConcern' => [
+ 'w' => 2,
+ 'wtimeout' => 0,
+ 'provenance' => 'clientSupplied',
+ ],
+ ],
+ ],
+ ]
+);
+
+$bulk = new MongoDB\Driver\BulkWrite;
+$bulk->insert(['_id' => 1]);
+
+try {
+ $server->executeBulkWrite(NS, $bulk);
+} catch (MongoDB\Driver\Exception\BulkWriteException $e) {
+ var_dump($e->getWriteResult()->getWriteConcernError()->getInfo());
+}
+
+?>
+===DONE===
+--EXPECTF--
+object(stdClass)#%d (%d) {
+ ["writeConcern"]=>
+ object(stdClass)#%d (%d) {
+ ["w"]=>
+ int(2)
+ ["wtimeout"]=>
+ int(0)
+ ["provenance"]=>
+ string(14) "clientSupplied"
+ }
+}
+===DONE===
diff --git a/mongodb-1.13.0/tests/writeConcernError/writeconcernerror-getmessage-001.phpt b/mongodb-1.13.0/tests/writeConcernError/writeconcernerror-getmessage-001.phpt
new file mode 100644
index 00000000..4f578ac3
--- /dev/null
+++ b/mongodb-1.13.0/tests/writeConcernError/writeconcernerror-getmessage-001.phpt
@@ -0,0 +1,28 @@
+--TEST--
+MongoDB\Driver\WriteConcernError::getMessage()
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_replica_set(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+$manager = create_test_manager();
+
+$bulk = new MongoDB\Driver\BulkWrite;
+$bulk->insert(['x' => 1]);
+
+try {
+ /* We assume that the replica set does not have 12 nodes */
+ $manager->executeBulkWrite(NS, $bulk, new MongoDB\Driver\WriteConcern(12));
+} catch(MongoDB\Driver\Exception\BulkWriteException $e) {
+ var_dump($e->getWriteResult()->getWriteConcernError()->getMessage());
+}
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+string(29) "Not enough data-bearing nodes"
+===DONE===
diff --git a/mongodb-1.12.0/tests/writeConcernError/writeconcernerror_error-001.phpt b/mongodb-1.13.0/tests/writeConcernError/writeconcernerror_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeConcernError/writeconcernerror_error-001.phpt
rename to mongodb-1.13.0/tests/writeConcernError/writeconcernerror_error-001.phpt
diff --git a/mongodb-1.12.0/tests/writeError/writeerror-debug-001.phpt b/mongodb-1.13.0/tests/writeError/writeerror-debug-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeError/writeerror-debug-001.phpt
rename to mongodb-1.13.0/tests/writeError/writeerror-debug-001.phpt
diff --git a/mongodb-1.12.0/tests/writeError/writeerror-getCode-001.phpt b/mongodb-1.13.0/tests/writeError/writeerror-getCode-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeError/writeerror-getCode-001.phpt
rename to mongodb-1.13.0/tests/writeError/writeerror-getCode-001.phpt
diff --git a/mongodb-1.12.0/tests/writeError/writeerror-getIndex-001.phpt b/mongodb-1.13.0/tests/writeError/writeerror-getIndex-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeError/writeerror-getIndex-001.phpt
rename to mongodb-1.13.0/tests/writeError/writeerror-getIndex-001.phpt
diff --git a/mongodb-1.12.0/tests/writeError/writeerror-getInfo-001.phpt b/mongodb-1.13.0/tests/writeError/writeerror-getInfo-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeError/writeerror-getInfo-001.phpt
rename to mongodb-1.13.0/tests/writeError/writeerror-getInfo-001.phpt
diff --git a/mongodb-1.12.0/tests/writeError/writeerror-getInfo-002.phpt b/mongodb-1.13.0/tests/writeError/writeerror-getInfo-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeError/writeerror-getInfo-002.phpt
rename to mongodb-1.13.0/tests/writeError/writeerror-getInfo-002.phpt
diff --git a/mongodb-1.12.0/tests/writeError/writeerror-getMessage-001.phpt b/mongodb-1.13.0/tests/writeError/writeerror-getMessage-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeError/writeerror-getMessage-001.phpt
rename to mongodb-1.13.0/tests/writeError/writeerror-getMessage-001.phpt
diff --git a/mongodb-1.12.0/tests/writeError/writeerror_error-001.phpt b/mongodb-1.13.0/tests/writeError/writeerror_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeError/writeerror_error-001.phpt
rename to mongodb-1.13.0/tests/writeError/writeerror_error-001.phpt
diff --git a/mongodb-1.12.0/tests/writeResult/bug0671-003.phpt b/mongodb-1.13.0/tests/writeResult/bug0671-003.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeResult/bug0671-003.phpt
rename to mongodb-1.13.0/tests/writeResult/bug0671-003.phpt
diff --git a/mongodb-1.12.0/tests/writeResult/writeresult-debug-001.phpt b/mongodb-1.13.0/tests/writeResult/writeresult-debug-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeResult/writeresult-debug-001.phpt
rename to mongodb-1.13.0/tests/writeResult/writeresult-debug-001.phpt
diff --git a/mongodb-1.12.0/tests/writeResult/writeresult-debug-002.phpt b/mongodb-1.13.0/tests/writeResult/writeresult-debug-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeResult/writeresult-debug-002.phpt
rename to mongodb-1.13.0/tests/writeResult/writeresult-debug-002.phpt
diff --git a/mongodb-1.12.0/tests/writeResult/writeresult-getdeletedcount-001.phpt b/mongodb-1.13.0/tests/writeResult/writeresult-getdeletedcount-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeResult/writeresult-getdeletedcount-001.phpt
rename to mongodb-1.13.0/tests/writeResult/writeresult-getdeletedcount-001.phpt
diff --git a/mongodb-1.12.0/tests/writeResult/writeresult-getdeletedcount-002.phpt b/mongodb-1.13.0/tests/writeResult/writeresult-getdeletedcount-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeResult/writeresult-getdeletedcount-002.phpt
rename to mongodb-1.13.0/tests/writeResult/writeresult-getdeletedcount-002.phpt
diff --git a/mongodb-1.12.0/tests/writeResult/writeresult-getinsertedcount-001.phpt b/mongodb-1.13.0/tests/writeResult/writeresult-getinsertedcount-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeResult/writeresult-getinsertedcount-001.phpt
rename to mongodb-1.13.0/tests/writeResult/writeresult-getinsertedcount-001.phpt
diff --git a/mongodb-1.12.0/tests/writeResult/writeresult-getinsertedcount-002.phpt b/mongodb-1.13.0/tests/writeResult/writeresult-getinsertedcount-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeResult/writeresult-getinsertedcount-002.phpt
rename to mongodb-1.13.0/tests/writeResult/writeresult-getinsertedcount-002.phpt
diff --git a/mongodb-1.12.0/tests/writeResult/writeresult-getmatchedcount-001.phpt b/mongodb-1.13.0/tests/writeResult/writeresult-getmatchedcount-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeResult/writeresult-getmatchedcount-001.phpt
rename to mongodb-1.13.0/tests/writeResult/writeresult-getmatchedcount-001.phpt
diff --git a/mongodb-1.12.0/tests/writeResult/writeresult-getmatchedcount-002.phpt b/mongodb-1.13.0/tests/writeResult/writeresult-getmatchedcount-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeResult/writeresult-getmatchedcount-002.phpt
rename to mongodb-1.13.0/tests/writeResult/writeresult-getmatchedcount-002.phpt
diff --git a/mongodb-1.12.0/tests/writeResult/writeresult-getmodifiedcount-001.phpt b/mongodb-1.13.0/tests/writeResult/writeresult-getmodifiedcount-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeResult/writeresult-getmodifiedcount-001.phpt
rename to mongodb-1.13.0/tests/writeResult/writeresult-getmodifiedcount-001.phpt
diff --git a/mongodb-1.12.0/tests/writeResult/writeresult-getmodifiedcount-002.phpt b/mongodb-1.13.0/tests/writeResult/writeresult-getmodifiedcount-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeResult/writeresult-getmodifiedcount-002.phpt
rename to mongodb-1.13.0/tests/writeResult/writeresult-getmodifiedcount-002.phpt
diff --git a/mongodb-1.12.0/tests/writeResult/writeresult-getserver-001.phpt b/mongodb-1.13.0/tests/writeResult/writeresult-getserver-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeResult/writeresult-getserver-001.phpt
rename to mongodb-1.13.0/tests/writeResult/writeresult-getserver-001.phpt
diff --git a/mongodb-1.12.0/tests/writeResult/writeresult-getupsertedcount-001.phpt b/mongodb-1.13.0/tests/writeResult/writeresult-getupsertedcount-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeResult/writeresult-getupsertedcount-001.phpt
rename to mongodb-1.13.0/tests/writeResult/writeresult-getupsertedcount-001.phpt
diff --git a/mongodb-1.12.0/tests/writeResult/writeresult-getupsertedcount-002.phpt b/mongodb-1.13.0/tests/writeResult/writeresult-getupsertedcount-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeResult/writeresult-getupsertedcount-002.phpt
rename to mongodb-1.13.0/tests/writeResult/writeresult-getupsertedcount-002.phpt
diff --git a/mongodb-1.12.0/tests/writeResult/writeresult-getupsertedids-001.phpt b/mongodb-1.13.0/tests/writeResult/writeresult-getupsertedids-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeResult/writeresult-getupsertedids-001.phpt
rename to mongodb-1.13.0/tests/writeResult/writeresult-getupsertedids-001.phpt
diff --git a/mongodb-1.13.0/tests/writeResult/writeresult-getupsertedids-002.phpt b/mongodb-1.13.0/tests/writeResult/writeresult-getupsertedids-002.phpt
new file mode 100644
index 00000000..786fa095
--- /dev/null
+++ b/mongodb-1.13.0/tests/writeResult/writeresult-getupsertedids-002.phpt
@@ -0,0 +1,104 @@
+--TEST--
+MongoDB\Driver\WriteResult::getUpsertedIds() with client-generated values
+--SKIPIF--
+<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
+<?php skip_if_not_live(); ?>
+<?php skip_if_not_clean(); ?>
+--FILE--
+<?php
+require_once __DIR__ . "/../utils/basic.inc";
+
+/* Do not test array or Regex types, which are not permitted to be used as an
+ * ID. If a regular expression is used in upsert criteria and does not match an
+ * existing document, the server generates a new ObjectId. */
+$tests = [
+ null,
+ true,
+ 1,
+ 4.125,
+ 'foo',
+ (object) [],
+ new MongoDB\BSON\Binary('foo', MongoDB\BSON\Binary::TYPE_GENERIC),
+ new MongoDB\BSON\Decimal128('1234.5678'),
+ new MongoDB\BSON\Javascript('function(){}'),
+ new MongoDB\BSON\MaxKey,
+ new MongoDB\BSON\MinKey,
+ new MongoDB\BSON\ObjectId('586c18d86118fd6c9012dec1'),
+ new MongoDB\BSON\Timestamp(1234, 5678),
+ new MongoDB\BSON\UTCDateTime('1483479256924'),
+];
+
+$manager = create_test_manager();
+
+$bulk = new MongoDB\Driver\BulkWrite;
+
+foreach ($tests as $value) {
+ $bulk->update(['_id' => $value], ['$set' => ['x' => 1]], ['upsert' => true]);
+}
+
+$result = $manager->executeBulkWrite(NS, $bulk);
+
+var_dump($result->getUpsertedIds());
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+array(14) {
+ [0]=>
+ NULL
+ [1]=>
+ bool(true)
+ [2]=>
+ int(1)
+ [3]=>
+ float(4.125)
+ [4]=>
+ string(3) "foo"
+ [5]=>
+ object(stdClass)#%d (%d) {
+ }
+ [6]=>
+ object(MongoDB\BSON\Binary)#%d (%d) {
+ ["data"]=>
+ string(3) "foo"
+ ["type"]=>
+ int(0)
+ }
+ [7]=>
+ object(MongoDB\BSON\Decimal128)#%d (%d) {
+ ["dec"]=>
+ string(9) "1234.5678"
+ }
+ [8]=>
+ object(MongoDB\BSON\Javascript)#%d (%d) {
+ ["code"]=>
+ string(12) "function(){}"
+ ["scope"]=>
+ NULL
+ }
+ [9]=>
+ object(MongoDB\BSON\MaxKey)#%d (%d) {
+ }
+ [10]=>
+ object(MongoDB\BSON\MinKey)#%d (%d) {
+ }
+ [11]=>
+ object(MongoDB\BSON\ObjectId)#%d (%d) {
+ ["oid"]=>
+ string(24) "586c18d86118fd6c9012dec1"
+ }
+ [12]=>
+ object(MongoDB\BSON\Timestamp)#%d (%d) {
+ ["increment"]=>
+ string(4) "1234"
+ ["timestamp"]=>
+ string(4) "5678"
+ }
+ [13]=>
+ object(MongoDB\BSON\UTCDateTime)#%d (%d) {
+ ["milliseconds"]=>
+ string(13) "1483479256924"
+ }
+}
+===DONE===
diff --git a/mongodb-1.12.0/tests/writeResult/writeresult-getwriteconcernerror-001.phpt b/mongodb-1.13.0/tests/writeResult/writeresult-getwriteconcernerror-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeResult/writeresult-getwriteconcernerror-001.phpt
rename to mongodb-1.13.0/tests/writeResult/writeresult-getwriteconcernerror-001.phpt
diff --git a/mongodb-1.12.0/tests/writeResult/writeresult-getwriteerrors-001.phpt b/mongodb-1.13.0/tests/writeResult/writeresult-getwriteerrors-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeResult/writeresult-getwriteerrors-001.phpt
rename to mongodb-1.13.0/tests/writeResult/writeresult-getwriteerrors-001.phpt
diff --git a/mongodb-1.12.0/tests/writeResult/writeresult-getwriteerrors-002.phpt b/mongodb-1.13.0/tests/writeResult/writeresult-getwriteerrors-002.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeResult/writeresult-getwriteerrors-002.phpt
rename to mongodb-1.13.0/tests/writeResult/writeresult-getwriteerrors-002.phpt
diff --git a/mongodb-1.12.0/tests/writeResult/writeresult-isacknowledged-001.phpt b/mongodb-1.13.0/tests/writeResult/writeresult-isacknowledged-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeResult/writeresult-isacknowledged-001.phpt
rename to mongodb-1.13.0/tests/writeResult/writeresult-isacknowledged-001.phpt
diff --git a/mongodb-1.12.0/tests/writeResult/writeresult_error-001.phpt b/mongodb-1.13.0/tests/writeResult/writeresult_error-001.phpt
similarity index 100%
rename from mongodb-1.12.0/tests/writeResult/writeresult_error-001.phpt
rename to mongodb-1.13.0/tests/writeResult/writeresult_error-001.phpt
diff --git a/package.xml b/package.xml
index 519454fe..60897217 100644
--- a/package.xml
+++ b/package.xml
@@ -1,2769 +1,2863 @@
<?xml version="1.0" encoding="UTF-8"?>
-<package packagerversion="1.10.12" version="2.1" xmlns="http://pear.php.net/dtd/package-2.1" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.1 http://pear.php.net/dtd/package-2.1.xsd">
+<package packagerversion="1.10.13" version="2.1" xmlns="http://pear.php.net/dtd/package-2.1" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.1 http://pear.php.net/dtd/package-2.1.xsd">
<name>mongodb</name>
<channel>pecl.php.net</channel>
<summary>MongoDB driver for PHP</summary>
<description>The purpose of this driver is to provide exceptionally thin glue between MongoDB
and PHP, implementing only fundamental and performance-critical components
necessary to build a fully-functional MongoDB driver.</description>
<lead>
<name>Andreas Braun</name>
<user>alcaeus</user>
<email>alcaeus@php.net</email>
<active>yes</active>
</lead>
<lead>
<name>Jeremy Mikola</name>
<user>jmikola</user>
<email>jmikola@php.net</email>
<active>yes</active>
</lead>
<lead>
<name>Derick Rethans</name>
<user>derick</user>
<email>derick@php.net</email>
<active>no</active>
</lead>
<lead>
<name>Hannes Magnusson</name>
<user>bjori</user>
<email>bjori@php.net</email>
<active>no</active>
</lead>
<developer>
<name>Katherine Walker</name>
<user>kvwalker</user>
<email>kvwalker@php.net</email>
<active>no</active>
</developer>
- <date>2021-12-14</date>
- <time>22:17:56</time>
+ <date>2022-03-23</date>
+ <time>16:49:06</time>
<version>
- <release>1.12.0</release>
- <api>1.12.0</api>
+ <release>1.13.0</release>
+ <api>1.13.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<license uri="http://www.apache.org/licenses/LICENSE-2.0">Apache License</license>
<notes>
+** Bug
+ * [PHPC-2013] - RHEL 7.0 and 7.1 builds fail due to incompatible pointer warnings
+ * [PHPC-2020] - Validate loadBalanced URI array option
+
** Epic
- * [PHPC-1850] - Support PHP 8.1
- * [PHPC-1912] - CSFLE 1.0 KMIP Support
+ * [PHPC-1150] - Support SDAM Monitoring
** New Feature
- * [PHPC-2009] - Support tlsOptions encryption option
+ * [PHPC-1805] - Implement ServerDescription class
+ * [PHPC-1891] - Implement TopologyDescription class
+ * [PHPC-1892] - Define SDAMSubscriber interface
+ * [PHPC-1893] - Define SDAM event classes
+ * [PHPC-1900] - Allow custom service names with srvServiceName URI option
+ * [PHPC-1908] - Allow limiting mongos servers with srvMaxHosts option
** Task
- * [PHPC-1878] - Unexpected primary step down when testing on MongoDB latest
- * [PHPC-1880] - Drop support for PHP 7.1
- * [PHPC-1931] - Add PHP 8.1 to PHP toolchain
- * [PHPC-1997] - Update calls to deprecated bson_atomic_int_add function
- * [PHPC-2011] - Upgrade libmongoc to 1.20.0 and libmongocrypt to 1.3.0
+ * [PHPC-1342] - Add documentation warning against the use of duplicate key names
+ * [PHPC-1909] - Set minWireVersion to 6 (MongoDB 3.6)
+ * [PHPC-1953] - Create tests for event object debug handlers
+ * [PHPC-1958] - Ensure that getTopologyId() gives the same result for all SDAM events
+ * [PHPC-1959] - Change SDAM event tests to use Manager::addSubscriber()
+ * [PHPC-1973] - Bump maxWireVersion to 14 for MongoDB 5.1
+ * [PHPC-2008] - writeresult-getserver-002 fails to drop collection in local db on replicaset-auth
+ * [PHPC-2012] - Remove extra AX_CHECK_COMPILE_FLAG args
+ * [PHPC-2019] - Remove Solaris checks in m4 build scripts
+ * [PHPC-2022] - Use mongoc_host_list in event structs
+ * [PHPC-2023] - Allow observation of TopologyClosedEvent
+ * [PHPC-2028] - Replace PHONGO_ALLOC_OBJECT_T macro with zend_object_alloc
+ * [PHPC-2031] - Upgrade libmongoc to 1.21.1 and libmongocrypt to 1.3.2
+ * [PHPC-2034] - Bump maxWireVersion for MongoDB 5.2
+ * [PHPC-2036] - Remove outdated prose test in causal consistency spec
+ * [PHPC-2037] - Remove vim modeline comments
+ * [PHPC-2038] - Initialize zval in phongo_clientencryption_init
+ * [PHPC-2039] - Remove disabled debugging code in bson.c
+ * [PHPC-2040] - Break down php_phongo.c into smaller files
+ * [PHPC-2042] - Remove conditional win32/time.h include in UTCDateTime.c
+ * [PHPC-2047] - Update load balancer tests to support dedicated load balancer port
+ * [PHPC-2073] - Remove test environments and checks for pre-3.6 server versions
+ * [PHPC-2074] - Clarify in contributing docs that mongo-orchestration is not required to run tests
** Improvement
- * [PHPC-1942] - Support BSON Binary subtype 0x07 (column)
- * [PHPC-2004] - Specify string return type in __toString() arginfos
- * [PHPC-2007] - Explicitly implement Stringable for PHP 8+
- * [PHPC-2010] - Type validation for autoEncryption.extraOptions
+ * [PHPC-1647] - Defer to libmongoc for cross-option URI validation
+ * [PHPC-1910] - Implement Server::getServerDescription
+ * [PHPC-1925] - ServerDescription::getType() should return a string
+ * [PHPC-1934] - Check for uninitialized intern in ServerDescription get_properties_hash
+ * [PHPC-1950] - Lift restriction on authSource without credentials when set in URI options array
+ * [PHPC-2003] - Expose whether a client session is dirty
+ * [PHPC-2025] - Support load balancer in ServerDescription and TopologyDescription
+ * [PHPC-2026] - Warn if ServerDescription::getLastUpdateTime() must be truncated
+ * [PHPC-2030] - Allow observation of commands issued during mongoc_client_destroy()
+ * [PHPC-2032] - Report more concise debug info for ended sessions
</notes>
<contents>
<dir name="/">
<file md5sum="c78c5e9b49b67a725e831823492642da" name="scripts/autotools/libbson/CheckAtomics.m4" role="src" />
<file md5sum="24efc529aa9f2b40d80cbec3bb635d01" name="scripts/autotools/libbson/CheckHeaders.m4" role="src" />
<file md5sum="fcce6a6a1e782b4482a50b18f78a2114" name="scripts/autotools/libbson/Endian.m4" role="src" />
- <file md5sum="f1678968409f821893deb37ce58de6ee" name="scripts/autotools/libbson/FindDependencies.m4" role="src" />
+ <file md5sum="422e66c86688aa02db4c6d98378aa0e2" name="scripts/autotools/libbson/FindDependencies.m4" role="src" />
<file md5sum="0ea5922bfcf826e14a5f3c0a5563e410" name="scripts/autotools/libbson/Versions.m4" role="src" />
- <file md5sum="8ad59ded5a1ccc434742345553373cfd" name="scripts/autotools/libmongoc/CheckCompression.m4" role="src" />
+ <file md5sum="796238ff21022249fc485a8eb53be09e" name="scripts/autotools/libmongoc/CheckCompression.m4" role="src" />
<file md5sum="96ddbeccbaa3c00f367810f56df074e4" name="scripts/autotools/libmongoc/CheckICU.m4" role="src" />
<file md5sum="79ffd99afdc875d93f016f693b787468" name="scripts/autotools/libmongoc/CheckResolv.m4" role="src" />
<file md5sum="1402931faf1e48f2159acbb7f0a36452" name="scripts/autotools/libmongoc/CheckSSL.m4" role="src" />
<file md5sum="39e1c1663469b0d6222b6babd183fb40" name="scripts/autotools/libmongoc/CheckSasl.m4" role="src" />
- <file md5sum="416b3bbfdd1ade68dd3f8ec1ceda5186" name="scripts/autotools/libmongoc/FindDependencies.m4" role="src" />
- <file md5sum="bba9dc2de93bdadc29dc0927676161c7" name="scripts/autotools/libmongoc/PlatformFlags.m4" role="src" />
+ <file md5sum="2d7d36844c77bceb9da76b448455353d" name="scripts/autotools/libmongoc/FindDependencies.m4" role="src" />
+ <file md5sum="d429836468174085140a6958c5926402" name="scripts/autotools/libmongoc/PlatformFlags.m4" role="src" />
<file md5sum="08214982201e2c7805b62a3a4ca915a6" name="scripts/autotools/libmongoc/Versions.m4" role="src" />
<file md5sum="76e2c1a2aa19f5fab3661c992ac603fa" name="scripts/autotools/libmongoc/WeakSymbols.m4" role="src" />
<file md5sum="906a71d7858713742f5febc043b9b51b" name="scripts/autotools/libmongocrypt/CheckSSL.m4" role="src" />
<file md5sum="59f94718c53faf3661bf1a9aadb2991e" name="scripts/autotools/libmongocrypt/Endian.m4" role="src" />
<file md5sum="471ed55586aaeef30e1d54a235133735" name="scripts/autotools/libmongocrypt/Version.m4" role="src" />
<file md5sum="0091c30d8927966e5ba54ce90b62bf6e" name="scripts/autotools/m4/as_var_copy.m4" role="src" />
<file md5sum="8d942f69b5f3c15ecae4b75bb7e80614" name="scripts/autotools/m4/ax_check_compile_flag.m4" role="src" />
<file md5sum="c2221efd4309e58ff7e2ef989c8e8ac4" name="scripts/autotools/m4/ax_prototype.m4" role="src" />
<file md5sum="b5114dfcf027b0f9a47b6e6841015be6" name="scripts/autotools/m4/ax_pthread.m4" role="src" />
<file md5sum="01a9faee79ca2be030b72f2046976b09" name="scripts/autotools/m4/php_mongodb.m4" role="src" />
<file md5sum="ad8d52d54e0f97c0e4e385376ea73bc0" name="scripts/autotools/m4/pkg.m4" role="src" />
<file md5sum="0601fcdfbdc1e25d6f5601cf78693669" name="scripts/autotools/CheckCompiler.m4" role="src" />
<file md5sum="51c4dd11458ad655113dcdb101640b49" name="scripts/autotools/CheckHost.m4" role="src" />
<file md5sum="e6c8420017ff6f2090eccbe800b3ad14" name="scripts/clang-format.sh" role="test" />
<file md5sum="992cbbe1b006fdf00448ed6f106c730c" name="scripts/convert-bson-corpus-tests.php" role="test" />
+ <file md5sum="a3ee9619493782cf80261595fe7fd9dd" name="scripts/mongo-orchestration.php" role="test" />
<file md5sum="fb8d8138eb989fe03e2ed7ccac3b7921" name="scripts/update-submodule-sources.php" role="test" />
- <file md5sum="054b2bb8f5c6689888eb7766ab406d65" name="src/BSON/Binary.c" role="src" />
- <file md5sum="5b2a453dca0210a531a1bb912da19d04" name="src/BSON/BinaryInterface.c" role="src" />
- <file md5sum="e5c27763e77c654b0fb5d626b5ff722e" name="src/BSON/DBPointer.c" role="src" />
- <file md5sum="d9e07dbb88feb1081c7844a31d749101" name="src/BSON/Decimal128.c" role="src" />
- <file md5sum="d05ae892293010ac58b6e3dae41bd4b3" name="src/BSON/Decimal128Interface.c" role="src" />
- <file md5sum="f62ab2707da7b7434347d98da3b71ae7" name="src/BSON/Int64.c" role="src" />
- <file md5sum="7546789f7813f3fd20833d6b744e660b" name="src/BSON/Javascript.c" role="src" />
- <file md5sum="0102d2d400223fab1b54ebfd485b5210" name="src/BSON/JavascriptInterface.c" role="src" />
- <file md5sum="316c0d4bca661752d3c17f2fb46f1977" name="src/BSON/MaxKey.c" role="src" />
- <file md5sum="b705031ae7da88453b1325553b59dac9" name="src/BSON/MaxKeyInterface.c" role="src" />
- <file md5sum="6fabdfc06fd0afe702d4c4f79492aace" name="src/BSON/MinKey.c" role="src" />
- <file md5sum="07c73bf7a185f3800a018da117b5a510" name="src/BSON/MinKeyInterface.c" role="src" />
- <file md5sum="d7dde26a9fa1d0829b1a1649395346cb" name="src/BSON/ObjectId.c" role="src" />
- <file md5sum="a3954737b089c86f6968eebc9e6b1386" name="src/BSON/ObjectIdInterface.c" role="src" />
- <file md5sum="078a7e2ad997ebcfabb200b37199f8f8" name="src/BSON/Persistable.c" role="src" />
- <file md5sum="349bd297d327a5caf18bf0e16b392755" name="src/BSON/Regex.c" role="src" />
- <file md5sum="6f9df76ff27eb1972a28dd6d6415a089" name="src/BSON/RegexInterface.c" role="src" />
- <file md5sum="a5b29dfe208dac9578a9e6c17d8e173a" name="src/BSON/Serializable.c" role="src" />
- <file md5sum="7e920dbac30b33c9b4cd84ba76f52f29" name="src/BSON/Symbol.c" role="src" />
- <file md5sum="bd28c3d1ee3d34f844235e5c6819c3e4" name="src/BSON/Timestamp.c" role="src" />
- <file md5sum="5bd504112a865158956011d70693d934" name="src/BSON/TimestampInterface.c" role="src" />
- <file md5sum="dc8ec6d3e1e53fad62230d7ceb7ec426" name="src/BSON/Type.c" role="src" />
- <file md5sum="4f14f5525423897d30d426b47aeb1393" name="src/BSON/UTCDateTime.c" role="src" />
- <file md5sum="6b12e1189d74c4ede4110b68dd5fcd49" name="src/BSON/UTCDateTimeInterface.c" role="src" />
- <file md5sum="6cd494a295a7d39d39b3c8f39ade8bc9" name="src/BSON/Undefined.c" role="src" />
- <file md5sum="0014e8b547de1e4644937165e4392e74" name="src/BSON/Unserializable.c" role="src" />
- <file md5sum="e921e17f63a293e5f08c33ed8e1c0ced" name="src/BSON/functions.c" role="src" />
- <file md5sum="805bc8540933f77f1b9613741a0f82c5" name="src/BSON/functions.h" role="src" />
- <file md5sum="16c87a6db1f597eb3067c68dcd684c6d" name="src/MongoDB/Exception/AuthenticationException.c" role="src" />
- <file md5sum="ecdd953840d644f9e0f8c32611732aa0" name="src/MongoDB/Exception/BulkWriteException.c" role="src" />
- <file md5sum="a9b6bb75234bcbea04cf4780be46cb39" name="src/MongoDB/Exception/CommandException.c" role="src" />
- <file md5sum="5c9122ea6bb3e5aa952bde0018586cc6" name="src/MongoDB/Exception/ConnectionException.c" role="src" />
- <file md5sum="1d32ba861cd111a6a49e04ec1cbd540d" name="src/MongoDB/Exception/ConnectionTimeoutException.c" role="src" />
- <file md5sum="23510875508b2e6fa36f63397c9553fa" name="src/MongoDB/Exception/EncryptionException.c" role="src" />
- <file md5sum="3be0382857fc770a68f7cd4df51d110e" name="src/MongoDB/Exception/Exception.c" role="src" />
- <file md5sum="577025579944045d7ebab713e4df3f06" name="src/MongoDB/Exception/ExecutionTimeoutException.c" role="src" />
- <file md5sum="88763149c1315fae7eb6b889ad135b39" name="src/MongoDB/Exception/InvalidArgumentException.c" role="src" />
- <file md5sum="0e3a74161f66fc16dbf85730a9c5c374" name="src/MongoDB/Exception/LogicException.c" role="src" />
- <file md5sum="eba8efc033c9554f7b80e53280cae690" name="src/MongoDB/Exception/RuntimeException.c" role="src" />
- <file md5sum="f8d77c2809303f8c6ab65e0d595da3a8" name="src/MongoDB/Exception/SSLConnectionException.c" role="src" />
- <file md5sum="dbcd7a847b8fe9a44c45ff9b60816b63" name="src/MongoDB/Exception/ServerException.c" role="src" />
- <file md5sum="df3af2e4c1f14515e5cf4ee086f918e2" name="src/MongoDB/Exception/UnexpectedValueException.c" role="src" />
- <file md5sum="b15775643dca5f5246eeb1e644cd67c5" name="src/MongoDB/Exception/WriteException.c" role="src" />
- <file md5sum="574853138ada5ae6005280380c23605d" name="src/MongoDB/Monitoring/CommandFailedEvent.c" role="src" />
- <file md5sum="01ca8aaf558c020714426eb0ccd5aacf" name="src/MongoDB/Monitoring/CommandStartedEvent.c" role="src" />
- <file md5sum="6b6d40f3c4d83a0d73bd9b9db7401af9" name="src/MongoDB/Monitoring/CommandSubscriber.c" role="src" />
- <file md5sum="a5e5e20223aea300f0a725f4832d5709" name="src/MongoDB/Monitoring/CommandSucceededEvent.c" role="src" />
- <file md5sum="7a35bb700ee462825677008a5caaa731" name="src/MongoDB/Monitoring/Subscriber.c" role="src" />
- <file md5sum="fa1c61b402d9379b5d382f71b5fd703f" name="src/MongoDB/Monitoring/functions.c" role="src" />
- <file md5sum="aa5f4add8324348fee968fb781795217" name="src/MongoDB/Monitoring/functions.h" role="src" />
- <file md5sum="72f4f38424f0a37bb5540bca089fdd07" name="src/MongoDB/BulkWrite.c" role="src" />
- <file md5sum="647f0dfc028c38debcf43d5b02d40326" name="src/MongoDB/ClientEncryption.c" role="src" />
- <file md5sum="52aa217e8a09bab73d6add5507b86205" name="src/MongoDB/Command.c" role="src" />
- <file md5sum="cdf80a8a43fe72c6d197759151acca6c" name="src/MongoDB/Cursor.c" role="src" />
- <file md5sum="c2b57c4a7989e82fdda5f0a1136a1ff9" name="src/MongoDB/CursorId.c" role="src" />
- <file md5sum="ffa4b679a3eecd3c9827f4fab386d65c" name="src/MongoDB/CursorInterface.c" role="src" />
- <file md5sum="aa666fb0c56b3ce8cdab71cc9d3846da" name="src/MongoDB/Manager.c" role="src" />
- <file md5sum="6898acaca7986a1504487eed0e6a3544" name="src/MongoDB/Query.c" role="src" />
- <file md5sum="ae3da747845fdc6a5894fba7b0949b16" name="src/MongoDB/ReadConcern.c" role="src" />
- <file md5sum="7d10a8b473015576c9db577b1b334cff" name="src/MongoDB/ReadPreference.c" role="src" />
- <file md5sum="c3ded4441967afc860b04643159c9061" name="src/MongoDB/Server.c" role="src" />
- <file md5sum="35ce2ab9bd75b1a4bf88d3227ae7ed3a" name="src/MongoDB/ServerApi.c" role="src" />
- <file md5sum="b705621315715911b2b01d43f4ffe202" name="src/MongoDB/Session.c" role="src" />
- <file md5sum="4b0760fce377889f0c71d60682d5af0e" name="src/MongoDB/Session.h" role="src" />
- <file md5sum="a416c6a66d9d88be2e29629e484528e0" name="src/MongoDB/WriteConcern.c" role="src" />
- <file md5sum="621bb4da3b50554c73fb787bf6c32342" name="src/MongoDB/WriteConcernError.c" role="src" />
- <file md5sum="8a6cb71e8aa0aaafe7ee873264a87055" name="src/MongoDB/WriteError.c" role="src" />
- <file md5sum="1c0687fd9e377b6e680ab253dbcbb282" name="src/MongoDB/WriteResult.c" role="src" />
+ <file md5sum="38e98c2bfc7f56dffb9db7b09ade5141" name="src/BSON/Binary.c" role="src" />
+ <file md5sum="afdb4c218b1832b967dc83b9275109b3" name="src/BSON/BinaryInterface.c" role="src" />
+ <file md5sum="20874183dc96c87639760ca1a11efb4e" name="src/BSON/DBPointer.c" role="src" />
+ <file md5sum="5731e850094db36f5232ad2600eb5dbe" name="src/BSON/Decimal128.c" role="src" />
+ <file md5sum="fe9045fdaf1c04fa2cb1d4c1721c4456" name="src/BSON/Decimal128Interface.c" role="src" />
+ <file md5sum="60e97c448e99619b273395c7138661c1" name="src/BSON/Int64.c" role="src" />
+ <file md5sum="3970c46eaf0f8ea0ca67ad79229fc070" name="src/BSON/Javascript.c" role="src" />
+ <file md5sum="28f0e47660ff76131121e0bf10afa022" name="src/BSON/JavascriptInterface.c" role="src" />
+ <file md5sum="7314bb17e6770cbc5d848d4c3192c7a3" name="src/BSON/MaxKey.c" role="src" />
+ <file md5sum="e9296e8b8a30aba292300de75fe6606a" name="src/BSON/MaxKeyInterface.c" role="src" />
+ <file md5sum="fd48fae3962305ae57f5d5afa3451dbb" name="src/BSON/MinKey.c" role="src" />
+ <file md5sum="39a764c5bcd276a553c5472283ce3cdd" name="src/BSON/MinKeyInterface.c" role="src" />
+ <file md5sum="eeee505fb094618d3b5e743bdc3b3e15" name="src/BSON/ObjectId.c" role="src" />
+ <file md5sum="397725a29c9cc16edbf7c9449898a292" name="src/BSON/ObjectId.h" role="src" />
+ <file md5sum="5a165c6c79f34f3e6451749dc80df8e9" name="src/BSON/ObjectIdInterface.c" role="src" />
+ <file md5sum="415e1d9e4a33c1600b251494e7a04b18" name="src/BSON/Persistable.c" role="src" />
+ <file md5sum="72bb1a49db40a364548960051bcd892f" name="src/BSON/Regex.c" role="src" />
+ <file md5sum="c30ecde8019c72065e6a059f3666b46f" name="src/BSON/RegexInterface.c" role="src" />
+ <file md5sum="97eddda27c4a289deb5643c27876ff69" name="src/BSON/Serializable.c" role="src" />
+ <file md5sum="8eb00e2954e04d252c9ad61d1d0d91e9" name="src/BSON/Symbol.c" role="src" />
+ <file md5sum="ba5f708808d7dab0e06a56824bfdc8b6" name="src/BSON/Timestamp.c" role="src" />
+ <file md5sum="5d78979ab806321720326880f10fb1e2" name="src/BSON/TimestampInterface.c" role="src" />
+ <file md5sum="a768013d507ab726b4de0c2ef44f28aa" name="src/BSON/Type.c" role="src" />
+ <file md5sum="1dc53b517c53ef57bb6afeb95dc43b2f" name="src/BSON/UTCDateTime.c" role="src" />
+ <file md5sum="03bb2b27c777674c1f252befa318148e" name="src/BSON/UTCDateTimeInterface.c" role="src" />
+ <file md5sum="29a5a26c8aea93fc68da6ef8aec1d4e3" name="src/BSON/Undefined.c" role="src" />
+ <file md5sum="ab50b5d9374db3ac59b898a772e74dfa" name="src/BSON/Unserializable.c" role="src" />
+ <file md5sum="405d86c89ce754e9d77a23db4b7bfe9e" name="src/BSON/functions.c" role="src" />
+ <file md5sum="96e2b2aada16d13a3e58834e5384a232" name="src/BSON/functions.h" role="src" />
+ <file md5sum="b9d87a9dc3b1a8351c0a44c659940cab" name="src/MongoDB/Exception/AuthenticationException.c" role="src" />
+ <file md5sum="74548742592f4202bbb61a7747ecd678" name="src/MongoDB/Exception/BulkWriteException.c" role="src" />
+ <file md5sum="e19afc936327ed3572462d048ee7997e" name="src/MongoDB/Exception/CommandException.c" role="src" />
+ <file md5sum="aee60b2d392bd9213a6d7e4bceaa2a82" name="src/MongoDB/Exception/ConnectionException.c" role="src" />
+ <file md5sum="7c60c07144f509d2d500ccdcb4de9a80" name="src/MongoDB/Exception/ConnectionTimeoutException.c" role="src" />
+ <file md5sum="e5cb1c4a9280f1e0f0dc0c711ea8ea99" name="src/MongoDB/Exception/EncryptionException.c" role="src" />
+ <file md5sum="e62632a8b843dc20d2d5e133370319d5" name="src/MongoDB/Exception/Exception.c" role="src" />
+ <file md5sum="f47d6e58f9ddccbf3aee5fc3656fbcac" name="src/MongoDB/Exception/ExecutionTimeoutException.c" role="src" />
+ <file md5sum="8782de57dd76a17b13a26914dd420ab0" name="src/MongoDB/Exception/InvalidArgumentException.c" role="src" />
+ <file md5sum="851a91b39708007689071a20d727025a" name="src/MongoDB/Exception/LogicException.c" role="src" />
+ <file md5sum="8f326b44e15fe89bc237b2c6800cea58" name="src/MongoDB/Exception/RuntimeException.c" role="src" />
+ <file md5sum="5c96b995f505edb36c61a3a8f3195d61" name="src/MongoDB/Exception/SSLConnectionException.c" role="src" />
+ <file md5sum="d5030f938bb0ed9c5e5e957957cf46d0" name="src/MongoDB/Exception/ServerException.c" role="src" />
+ <file md5sum="30f24dfa27447dc59598789562447814" name="src/MongoDB/Exception/UnexpectedValueException.c" role="src" />
+ <file md5sum="80e3bdb8b53b211b9a9def542ac00a90" name="src/MongoDB/Exception/WriteException.c" role="src" />
+ <file md5sum="08d5b2e94488f25a7e63c3358aa4b31d" name="src/MongoDB/Monitoring/CommandFailedEvent.c" role="src" />
+ <file md5sum="f73d2111cd5221a44faa96e3dcdd9169" name="src/MongoDB/Monitoring/CommandStartedEvent.c" role="src" />
+ <file md5sum="50cb8481803e057d183cd6d2f6acf399" name="src/MongoDB/Monitoring/CommandSubscriber.c" role="src" />
+ <file md5sum="bcc96e558b26dedc27c84401324c3bad" name="src/MongoDB/Monitoring/CommandSucceededEvent.c" role="src" />
+ <file md5sum="ccd3d921993593b6681b1cf0bd894c51" name="src/MongoDB/Monitoring/SDAMSubscriber.c" role="src" />
+ <file md5sum="d8a8c7951b2ef5a471b61ace623e65ef" name="src/MongoDB/Monitoring/ServerChangedEvent.c" role="src" />
+ <file md5sum="474adf321e6df0f19e9a72ee5b25f173" name="src/MongoDB/Monitoring/ServerClosedEvent.c" role="src" />
+ <file md5sum="e054dd5ba7903f6c014fdc45853aea6d" name="src/MongoDB/Monitoring/ServerHeartbeatFailedEvent.c" role="src" />
+ <file md5sum="e316e0880df5bd0049cb2818d0146303" name="src/MongoDB/Monitoring/ServerHeartbeatStartedEvent.c" role="src" />
+ <file md5sum="9729a4e3482684eac938f89a0c58d6c4" name="src/MongoDB/Monitoring/ServerHeartbeatSucceededEvent.c" role="src" />
+ <file md5sum="948e175b3bbd8dfba99508160595ee82" name="src/MongoDB/Monitoring/ServerOpeningEvent.c" role="src" />
+ <file md5sum="61eac332e392a2b82e809b8ff78121af" name="src/MongoDB/Monitoring/Subscriber.c" role="src" />
+ <file md5sum="e31280f973092e9eb55403bff8e45ef7" name="src/MongoDB/Monitoring/TopologyChangedEvent.c" role="src" />
+ <file md5sum="614f6f0e319b31da439c37435c0dafa7" name="src/MongoDB/Monitoring/TopologyClosedEvent.c" role="src" />
+ <file md5sum="ca2fdcbd1d277b0152c89cbb45bb3adc" name="src/MongoDB/Monitoring/TopologyOpeningEvent.c" role="src" />
+ <file md5sum="cc3aeca178c0f9b3df384a9ac389b53f" name="src/MongoDB/Monitoring/functions.c" role="src" />
+ <file md5sum="1f2bab28965c93a8ac7ee6a923fb5f5f" name="src/MongoDB/Monitoring/functions.h" role="src" />
+ <file md5sum="25bd3f0dffd3d9b61d491ce16f23358e" name="src/MongoDB/BulkWrite.c" role="src" />
+ <file md5sum="84389398b112c7a09ee8f1c8f218ad72" name="src/MongoDB/ClientEncryption.c" role="src" />
+ <file md5sum="39019b79a607dbaa734c95f3fa206da9" name="src/MongoDB/ClientEncryption.h" role="src" />
+ <file md5sum="41517cdf61c91efd359ae8dff544e497" name="src/MongoDB/Command.c" role="src" />
+ <file md5sum="662e226d6568974d6e40dca03f7cf9a0" name="src/MongoDB/Cursor.c" role="src" />
+ <file md5sum="b96c7e5787a25dde042893eb3dde62e0" name="src/MongoDB/Cursor.h" role="src" />
+ <file md5sum="18fd606bc9223f826568f32c13122e0f" name="src/MongoDB/CursorId.c" role="src" />
+ <file md5sum="63249beb0af413ca7f34095676abe4bc" name="src/MongoDB/CursorInterface.c" role="src" />
+ <file md5sum="e5b5dc1d570661b81d88c76fff0de0e5" name="src/MongoDB/Manager.c" role="src" />
+ <file md5sum="ef61de949eb4afc2544960c0d7702e94" name="src/MongoDB/Query.c" role="src" />
+ <file md5sum="8f181751d906a6f258b982ab2b2e71e8" name="src/MongoDB/ReadConcern.c" role="src" />
+ <file md5sum="dfc43f39b619cba2223dfe0ec89a1317" name="src/MongoDB/ReadConcern.h" role="src" />
+ <file md5sum="a93c01f9bd5e466e0c1e77bd53d21616" name="src/MongoDB/ReadPreference.c" role="src" />
+ <file md5sum="faeca5d6267879c0680eca37b3004631" name="src/MongoDB/ReadPreference.h" role="src" />
+ <file md5sum="a258e198dd195d3c72958c9c932828a2" name="src/MongoDB/Server.c" role="src" />
+ <file md5sum="d88d4c2dbbc0801b2e193add88fbb282" name="src/MongoDB/Server.h" role="src" />
+ <file md5sum="fdbedd5ba375592924ef9642594dee4f" name="src/MongoDB/ServerApi.c" role="src" />
+ <file md5sum="db36048a60e83f7b02808097da5f73fc" name="src/MongoDB/ServerDescription.c" role="src" />
+ <file md5sum="e002fc9dbbbccc3a6139b4b9e412ca88" name="src/MongoDB/ServerDescription.h" role="src" />
+ <file md5sum="eaaac065f3e662f931a93b159fe13504" name="src/MongoDB/Session.c" role="src" />
+ <file md5sum="374083edb0982f2547c33e83f4d2ed05" name="src/MongoDB/Session.h" role="src" />
+ <file md5sum="66b2814a84d0c5e10c2e19fe8b9ff827" name="src/MongoDB/TopologyDescription.c" role="src" />
+ <file md5sum="9a1687de6465c1eaf5bf325e3ca0ad48" name="src/MongoDB/TopologyDescription.h" role="src" />
+ <file md5sum="338e4ad14703a5bf7c41ade1064c4772" name="src/MongoDB/WriteConcern.c" role="src" />
+ <file md5sum="2b08c4db364d4a012ab7b2943fb8e568" name="src/MongoDB/WriteConcern.h" role="src" />
+ <file md5sum="f25d93e513b68cab0100a982351eec5e" name="src/MongoDB/WriteConcernError.c" role="src" />
+ <file md5sum="b46861101a81c17fccb3aa38564903cc" name="src/MongoDB/WriteConcernError.h" role="src" />
+ <file md5sum="c31462424849d03050cb5d9e6985e9ab" name="src/MongoDB/WriteError.c" role="src" />
+ <file md5sum="fd1faccf09fa47a68bd3ce3e373464fc" name="src/MongoDB/WriteError.h" role="src" />
+ <file md5sum="3799c93405c1fa842e4a2e7ade43752a" name="src/MongoDB/WriteResult.c" role="src" />
+ <file md5sum="b993163f17bfcf57e270271b58e05866" name="src/MongoDB/WriteResult.h" role="src" />
<file md5sum="ee59b98c49f5b5ee3c3dd7a4a21c3aca" name="src/contrib/php_array_api.h" role="src" />
<file md5sum="d36f9ceb3ac1fc1c5a9e5add685cf12a" name="src/libmongoc/src/common/common-b64-private.h" role="src" />
<file md5sum="66f9014b39f05a20a26d288d51ab5485" name="src/libmongoc/src/common/common-b64.c" role="src" />
<file md5sum="de3c3dfa7949127b9ca6bced2928b728" name="src/libmongoc/src/common/common-config.h" role="src" />
<file md5sum="619956e6cecc5eb8810b568529e2f63a" name="src/libmongoc/src/common/common-config.h.in" role="src" />
<file md5sum="b1207130abc13297c5d711a1974bb2ae" name="src/libmongoc/src/common/common-macros-private.h" role="src" />
<file md5sum="15b3cf122cbd4a57f4477169f367fde9" name="src/libmongoc/src/common/common-md5-private.h" role="src" />
<file md5sum="50917245079095c514f4955c8ea62687" name="src/libmongoc/src/common/common-md5.c" role="src" />
<file md5sum="0918456265baeddaf1234efe7c8ad055" name="src/libmongoc/src/common/common-prelude.h" role="src" />
- <file md5sum="b416ed4aa6cc347183c039142980424a" name="src/libmongoc/src/common/common-thread-private.h" role="src" />
+ <file md5sum="40a58bcc61821c90a05c8d1b296e9b79" name="src/libmongoc/src/common/common-thread-private.h" role="src" />
<file md5sum="0de9014cf70947409e870b48f28f6fcc" name="src/libmongoc/src/common/common-thread.c" role="src" />
<file md5sum="6afe2ac1833309ef5337e5a04945b4d3" name="src/libmongoc/src/kms-message/src/kms_message/kms_b64.h" role="src" />
<file md5sum="d4883934913f8b0693f90207b21bcc8b" name="src/libmongoc/src/kms-message/src/kms_message/kms_caller_identity_request.h" role="src" />
<file md5sum="3a4c30c28593474cb53c81bb30c0b656" name="src/libmongoc/src/kms-message/src/kms_message/kms_decrypt_request.h" role="src" />
<file md5sum="c6dc01b044efe5c7ba582bd36b3f18e0" name="src/libmongoc/src/kms-message/src/kms_message/kms_encrypt_request.h" role="src" />
<file md5sum="9463d1727695035852304d5947d2e86a" name="src/libmongoc/src/kms-message/src/kms_message/kms_message.h" role="src" />
<file md5sum="d00d408056f02b5ad2bd515e6dda4450" name="src/libmongoc/src/kms-message/src/kms_message/kms_message_defines.h" role="src" />
<file md5sum="a3bc2896fca774b80db0c60cdd1ecb60" name="src/libmongoc/src/kms-message/src/kms_message/kms_request.h" role="src" />
<file md5sum="771832eae920dc27ee493a736dcd0f07" name="src/libmongoc/src/kms-message/src/kms_message/kms_request_opt.h" role="src" />
<file md5sum="5341a53253bb71fdde40ef2733eed413" name="src/libmongoc/src/kms-message/src/kms_message/kms_response.h" role="src" />
<file md5sum="5d8416124f251cd69c9b6c37305aed1e" name="src/libmongoc/src/kms-message/src/kms_message/kms_response_parser.h" role="src" />
<file md5sum="001504937a1c62a19d6c1b56fe353eb1" name="src/libmongoc/src/kms-message/src/hexlify.c" role="src" />
<file md5sum="3ae9830c7804a56d602283845ed86651" name="src/libmongoc/src/kms-message/src/hexlify.h" role="src" />
<file md5sum="e8a52f0b2bc3e28f7c64f0a777ce3770" name="src/libmongoc/src/kms-message/src/kms_b64.c" role="src" />
<file md5sum="9cb501a5bfed23a74f5e38be89c1a6d5" name="src/libmongoc/src/kms-message/src/kms_caller_identity_request.c" role="src" />
<file md5sum="9c64a953bbdfa8ba90cbdc1a1d4519c9" name="src/libmongoc/src/kms-message/src/kms_crypto.h" role="src" />
<file md5sum="f4c1b39c72e5f25c7660bd86d87ca85e" name="src/libmongoc/src/kms-message/src/kms_crypto_apple.c" role="src" />
<file md5sum="32436c05f4a3e55cd176a882e21e13ad" name="src/libmongoc/src/kms-message/src/kms_crypto_libcrypto.c" role="src" />
<file md5sum="74b56cf66ea6e9cff053efb192a29add" name="src/libmongoc/src/kms-message/src/kms_crypto_none.c" role="src" />
<file md5sum="37f833a2d0dbb40323de0ddbacd461d6" name="src/libmongoc/src/kms-message/src/kms_crypto_windows.c" role="src" />
<file md5sum="9142dedbdc54951149219e8d7d733e36" name="src/libmongoc/src/kms-message/src/kms_decrypt_request.c" role="src" />
<file md5sum="69ec5d3da1ee1f8d3185854c883cd707" name="src/libmongoc/src/kms-message/src/kms_encrypt_request.c" role="src" />
<file md5sum="2a7f41d0b533d839384c449f05db13c5" name="src/libmongoc/src/kms-message/src/kms_kv_list.c" role="src" />
<file md5sum="69e374f65d9b21695d194e3495941f37" name="src/libmongoc/src/kms-message/src/kms_kv_list.h" role="src" />
<file md5sum="c2189649bce27380a9b07897662901e0" name="src/libmongoc/src/kms-message/src/kms_message.c" role="src" />
<file md5sum="47167d6a5e423a441d7df65d9feda9d7" name="src/libmongoc/src/kms-message/src/kms_message_private.h" role="src" />
- <file md5sum="7b246b6b0a5c36862b79364d8e336b2a" name="src/libmongoc/src/kms-message/src/kms_port.c" role="src" />
+ <file md5sum="e470c7dcd696d7c4a2f401d23e93a218" name="src/libmongoc/src/kms-message/src/kms_port.c" role="src" />
<file md5sum="52247eca34cb25b7d80aad345e393e81" name="src/libmongoc/src/kms-message/src/kms_port.h" role="src" />
<file md5sum="f38035514480120b10b4bcb2c334e2a0" name="src/libmongoc/src/kms-message/src/kms_request.c" role="src" />
<file md5sum="0e650d43199b0e12ffb08b38f54c9b90" name="src/libmongoc/src/kms-message/src/kms_request_opt.c" role="src" />
<file md5sum="4c851b149d17a8d3818de213af8f2d06" name="src/libmongoc/src/kms-message/src/kms_request_opt_private.h" role="src" />
<file md5sum="888bf715d142e373232463eccf0dffcf" name="src/libmongoc/src/kms-message/src/kms_request_str.c" role="src" />
<file md5sum="7d8d321cf69c6316096ca2aab4c9728c" name="src/libmongoc/src/kms-message/src/kms_request_str.h" role="src" />
<file md5sum="ea5d236af2499b31ad2d6b8820376313" name="src/libmongoc/src/kms-message/src/kms_response.c" role="src" />
<file md5sum="2253d59b564ae589d7f0bc6c41626ec2" name="src/libmongoc/src/kms-message/src/kms_response_parser.c" role="src" />
<file md5sum="dff15b5018efb6269a2a0269c5ddb798" name="src/libmongoc/src/kms-message/src/sort.c" role="src" />
<file md5sum="18f9bd055f6a60e7702603b6b8bf07d5" name="src/libmongoc/src/kms-message/src/sort.h" role="src" />
<file md5sum="889d90340a7b3210d087b2a2f02699cf" name="src/libmongoc/src/libbson/src/bson/bcon.c" role="src" />
<file md5sum="af5d3c6890b4fec8709a349289f8f9d3" name="src/libmongoc/src/libbson/src/bson/bcon.h" role="src" />
- <file md5sum="ec0cd6538c9e8b677c1ab78a4a27d15a" name="src/libmongoc/src/libbson/src/bson/bson-atomic.c" role="src" />
- <file md5sum="05384ba5941ab0dde8c10a4a4041dd41" name="src/libmongoc/src/libbson/src/bson/bson-atomic.h" role="src" />
+ <file md5sum="d6e124824ed51206dcab5ddf67bc230e" name="src/libmongoc/src/libbson/src/bson/bson-atomic.c" role="src" />
+ <file md5sum="8d34494ea96177002420f9aeea1fd7e0" name="src/libmongoc/src/libbson/src/bson/bson-atomic.h" role="src" />
<file md5sum="ef3d475df2f82f4fdd78daaf6d754a35" name="src/libmongoc/src/libbson/src/bson/bson-clock.c" role="src" />
<file md5sum="941aa21f16b18e768fd8072a15a4da71" name="src/libmongoc/src/libbson/src/bson/bson-clock.h" role="src" />
<file md5sum="c6a908f8f5612d723e3f81d8a4eb08bd" name="src/libmongoc/src/libbson/src/bson/bson-compat.h" role="src" />
- <file md5sum="6d8a8fc37517108e8b885679da05cb05" name="src/libmongoc/src/libbson/src/bson/bson-config.h" role="src" />
- <file md5sum="7965b311df14db8c4551616872554929" name="src/libmongoc/src/libbson/src/bson/bson-config.h.in" role="src" />
- <file md5sum="5b655a3af4caa6c8369dd000e482292a" name="src/libmongoc/src/libbson/src/bson/bson-context-private.h" role="src" />
- <file md5sum="c0de976cbc811683a25d70fe3c596d95" name="src/libmongoc/src/libbson/src/bson/bson-context.c" role="src" />
- <file md5sum="ac370a2562029eaed0f8b97b0d6fe90f" name="src/libmongoc/src/libbson/src/bson/bson-context.h" role="src" />
+ <file md5sum="0462387cd269514d5e9742b02860cbd3" name="src/libmongoc/src/libbson/src/bson/bson-config.h" role="src" />
+ <file md5sum="1ebb885e9482b3e8d3afaef498ccf209" name="src/libmongoc/src/libbson/src/bson/bson-config.h.in" role="src" />
+ <file md5sum="61e6cd1fe450560f487cabbb69c8de40" name="src/libmongoc/src/libbson/src/bson/bson-context-private.h" role="src" />
+ <file md5sum="2e0640f2ec04abc1210d976393e960b5" name="src/libmongoc/src/libbson/src/bson/bson-context.c" role="src" />
+ <file md5sum="1a25c8d61105c7da95a9563835b8bc3a" name="src/libmongoc/src/libbson/src/bson/bson-context.h" role="src" />
<file md5sum="5840b8ec20580e9fd360a86fbb37baaf" name="src/libmongoc/src/libbson/src/bson/bson-decimal128.c" role="src" />
<file md5sum="6700198519a93ee85b8c95bcddfced30" name="src/libmongoc/src/libbson/src/bson/bson-decimal128.h" role="src" />
- <file md5sum="8bbf15ea4a0155435036722b564ed558" name="src/libmongoc/src/libbson/src/bson/bson-endian.h" role="src" />
+ <file md5sum="07b4f9d909657026cc8261d63084d67b" name="src/libmongoc/src/libbson/src/bson/bson-endian.h" role="src" />
<file md5sum="4f643560fbb549b900ea02d2a7b34484" name="src/libmongoc/src/libbson/src/bson/bson-error.c" role="src" />
<file md5sum="5ee55f4f9a3401900b82a0381ab8f2a8" name="src/libmongoc/src/libbson/src/bson/bson-error.h" role="src" />
<file md5sum="6910b34f7cf6d0b522f548aa2599b490" name="src/libmongoc/src/libbson/src/bson/bson-iso8601-private.h" role="src" />
<file md5sum="4d80e24fadedcfce63799efad8333489" name="src/libmongoc/src/libbson/src/bson/bson-iso8601.c" role="src" />
<file md5sum="e726ae34c8b34e8ab7e414032791160b" name="src/libmongoc/src/libbson/src/bson/bson-iter.c" role="src" />
<file md5sum="1d7b25e4b7051c95da6dda05e8703894" name="src/libmongoc/src/libbson/src/bson/bson-iter.h" role="src" />
<file md5sum="037b65f0f7695a6c779bda5a108b708a" name="src/libmongoc/src/libbson/src/bson/bson-json-private.h" role="src" />
<file md5sum="fbf8b4e7a5a9a15ff1e804c1608137ea" name="src/libmongoc/src/libbson/src/bson/bson-json.c" role="src" />
<file md5sum="cbb1cff3aaa7472a50bb185a455f6544" name="src/libmongoc/src/libbson/src/bson/bson-json.h" role="src" />
<file md5sum="5addb8761faac2e8d52f4ded8ecdc0c0" name="src/libmongoc/src/libbson/src/bson/bson-keys.c" role="src" />
<file md5sum="e1973fc044b52bfc2bb35b440350d228" name="src/libmongoc/src/libbson/src/bson/bson-keys.h" role="src" />
<file md5sum="8dd1917f2dea0d985a707db37494ae78" name="src/libmongoc/src/libbson/src/bson/bson-macros.h" role="src" />
<file md5sum="69c9a5bd0fcdeacffadb994c6d2e9e57" name="src/libmongoc/src/libbson/src/bson/bson-md5.c" role="src" />
<file md5sum="64bfaad7b9c371ac3cc5b19ae0d88fb5" name="src/libmongoc/src/libbson/src/bson/bson-md5.h" role="src" />
<file md5sum="e1ab64fb2919ea159ad8d72a29f5b544" name="src/libmongoc/src/libbson/src/bson/bson-memory.c" role="src" />
<file md5sum="a50cea3f9a11bd1a11448b2b865b656e" name="src/libmongoc/src/libbson/src/bson/bson-memory.h" role="src" />
- <file md5sum="1d11c5001d5975fbed63e11b96edbf49" name="src/libmongoc/src/libbson/src/bson/bson-oid.c" role="src" />
- <file md5sum="1fc22f6fb12d962ff23ba7eebad1c18e" name="src/libmongoc/src/libbson/src/bson/bson-oid.h" role="src" />
+ <file md5sum="8301daa3ba4306b2a89af70c619aa209" name="src/libmongoc/src/libbson/src/bson/bson-oid.c" role="src" />
+ <file md5sum="2e25ec392f12cf4afd970fff2bedacd4" name="src/libmongoc/src/libbson/src/bson/bson-oid.h" role="src" />
<file md5sum="1cf75fbb62bcbe7bfed5906fce7bd0cd" name="src/libmongoc/src/libbson/src/bson/bson-prelude.h" role="src" />
<file md5sum="9173795c678991efc29bec5c95e402b4" name="src/libmongoc/src/libbson/src/bson/bson-private.h" role="src" />
<file md5sum="b351f160949566778783d1ba7a5b4d60" name="src/libmongoc/src/libbson/src/bson/bson-reader.c" role="src" />
<file md5sum="eda7ef0c3380276709b2f8e833867689" name="src/libmongoc/src/libbson/src/bson/bson-reader.h" role="src" />
<file md5sum="fc1eb647810867d1db76dccb3ea3b663" name="src/libmongoc/src/libbson/src/bson/bson-string.c" role="src" />
<file md5sum="84bb7fecb29271e3a8fdc145cb33a77b" name="src/libmongoc/src/libbson/src/bson/bson-string.h" role="src" />
<file md5sum="f80c7197ff122c24f1a2642b083fb523" name="src/libmongoc/src/libbson/src/bson/bson-timegm-private.h" role="src" />
<file md5sum="cf1148af5b260d787b5a8de5ba82de77" name="src/libmongoc/src/libbson/src/bson/bson-timegm.c" role="src" />
- <file md5sum="935dab1bd5d77d1643d5a02583097141" name="src/libmongoc/src/libbson/src/bson/bson-types.h" role="src" />
+ <file md5sum="89ccd18b278677e3f25297a8c3171624" name="src/libmongoc/src/libbson/src/bson/bson-types.h" role="src" />
<file md5sum="4b3ce4f29b9b19e9db849d4a674ad3e4" name="src/libmongoc/src/libbson/src/bson/bson-utf8.c" role="src" />
<file md5sum="f23b07d93c8c65df5c0142f8ede21612" name="src/libmongoc/src/libbson/src/bson/bson-utf8.h" role="src" />
<file md5sum="5db2801d1c52e5027937dd5facab1b3d" name="src/libmongoc/src/libbson/src/bson/bson-value.c" role="src" />
<file md5sum="6d175e5373d24e3f403416b7871be3ca" name="src/libmongoc/src/libbson/src/bson/bson-value.h" role="src" />
<file md5sum="0bcfe98e683ae4fa5a6321fd6cafd9cd" name="src/libmongoc/src/libbson/src/bson/bson-version-functions.c" role="src" />
<file md5sum="0f7724eca64476682b9fd7f7a970cc04" name="src/libmongoc/src/libbson/src/bson/bson-version-functions.h" role="src" />
- <file md5sum="1f391f9ee09d6313a565a6aa4e128d7a" name="src/libmongoc/src/libbson/src/bson/bson-version.h" role="src" />
+ <file md5sum="3f9e5f3a1d5482d58d08929e98b22e96" name="src/libmongoc/src/libbson/src/bson/bson-version.h" role="src" />
<file md5sum="1f473fea4d18c65e7bb00be8bf2e841c" name="src/libmongoc/src/libbson/src/bson/bson-version.h.in" role="src" />
<file md5sum="61ba6f5aa4028b691ee22ea27eb3c3c5" name="src/libmongoc/src/libbson/src/bson/bson-writer.c" role="src" />
<file md5sum="05d85f6ccc42974bc14cf0eab289ebce" name="src/libmongoc/src/libbson/src/bson/bson-writer.h" role="src" />
<file md5sum="42ab62f44421b55736ca0e26e656ae9c" name="src/libmongoc/src/libbson/src/bson/bson.c" role="src" />
<file md5sum="30bce06980f59cd0b2785119a75fe3cf" name="src/libmongoc/src/libbson/src/bson/bson.h" role="src" />
<file md5sum="cc8e625953a6cdb6147172f86f8d0c20" name="src/libmongoc/src/libbson/src/jsonsl/jsonsl.c" role="src" />
<file md5sum="cc4d69576f4fe9b87cd116d399309454" name="src/libmongoc/src/libbson/src/jsonsl/jsonsl.h" role="src" />
<file md5sum="715a53b77739b4f6d87b7236792b3501" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-aggregate-private.h" role="src" />
- <file md5sum="3176cbf8be4a4eb647bd521841e6edfd" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-aggregate.c" role="src" />
+ <file md5sum="648dc84b316f30cfee1e349d23d0cbe4" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-aggregate.c" role="src" />
<file md5sum="d9a75b51a24fee7ec1199d905d143a92" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-apm-private.h" role="src" />
<file md5sum="e9893c44b0a5074b8c98a95813540151" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-apm.c" role="src" />
<file md5sum="790a6172ae0da5905bbbc0dc1c1afd32" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-apm.h" role="src" />
<file md5sum="02429f357ecd89327482930aec8bf34b" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-array-private.h" role="src" />
<file md5sum="475df6bf5cd4e55e0d4b26db29ea71fc" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-array.c" role="src" />
<file md5sum="766374d866c30f32a4e5a313494d7cce" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-async-cmd-private.h" role="src" />
<file md5sum="d39616bfb99494f48a63d8de5f59d9e7" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-async-cmd.c" role="src" />
<file md5sum="6117af585e6f280e22535fee10458148" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-async-private.h" role="src" />
<file md5sum="73f6de02c9db4135e7e7c355ae1a2c40" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-async.c" role="src" />
<file md5sum="5e7c0de09a22745fce5b273d8e9e964c" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-buffer-private.h" role="src" />
<file md5sum="f4b3b177551d2703d24cd5be1add89e6" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-buffer.c" role="src" />
<file md5sum="d099437d7ea96ce3115170be386adceb" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-bulk-operation-private.h" role="src" />
<file md5sum="190e9e9843d5449a86ff5a6a14cb8737" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-bulk-operation.c" role="src" />
<file md5sum="f403a3a84cde66d80a223638f14f5f9f" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-bulk-operation.h" role="src" />
<file md5sum="178d695599ed8eb98de6672aff1ca0bc" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-change-stream-private.h" role="src" />
- <file md5sum="0bf4a126adc047c7d1b8d6d8026145eb" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-change-stream.c" role="src" />
+ <file md5sum="98e5ebfb273118744c8c808dd362f7b1" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-change-stream.c" role="src" />
<file md5sum="a28176a567c6cd9b3e06246256c7ac7d" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-change-stream.h" role="src" />
<file md5sum="dd048997f3230e0f019ad17ecfcf9dfd" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-pool-private.h" role="src" />
- <file md5sum="cd52c9821d61ad47db14f17c770df00f" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-pool.c" role="src" />
- <file md5sum="98a0b219dd0bd2455058315ea2dc20b4" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-pool.h" role="src" />
- <file md5sum="dcab21f430ac445f7a80c8f94c7e35c6" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-private.h" role="src" />
+ <file md5sum="b72259ca1a8d2cac04b988e34eed3346" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-pool.c" role="src" />
+ <file md5sum="b7ec158f7e0c1f298aefaa9bdeb41563" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-pool.h" role="src" />
+ <file md5sum="14b66b6f1433f8dd36dad38102f12dac" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-private.h" role="src" />
<file md5sum="be1f432f9f37b512ecd98c1c21e6ff05" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-session-private.h" role="src" />
<file md5sum="0de5b07694d64591f176f100e4557810" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-session.c" role="src" />
<file md5sum="3d591f816481c1584c3aa1f870b42aea" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-session.h" role="src" />
<file md5sum="829e08021e4b012a3df657e9d3745aed" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-side-encryption-private.h" role="src" />
<file md5sum="8dfb1264e95c1ca51d236703979fe590" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-side-encryption.c" role="src" />
<file md5sum="b5be0a43bc59dc23fea512cd25d3fbf7" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-client-side-encryption.h" role="src" />
- <file md5sum="b8f11f89342bbdd53489ffa6b560c1c0" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-client.c" role="src" />
- <file md5sum="77a6d994588e947c2d65f2c4ac7ed73c" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-client.h" role="src" />
+ <file md5sum="28b37e67f9e183c94496ed239ceb1cc4" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-client.c" role="src" />
+ <file md5sum="a1b1212bb6ae352f4d6cd67651bf4990" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-client.h" role="src" />
<file md5sum="ea98e4e4ae56c176e8286f3373b93872" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-cluster-aws-private.h" role="src" />
<file md5sum="b33a55893a9031048815f4bf7bde06fe" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-cluster-aws.c" role="src" />
<file md5sum="abc87a40623b01a2848a13483f55c0eb" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-cluster-cyrus-private.h" role="src" />
<file md5sum="6ceb56409fb779b40887d8c597ae585d" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-cluster-cyrus.c" role="src" />
- <file md5sum="f10a1fcc37f3bb920a3f2d042af1a5ec" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-cluster-private.h" role="src" />
+ <file md5sum="ebd5c2aba2df20f73a0a663726e4fcec" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-cluster-private.h" role="src" />
<file md5sum="7b7c909f1fa7029ea48d4d06e18c23a1" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-cluster-sasl-private.h" role="src" />
<file md5sum="9c05f27fa8164bfdb5b9d9d2afd7c8ec" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-cluster-sasl.c" role="src" />
<file md5sum="820290eb3904bfc15d4b8bd246407472" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-cluster-sspi-private.h" role="src" />
<file md5sum="9d09cad4e1c89c4f22540ecbf58b6f8a" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-cluster-sspi.c" role="src" />
- <file md5sum="eec8e22d212d66c645cfced79b9378a2" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-cluster.c" role="src" />
+ <file md5sum="d43168f26bc6f50b83858fa904b54f39" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-cluster.c" role="src" />
<file md5sum="83eee40cd11208e81a44593e173464a7" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-cmd-private.h" role="src" />
- <file md5sum="ad068dc673e23d9cb944051097ddb79b" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-cmd.c" role="src" />
+ <file md5sum="e2a1834c201488ad8d5d16992dc58ae0" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-cmd.c" role="src" />
<file md5sum="7be3fb1fffde65a0a4f9864cc666585f" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-collection-private.h" role="src" />
- <file md5sum="03936c707246bd2eeb260dfec410ae2a" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-collection.c" role="src" />
+ <file md5sum="280ac84e5c3a1220231e5aa073043e9c" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-collection.c" role="src" />
<file md5sum="2cea9224f2c11ca0048d3faf871f3e43" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-collection.h" role="src" />
<file md5sum="51a5f2b055faf65386ed28d537af94e2" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-compression-private.h" role="src" />
<file md5sum="c8efb75e7a6278b654502ad1f16b5e50" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-compression.c" role="src" />
- <file md5sum="d74b6e72f5dccd4b936af1f5715303dd" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-config.h" role="src" />
- <file md5sum="fb670b99174d436ab00fa4976585e9d1" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-config.h.in" role="src" />
- <file md5sum="2016a0e8dcf25bd621ff4e2d1b0ccea0" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-counters-private.h" role="src" />
+ <file md5sum="d347554bc29b7c2687a51c2ac01b355e" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-config.h" role="src" />
+ <file md5sum="2626cb59611d7ff06184fdf3d59deff7" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-config.h.in" role="src" />
+ <file md5sum="83b01f3ae0287022e4c5b4dbe0512904" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-counters-private.h" role="src" />
<file md5sum="0e75630e4d381fba80801afc10811173" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-counters.c" role="src" />
<file md5sum="04d57743da7337aaec4dfe958a5742b7" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-counters.defs" role="src" />
<file md5sum="d1111578a21c720b026904bb1e3ae223" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-crypt-private.h" role="src" />
<file md5sum="c25a245ac4db12e014ddd4bfe67bf27b" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-crypt.c" role="src" />
<file md5sum="92fd26e85664f6c9d2d369c0fadc025b" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-crypto-cng-private.h" role="src" />
<file md5sum="4962154517e614c682f72ec91a2dfb21" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-crypto-cng.c" role="src" />
<file md5sum="b3e1538050bff40cd2232ccc57978580" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-crypto-common-crypto-private.h" role="src" />
<file md5sum="05bc88780422e1fecf959938dba4f37c" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-crypto-common-crypto.c" role="src" />
<file md5sum="b8182112c242fe00bfb665e7b7af8d09" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-crypto-openssl-private.h" role="src" />
- <file md5sum="0b30ddc797dd00fdcaf2a7d947d97c85" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-crypto-openssl.c" role="src" />
+ <file md5sum="45f55e6aa1c9ca8dd427bd45c28f50ed" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-crypto-openssl.c" role="src" />
<file md5sum="d917683855b94173416b062df755d960" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-crypto-private.h" role="src" />
<file md5sum="2dc0df9846f851aead72d9fd4d734760" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-crypto.c" role="src" />
<file md5sum="f1f255dcc6c9c9abc06423b00553a660" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor-array.c" role="src" />
<file md5sum="f39ea72235be77d77a30ad06c15be5b4" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor-change-stream.c" role="src" />
<file md5sum="13772036c14fa28597bae438270f5494" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor-cmd-deprecated.c" role="src" />
- <file md5sum="f68c43de1d7d090b6d9dc0d8f73911f5" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor-cmd.c" role="src" />
+ <file md5sum="34522fc38976abd9e0ea6fbfce136a98" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor-cmd.c" role="src" />
<file md5sum="436a0c9fea83bc37dfde5b82044db2de" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor-find-cmd.c" role="src" />
<file md5sum="d4664b89578808b1581a6a971e47f49e" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor-find-opquery.c" role="src" />
- <file md5sum="d2e19c9e8b69b30b2cf19639975cd51b" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor-find.c" role="src" />
+ <file md5sum="7f05b5ea17fabe3535bc9bff4287c694" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor-find.c" role="src" />
<file md5sum="1eb05f279e142f8ba2d98234dc65bf9c" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor-legacy.c" role="src" />
- <file md5sum="7ca9d83ba28d474e461fb9465ddb7c6b" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor-private.h" role="src" />
- <file md5sum="a822200c769567cbcd15613c5262989d" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor.c" role="src" />
+ <file md5sum="ada83d26ea3f38bde4ee190b94ef4823" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor-private.h" role="src" />
+ <file md5sum="2fb83683c83eac38e3aa32052b38736c" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor.c" role="src" />
<file md5sum="ab02e4cb247e4dedbf49e30b4b02e193" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-cursor.h" role="src" />
<file md5sum="cf20c0277c2b973281325739721d635b" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-cyrus-private.h" role="src" />
<file md5sum="5c67ae23fe25b60c480c4955af75dfe2" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-cyrus.c" role="src" />
<file md5sum="31a9b3420812c03b4446dd9ab13f222d" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-database-private.h" role="src" />
<file md5sum="46104d074e3c88a22e968d7148d6f22a" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-database.c" role="src" />
<file md5sum="8b34d317248c622bf08e1fe26dddf437" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-database.h" role="src" />
<file md5sum="28d90894b4e7c78bef2b1ca1834d0fcb" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-errno-private.h" role="src" />
<file md5sum="768d0fbe35f8ba072ca468716d6bfe98" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-error-private.h" role="src" />
<file md5sum="7958f96545cdfd6141f233b92f446cf7" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-error.c" role="src" />
<file md5sum="f40e2b5ae830e43faf63d180d2e55b6b" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-error.h" role="src" />
<file md5sum="1ba39aca81a5d25857b77542e307b97b" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-find-and-modify-private.h" role="src" />
<file md5sum="d0253ef5feb5587064d86eeb19577a1c" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-find-and-modify.c" role="src" />
<file md5sum="4baf895100d5eeffe2fde56396a06b08" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-find-and-modify.h" role="src" />
<file md5sum="75af2dc3e1069036fb8d78c1a94ca3c8" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-flags-private.h" role="src" />
<file md5sum="dcb65a56ce1b685779763817f44c5581" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-flags.h" role="src" />
<file md5sum="678c516515546e641e5eca6cfce0ee48" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-generation-map-private.h" role="src" />
<file md5sum="cd7f1914be3de0388504ac87a199e0d2" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-generation-map.c" role="src" />
<file md5sum="61a20bbf13213628a988af242bec479b" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-bucket-file-private.h" role="src" />
<file md5sum="a805e8f77e86cb9b806c48b6677a8ec8" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-bucket-file.c" role="src" />
<file md5sum="58fcf3011bfd394f310f3daa9594855b" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-bucket-private.h" role="src" />
<file md5sum="916ebb08602002a944ccb104b02f8ca4" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-bucket.c" role="src" />
<file md5sum="9ae55fdb24c8d042514b4beaeffbbc37" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-bucket.h" role="src" />
<file md5sum="952b93d5ee76b7402ea500906809161b" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-file-list-private.h" role="src" />
<file md5sum="8597d29f134e6d78cb6a34ea74423bab" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-file-list.c" role="src" />
<file md5sum="869dae5d01adf048bb1299cca4afba84" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-file-list.h" role="src" />
<file md5sum="282f5e691bb325deb6b8891eb13149f2" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-file-page-private.h" role="src" />
<file md5sum="6f0ed4d860816a02bfd98c9b50340227" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-file-page.c" role="src" />
<file md5sum="3b932d73546d72dae9fcb918c41de57d" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-file-page.h" role="src" />
<file md5sum="c03dd7e85d3095caf235744ebb562a0e" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-file-private.h" role="src" />
<file md5sum="3a40c1bac045fbcf2cc6cfa985be4c56" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-file.c" role="src" />
<file md5sum="4391ad3ca3396e9fc9b4c0c4e5772bfb" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-file.h" role="src" />
<file md5sum="ef7007f002b46c8354fee538e885de40" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs-private.h" role="src" />
<file md5sum="8a825992520617af35e9bddb0aabe9c6" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs.c" role="src" />
<file md5sum="d20582bf915d78253359a937ed28bbea" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-gridfs.h" role="src" />
<file md5sum="bbc260b536678d5331744aee0c186256" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-handshake-compiler-private.h" role="src" />
<file md5sum="67039f2c6bc58df9e35fcb0cab2c2dbc" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-handshake-os-private.h" role="src" />
<file md5sum="1814373012d79db5741434170a2b6fee" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-handshake-private.h" role="src" />
- <file md5sum="f487bd42d0673750a268e5a66ccd6759" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-handshake.c" role="src" />
+ <file md5sum="5bfc06e8d27d29ccc1b8417c83caf86c" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-handshake.c" role="src" />
<file md5sum="fa8bc2ce220ac698bc154b1b245750cd" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-handshake.h" role="src" />
- <file md5sum="4fb133fd139b69892eea86eec693fac2" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-host-list-private.h" role="src" />
- <file md5sum="08a38ce358289afe1d3946fd121d2fa9" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-host-list.c" role="src" />
+ <file md5sum="7c57b5152a74508c5ff78f14b2f1ffea" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-host-list-private.h" role="src" />
+ <file md5sum="48b031f3f051bfd4c8f014a1f8a6aa86" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-host-list.c" role="src" />
<file md5sum="5e2da30e912e909ed594a59683833f7d" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-host-list.h" role="src" />
<file md5sum="c1934ce90e02b46a05a9a4751dbc0262" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-http-private.h" role="src" />
<file md5sum="552f945bb02a4c698a66608dd30f1fe1" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-http.c" role="src" />
<file md5sum="5ac6b6febc5f47878215fbc74bd44de7" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-index.c" role="src" />
<file md5sum="dad1a4af8adf72a13809fd6c1c10afee" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-index.h" role="src" />
<file md5sum="9a065aa2944698f9d0f64496cd59c8bd" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-init.c" role="src" />
<file md5sum="747ea7ab1744daf2a7e42508780575b1" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-init.h" role="src" />
<file md5sum="3502d9809ba3e5866ce10037c4b3563c" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-interrupt-private.h" role="src" />
<file md5sum="3177cbfad1c5079952840fbb4c4dfbe4" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-interrupt.c" role="src" />
<file md5sum="c3d4de8405f528f15caf2ab7f847ca12" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-iovec.h" role="src" />
<file md5sum="c06c20bc7e775d6d8bced165cd04f8ee" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-libressl-private.h" role="src" />
<file md5sum="0c90387fd3fe9289c20cf4354d6bd87e" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-libressl.c" role="src" />
<file md5sum="8c0701b9c767f009ba52d7231059d12b" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-linux-distro-scanner-private.h" role="src" />
<file md5sum="54d78d18718c9b8705de0862b931f476" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-linux-distro-scanner.c" role="src" />
<file md5sum="88813fcf803fccf84966f26431b3b71a" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-list-private.h" role="src" />
<file md5sum="ab4d31b167f229b490faf5b71a714339" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-list.c" role="src" />
<file md5sum="be914702b66b1e1b8582cb9277239001" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-log-private.h" role="src" />
- <file md5sum="66c266ba76993a4d149db3b849ab6d0e" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-log.c" role="src" />
+ <file md5sum="7df5c2164e44e9f2697de0833ceb53cf" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-log.c" role="src" />
<file md5sum="1c741c1aed2b563cacb6bced8e97d0b0" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-log.h" role="src" />
<file md5sum="439f25680fbc4c8a7542502287e3675e" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-macros.h" role="src" />
<file md5sum="5a3506bda8c1638be4b76999c3c50f12" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-matcher-op-private.h" role="src" />
<file md5sum="e3555fc6a1007c07d55f4f210097d689" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-matcher-op.c" role="src" />
<file md5sum="dd1d23edde3907521792649267b48bc3" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-matcher-private.h" role="src" />
<file md5sum="cf91b7fcfb80ccaa33329d6bf14f8fbc" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-matcher.c" role="src" />
<file md5sum="30f6ed82f9988d2e4485e6fd23632d02" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-matcher.h" role="src" />
<file md5sum="86736045e6dcc91d8c525c87720b2911" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-memcmp-private.h" role="src" />
<file md5sum="cc510669bc8cdbfab031f54e143085e2" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-memcmp.c" role="src" />
<file md5sum="a5d748bdf1c4b5cb845c6a81370d7961" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-ocsp-cache-private.h" role="src" />
<file md5sum="f2c3545733f228d2457f64373ee5831b" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-ocsp-cache.c" role="src" />
<file md5sum="14f209fb86ed514cdde4b187d35ac83b" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-opcode.h" role="src" />
<file md5sum="810df1337011be8f15d0719f1e03d798" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-openssl-private.h" role="src" />
<file md5sum="e429f31c6f1d66a0ac819f2a27adee72" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-openssl.c" role="src" />
<file md5sum="eb42adc455bdb25e9180243e56cdd812" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-optional.c" role="src" />
<file md5sum="f90b93bf8d4e15329353b361b19eb1e5" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-optional.h" role="src" />
<file md5sum="eb48d60cbcae6ce34b3b1b3edc3b9e73" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-opts-helpers-private.h" role="src" />
<file md5sum="abae85a1d96099484ea092abd7459a6a" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-opts-helpers.c" role="src" />
<file md5sum="6ac236f005b1b09c334689d9257aef04" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-opts-private.h" role="src" />
<file md5sum="cfb8187dc6e8a2f3d6a700cb435792fa" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-opts.c" role="src" />
<file md5sum="a5a16bf330ec389692145c0a0f796d40" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-prelude.h" role="src" />
<file md5sum="9d479bd2f13f239d558616322f8b4fb6" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-queue-private.h" role="src" />
<file md5sum="7da2ed3fabbeee9a88c7ddeab9f11a20" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-queue.c" role="src" />
<file md5sum="fa9297dcbff7191c36b6fb2b2a5a9c91" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-rand-cng.c" role="src" />
<file md5sum="b8818c8c7c155272ab33a04dfb0c464c" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-rand-common-crypto.c" role="src" />
<file md5sum="12887a2170ee9f8678c22675ac706b03" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-rand-openssl.c" role="src" />
<file md5sum="d665e822fefc6c01c4dd9ee4d1a02f2b" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-rand-private.h" role="src" />
<file md5sum="41c7cd3177c60893f4eec6b144ceedc9" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-rand.h" role="src" />
<file md5sum="a9abe88c57feeade91e4617b1582ea84" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-read-concern-private.h" role="src" />
<file md5sum="f877494d6f2aacb31a7aab8f2e46c911" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-read-concern.c" role="src" />
<file md5sum="6e1554a4f43b405f70bbf2c59ead73dd" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-read-concern.h" role="src" />
<file md5sum="a200756c4228fc0675ab5e7057546068" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-read-prefs-private.h" role="src" />
- <file md5sum="024ad5f92fd0ac2c62b3024c2afaa249" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-read-prefs.c" role="src" />
- <file md5sum="2cdc8a9ab7a2ae04bda53545ce01ce73" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-read-prefs.h" role="src" />
+ <file md5sum="26b9e46531eb411d8100ce1244e17bde" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-read-prefs.c" role="src" />
+ <file md5sum="39494b56050754f341ac9e1aa259b8a6" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-read-prefs.h" role="src" />
<file md5sum="14d70d8935bf21f4c3239e45d86f4e6e" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-rpc-private.h" role="src" />
<file md5sum="4346415ce0acd31256f6c337054946b8" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-rpc.c" role="src" />
<file md5sum="02680a898c086020b12d6efdcefaef1b" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-sasl-private.h" role="src" />
<file md5sum="f12439745ff93ee7d533b34cdfd76fdf" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-sasl.c" role="src" />
<file md5sum="fb161be2bdaf05d53d5e8e4bb4760b0a" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-scram-private.h" role="src" />
<file md5sum="0dd217d6feb694507b2c572b4f2e0762" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-scram.c" role="src" />
<file md5sum="b2795ae4c107dbbc11aa3d97d0c61d84" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-secure-channel-private.h" role="src" />
<file md5sum="7091fbaa03b9dcfd7f2c26a798ab0ad8" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-secure-channel.c" role="src" />
<file md5sum="a6abefa0bc83ec37be8176b2df7de977" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-secure-transport-private.h" role="src" />
<file md5sum="791823b6db4e4901f985450b553a65ca" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-secure-transport.c" role="src" />
<file md5sum="b3dc46ca7adc34861ea6e9c45e50b05b" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-api-private.h" role="src" />
<file md5sum="af60f4e10e4dc9c35f421a5601169d4d" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-api.c" role="src" />
<file md5sum="78dfc9819e8f8bc83a71b53404eadf3c" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-api.h" role="src" />
<file md5sum="e49225578378e16850bb21e4027e25b0" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-description-private.h" role="src" />
<file md5sum="fb336c049ea18c8b2826ddaa9a859bdf" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-description.c" role="src" />
<file md5sum="cc8bf5c6bc4fdc600a2455ea4c236259" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-description.h" role="src" />
<file md5sum="e75b07c14e3879fb67832dd839de29e0" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-monitor-private.h" role="src" />
- <file md5sum="e0bc3c9ac59eb556207812f0d78fd8bf" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-monitor.c" role="src" />
- <file md5sum="03bd5c9d7835ffba2717baf8e565c98b" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-stream-private.h" role="src" />
- <file md5sum="ffc10eef8451934a6ff8169a86b6bfa7" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-stream.c" role="src" />
+ <file md5sum="2b970c294a8f7ee7d4e0f0c2b93bb649" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-monitor.c" role="src" />
+ <file md5sum="63f17f6ae6d2f79dcbdf2113c7db20fb" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-stream-private.h" role="src" />
+ <file md5sum="f1af771373ac1bdcb03a6fbb6358e74d" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-server-stream.c" role="src" />
<file md5sum="cede4eeffec68b7ada9b86cf41955c74" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-set-private.h" role="src" />
<file md5sum="e273f247bdd66f3e66dd96c218b01d9c" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-set.c" role="src" />
<file md5sum="bd017efd5e6206fb55a3ac7306a95f24" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-shared-private.h" role="src" />
<file md5sum="bcd3b9c778ecf5639a06be567674d340" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-shared.c" role="src" />
<file md5sum="37376243128180b5b0d7eacef659f3d6" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-socket-private.h" role="src" />
- <file md5sum="5f4dc323b7a0419b6a6f22ae1fcf95af" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-socket.c" role="src" />
+ <file md5sum="16b1377ba13959205b9ee171e49edeb1" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-socket.c" role="src" />
<file md5sum="3f61c4bf2a022ee0a3d85154a5bee770" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-socket.h" role="src" />
<file md5sum="41500393a9c5ffdb8cc7c66c4a1960c0" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-ssl-private.h" role="src" />
<file md5sum="b463a4cff8d5d424c62c726aaa657982" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-ssl.c" role="src" />
<file md5sum="42c133e3ad18a70058177091190401fd" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-ssl.h" role="src" />
<file md5sum="cc755861d5be912193591ad063bcad48" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-sspi-private.h" role="src" />
<file md5sum="11a45877cdfc2df905aa0d162bb493b7" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-sspi.c" role="src" />
<file md5sum="cc3fc77850ae4bea293bd74b4cf60a04" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-buffered.c" role="src" />
<file md5sum="9b245df6c45d411766be5f7290e8da04" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-buffered.h" role="src" />
<file md5sum="f25a6cc9eeb840f34847f81cc2f36b60" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-file.c" role="src" />
<file md5sum="4ce12f6db0b74f55d3c49c34332b6f7d" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-file.h" role="src" />
<file md5sum="dc85d644079ad2e79d9d9dbe49facf10" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-gridfs-download-private.h" role="src" />
<file md5sum="131246e2d632381ce14d72fdbb1b3f21" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-gridfs-download.c" role="src" />
<file md5sum="7c0cce0559efc51ffe81a5465aa41484" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-gridfs-upload-private.h" role="src" />
<file md5sum="b2eb639aae1caed00f7032b27e73cfbd" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-gridfs-upload.c" role="src" />
<file md5sum="d247dac07fdfffa79422f0682f546a77" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-gridfs.c" role="src" />
<file md5sum="f66d645623c5b2ba02e6afe1cc0b00df" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-gridfs.h" role="src" />
<file md5sum="fa30b8c754b1523186b0c0c19bf017dc" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-private.h" role="src" />
<file md5sum="3dbc0c52c735d318b3efbedb25a6005e" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-socket.c" role="src" />
<file md5sum="c25f4029b8bbb9990ffe947511a4d534" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-socket.h" role="src" />
<file md5sum="90ec84cb182c98c7fc8fa8af0e85bdf0" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-libressl-private.h" role="src" />
<file md5sum="116918bf8bb96c6f9165c13a4c1096a7" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-libressl.c" role="src" />
<file md5sum="986de196a5775636248360a89ac342ce" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-libressl.h" role="src" />
<file md5sum="3fd16580fa667309339b94b19a396b9e" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-openssl-bio-private.h" role="src" />
<file md5sum="f72dd2878dcd9333a138e6c62adcd971" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-openssl-bio.c" role="src" />
<file md5sum="377279ab2c57036be34ac0b8684d74c8" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-openssl-private.h" role="src" />
<file md5sum="98c94302efb2e4d3198d9de9390c00b6" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-openssl.c" role="src" />
<file md5sum="d304866f9dfa3e2372b0e94abf58452f" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-openssl.h" role="src" />
<file md5sum="cfdd7f4e9b7619ec17a2af509ca99714" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-private.h" role="src" />
<file md5sum="8df0fd4f5dc00181e9ebbe3eef3f321e" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel-private.h" role="src" />
<file md5sum="f5bff5eaedc38a85fd334045e0f95b31" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c" role="src" />
<file md5sum="a548717b6ae53390c8f44dcb02c5af18" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.h" role="src" />
<file md5sum="0d18b0e579e693ff1e484632a7ffbe3c" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-transport-private.h" role="src" />
<file md5sum="6c7f4e134ef9fbe5ece63ede7b34e618" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-transport.c" role="src" />
<file md5sum="db9560efe8c38948cf3d0935566475c4" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-transport.h" role="src" />
<file md5sum="b4c2290ab76580b8428b18ada4760f53" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls.c" role="src" />
<file md5sum="7cf653c627cc7708161dbb9c2cad7f1e" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream-tls.h" role="src" />
<file md5sum="77d9779c925cbdcc010c708ceff13495" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream.c" role="src" />
<file md5sum="e8a3b99226da0b724dd3e01f845f3207" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-stream.h" role="src" />
<file md5sum="b5ceb7c14c3ca2c2407d80a2db2d28d0" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-thread-private.h" role="src" />
<file md5sum="3773c7ef3ac14e7f138fdb1182f91e80" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-timeout-private.h" role="src" />
<file md5sum="eb72065aec6b9338f3300f5ab638f375" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-timeout.c" role="src" />
<file md5sum="acaa4ec85c67a8aa87a89c11da253c3c" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-background-monitoring-private.h" role="src" />
<file md5sum="5d151338cb01096ebbef9d961bd98ae2" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-background-monitoring.c" role="src" />
<file md5sum="395d5e3342ba5a943413926f65ccc9a1" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-description-apm-private.h" role="src" />
<file md5sum="9e33bee391288851c85bbf348c5a6056" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-description-apm.c" role="src" />
- <file md5sum="8e91ddfe8f03801e096a4d6a371c8c57" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-description-private.h" role="src" />
- <file md5sum="dc42ce4b2af0e60235464ac5e7c17d6d" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-description.c" role="src" />
+ <file md5sum="c8960b386615370139dcb753f6006fb3" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-description-private.h" role="src" />
+ <file md5sum="00c18293e63fa882bafaed3d94216534" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-description.c" role="src" />
<file md5sum="7216b55e1e9684b298b54af143edd9a6" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-description.h" role="src" />
- <file md5sum="4c0b134e952c324553286c52aafbeeac" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-private.h" role="src" />
- <file md5sum="2d95f06e43d5e8ea5039d4cd17f07f72" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-scanner-private.h" role="src" />
- <file md5sum="424fd98fc6fc3fbc40271f576e4d8d88" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-scanner.c" role="src" />
- <file md5sum="e96dc19126d0acb3c343b7e88bfc516e" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology.c" role="src" />
- <file md5sum="fa4f353bf23ccae90497d2ef82b8b35f" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-trace-private.h" role="src" />
+ <file md5sum="4030cc8fd66093079f6ad356582490c0" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-private.h" role="src" />
+ <file md5sum="ef81ed481d1c1290f10e4e54db2980da" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-scanner-private.h" role="src" />
+ <file md5sum="0e0c077ce62414d05e9c775f48a533d5" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology-scanner.c" role="src" />
+ <file md5sum="47c012bf597764130b7da8501e0227f1" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-topology.c" role="src" />
+ <file md5sum="74353ddb00d3f8a4d5423dc86a5be7e0" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-trace-private.h" role="src" />
<file md5sum="10fbbc3cf1ba5c22883635e3bca4d2d0" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-ts-pool-private.h" role="src" />
<file md5sum="e34b16cbe4d47974b6bb9182c4b605bb" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-ts-pool.c" role="src" />
- <file md5sum="51468c1c1c582aff492bfb815027aefa" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-uri-private.h" role="src" />
- <file md5sum="5d9df98d337f3d142f388b0370fec8df" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-uri.c" role="src" />
- <file md5sum="3f50b4152d7bdd42ef4a00fd9d21bb8f" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-uri.h" role="src" />
- <file md5sum="36756a32548761c8b2ba3ce1da0ffa30" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-util-private.h" role="src" />
- <file md5sum="9b860052032d9930494e517b5e4f302e" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-util.c" role="src" />
+ <file md5sum="2d0158d029d00435eaf3b98fdd9f1c3b" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-uri-private.h" role="src" />
+ <file md5sum="00ebae12fca5c180c653f10da08ff6dc" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-uri.c" role="src" />
+ <file md5sum="ec8a82d2d8c002b1517fee400464e7cc" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-uri.h" role="src" />
+ <file md5sum="b415b8bf55bcb220c31f0db30b6422f4" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-util-private.h" role="src" />
+ <file md5sum="fbca4cc6014a2272f04607ed27d04a29" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-util.c" role="src" />
<file md5sum="5c7c2a82e500e9a518fa596ff9c44021" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-version-functions.c" role="src" />
<file md5sum="c7cfe57411c17d6d3028ee180f1772e9" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-version-functions.h" role="src" />
- <file md5sum="cdd2323c2992973618214afb47aafa57" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-version.h" role="src" />
+ <file md5sum="98de9dc51da20da2e319c0c437c89019" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-version.h" role="src" />
<file md5sum="ff10fb268641d60f7b14f911208fb2b1" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-version.h.in" role="src" />
<file md5sum="0808798e16ae4d6d7d8d01df40a54052" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-write-command-legacy-private.h" role="src" />
<file md5sum="6130f80234c368dcb70cf713b8effbc4" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-write-command-legacy.c" role="src" />
<file md5sum="ee107bf849dd6644a6453a395651c2d0" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-write-command-private.h" role="src" />
<file md5sum="c526d42415961800fb727d241b4863ea" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-write-command.c" role="src" />
<file md5sum="e5bce2b46dbf04b76fe5485db9de7e4e" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-write-concern-private.h" role="src" />
<file md5sum="2b01095b4919618f6d33b2c418c29455" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-write-concern.c" role="src" />
<file md5sum="d777c85e5593d047218fef92f7ab5434" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc-write-concern.h" role="src" />
<file md5sum="22b9dfd9aacdbca888e8fb7a71dfe4f7" name="src/libmongoc/src/libmongoc/src/mongoc/mongoc.h" role="src" />
<file md5sum="f3e25b8f4865b4ff5ce5830870d8cec5" name="src/libmongoc/src/libmongoc/src/mongoc/op-compressed.def" role="src" />
<file md5sum="ed1890accd7d9a1426fdac121ed42ad4" name="src/libmongoc/src/libmongoc/src/mongoc/op-delete.def" role="src" />
<file md5sum="9af88adf2ef432761bbe81db2f9bdce7" name="src/libmongoc/src/libmongoc/src/mongoc/op-get-more.def" role="src" />
<file md5sum="242fff22640f143ae262e363e8552a7e" name="src/libmongoc/src/libmongoc/src/mongoc/op-header.def" role="src" />
<file md5sum="2efe34631dd0d540d0f1d2fdb2d57813" name="src/libmongoc/src/libmongoc/src/mongoc/op-insert.def" role="src" />
<file md5sum="79ab986cb49a47e7c9bccdc4005a9697" name="src/libmongoc/src/libmongoc/src/mongoc/op-kill-cursors.def" role="src" />
<file md5sum="7e1f1d29f10ca2b86aed48b4071b9800" name="src/libmongoc/src/libmongoc/src/mongoc/op-msg.def" role="src" />
<file md5sum="a986d22cb495d652dc6059d722bb3266" name="src/libmongoc/src/libmongoc/src/mongoc/op-query.def" role="src" />
<file md5sum="f82bc931404ce00b318675126572d667" name="src/libmongoc/src/libmongoc/src/mongoc/op-reply-header.def" role="src" />
<file md5sum="dd22bb15cb70d35fe25192f0f304871b" name="src/libmongoc/src/libmongoc/src/mongoc/op-reply.def" role="src" />
<file md5sum="03c6179a4fe8b51c606b03a763529d55" name="src/libmongoc/src/libmongoc/src/mongoc/op-update.def" role="src" />
<file md5sum="28e467e1c2bfe811edfcfc86662f3987" name="src/libmongoc/src/libmongoc/src/mongoc/utlist.h" role="src" />
<file md5sum="4dc406b7d1b6e49c22eee2e01177c195" name="src/libmongoc/src/zlib-1.2.11/adler32.c" role="src" />
<file md5sum="bca8dc2f982dfce8944aec9f4a83626c" name="src/libmongoc/src/zlib-1.2.11/compress.c" role="src" />
<file md5sum="f9a17af8e4efe8019fca94827ea1c0db" name="src/libmongoc/src/zlib-1.2.11/crc32.c" role="src" />
<file md5sum="f28d16b67efecdfafa0d816a7d982124" name="src/libmongoc/src/zlib-1.2.11/crc32.h" role="src" />
<file md5sum="9e645d2cc17f3e324028b90d25edc969" name="src/libmongoc/src/zlib-1.2.11/deflate.c" role="src" />
<file md5sum="c5839b3f66d79c5aa0daa5062de59bd5" name="src/libmongoc/src/zlib-1.2.11/deflate.h" role="src" />
<file md5sum="29d02cff161bde3e4e717b25a2ab7050" name="src/libmongoc/src/zlib-1.2.11/gzclose.c" role="src" />
<file md5sum="de472a3069a84c6e6b1eb083c3f91b53" name="src/libmongoc/src/zlib-1.2.11/gzguts.h" role="src" />
<file md5sum="2c08acd5014596272031fdd1a36d0f1c" name="src/libmongoc/src/zlib-1.2.11/gzlib.c" role="src" />
<file md5sum="a2a2f3a65c2891b1a8cf98be9b499e96" name="src/libmongoc/src/zlib-1.2.11/gzread.c" role="src" />
<file md5sum="92c3520553ac47aaa67f36ac9a571761" name="src/libmongoc/src/zlib-1.2.11/gzwrite.c" role="src" />
<file md5sum="f2adcadab3504b146be9c4928821f233" name="src/libmongoc/src/zlib-1.2.11/infback.c" role="src" />
<file md5sum="20d7b26f5ae64f4e8501f846beab550c" name="src/libmongoc/src/zlib-1.2.11/inffast.c" role="src" />
<file md5sum="f3669099d3f571dbc0426401ed5f50e3" name="src/libmongoc/src/zlib-1.2.11/inffast.h" role="src" />
<file md5sum="7fa3e91804601b6618c915b76a8dc332" name="src/libmongoc/src/zlib-1.2.11/inffixed.h" role="src" />
<file md5sum="c892c303a1be104ed0efb628e18ed85a" name="src/libmongoc/src/zlib-1.2.11/inflate.c" role="src" />
<file md5sum="12c1f3adaf005c8a4cfb629f2e266d30" name="src/libmongoc/src/zlib-1.2.11/inflate.h" role="src" />
<file md5sum="34a634c4c6e1de2e357f18c170e6b96c" name="src/libmongoc/src/zlib-1.2.11/inftrees.c" role="src" />
<file md5sum="ec87be89b9bcca8ced80a70f857e823b" name="src/libmongoc/src/zlib-1.2.11/inftrees.h" role="src" />
<file md5sum="fddcbf441ed0140dec23927ee34de9a7" name="src/libmongoc/src/zlib-1.2.11/trees.c" role="src" />
<file md5sum="51fdcb3e2ccf60ca13c06920c89296a3" name="src/libmongoc/src/zlib-1.2.11/trees.h" role="src" />
<file md5sum="dc210f08738914519d15edf1bb6e5141" name="src/libmongoc/src/zlib-1.2.11/uncompr.c" role="src" />
+ <file md5sum="66c6b3953f574eca8b709dd5f6865745" name="src/libmongoc/src/zlib-1.2.11/zconf.h" role="src" />
<file md5sum="66c6b3953f574eca8b709dd5f6865745" name="src/libmongoc/src/zlib-1.2.11/zconf.h.in" role="src" />
<file md5sum="0338828e9d00c94645648b1517108324" name="src/libmongoc/src/zlib-1.2.11/zlib.h" role="src" />
<file md5sum="69d0e0950d3ab5c1938d8566257c33a3" name="src/libmongoc/src/zlib-1.2.11/zutil.c" role="src" />
<file md5sum="b8a47cd8873cbfa8daf689f88dd62f75" name="src/libmongoc/src/zlib-1.2.11/zutil.h" role="src" />
<file md5sum="801dd41ee3301f2e0385658e8d409cb0" name="src/libmongocrypt-compat/mongocrypt/mongocrypt.h" role="src" />
<file md5sum="94b739a5ca4735c9efbef6c7c29c8e60" name="src/libmongocrypt-compat/mongocrypt-export.h" role="src" />
<file md5sum="ffc011eff957abdff3b1b2dc3360c9ff" name="src/libmongocrypt/kms-message/src/kms_message/kms_azure_request.h" role="src" />
<file md5sum="178bd08ac73470d35b4986e388085161" name="src/libmongocrypt/kms-message/src/kms_message/kms_b64.h" role="src" />
<file md5sum="39ee9cf46b0439403a0f7c8073f583d5" name="src/libmongocrypt/kms-message/src/kms_message/kms_caller_identity_request.h" role="src" />
<file md5sum="8ebc97b8d9401873858ade801e9feb35" name="src/libmongocrypt/kms-message/src/kms_message/kms_decrypt_request.h" role="src" />
<file md5sum="d0fed9c2821dff65ae9dc6879ee881b6" name="src/libmongocrypt/kms-message/src/kms_message/kms_encrypt_request.h" role="src" />
<file md5sum="610a7df9b3f166d1173a890a19784b84" name="src/libmongocrypt/kms-message/src/kms_message/kms_gcp_request.h" role="src" />
<file md5sum="320d3ed66a12df7b88f3e2aacfd1f26d" name="src/libmongocrypt/kms-message/src/kms_message/kms_kmip_request.h" role="src" />
<file md5sum="a1eb97816ae793c9701208349233eb12" name="src/libmongocrypt/kms-message/src/kms_message/kms_kmip_response.h" role="src" />
<file md5sum="0cd5c466ec235998c2a758540154ed75" name="src/libmongocrypt/kms-message/src/kms_message/kms_kmip_response_parser.h" role="src" />
<file md5sum="c1a35d0b49f3f920d16ffc84f4d8e373" name="src/libmongocrypt/kms-message/src/kms_message/kms_message.h" role="src" />
<file md5sum="cfef23bb3ac62cf8d3fbd8e08015f0c0" name="src/libmongocrypt/kms-message/src/kms_message/kms_message_defines.h" role="src" />
<file md5sum="5663ee4fe8bcca2dc395cd5be3617b44" name="src/libmongocrypt/kms-message/src/kms_message/kms_request.h" role="src" />
<file md5sum="ad85fcbd4c473f138818a4bd9e7f0815" name="src/libmongocrypt/kms-message/src/kms_message/kms_request_opt.h" role="src" />
<file md5sum="209083716262424fab84d670209755c8" name="src/libmongocrypt/kms-message/src/kms_message/kms_response.h" role="src" />
<file md5sum="36754553406792f1c571ec1133d76785" name="src/libmongocrypt/kms-message/src/kms_message/kms_response_parser.h" role="src" />
<file md5sum="e87486a63aa846e479f3bf1af7380038" name="src/libmongocrypt/kms-message/src/hexlify.c" role="src" />
<file md5sum="60664bb6d46c14b4eea28f15e6a082e5" name="src/libmongocrypt/kms-message/src/hexlify.h" role="src" />
<file md5sum="1e4af07511a196a91fd60a0e24a6e158" name="src/libmongocrypt/kms-message/src/kms_azure_request.c" role="src" />
<file md5sum="7ea85b23709fab14de6e2ac7f5ba66f2" name="src/libmongocrypt/kms-message/src/kms_b64.c" role="src" />
<file md5sum="29d5db2215a92ef6121c729f6c75ee00" name="src/libmongocrypt/kms-message/src/kms_caller_identity_request.c" role="src" />
<file md5sum="32b4b23b26fceaed3874af2f4a012f68" name="src/libmongocrypt/kms-message/src/kms_crypto.h" role="src" />
<file md5sum="d23244b72417192b5a8f6d2afed4410a" name="src/libmongocrypt/kms-message/src/kms_crypto_apple.c" role="src" />
<file md5sum="d6ef24b2ededc8139cd4137397325368" name="src/libmongocrypt/kms-message/src/kms_crypto_libcrypto.c" role="src" />
<file md5sum="1636e264b74abccf68fcf0df1806fbe3" name="src/libmongocrypt/kms-message/src/kms_crypto_none.c" role="src" />
<file md5sum="6c2dd3a27026c65f88694d615fe7d0a9" name="src/libmongocrypt/kms-message/src/kms_crypto_windows.c" role="src" />
<file md5sum="aba07d5c53233adfe5d8928b5ef92e06" name="src/libmongocrypt/kms-message/src/kms_decrypt_request.c" role="src" />
<file md5sum="65692a06262c9889f7ce0ae81928d390" name="src/libmongocrypt/kms-message/src/kms_encrypt_request.c" role="src" />
<file md5sum="d353001a1f4139bfae3631f2cd41b4e8" name="src/libmongocrypt/kms-message/src/kms_endian_private.h" role="src" />
<file md5sum="9e2953c624d8a37b2cabc3358d54db4a" name="src/libmongocrypt/kms-message/src/kms_gcp_request.c" role="src" />
<file md5sum="593d915279b88dcc90ccdc13562ade1d" name="src/libmongocrypt/kms-message/src/kms_kmip_item_type_private.h" role="src" />
<file md5sum="598d5fa1534ca2a169440f56ae8853d6" name="src/libmongocrypt/kms-message/src/kms_kmip_reader_writer.c" role="src" />
<file md5sum="9a659b418853e5b1895776b46fef7870" name="src/libmongocrypt/kms-message/src/kms_kmip_reader_writer_private.h" role="src" />
<file md5sum="e854b55dc5e3bc8c377435246a8ac843" name="src/libmongocrypt/kms-message/src/kms_kmip_request.c" role="src" />
<file md5sum="5cf970d24111daf63277cc3c49425938" name="src/libmongocrypt/kms-message/src/kms_kmip_response.c" role="src" />
<file md5sum="470eb89defd7c4d57636938192192e89" name="src/libmongocrypt/kms-message/src/kms_kmip_response_parser.c" role="src" />
<file md5sum="f64765a9c63171b8aa2c5fd7de738072" name="src/libmongocrypt/kms-message/src/kms_kmip_response_parser_private.h" role="src" />
<file md5sum="21898fd3923dfa059f2139a555643e14" name="src/libmongocrypt/kms-message/src/kms_kmip_result_reason_private.h" role="src" />
<file md5sum="8f826227b67ce2503aeb359cea5a3402" name="src/libmongocrypt/kms-message/src/kms_kmip_result_status_private.h" role="src" />
<file md5sum="ec4325cc2b8516ba039d41b922e78e82" name="src/libmongocrypt/kms-message/src/kms_kmip_tag_type_private.h" role="src" />
<file md5sum="2a7f41d0b533d839384c449f05db13c5" name="src/libmongocrypt/kms-message/src/kms_kv_list.c" role="src" />
<file md5sum="69e374f65d9b21695d194e3495941f37" name="src/libmongocrypt/kms-message/src/kms_kv_list.h" role="src" />
<file md5sum="c2189649bce27380a9b07897662901e0" name="src/libmongocrypt/kms-message/src/kms_message.c" role="src" />
<file md5sum="1a522b4a4306818d69b41961575dcc4f" name="src/libmongocrypt/kms-message/src/kms_message_private.h" role="src" />
<file md5sum="f27094bd3cd0c6174a279875623af84e" name="src/libmongocrypt/kms-message/src/kms_port.c" role="src" />
<file md5sum="52247eca34cb25b7d80aad345e393e81" name="src/libmongocrypt/kms-message/src/kms_port.h" role="src" />
<file md5sum="2b999b9501258a2aaa8989b5af4a1f9a" name="src/libmongocrypt/kms-message/src/kms_request.c" role="src" />
<file md5sum="fd15be17d87fa70a2bab1a0309b71b82" name="src/libmongocrypt/kms-message/src/kms_request_opt.c" role="src" />
<file md5sum="c7079940f8096ea3bce05d343de44481" name="src/libmongocrypt/kms-message/src/kms_request_opt_private.h" role="src" />
<file md5sum="888bf715d142e373232463eccf0dffcf" name="src/libmongocrypt/kms-message/src/kms_request_str.c" role="src" />
<file md5sum="8943a55e4b590e6aaf6e7df818922699" name="src/libmongocrypt/kms-message/src/kms_request_str.h" role="src" />
<file md5sum="92b75e5851d90b8d28949ef18417c789" name="src/libmongocrypt/kms-message/src/kms_response.c" role="src" />
<file md5sum="fbeb43438b539423d1ba7ea55f8fc545" name="src/libmongocrypt/kms-message/src/kms_response_parser.c" role="src" />
<file md5sum="dff15b5018efb6269a2a0269c5ddb798" name="src/libmongocrypt/kms-message/src/sort.c" role="src" />
<file md5sum="18f9bd055f6a60e7702603b6b8bf07d5" name="src/libmongocrypt/kms-message/src/sort.h" role="src" />
- <file md5sum="a791784364e86ef3029164fe8fafb4e7" name="src/libmongocrypt/src/crypto/cng.c" role="src" />
- <file md5sum="53fc5575aff7106efd138447402987a0" name="src/libmongocrypt/src/crypto/commoncrypto.c" role="src" />
- <file md5sum="977c2919c40b709e500db58b32cef614" name="src/libmongocrypt/src/crypto/libcrypto.c" role="src" />
- <file md5sum="5f74a939598e843394ba5292069ace50" name="src/libmongocrypt/src/crypto/none.c" role="src" />
+ <file md5sum="7199d9d1b761dd3e7bb98dd5872fe4dd" name="src/libmongocrypt/src/crypto/cng.c" role="src" />
+ <file md5sum="7cdc2caf59a0624bf98b339d944a84c8" name="src/libmongocrypt/src/crypto/commoncrypto.c" role="src" />
+ <file md5sum="fdc1e194924183150c685cf8f884e23f" name="src/libmongocrypt/src/crypto/libcrypto.c" role="src" />
+ <file md5sum="e66c0b266bc841431bc251bc5f0044e8" name="src/libmongocrypt/src/crypto/none.c" role="src" />
+ <file md5sum="2678e814143dfde62c0bdf8ee7ddab28" name="src/libmongocrypt/src/mlib/error.h" role="src" />
+ <file md5sum="8e0b42bcd1eaa9a8ac1f31283d162cab" name="src/libmongocrypt/src/mlib/path.h" role="src" />
+ <file md5sum="16eb747980bd3f1e69cbb8498c35765f" name="src/libmongocrypt/src/mlib/str.h" role="src" />
+ <file md5sum="19cde120e49273bc0197da1656a0fba3" name="src/libmongocrypt/src/mlib/thread.h" role="src" />
+ <file md5sum="0f4e6528293d8a8ef1e2cd3771a67053" name="src/libmongocrypt/src/mlib/user-check.h" role="src" />
+ <file md5sum="9c0cd74b3c026396ed50fd40839c1a26" name="src/libmongocrypt/src/mlib/windows-lean.h" role="src" />
+ <file md5sum="b89f9a8d3dee058a2b6d56375b698343" name="src/libmongocrypt/src/os_posix/os_dll.c" role="src" />
<file md5sum="39a4c1f631e35ead04f8ba13a11bba65" name="src/libmongocrypt/src/os_posix/os_mutex.c" role="src" />
- <file md5sum="f36340408ed3b922617c53f5dc5570fb" name="src/libmongocrypt/src/os_posix/os_once.c" role="src" />
+ <file md5sum="838723a785bd5f1ff1b6ccd8928daca4" name="src/libmongocrypt/src/os_win/os_dll.c" role="src" />
<file md5sum="f95d328d2484c7369dc938a5366cf846" name="src/libmongocrypt/src/os_win/os_mutex.c" role="src" />
- <file md5sum="af647ade57dd876ee77cf5dd106035d4" name="src/libmongocrypt/src/os_win/os_once.c" role="src" />
+ <file md5sum="9bf1794f8ac3532ea4ffd96ae52888ae" name="src/libmongocrypt/src/mongo_csfle-v1.h" role="src" />
<file md5sum="34e15d89ffa2a308ea86b1ae2cb0088f" name="src/libmongocrypt/src/mongocrypt-binary-private.h" role="src" />
<file md5sum="b81c6d7cb5e9526df940d94c813284e9" name="src/libmongocrypt/src/mongocrypt-binary.c" role="src" />
<file md5sum="0a81f609be9fa064a2747ce49f9d9295" name="src/libmongocrypt/src/mongocrypt-buffer-private.h" role="src" />
<file md5sum="12cb785445ab7d10ef0e5409e8827da5" name="src/libmongocrypt/src/mongocrypt-buffer.c" role="src" />
<file md5sum="b5e9bc242b7d785f6c293d875c2d3c71" name="src/libmongocrypt/src/mongocrypt-cache-collinfo-private.h" role="src" />
<file md5sum="48c5eb499d93bd2e230d38b78515deaa" name="src/libmongocrypt/src/mongocrypt-cache-collinfo.c" role="src" />
<file md5sum="1b4df4f22323d029c972086c956926d4" name="src/libmongocrypt/src/mongocrypt-cache-key-private.h" role="src" />
<file md5sum="21c432424e1a3160a71c8daa03a64cb5" name="src/libmongocrypt/src/mongocrypt-cache-key.c" role="src" />
<file md5sum="b2bfeff59a23a567715a46b7f1e56b8f" name="src/libmongocrypt/src/mongocrypt-cache-oauth-private.h" role="src" />
<file md5sum="6a6bdd6ae519a198bd9cc38fd3d66187" name="src/libmongocrypt/src/mongocrypt-cache-oauth.c" role="src" />
<file md5sum="56a3c0f20b220f11a18965282facea22" name="src/libmongocrypt/src/mongocrypt-cache-private.h" role="src" />
<file md5sum="cf785575cca4c00c45dac5de2251c0c3" name="src/libmongocrypt/src/mongocrypt-cache.c" role="src" />
<file md5sum="3ee978103ce2a2f53b87f03b5bf9c12f" name="src/libmongocrypt/src/mongocrypt-ciphertext-private.h" role="src" />
<file md5sum="bdecd2c011f4f816c8660e3324115ca1" name="src/libmongocrypt/src/mongocrypt-ciphertext.c" role="src" />
<file md5sum="e4ef675e85348b5ec19de83aede925ee" name="src/libmongocrypt/src/mongocrypt-compat.h" role="src" />
<file md5sum="b13ae1e7606af6047d74166b4ef2495f" name="src/libmongocrypt/src/mongocrypt-config.h" role="src" />
<file md5sum="6f51385c8021d849d4338bec0a8d0afc" name="src/libmongocrypt/src/mongocrypt-config.h.in" role="src" />
- <file md5sum="335c2ba157a26119801f0bd244a4538b" name="src/libmongocrypt/src/mongocrypt-crypto-private.h" role="src" />
- <file md5sum="d2f4379fd9678e97bbf65de01b09734e" name="src/libmongocrypt/src/mongocrypt-crypto.c" role="src" />
- <file md5sum="5b519da1cd8a77b1958a0d594aa4d7d4" name="src/libmongocrypt/src/mongocrypt-ctx-datakey.c" role="src" />
+ <file md5sum="4b9f7565a5cefe8a40c6c65f196c7b59" name="src/libmongocrypt/src/mongocrypt-crypto-private.h" role="src" />
+ <file md5sum="fbdf3042130dc80240c5c73b127f2d9d" name="src/libmongocrypt/src/mongocrypt-crypto.c" role="src" />
+ <file md5sum="e262ada6e5d2d7bc646c620069302722" name="src/libmongocrypt/src/mongocrypt-ctx-datakey.c" role="src" />
<file md5sum="502f446a79814987c271a6baa18b50d2" name="src/libmongocrypt/src/mongocrypt-ctx-decrypt.c" role="src" />
- <file md5sum="58d5c7a17773752026a4faca9c2ffe22" name="src/libmongocrypt/src/mongocrypt-ctx-encrypt.c" role="src" />
- <file md5sum="a8943c54a0aeb41c3e7a0b1a738f5f21" name="src/libmongocrypt/src/mongocrypt-ctx-private.h" role="src" />
- <file md5sum="1d5e71ca98511c1797b7299526d5f051" name="src/libmongocrypt/src/mongocrypt-ctx.c" role="src" />
+ <file md5sum="ea86fe107be10e7948b71dce661d548b" name="src/libmongocrypt/src/mongocrypt-ctx-encrypt.c" role="src" />
+ <file md5sum="10c2dfeacad9be275f71912a6d0f5ec2" name="src/libmongocrypt/src/mongocrypt-ctx-private.h" role="src" />
+ <file md5sum="297ba78f17e16f5b7d971b358c9f0b80" name="src/libmongocrypt/src/mongocrypt-ctx.c" role="src" />
+ <file md5sum="27ad6650139510beb8165907458c615b" name="src/libmongocrypt/src/mongocrypt-dll-private.h" role="src" />
<file md5sum="4fb2bf18afde014629d7b1df81572dfa" name="src/libmongocrypt/src/mongocrypt-endpoint-private.h" role="src" />
<file md5sum="8168656596c38d21c201c95080311b71" name="src/libmongocrypt/src/mongocrypt-endpoint.c" role="src" />
<file md5sum="92add912564fdbe450689d91b2590d9c" name="src/libmongocrypt/src/mongocrypt-kek-private.h" role="src" />
<file md5sum="7b9ff46d60ade202961a7c7b33b3532c" name="src/libmongocrypt/src/mongocrypt-kek.c" role="src" />
<file md5sum="527813694437bfcb77a3bad1740fa2ec" name="src/libmongocrypt/src/mongocrypt-key-broker-private.h" role="src" />
<file md5sum="456ed3802e13cf774b38fec713e50eab" name="src/libmongocrypt/src/mongocrypt-key-broker.c" role="src" />
<file md5sum="91c5a372f6acc679feb1dd22dab38b3f" name="src/libmongocrypt/src/mongocrypt-key-private.h" role="src" />
<file md5sum="0c4d0412192d819be45437de6d89569e" name="src/libmongocrypt/src/mongocrypt-key.c" role="src" />
<file md5sum="b2ca40703288e618e2ae607d541700fe" name="src/libmongocrypt/src/mongocrypt-kms-ctx-private.h" role="src" />
<file md5sum="120e8aaf6ca0f00cac0cd6871a31ca41" name="src/libmongocrypt/src/mongocrypt-kms-ctx.c" role="src" />
<file md5sum="811275f18e5aee6299146b79a08a0542" name="src/libmongocrypt/src/mongocrypt-log-private.h" role="src" />
<file md5sum="791498257b4fc5601a91792bdc55c2cc" name="src/libmongocrypt/src/mongocrypt-log.c" role="src" />
<file md5sum="0453849c026e5fd24e80ad50c1aef528" name="src/libmongocrypt/src/mongocrypt-marking-private.h" role="src" />
<file md5sum="2993cd22ed2359e653f753f6a6c7ee16" name="src/libmongocrypt/src/mongocrypt-marking.c" role="src" />
<file md5sum="de4411fc003a25f9dbcc9d3f8fe80c2c" name="src/libmongocrypt/src/mongocrypt-mutex-private.h" role="src" />
- <file md5sum="1ec44878e0f0393ae13939265f8b6c01" name="src/libmongocrypt/src/mongocrypt-opts-private.h" role="src" />
- <file md5sum="4df417fcac7223dcc0629862af13d453" name="src/libmongocrypt/src/mongocrypt-opts.c" role="src" />
- <file md5sum="3a8ee36ad63019ebde0f9c405d23aefd" name="src/libmongocrypt/src/mongocrypt-os-private.h" role="src" />
- <file md5sum="62178bad4ccdda1272b530093f383baf" name="src/libmongocrypt/src/mongocrypt-private.h" role="src" />
+ <file md5sum="c5b7d9a9d433425cd2d720f8a901c7b1" name="src/libmongocrypt/src/mongocrypt-opts-private.h" role="src" />
+ <file md5sum="0b92bfc935d47233603d982e00bdc3f8" name="src/libmongocrypt/src/mongocrypt-opts.c" role="src" />
+ <file md5sum="32f72f2c7d8fc8a57ecd5a39c1d78a4d" name="src/libmongocrypt/src/mongocrypt-private.h" role="src" />
<file md5sum="1ba59cdac21a95f2b2adf02b651dd952" name="src/libmongocrypt/src/mongocrypt-status-private.h" role="src" />
<file md5sum="3c8dfcd10882c001534fe287ba2d0744" name="src/libmongocrypt/src/mongocrypt-status.c" role="src" />
<file md5sum="c532c0d6ed2d0d97df2ac1b2bb01f469" name="src/libmongocrypt/src/mongocrypt-traverse-util-private.h" role="src" />
<file md5sum="93bf9b4cec817a1b527ddcaf1ee4f812" name="src/libmongocrypt/src/mongocrypt-traverse-util.c" role="src" />
- <file md5sum="79841077a7d61efcdf65b95a5a481cdd" name="src/libmongocrypt/src/mongocrypt-util-private.h" role="src" />
- <file md5sum="3768303617c6cffb521470f984cffa0a" name="src/libmongocrypt/src/mongocrypt-util.c" role="src" />
- <file md5sum="72326079bea76fd9b9781bbf1e3f17f9" name="src/libmongocrypt/src/mongocrypt.c" role="src" />
- <file md5sum="248ff11634e81d8830cc665e71390e80" name="src/libmongocrypt/src/mongocrypt.h" role="src" />
- <file md5sum="6a5cfd158c55e84bf478c5987fb7f4b0" name="src/libmongocrypt/src/mongocrypt.h.in" role="src" />
- <file md5sum="0589f66713bc44029a1a720b9a0d850d" name="src/LIBMONGOCRYPT_VERSION_CURRENT" role="src" />
- <file md5sum="fa5521f49896b13332f478fe9e31d5ef" name="src/LIBMONGOC_VERSION_CURRENT" role="src" />
- <file md5sum="6fd51a2af939917ff7803a779e5e5680" name="src/bson-encode.c" role="src" />
- <file md5sum="b8eec842736ead473bb3e86a598bb59d" name="src/bson.c" role="src" />
- <file md5sum="98a6296190408c3bfb203e3aca4868c4" name="src/phongo_apm.c" role="src" />
- <file md5sum="b9637fa9027c9a244615c63d4180062e" name="src/phongo_apm.h" role="src" />
- <file md5sum="fd5bff0c591140fedbddaa266ce27298" name="src/phongo_ini.c" role="src" />
- <file md5sum="2405965008bd526492f2d0de355fe878" name="src/phongo_ini.h" role="src" />
+ <file md5sum="05c50f0b644756e3d2e40f3e3242c5fd" name="src/libmongocrypt/src/mongocrypt-util-private.h" role="src" />
+ <file md5sum="58cf61bd5459d0685e7829c8680f1aaf" name="src/libmongocrypt/src/mongocrypt-util.c" role="src" />
+ <file md5sum="3f1b175cdaa9cb1157444f76e84cd2aa" name="src/libmongocrypt/src/mongocrypt.c" role="src" />
+ <file md5sum="5d5c64d1dc85ed14116a0dd7507fb504" name="src/libmongocrypt/src/mongocrypt.h" role="src" />
+ <file md5sum="1c86beb27422a7fdbd5a656bd785c273" name="src/libmongocrypt/src/mongocrypt.h.in" role="src" />
+ <file md5sum="8dadbeb3ae0d6e8cf2c8b7df7a24ec0b" name="src/LIBMONGOCRYPT_VERSION_CURRENT" role="src" />
+ <file md5sum="b01d92c0fadad032b18541b9cf71061c" name="src/LIBMONGOC_VERSION_CURRENT" role="src" />
+ <file md5sum="ec7c7268228fb4ce9e41507d3c1bbc25" name="src/phongo_apm.c" role="src" />
+ <file md5sum="77a9ea21f15bc0112af0540372bbb10f" name="src/phongo_apm.h" role="src" />
+ <file md5sum="1d1ab42a1177faeb4f06a4ff3428d8db" name="src/phongo_bson.c" role="src" />
+ <file md5sum="10d7fa5ef5c64a01cabd548b7e71fef4" name="src/phongo_bson.h" role="src" />
+ <file md5sum="3aec47c3d88894dd86653475ba6dc712" name="src/phongo_bson_encode.c" role="src" />
+ <file md5sum="5318a01c78fe27a1567f66d09fc87e8a" name="src/phongo_bson_encode.h" role="src" />
+ <file md5sum="6453bc69bde12bc20c2f268f671dd28b" name="src/phongo_classes.h" role="src" />
+ <file md5sum="1746081a1aec4b78e492381b4253f7f6" name="src/phongo_client.c" role="src" />
+ <file md5sum="1e53a91f977a06878a8d68d769e3eac9" name="src/phongo_client.h" role="src" />
+ <file md5sum="a008716fd427c048f4fc952e3503ebc4" name="src/phongo_compat.c" role="src" />
+ <file md5sum="67bce0014d8765d3fefc3573acd7adc2" name="src/phongo_compat.h" role="src" />
+ <file md5sum="f06e720068afa4d263aaefe6c68f5efb" name="src/phongo_error.c" role="src" />
+ <file md5sum="136d20717f05027d7b90dd327460cbaf" name="src/phongo_error.h" role="src" />
+ <file md5sum="b79f2fd89df437644ebc935d3f7da28e" name="src/phongo_execute.c" role="src" />
+ <file md5sum="edcaff696c46e8d86b4bfb82afa944eb" name="src/phongo_execute.h" role="src" />
+ <file md5sum="01fc6f8e57bf12bd2f6b2a7021a819a3" name="src/phongo_ini.c" role="src" />
+ <file md5sum="6c4fdb6112eb54d2cc89abeae499630f" name="src/phongo_ini.h" role="src" />
+ <file md5sum="0ff01adac3d2c2a3e4f5b1ae7b5f6877" name="src/phongo_structs.h" role="src" />
+ <file md5sum="0be03ab06536bfe3bed1c60832d9623f" name="src/phongo_util.c" role="src" />
+ <file md5sum="d18cbbc1f0fb6015c452b74d2165dbd1" name="src/phongo_util.h" role="src" />
+ <file md5sum="78a17be7d97c69f434d836ffebeb55b3" name="src/phongo_version.h" role="src" />
<file md5sum="ca2c5031647b050893a81fef62317af2" name="tests/apm/bug0950-001.phpt" role="test" />
<file md5sum="c57aecc8032252158a190e7e10270417" name="tests/apm/bug0950-002.phpt" role="test" />
<file md5sum="9ee1bcb875babea7612bf831f108eb6d" name="tests/apm/commandFailedEvent-001.phpt" role="test" />
<file md5sum="5267ddfa53b8ee6c786c950e29e1808c" name="tests/apm/commandFailedEvent-002.phpt" role="test" />
<file md5sum="ea20ae402869d360bbf2c7dcc9e740c2" name="tests/apm/commandFailedEvent-debug-001.phpt" role="test" />
- <file md5sum="6c77dd343ac2c363685af78b276b9ca9" name="tests/apm/commandFailedEvent-getReply-001.phpt" role="test" />
+ <file md5sum="5ee004ab5b1703aa00a2ef35767e2837" name="tests/apm/commandFailedEvent-getReply-001.phpt" role="test" />
<file md5sum="d95da38cbecdecd04107722de552f099" name="tests/apm/commandFailedEvent-getServiceId-001.phpt" role="test" />
<file md5sum="59a7eea238c21c7fcd7d95342f6d14ed" name="tests/apm/commandFailedEvent-getServiceId-002.phpt" role="test" />
<file md5sum="e0abc3a888f028ee72dd1142523dd511" name="tests/apm/commandStartedEvent-001.phpt" role="test" />
+ <file md5sum="26294cdbe7578806d138b4a5ac445512" name="tests/apm/commandStartedEvent-002.phpt" role="test" />
<file md5sum="a84cad5b5225c55bd08fa8edcc6665cc" name="tests/apm/commandStartedEvent-debug-001.phpt" role="test" />
<file md5sum="2efc2678d58fdb5fca68c6985d3fe3fd" name="tests/apm/commandStartedEvent-getServiceId-001.phpt" role="test" />
<file md5sum="c7429a87f93581dff47305bf4131171e" name="tests/apm/commandStartedEvent-getServiceId-002.phpt" role="test" />
<file md5sum="9f529376edb9f66409f91d5230d521e2" name="tests/apm/commandSucceededEvent-001.phpt" role="test" />
<file md5sum="8f10fc1f4932f3e65d8e3fce952bb15b" name="tests/apm/commandSucceededEvent-002.phpt" role="test" />
<file md5sum="5d851446a3015daffaf842fc87a2de62" name="tests/apm/commandSucceededEvent-debug-001.phpt" role="test" />
<file md5sum="e5f7d842a2bd1f1df4515534a567a407" name="tests/apm/commandSucceededEvent-getServiceId-001.phpt" role="test" />
<file md5sum="9be8be033e66fa07907935142670f2d8" name="tests/apm/commandSucceededEvent-getServiceId-002.phpt" role="test" />
<file md5sum="3e1e7674a4c01c8c57cdaf378655d1d6" name="tests/apm/monitoring-addSubscriber-001.phpt" role="test" />
<file md5sum="63cce7df4352b6f96dda09e9f0ae85ca" name="tests/apm/monitoring-addSubscriber-002.phpt" role="test" />
<file md5sum="58956419747418a41465fded0466b612" name="tests/apm/monitoring-addSubscriber-003.phpt" role="test" />
<file md5sum="560368f53701ebd1565badaa4cba3f83" name="tests/apm/monitoring-addSubscriber-004.phpt" role="test" />
<file md5sum="716845017e446303a39d968f773649d1" name="tests/apm/monitoring-removeSubscriber-001.phpt" role="test" />
<file md5sum="d9df59c5dfd66e0be123831e79cfe009" name="tests/apm/monitoring-removeSubscriber-002.phpt" role="test" />
+ <file md5sum="9fc0cc57de28c7c927aee7ba0f746687" name="tests/apm/serverChangedEvent-001.phpt" role="test" />
+ <file md5sum="45af08eb3b36b3c67dc9a2cce119cac6" name="tests/apm/serverClosedEvent-001.phpt" role="test" />
+ <file md5sum="91dcb096b1025f0979ce29676446ba42" name="tests/apm/serverHeartbeatFailedEvent-001.phpt" role="test" />
+ <file md5sum="9d50aac0a474fa62702f305d7deac176" name="tests/apm/serverHeartbeatStartedEvent-001.phpt" role="test" />
+ <file md5sum="d5912d918a99a72382a4b86910ded322" name="tests/apm/serverHeartbeatSucceededEvent-001.phpt" role="test" />
+ <file md5sum="dd3da20b90a02fc91570cf93df197c0b" name="tests/apm/serverOpeningEvent-001.phpt" role="test" />
+ <file md5sum="51b96829647749816cacfbe94c217f8a" name="tests/apm/topologyChangedEvent-001.phpt" role="test" />
+ <file md5sum="a5ce87b8ccca2c98b4322a06a23aeaa6" name="tests/apm/topologyClosedEvent-001.phpt" role="test" />
+ <file md5sum="6d95ae9d8775b9708e7b345661bc9ee5" name="tests/apm/topologyOpeningEvent-001.phpt" role="test" />
+ <file md5sum="3f8dcd773327b14ee445ef51bde6c21c" name="tests/apm/topologyOpeningEvent-002.phpt" role="test" />
<file md5sum="baa3d7edf68691614eadee83b7708638" name="tests/bson-corpus/array-decodeError-001.phpt" role="test" />
<file md5sum="eec94d5ab15a126f72a30b2b79306ce9" name="tests/bson-corpus/array-decodeError-002.phpt" role="test" />
<file md5sum="6d18f10c0068020a9d6a48f8d84414b9" name="tests/bson-corpus/array-decodeError-003.phpt" role="test" />
<file md5sum="98d114d97f7e23b40a83908a6bb796f5" name="tests/bson-corpus/array-valid-001.phpt" role="test" />
<file md5sum="d4a761de533a0712a8bbc852b154076c" name="tests/bson-corpus/array-valid-002.phpt" role="test" />
<file md5sum="c465ab144497f93ed869057cc2abb304" name="tests/bson-corpus/array-valid-003.phpt" role="test" />
<file md5sum="aae5943c9338ef5f953332c685f81d57" name="tests/bson-corpus/array-valid-004.phpt" role="test" />
<file md5sum="54dd965efb05d28d8fd2e908333e0810" name="tests/bson-corpus/array-valid-005.phpt" role="test" />
<file md5sum="d807b5a839294209cc4dc11a7529249d" name="tests/bson-corpus/binary-decodeError-001.phpt" role="test" />
<file md5sum="0a9f951a09caabfbc75ecb326c227811" name="tests/bson-corpus/binary-decodeError-002.phpt" role="test" />
<file md5sum="5b77030b5ebae42e37aca99ef3821116" name="tests/bson-corpus/binary-decodeError-003.phpt" role="test" />
<file md5sum="40c878a95d22ed3155a9f234cfbf9c9c" name="tests/bson-corpus/binary-decodeError-004.phpt" role="test" />
<file md5sum="0d0015a55c033db887b0ff045f1347e1" name="tests/bson-corpus/binary-decodeError-005.phpt" role="test" />
<file md5sum="14774d1f29828780b0766476b4dd37a5" name="tests/bson-corpus/binary-parseError-001.phpt" role="test" />
<file md5sum="522004a8e00d656e77572ea5fdcca2c6" name="tests/bson-corpus/binary-parseError-002.phpt" role="test" />
<file md5sum="6f3b84da88b0b33ad66c1e86c2905458" name="tests/bson-corpus/binary-parseError-003.phpt" role="test" />
<file md5sum="eb55593431d6bddd64f25be7d43d6ef0" name="tests/bson-corpus/binary-parseError-004.phpt" role="test" />
<file md5sum="c54515e589c765e5e07ffbe5787472b7" name="tests/bson-corpus/binary-parseError-005.phpt" role="test" />
<file md5sum="dae4f19c166a8f2f3ca5ad05bab8ab8b" name="tests/bson-corpus/binary-valid-001.phpt" role="test" />
<file md5sum="d113ebef12ab87e860079a78ed90dd6a" name="tests/bson-corpus/binary-valid-002.phpt" role="test" />
<file md5sum="ea9b49e5334a6d0dfb02676fed32f1c6" name="tests/bson-corpus/binary-valid-003.phpt" role="test" />
<file md5sum="4664b9940a9a42330a286cfaa4be8d3a" name="tests/bson-corpus/binary-valid-004.phpt" role="test" />
<file md5sum="ec4ee1c5c365cbe03cf767d1b9feb1f1" name="tests/bson-corpus/binary-valid-005.phpt" role="test" />
<file md5sum="4b915c50885402aef86cb5bf6cd781e5" name="tests/bson-corpus/binary-valid-006.phpt" role="test" />
<file md5sum="65524ba0237dc7292908c02bd60bab55" name="tests/bson-corpus/binary-valid-007.phpt" role="test" />
<file md5sum="a1974955b3013148af357575dadbd42a" name="tests/bson-corpus/binary-valid-008.phpt" role="test" />
<file md5sum="8ed7e75059848bb2fa8dae968b3165b4" name="tests/bson-corpus/binary-valid-009.phpt" role="test" />
<file md5sum="ec668b2d309bde01d389f375173c4237" name="tests/bson-corpus/binary-valid-010.phpt" role="test" />
<file md5sum="59f90daf0580a24e4e2a7adc25339fb5" name="tests/bson-corpus/binary-valid-011.phpt" role="test" />
<file md5sum="e34a0a285fb2cf5c3b31b68ba8d64b60" name="tests/bson-corpus/binary-valid-012.phpt" role="test" />
<file md5sum="a4015fa1fd13d04c2624314693aa79f0" name="tests/bson-corpus/binary-valid-013.phpt" role="test" />
<file md5sum="8c555f641e62f188c760ea259fa0905b" name="tests/bson-corpus/boolean-decodeError-001.phpt" role="test" />
<file md5sum="81399e6126c3c56fe847ae51d1ac5321" name="tests/bson-corpus/boolean-decodeError-002.phpt" role="test" />
<file md5sum="5219cd5251957aecac799dd3756902bc" name="tests/bson-corpus/boolean-valid-001.phpt" role="test" />
<file md5sum="adc8666825689f459d7369276f93aa77" name="tests/bson-corpus/boolean-valid-002.phpt" role="test" />
<file md5sum="07ce410a97dbe7fdc9f5bdb36f6d565d" name="tests/bson-corpus/code-decodeError-001.phpt" role="test" />
<file md5sum="75a6535d50dad93710f03f085e63a4a2" name="tests/bson-corpus/code-decodeError-002.phpt" role="test" />
<file md5sum="6eb0eafd83bcb0534ab4194cee305a97" name="tests/bson-corpus/code-decodeError-003.phpt" role="test" />
<file md5sum="0cfa9c4f0a74d15f202c757980a906a7" name="tests/bson-corpus/code-decodeError-004.phpt" role="test" />
<file md5sum="e667e4a51dc0168c571198f989ef779a" name="tests/bson-corpus/code-decodeError-005.phpt" role="test" />
<file md5sum="7504b851a985838f5e72219cd52e325b" name="tests/bson-corpus/code-decodeError-006.phpt" role="test" />
<file md5sum="be44ea4b2585d4c835e16c48fcf38e13" name="tests/bson-corpus/code-decodeError-007.phpt" role="test" />
<file md5sum="7057b47d0b9af05a56f9d10c29180046" name="tests/bson-corpus/code-valid-001.phpt" role="test" />
<file md5sum="1aeda4cf9b01aaf44da141c159355353" name="tests/bson-corpus/code-valid-002.phpt" role="test" />
<file md5sum="a622d156ef6459b4f1198f29d196dc64" name="tests/bson-corpus/code-valid-003.phpt" role="test" />
<file md5sum="b8715bcfe56a16c54563decb94652dac" name="tests/bson-corpus/code-valid-004.phpt" role="test" />
<file md5sum="79a555c483b2cad930b2469adf3465b2" name="tests/bson-corpus/code-valid-005.phpt" role="test" />
<file md5sum="81a20ddf7b39fd77d035abd711603ca4" name="tests/bson-corpus/code-valid-006.phpt" role="test" />
<file md5sum="7cbb03c444968469684d43b617a651c9" name="tests/bson-corpus/code_w_scope-decodeError-001.phpt" role="test" />
<file md5sum="90b2b80ca43b71c65db39d2bac6e0d08" name="tests/bson-corpus/code_w_scope-decodeError-002.phpt" role="test" />
<file md5sum="0977a3a73073fef3a88bc60fa63624c2" name="tests/bson-corpus/code_w_scope-decodeError-003.phpt" role="test" />
<file md5sum="82fd83d89a738bff8ed74b3f1afa32c6" name="tests/bson-corpus/code_w_scope-decodeError-004.phpt" role="test" />
<file md5sum="cd9130276550b837ee5c15a2cbfa85df" name="tests/bson-corpus/code_w_scope-decodeError-005.phpt" role="test" />
<file md5sum="7a0fe48f99f58fb05fd5a937ae23c585" name="tests/bson-corpus/code_w_scope-decodeError-006.phpt" role="test" />
<file md5sum="96b9583e3fecc7ca67df568726c39b62" name="tests/bson-corpus/code_w_scope-decodeError-007.phpt" role="test" />
<file md5sum="8341838b0a95b053f7a82d457c34a539" name="tests/bson-corpus/code_w_scope-decodeError-008.phpt" role="test" />
<file md5sum="0e85755385c1d1b7daa3ec469cfc27eb" name="tests/bson-corpus/code_w_scope-decodeError-009.phpt" role="test" />
<file md5sum="1a9fb68565a64903639f1b3c1bc9d543" name="tests/bson-corpus/code_w_scope-decodeError-010.phpt" role="test" />
<file md5sum="27fb6ca6fc059f12566888eeb335154f" name="tests/bson-corpus/code_w_scope-decodeError-011.phpt" role="test" />
<file md5sum="17f3a5eba8cdd56ce2f73d781575d8ff" name="tests/bson-corpus/code_w_scope-valid-001.phpt" role="test" />
<file md5sum="7cc17cee915c73328f77579db2eb8b32" name="tests/bson-corpus/code_w_scope-valid-002.phpt" role="test" />
<file md5sum="f2516438c2f05da6a05ca66e50f488d5" name="tests/bson-corpus/code_w_scope-valid-003.phpt" role="test" />
<file md5sum="4dc3544ace08e85e90315fa7aa9a5bd7" name="tests/bson-corpus/code_w_scope-valid-004.phpt" role="test" />
<file md5sum="ea1dad39a5e650989bde4cce50b6912c" name="tests/bson-corpus/code_w_scope-valid-005.phpt" role="test" />
<file md5sum="a5e367bba0680e4f5c0232fa99ff5830" name="tests/bson-corpus/datetime-decodeError-001.phpt" role="test" />
<file md5sum="4a64a9e7365127a23315db6d1ad4b45e" name="tests/bson-corpus/datetime-valid-001.phpt" role="test" />
<file md5sum="89cecd3e5fc22f38695b071d0592d20b" name="tests/bson-corpus/datetime-valid-002.phpt" role="test" />
<file md5sum="5142efd68b779142234912f9130a893a" name="tests/bson-corpus/datetime-valid-003.phpt" role="test" />
<file md5sum="82be9c1517e9ac71980d5dd1e63692a1" name="tests/bson-corpus/datetime-valid-004.phpt" role="test" />
<file md5sum="b9b2985697d4018a5349f26b6a2189fa" name="tests/bson-corpus/datetime-valid-005.phpt" role="test" />
<file md5sum="3ad3e33946bfc413e1671eee8b1a56af" name="tests/bson-corpus/dbpointer-decodeError-001.phpt" role="test" />
<file md5sum="3dc01fb79532e373dd3a4b0ceaa2b70c" name="tests/bson-corpus/dbpointer-decodeError-002.phpt" role="test" />
<file md5sum="9262cfd01cf672724ac59995be78e54b" name="tests/bson-corpus/dbpointer-decodeError-003.phpt" role="test" />
<file md5sum="4466fd41c0a2cd02530821f7c6794655" name="tests/bson-corpus/dbpointer-decodeError-004.phpt" role="test" />
<file md5sum="e2309452e28485a05226c6b72842f2fc" name="tests/bson-corpus/dbpointer-decodeError-005.phpt" role="test" />
<file md5sum="68b0583db17d887509f8c3a88b234348" name="tests/bson-corpus/dbpointer-decodeError-006.phpt" role="test" />
<file md5sum="1c5600661ffa39dba86dfe6abc2df5c7" name="tests/bson-corpus/dbpointer-valid-001.phpt" role="test" />
<file md5sum="609cf521db0f3b398885c64633cd4cb0" name="tests/bson-corpus/dbpointer-valid-002.phpt" role="test" />
<file md5sum="27e0dab75f44c055149387169ebbdca3" name="tests/bson-corpus/dbpointer-valid-003.phpt" role="test" />
<file md5sum="69b6af5f6fb37408ac4b5268a9709463" name="tests/bson-corpus/dbref-valid-001.phpt" role="test" />
<file md5sum="c4d059e997c1d804e0472c4307b45eea" name="tests/bson-corpus/dbref-valid-002.phpt" role="test" />
<file md5sum="0aa924cb47180b3e8d5a5dddb781d5b6" name="tests/bson-corpus/dbref-valid-003.phpt" role="test" />
<file md5sum="d82fabf93ab940d550b8b3b43985740c" name="tests/bson-corpus/dbref-valid-004.phpt" role="test" />
<file md5sum="af733d65729db7d267ba44333e087f7c" name="tests/bson-corpus/dbref-valid-005.phpt" role="test" />
<file md5sum="964d823680ff081351b44b1210f85938" name="tests/bson-corpus/dbref-valid-006.phpt" role="test" />
<file md5sum="50fdfd40d749b7faa722388a8719be35" name="tests/bson-corpus/dbref-valid-007.phpt" role="test" />
<file md5sum="46e2f6615d23e0e93d831feece91edb8" name="tests/bson-corpus/dbref-valid-008.phpt" role="test" />
<file md5sum="f497c15e3c5d4f91bb5e4b811d0f626a" name="tests/bson-corpus/dbref-valid-009.phpt" role="test" />
<file md5sum="181777f44bb24d2d123b78e1f951cc48" name="tests/bson-corpus/decimal128-1-valid-001.phpt" role="test" />
<file md5sum="05636e1736addca153d9cb2296279e6c" name="tests/bson-corpus/decimal128-1-valid-002.phpt" role="test" />
<file md5sum="9093cb6ea89b3aee8f8455c6c68f6793" name="tests/bson-corpus/decimal128-1-valid-003.phpt" role="test" />
<file md5sum="53aa5f575355bd3223e915f3a337cb5f" name="tests/bson-corpus/decimal128-1-valid-004.phpt" role="test" />
<file md5sum="2685f03107eefd6486f9b390b4fa6ab8" name="tests/bson-corpus/decimal128-1-valid-005.phpt" role="test" />
<file md5sum="46437b3d39725d2bfaa6be64f2d593b4" name="tests/bson-corpus/decimal128-1-valid-006.phpt" role="test" />
<file md5sum="515c2938f91bfe74a4b8f95da78d9821" name="tests/bson-corpus/decimal128-1-valid-007.phpt" role="test" />
<file md5sum="c024cb4305dac855b8af9c7b74958c36" name="tests/bson-corpus/decimal128-1-valid-008.phpt" role="test" />
<file md5sum="20ec3b4074921e7e910887fb75af5d42" name="tests/bson-corpus/decimal128-1-valid-009.phpt" role="test" />
<file md5sum="0737fe57984b0da8c73c1f72e23ece55" name="tests/bson-corpus/decimal128-1-valid-010.phpt" role="test" />
<file md5sum="6bd52fe6e3790c7c8a33ef5ee047ba75" name="tests/bson-corpus/decimal128-1-valid-011.phpt" role="test" />
<file md5sum="3223159cc842967a3599de2fe101ee54" name="tests/bson-corpus/decimal128-1-valid-012.phpt" role="test" />
<file md5sum="4dc802e60530028adc8d5c8ded3c569a" name="tests/bson-corpus/decimal128-1-valid-013.phpt" role="test" />
<file md5sum="9f64ff435e0f0f85ac4fcc85634a83d7" name="tests/bson-corpus/decimal128-1-valid-014.phpt" role="test" />
<file md5sum="4e3083d4c813fab736ed3b7542a7cdcc" name="tests/bson-corpus/decimal128-1-valid-015.phpt" role="test" />
<file md5sum="0152c6c8f959dfde6d1f70da8c7c3fe6" name="tests/bson-corpus/decimal128-1-valid-016.phpt" role="test" />
<file md5sum="febdbd923021222449042454301b1a47" name="tests/bson-corpus/decimal128-1-valid-017.phpt" role="test" />
<file md5sum="26bf546e763fc1772b40095d85b1fe7e" name="tests/bson-corpus/decimal128-1-valid-018.phpt" role="test" />
<file md5sum="4133cc0a34fe402ef3c343087cb3b862" name="tests/bson-corpus/decimal128-1-valid-019.phpt" role="test" />
<file md5sum="527ee9d3c8c22374136f31a84f1f3afe" name="tests/bson-corpus/decimal128-1-valid-020.phpt" role="test" />
<file md5sum="ae47f2b1197250d42b0a374643ec3fd8" name="tests/bson-corpus/decimal128-1-valid-021.phpt" role="test" />
<file md5sum="c141d9d9681098aa090bd9956cb41028" name="tests/bson-corpus/decimal128-1-valid-022.phpt" role="test" />
<file md5sum="0cac88fcc47e16f1ea3c2d7a79607b94" name="tests/bson-corpus/decimal128-1-valid-023.phpt" role="test" />
<file md5sum="b197806633c40722bf483c22bb5bbc14" name="tests/bson-corpus/decimal128-1-valid-024.phpt" role="test" />
<file md5sum="1c6b0566a8cc2a347a322cab39aad81b" name="tests/bson-corpus/decimal128-1-valid-025.phpt" role="test" />
<file md5sum="b6b92d177c102dfee5354f783ba14a34" name="tests/bson-corpus/decimal128-1-valid-026.phpt" role="test" />
<file md5sum="91cb770554b1cc1dd0ca604f605b3904" name="tests/bson-corpus/decimal128-1-valid-027.phpt" role="test" />
<file md5sum="8350180d7ce47e9046331a0a74947c92" name="tests/bson-corpus/decimal128-1-valid-028.phpt" role="test" />
<file md5sum="d8c763344490fc19e1487c5bbe3a3e87" name="tests/bson-corpus/decimal128-1-valid-029.phpt" role="test" />
<file md5sum="77b646bf805652b4bc5e4c9935bb7a72" name="tests/bson-corpus/decimal128-1-valid-030.phpt" role="test" />
<file md5sum="29a4bd0d922f58d564d81c1f2cfee38a" name="tests/bson-corpus/decimal128-1-valid-031.phpt" role="test" />
<file md5sum="9ce50bb8fc905b7687ec3491d11560c7" name="tests/bson-corpus/decimal128-1-valid-032.phpt" role="test" />
<file md5sum="4b246fa8bb1355f0af82432efd65381c" name="tests/bson-corpus/decimal128-1-valid-033.phpt" role="test" />
<file md5sum="d3ab028c37d49a5882b7d0b3620d5444" name="tests/bson-corpus/decimal128-1-valid-034.phpt" role="test" />
<file md5sum="e36d9ad83dc52f209fbcd1b8b2c0fa2d" name="tests/bson-corpus/decimal128-1-valid-035.phpt" role="test" />
<file md5sum="bdbb2f3244bf9668cbcc1831c2999415" name="tests/bson-corpus/decimal128-1-valid-036.phpt" role="test" />
<file md5sum="a5c00e87e229cb3edabf431255a01fda" name="tests/bson-corpus/decimal128-1-valid-037.phpt" role="test" />
<file md5sum="c50985ab0b18d1ba4f40a5564e060beb" name="tests/bson-corpus/decimal128-1-valid-038.phpt" role="test" />
<file md5sum="b3c90cc2433a2d92ae2bae0b82459fdc" name="tests/bson-corpus/decimal128-1-valid-039.phpt" role="test" />
<file md5sum="f1ed2912db6a1af78f89f37eb2b28c72" name="tests/bson-corpus/decimal128-1-valid-040.phpt" role="test" />
<file md5sum="1a2fe9d1b42589351ff104f1591c6df4" name="tests/bson-corpus/decimal128-1-valid-041.phpt" role="test" />
<file md5sum="9a604049ea1265a20aae18aa0748ce60" name="tests/bson-corpus/decimal128-1-valid-042.phpt" role="test" />
<file md5sum="ed0f14a2df766171c95646afb73cbcf4" name="tests/bson-corpus/decimal128-1-valid-043.phpt" role="test" />
<file md5sum="0b038d9214ecdc4bb4cf5dca3f5bbbe8" name="tests/bson-corpus/decimal128-1-valid-044.phpt" role="test" />
<file md5sum="0f1af353b9da41f863dc760a7cfa9bb2" name="tests/bson-corpus/decimal128-1-valid-045.phpt" role="test" />
<file md5sum="03fbda063ba4dff9d85daa5cae771007" name="tests/bson-corpus/decimal128-1-valid-046.phpt" role="test" />
<file md5sum="e11b787f18052f0bb45d131a5f421016" name="tests/bson-corpus/decimal128-1-valid-047.phpt" role="test" />
<file md5sum="890ae8f1bd849c64dc212f0217a592cc" name="tests/bson-corpus/decimal128-1-valid-048.phpt" role="test" />
<file md5sum="6f3417465de2d6041accdf6d36983ed1" name="tests/bson-corpus/decimal128-1-valid-049.phpt" role="test" />
<file md5sum="a856a4e669ee0ca37abc26e8d4d7be3a" name="tests/bson-corpus/decimal128-1-valid-050.phpt" role="test" />
<file md5sum="c9fd1a8621d8d298a2a1ff46ce6fc2c4" name="tests/bson-corpus/decimal128-1-valid-051.phpt" role="test" />
<file md5sum="152855c622ca0f557268a43b5f33b9af" name="tests/bson-corpus/decimal128-1-valid-052.phpt" role="test" />
<file md5sum="f6be60d8df2faf214807026292b248fa" name="tests/bson-corpus/decimal128-1-valid-053.phpt" role="test" />
<file md5sum="4b0c216290010189cd5bdd34e6d20ab4" name="tests/bson-corpus/decimal128-1-valid-054.phpt" role="test" />
<file md5sum="c7c4cd25bb866dc7c31070b6925e295b" name="tests/bson-corpus/decimal128-1-valid-055.phpt" role="test" />
<file md5sum="64964fbbc267b35685f1228631834737" name="tests/bson-corpus/decimal128-1-valid-056.phpt" role="test" />
<file md5sum="04356b1831da8db1f176384482b33d3a" name="tests/bson-corpus/decimal128-2-valid-001.phpt" role="test" />
<file md5sum="c602b99310f55634e40dcc39dac6e939" name="tests/bson-corpus/decimal128-2-valid-002.phpt" role="test" />
<file md5sum="d4502c76bca1329d850d68832a2e7100" name="tests/bson-corpus/decimal128-2-valid-003.phpt" role="test" />
<file md5sum="dc5f8337029e4603a29e3e159abeb80a" name="tests/bson-corpus/decimal128-2-valid-004.phpt" role="test" />
<file md5sum="28eace8c67cc6c1e476b5055c23436b3" name="tests/bson-corpus/decimal128-2-valid-005.phpt" role="test" />
<file md5sum="7ddbeb89d56d31392ae60f8fa89101df" name="tests/bson-corpus/decimal128-2-valid-006.phpt" role="test" />
<file md5sum="728c35f1a068c4ae897f0492813f7f88" name="tests/bson-corpus/decimal128-2-valid-007.phpt" role="test" />
<file md5sum="ae211145f5b65359814225f1e9f857c9" name="tests/bson-corpus/decimal128-2-valid-008.phpt" role="test" />
<file md5sum="f7ccd654f0b66977e43c2beb9355f7d7" name="tests/bson-corpus/decimal128-2-valid-009.phpt" role="test" />
<file md5sum="48e39888de51d58169d405da6c02100d" name="tests/bson-corpus/decimal128-2-valid-010.phpt" role="test" />
<file md5sum="abcd6dce99a5878b0d828a5033a94ce0" name="tests/bson-corpus/decimal128-2-valid-011.phpt" role="test" />
<file md5sum="d73fc290bfe6a7cd3b6d1ff2d9058b3d" name="tests/bson-corpus/decimal128-2-valid-012.phpt" role="test" />
<file md5sum="c1a1bc361109c4e13fc609ffa720f7cd" name="tests/bson-corpus/decimal128-2-valid-013.phpt" role="test" />
<file md5sum="48d975b96f3ba6f03e1cb584a1eb778c" name="tests/bson-corpus/decimal128-2-valid-014.phpt" role="test" />
<file md5sum="5612753bed0a1957ebf7450c0ca61750" name="tests/bson-corpus/decimal128-2-valid-015.phpt" role="test" />
<file md5sum="0da73f1b93da8e714e0be3c6ed96e930" name="tests/bson-corpus/decimal128-2-valid-016.phpt" role="test" />
<file md5sum="b89faae69d2c310e3fbdacbc59d56be5" name="tests/bson-corpus/decimal128-2-valid-017.phpt" role="test" />
<file md5sum="6f82366fee736c5e1855aaea543f199c" name="tests/bson-corpus/decimal128-2-valid-018.phpt" role="test" />
<file md5sum="847c0cdf22d49c1ac2fa8d6a94998023" name="tests/bson-corpus/decimal128-2-valid-019.phpt" role="test" />
<file md5sum="d20bbf92de57c759be535f0f5726f9a9" name="tests/bson-corpus/decimal128-2-valid-020.phpt" role="test" />
<file md5sum="c0e82e9808daadfc4ddf66b5c5c4305f" name="tests/bson-corpus/decimal128-2-valid-021.phpt" role="test" />
<file md5sum="418a169d42a9f21299563ac66f68347e" name="tests/bson-corpus/decimal128-2-valid-022.phpt" role="test" />
<file md5sum="a6f2d6747a39f50a4d429a680b99fd6d" name="tests/bson-corpus/decimal128-2-valid-023.phpt" role="test" />
<file md5sum="a416f9b9750e34139eb58b7aef38402f" name="tests/bson-corpus/decimal128-2-valid-024.phpt" role="test" />
<file md5sum="711450c2690746ed5eae3d4640a28f9c" name="tests/bson-corpus/decimal128-2-valid-025.phpt" role="test" />
<file md5sum="4490e63afd6b0d198564b6a261b99b03" name="tests/bson-corpus/decimal128-2-valid-026.phpt" role="test" />
<file md5sum="eb7946eb347a9ef05c9e91ffcddfa133" name="tests/bson-corpus/decimal128-2-valid-027.phpt" role="test" />
<file md5sum="697e1da9a9a12a7953c7e5b5041dd597" name="tests/bson-corpus/decimal128-2-valid-028.phpt" role="test" />
<file md5sum="7747df1c67053a9d2c27e68bf662acb0" name="tests/bson-corpus/decimal128-2-valid-029.phpt" role="test" />
<file md5sum="2af7e14d59fd78f19955a9bfb1f46793" name="tests/bson-corpus/decimal128-2-valid-030.phpt" role="test" />
<file md5sum="044bb1532b756f91eb120961b609ddf8" name="tests/bson-corpus/decimal128-2-valid-031.phpt" role="test" />
<file md5sum="881ba5eab7f3e5a983ae78abd599e471" name="tests/bson-corpus/decimal128-2-valid-032.phpt" role="test" />
<file md5sum="357a3bfda8af22a07727a8f61b75e162" name="tests/bson-corpus/decimal128-2-valid-033.phpt" role="test" />
<file md5sum="cc4e62ea75c4e530cbf570ff29b01b68" name="tests/bson-corpus/decimal128-2-valid-034.phpt" role="test" />
<file md5sum="34a105ed800d5e7aa13522a55a436dae" name="tests/bson-corpus/decimal128-2-valid-035.phpt" role="test" />
<file md5sum="886a19018d5cc2f9101ade92ad839bc9" name="tests/bson-corpus/decimal128-2-valid-036.phpt" role="test" />
<file md5sum="4e5034286f541608d2b33aca6398de73" name="tests/bson-corpus/decimal128-2-valid-037.phpt" role="test" />
<file md5sum="e7252e40e67cd60d20b4718b4ba16ef6" name="tests/bson-corpus/decimal128-2-valid-038.phpt" role="test" />
<file md5sum="88b0173e05e093415083fd17406a8ae0" name="tests/bson-corpus/decimal128-2-valid-039.phpt" role="test" />
<file md5sum="fa82cc3d5be493a3ceb4fb38d6ab5267" name="tests/bson-corpus/decimal128-2-valid-040.phpt" role="test" />
<file md5sum="6445671c388fcc71180edc0e1461b3c6" name="tests/bson-corpus/decimal128-2-valid-041.phpt" role="test" />
<file md5sum="c011244d5ed85adc0eeb6bc411af3c77" name="tests/bson-corpus/decimal128-2-valid-042.phpt" role="test" />
<file md5sum="4b8cba61113053325624423f840d07eb" name="tests/bson-corpus/decimal128-2-valid-043.phpt" role="test" />
<file md5sum="7a3c43634667f64b0aae7075ef914682" name="tests/bson-corpus/decimal128-2-valid-044.phpt" role="test" />
<file md5sum="2647d390ceb2f81e710d82ddfd6f273c" name="tests/bson-corpus/decimal128-2-valid-045.phpt" role="test" />
<file md5sum="32f6abc6b58082c2141dc989ea349413" name="tests/bson-corpus/decimal128-2-valid-046.phpt" role="test" />
<file md5sum="c1bd96d2b8138ab299c29b6c266902da" name="tests/bson-corpus/decimal128-2-valid-047.phpt" role="test" />
<file md5sum="186bb114d5f3779a85561740bfa29240" name="tests/bson-corpus/decimal128-2-valid-048.phpt" role="test" />
<file md5sum="6ba6548ec25416196d36a08c8f3b7580" name="tests/bson-corpus/decimal128-2-valid-049.phpt" role="test" />
<file md5sum="ff01a7097f7c877f1943be959b80d5a3" name="tests/bson-corpus/decimal128-2-valid-050.phpt" role="test" />
<file md5sum="5381add30710b641345b8840d4f1bf84" name="tests/bson-corpus/decimal128-2-valid-051.phpt" role="test" />
<file md5sum="629f2c56cfbe2189fc29254bccb9b8e0" name="tests/bson-corpus/decimal128-2-valid-052.phpt" role="test" />
<file md5sum="ffdc837fb21ddf93f9709e8026652299" name="tests/bson-corpus/decimal128-2-valid-053.phpt" role="test" />
<file md5sum="a5878447b4e32364db64a9c93ec616e9" name="tests/bson-corpus/decimal128-2-valid-054.phpt" role="test" />
<file md5sum="a347cbdede675a48cc41badbfd7effd5" name="tests/bson-corpus/decimal128-2-valid-055.phpt" role="test" />
<file md5sum="50f429ef36974fc3d059ddb2328eedf0" name="tests/bson-corpus/decimal128-2-valid-056.phpt" role="test" />
<file md5sum="fe656db3f0c621a0f5eb94e7502864bf" name="tests/bson-corpus/decimal128-2-valid-057.phpt" role="test" />
<file md5sum="c92ffd0a1692916593ee2de9c9c6ac1f" name="tests/bson-corpus/decimal128-2-valid-058.phpt" role="test" />
<file md5sum="4ac8e7078192e42e4dc1dde944eed7bc" name="tests/bson-corpus/decimal128-2-valid-059.phpt" role="test" />
<file md5sum="f360ee5a9a26ac96fc5ee0e3ce50b3ef" name="tests/bson-corpus/decimal128-2-valid-060.phpt" role="test" />
<file md5sum="33226378bb0c279966d0ae98fb27554e" name="tests/bson-corpus/decimal128-2-valid-061.phpt" role="test" />
<file md5sum="7e42b5aa22e28785d76ceb0a5ade97e9" name="tests/bson-corpus/decimal128-2-valid-062.phpt" role="test" />
<file md5sum="15e05bb7d4de9bae7f1458343f36ac9f" name="tests/bson-corpus/decimal128-2-valid-063.phpt" role="test" />
<file md5sum="a6c6678dd5348816a61a41e4ec61a2ff" name="tests/bson-corpus/decimal128-2-valid-064.phpt" role="test" />
<file md5sum="cc05c7dac8a0ead9c46fe0a07d5c2164" name="tests/bson-corpus/decimal128-2-valid-065.phpt" role="test" />
<file md5sum="724100276a42dfd27b388a0e5efd498d" name="tests/bson-corpus/decimal128-2-valid-066.phpt" role="test" />
<file md5sum="e8f0fa361241363f50577d75b4e24f8d" name="tests/bson-corpus/decimal128-2-valid-067.phpt" role="test" />
<file md5sum="b07a18bd07d2bd0250fc41d84ef5d28d" name="tests/bson-corpus/decimal128-2-valid-068.phpt" role="test" />
<file md5sum="05f2f595336abe5c6c3c6e98a603ad12" name="tests/bson-corpus/decimal128-2-valid-069.phpt" role="test" />
<file md5sum="7be5fb3d2518b48762881731f8a1f809" name="tests/bson-corpus/decimal128-2-valid-070.phpt" role="test" />
<file md5sum="13752ade9b1d44648cee82acf78cee64" name="tests/bson-corpus/decimal128-2-valid-071.phpt" role="test" />
<file md5sum="ccd99d2d5a6246938d36cda50b0f449b" name="tests/bson-corpus/decimal128-2-valid-072.phpt" role="test" />
<file md5sum="3bfda7788aa33c8a06240871205d1e32" name="tests/bson-corpus/decimal128-2-valid-073.phpt" role="test" />
<file md5sum="72f72f8f249af0832bb8151a1cf59691" name="tests/bson-corpus/decimal128-2-valid-074.phpt" role="test" />
<file md5sum="1cffcc11e66c884ab0ff66081144baa8" name="tests/bson-corpus/decimal128-2-valid-075.phpt" role="test" />
<file md5sum="0283d995acec4a7952db741948162b53" name="tests/bson-corpus/decimal128-2-valid-076.phpt" role="test" />
<file md5sum="37f207b92b34d178dedbdf196a45dcb9" name="tests/bson-corpus/decimal128-2-valid-077.phpt" role="test" />
<file md5sum="9bcf356999f0bd8767261d8cee6567aa" name="tests/bson-corpus/decimal128-2-valid-078.phpt" role="test" />
<file md5sum="eff95b6516b729ec80ab27634b047b3b" name="tests/bson-corpus/decimal128-2-valid-079.phpt" role="test" />
<file md5sum="1535c9542ab51ce947a0229844cb1159" name="tests/bson-corpus/decimal128-2-valid-080.phpt" role="test" />
<file md5sum="72c8f9b3f1bbc3793b3897dcde98b185" name="tests/bson-corpus/decimal128-2-valid-081.phpt" role="test" />
<file md5sum="988358edc755774da91ae8e036e6f330" name="tests/bson-corpus/decimal128-2-valid-082.phpt" role="test" />
<file md5sum="8449063868c7078c844ea0353e12392d" name="tests/bson-corpus/decimal128-2-valid-083.phpt" role="test" />
<file md5sum="7901409614d56e86835d97755efbe927" name="tests/bson-corpus/decimal128-2-valid-084.phpt" role="test" />
<file md5sum="ea1abfd069a7ff24e447d996a404c63d" name="tests/bson-corpus/decimal128-2-valid-085.phpt" role="test" />
<file md5sum="3de31217d54f56be403267f41e238c2b" name="tests/bson-corpus/decimal128-2-valid-086.phpt" role="test" />
<file md5sum="21ea0d67772ba21de38876206877bf0e" name="tests/bson-corpus/decimal128-2-valid-087.phpt" role="test" />
<file md5sum="0bb26a44c2ae2be22e40d67c1cb90735" name="tests/bson-corpus/decimal128-2-valid-088.phpt" role="test" />
<file md5sum="3ad70a2f5233190c7ff8f5a0026d3fb6" name="tests/bson-corpus/decimal128-2-valid-089.phpt" role="test" />
<file md5sum="f78064a6d145e66d31391ff75ca14ef0" name="tests/bson-corpus/decimal128-2-valid-090.phpt" role="test" />
<file md5sum="85e01784b2fb103853cb8c7977c2b1b2" name="tests/bson-corpus/decimal128-2-valid-091.phpt" role="test" />
<file md5sum="e13bdd974d4e91009b78d29b47311be6" name="tests/bson-corpus/decimal128-2-valid-092.phpt" role="test" />
<file md5sum="98f340f6aea75095cacc28742e26ed0f" name="tests/bson-corpus/decimal128-2-valid-093.phpt" role="test" />
<file md5sum="db659d84605259969ecc0c4f0bf1ef77" name="tests/bson-corpus/decimal128-2-valid-094.phpt" role="test" />
<file md5sum="135e22cdba09010b35357fd83e69fa25" name="tests/bson-corpus/decimal128-2-valid-095.phpt" role="test" />
<file md5sum="43df03f766d7b73d20dfa628ce5a2789" name="tests/bson-corpus/decimal128-2-valid-096.phpt" role="test" />
<file md5sum="2544c121493bc6e1be45cddadcdd793e" name="tests/bson-corpus/decimal128-2-valid-097.phpt" role="test" />
<file md5sum="fa5b88bf5b1200657210163e663eac89" name="tests/bson-corpus/decimal128-2-valid-098.phpt" role="test" />
<file md5sum="988a407e1ef6cf8be8bf9224d7829c26" name="tests/bson-corpus/decimal128-2-valid-099.phpt" role="test" />
<file md5sum="4633926740b6ece1fd8fd201756ea9fc" name="tests/bson-corpus/decimal128-2-valid-100.phpt" role="test" />
<file md5sum="b5b21dd5f96c6df2f09e50636daef584" name="tests/bson-corpus/decimal128-2-valid-101.phpt" role="test" />
<file md5sum="406e01276827c3c0d895010f3854139a" name="tests/bson-corpus/decimal128-2-valid-102.phpt" role="test" />
<file md5sum="cbf91ab43a1b6bcd7646b1e8a7a32bea" name="tests/bson-corpus/decimal128-2-valid-103.phpt" role="test" />
<file md5sum="a57767b902c18f5ad1f511525dc8a934" name="tests/bson-corpus/decimal128-2-valid-104.phpt" role="test" />
<file md5sum="1f51031dd6120fc0f5d53ca13d0d251f" name="tests/bson-corpus/decimal128-2-valid-105.phpt" role="test" />
<file md5sum="b9fc4a6691c7954606553eaacfc98242" name="tests/bson-corpus/decimal128-2-valid-106.phpt" role="test" />
<file md5sum="91e279e096b4956b3e20d2157cf029e0" name="tests/bson-corpus/decimal128-2-valid-107.phpt" role="test" />
<file md5sum="f036833d51808c4ccc06b1d7342e75b1" name="tests/bson-corpus/decimal128-2-valid-108.phpt" role="test" />
<file md5sum="0a5f5986b4cef6f9a1c3f24796f655cc" name="tests/bson-corpus/decimal128-2-valid-109.phpt" role="test" />
<file md5sum="850c8371885e621a14319ef30823d63f" name="tests/bson-corpus/decimal128-2-valid-110.phpt" role="test" />
<file md5sum="3fc1076c5a759a62967e96bbda826ba4" name="tests/bson-corpus/decimal128-2-valid-111.phpt" role="test" />
<file md5sum="d33e2438cc5472883744d8e8d2635f71" name="tests/bson-corpus/decimal128-2-valid-112.phpt" role="test" />
<file md5sum="1c228103737aad44f12952ba13fb766c" name="tests/bson-corpus/decimal128-2-valid-113.phpt" role="test" />
<file md5sum="7a91a010680b55ffd726167f65c24904" name="tests/bson-corpus/decimal128-2-valid-114.phpt" role="test" />
<file md5sum="5667a619383ec4ae4312efcbf2c180d1" name="tests/bson-corpus/decimal128-2-valid-115.phpt" role="test" />
<file md5sum="c903782b8f4f6fafa969cafed31706ba" name="tests/bson-corpus/decimal128-2-valid-116.phpt" role="test" />
<file md5sum="2ecb80aadb80f03f2f6cfbab84749edd" name="tests/bson-corpus/decimal128-2-valid-117.phpt" role="test" />
<file md5sum="3dd542b557928081c036f533fe08e210" name="tests/bson-corpus/decimal128-2-valid-118.phpt" role="test" />
<file md5sum="625df8840a9c21b552a8ab79c6589c56" name="tests/bson-corpus/decimal128-2-valid-119.phpt" role="test" />
<file md5sum="26315b63c5ea5b2db2adc50b0e29f3a1" name="tests/bson-corpus/decimal128-2-valid-120.phpt" role="test" />
<file md5sum="ae0105879adf90c711100e546e32651f" name="tests/bson-corpus/decimal128-2-valid-121.phpt" role="test" />
<file md5sum="8a43675ce7fe983a84260dc6a966ed68" name="tests/bson-corpus/decimal128-2-valid-122.phpt" role="test" />
<file md5sum="024f18433a8c496375e6edea22b8706c" name="tests/bson-corpus/decimal128-2-valid-123.phpt" role="test" />
<file md5sum="5a0bc26b9750cf4b9904ca95035f4b32" name="tests/bson-corpus/decimal128-2-valid-124.phpt" role="test" />
<file md5sum="050ed6d772a24839576f3328291c91a2" name="tests/bson-corpus/decimal128-2-valid-125.phpt" role="test" />
<file md5sum="2ddad0fc63699392f4285ec09a848ac4" name="tests/bson-corpus/decimal128-2-valid-126.phpt" role="test" />
<file md5sum="c2458fd81ddd17872b43abaf00dbc20d" name="tests/bson-corpus/decimal128-2-valid-127.phpt" role="test" />
<file md5sum="5dd76e53120dc0a64a44d1932d18ef32" name="tests/bson-corpus/decimal128-2-valid-128.phpt" role="test" />
<file md5sum="64bd7100ad022fc085878fcb7ee41afe" name="tests/bson-corpus/decimal128-2-valid-129.phpt" role="test" />
<file md5sum="51406de0787a60e2e582e595b33badeb" name="tests/bson-corpus/decimal128-2-valid-130.phpt" role="test" />
<file md5sum="6623372f0b8e66d9585146e83ff917e8" name="tests/bson-corpus/decimal128-2-valid-131.phpt" role="test" />
<file md5sum="6257c6e4a35f5f2998f8e4435125bb91" name="tests/bson-corpus/decimal128-2-valid-132.phpt" role="test" />
<file md5sum="f393c373126f675d3905decc7f231c85" name="tests/bson-corpus/decimal128-2-valid-133.phpt" role="test" />
<file md5sum="c77aab4153ccb5a16264456ea6edded5" name="tests/bson-corpus/decimal128-2-valid-134.phpt" role="test" />
<file md5sum="ffb34dbc7f6a1a8acd512754d6e79cfa" name="tests/bson-corpus/decimal128-2-valid-135.phpt" role="test" />
<file md5sum="30ed4be2378b33db1d04b2917462cd76" name="tests/bson-corpus/decimal128-2-valid-136.phpt" role="test" />
<file md5sum="f18ba4545e1204135c615b308447d47e" name="tests/bson-corpus/decimal128-2-valid-137.phpt" role="test" />
<file md5sum="f0b3ab11a0a9ba9d40871e90de34b41d" name="tests/bson-corpus/decimal128-2-valid-138.phpt" role="test" />
<file md5sum="6a35e965d7ce6fd40fc0e7fc2c091289" name="tests/bson-corpus/decimal128-2-valid-139.phpt" role="test" />
<file md5sum="e6c010be7ed3d416e8089a959c8d745e" name="tests/bson-corpus/decimal128-2-valid-140.phpt" role="test" />
<file md5sum="c7f1126b2fb28dabee45846d260f05e0" name="tests/bson-corpus/decimal128-2-valid-141.phpt" role="test" />
<file md5sum="214afec9481b343a3feea6095cf7010f" name="tests/bson-corpus/decimal128-2-valid-142.phpt" role="test" />
<file md5sum="c6a9455454bbab3d6d4ac0193c304eeb" name="tests/bson-corpus/decimal128-2-valid-143.phpt" role="test" />
<file md5sum="bdba88fe0455d32178c4fc9dfe010335" name="tests/bson-corpus/decimal128-2-valid-144.phpt" role="test" />
<file md5sum="449afdc4b473224d9295b96a861e6915" name="tests/bson-corpus/decimal128-2-valid-145.phpt" role="test" />
<file md5sum="6e08ddf23c007cdf28d3ac57086d0fc0" name="tests/bson-corpus/decimal128-2-valid-146.phpt" role="test" />
<file md5sum="be920f0f728e6073e95ee1d64b0ef2bf" name="tests/bson-corpus/decimal128-2-valid-147.phpt" role="test" />
<file md5sum="cff7c99da96a2a5aaee956966d7eda61" name="tests/bson-corpus/decimal128-2-valid-148.phpt" role="test" />
<file md5sum="45bfc06f06be2d4c43d65ccf2510e793" name="tests/bson-corpus/decimal128-2-valid-149.phpt" role="test" />
<file md5sum="bdd47e2a97678678839e6f79399fbf13" name="tests/bson-corpus/decimal128-2-valid-150.phpt" role="test" />
<file md5sum="7226fcbe4f4592f55bf2b682c1bf5fe1" name="tests/bson-corpus/decimal128-2-valid-151.phpt" role="test" />
<file md5sum="0c82fef60426d39a15def51b7979e58a" name="tests/bson-corpus/decimal128-2-valid-152.phpt" role="test" />
<file md5sum="4fbf1e19d7f6df8dd99e1b001ab29aaf" name="tests/bson-corpus/decimal128-2-valid-153.phpt" role="test" />
<file md5sum="437693ec37fb699fd461a15ab03d6958" name="tests/bson-corpus/decimal128-2-valid-154.phpt" role="test" />
<file md5sum="04d19a4f052153ce438e7392fbede2ae" name="tests/bson-corpus/decimal128-2-valid-155.phpt" role="test" />
<file md5sum="83636b3c914c03294084335baad24308" name="tests/bson-corpus/decimal128-2-valid-156.phpt" role="test" />
<file md5sum="baed618c203d6939f981d76c52398e18" name="tests/bson-corpus/decimal128-2-valid-157.phpt" role="test" />
<file md5sum="d663958a9a04af4d7f440f6fbf01f218" name="tests/bson-corpus/decimal128-3-valid-001.phpt" role="test" />
<file md5sum="ecc07dbedc7fef899e29469b6d69cc77" name="tests/bson-corpus/decimal128-3-valid-002.phpt" role="test" />
<file md5sum="a335969c0bdbd3b2f293d6b190060607" name="tests/bson-corpus/decimal128-3-valid-003.phpt" role="test" />
<file md5sum="78595b3c17c04f349cff845cb9d9b297" name="tests/bson-corpus/decimal128-3-valid-004.phpt" role="test" />
<file md5sum="76b9fc8c1090c8a11663f918dca8db90" name="tests/bson-corpus/decimal128-3-valid-005.phpt" role="test" />
<file md5sum="ee876344d7b9dee33b3e8733f453e33a" name="tests/bson-corpus/decimal128-3-valid-006.phpt" role="test" />
<file md5sum="9cff4e8d62ddf9cc9e9ca3fe5c41b1e3" name="tests/bson-corpus/decimal128-3-valid-007.phpt" role="test" />
<file md5sum="91d898997cfe79ffee8379062559ea38" name="tests/bson-corpus/decimal128-3-valid-008.phpt" role="test" />
<file md5sum="169ca1653e767baaa0237566c7c83202" name="tests/bson-corpus/decimal128-3-valid-009.phpt" role="test" />
<file md5sum="4a86dffa38699350595f14cce92658e4" name="tests/bson-corpus/decimal128-3-valid-010.phpt" role="test" />
<file md5sum="08f15de590c2637d5b802a9290459121" name="tests/bson-corpus/decimal128-3-valid-011.phpt" role="test" />
<file md5sum="1d079a21207368445051a74f01a196bb" name="tests/bson-corpus/decimal128-3-valid-012.phpt" role="test" />
<file md5sum="5e85a73cee90262e146277cc095161a2" name="tests/bson-corpus/decimal128-3-valid-013.phpt" role="test" />
<file md5sum="bd803feb1215caf7264f07f4f13e9eeb" name="tests/bson-corpus/decimal128-3-valid-014.phpt" role="test" />
<file md5sum="a509970a1a2ac408f6352ba5a5d809db" name="tests/bson-corpus/decimal128-3-valid-015.phpt" role="test" />
<file md5sum="917dfdf1917ae90ca441f46797a0b36f" name="tests/bson-corpus/decimal128-3-valid-016.phpt" role="test" />
<file md5sum="b8c7e09412bf0009202af0f94cd8f4c2" name="tests/bson-corpus/decimal128-3-valid-017.phpt" role="test" />
<file md5sum="bc1c8501be2e8e5605efff6f9a5cfee8" name="tests/bson-corpus/decimal128-3-valid-018.phpt" role="test" />
<file md5sum="45efaf007818f2ab4ee9092497541cf1" name="tests/bson-corpus/decimal128-3-valid-019.phpt" role="test" />
<file md5sum="70281fc36152213a418150b2b5403eed" name="tests/bson-corpus/decimal128-3-valid-020.phpt" role="test" />
<file md5sum="df9b4abbb00157a20e7eb1515e1b92d2" name="tests/bson-corpus/decimal128-3-valid-021.phpt" role="test" />
<file md5sum="000060f6cb4188e439bacf6f05390406" name="tests/bson-corpus/decimal128-3-valid-022.phpt" role="test" />
<file md5sum="81f305b3f256dccab1ad47ffbacc5a0e" name="tests/bson-corpus/decimal128-3-valid-023.phpt" role="test" />
<file md5sum="bb8b21b4cff570a41127872a21cfbe1e" name="tests/bson-corpus/decimal128-3-valid-024.phpt" role="test" />
<file md5sum="4dd8129b25ba91c3d8b39061a2586e85" name="tests/bson-corpus/decimal128-3-valid-025.phpt" role="test" />
<file md5sum="15c58ac7ae27b71d678eb272134d4ac3" name="tests/bson-corpus/decimal128-3-valid-026.phpt" role="test" />
<file md5sum="c0092a6dbe98463d593560951b9ffcf8" name="tests/bson-corpus/decimal128-3-valid-027.phpt" role="test" />
<file md5sum="037a779426adf3a0bd0c142461fe1a40" name="tests/bson-corpus/decimal128-3-valid-028.phpt" role="test" />
<file md5sum="71b808193d118e1f2584196053f0572f" name="tests/bson-corpus/decimal128-3-valid-029.phpt" role="test" />
<file md5sum="5bdc09c50157a4c6da25cc1fbd89ca86" name="tests/bson-corpus/decimal128-3-valid-030.phpt" role="test" />
<file md5sum="617a9aa32ddafab1040d42299b4a569c" name="tests/bson-corpus/decimal128-3-valid-031.phpt" role="test" />
<file md5sum="aa944ceab34cf6a7212d3dfb1acbac1b" name="tests/bson-corpus/decimal128-3-valid-032.phpt" role="test" />
<file md5sum="293cc8ca7e1ac2882f792e03296dccb5" name="tests/bson-corpus/decimal128-3-valid-033.phpt" role="test" />
<file md5sum="caa1404d8010c57a2c44879e7d6a6cef" name="tests/bson-corpus/decimal128-3-valid-034.phpt" role="test" />
<file md5sum="14f7ca7e55262fbf31ae07ed24e80ef9" name="tests/bson-corpus/decimal128-3-valid-035.phpt" role="test" />
<file md5sum="a6ff5bda0b279be4bd8b8683df768392" name="tests/bson-corpus/decimal128-3-valid-036.phpt" role="test" />
<file md5sum="57d2969629d1259ecd78cf5dbb3a8480" name="tests/bson-corpus/decimal128-3-valid-037.phpt" role="test" />
<file md5sum="39fa63f7acc6f875df47208ee5ff8780" name="tests/bson-corpus/decimal128-3-valid-038.phpt" role="test" />
<file md5sum="e489ba54d002683333a38b3d3ae3a68c" name="tests/bson-corpus/decimal128-3-valid-039.phpt" role="test" />
<file md5sum="45a147ada15a6cd19d4b1f5d84c61f3b" name="tests/bson-corpus/decimal128-3-valid-040.phpt" role="test" />
<file md5sum="a50b5de4fc6b56718b73dc3eeaf90d84" name="tests/bson-corpus/decimal128-3-valid-041.phpt" role="test" />
<file md5sum="eb0bfd58f7e7c150ae6ba8a8cc694bf2" name="tests/bson-corpus/decimal128-3-valid-042.phpt" role="test" />
<file md5sum="de7928d46237131c3f62a0cdea6302ff" name="tests/bson-corpus/decimal128-3-valid-043.phpt" role="test" />
<file md5sum="ba4a91f8f44c2fe060585dfd0fe55541" name="tests/bson-corpus/decimal128-3-valid-044.phpt" role="test" />
<file md5sum="201ab1261f9e00ad51e34ff7cbac385d" name="tests/bson-corpus/decimal128-3-valid-045.phpt" role="test" />
<file md5sum="73cd0ab3b85b7876b62dafcc6b47862a" name="tests/bson-corpus/decimal128-3-valid-046.phpt" role="test" />
<file md5sum="e9fc32da279c5eb92658689a10235399" name="tests/bson-corpus/decimal128-3-valid-047.phpt" role="test" />
<file md5sum="ea0c1bd4adcc97adea6060fe037a39ff" name="tests/bson-corpus/decimal128-3-valid-048.phpt" role="test" />
<file md5sum="583fb51b1b9edd2fe6d762fa4e1f080f" name="tests/bson-corpus/decimal128-3-valid-049.phpt" role="test" />
<file md5sum="3f34801e62a987e85f69ed36161263e3" name="tests/bson-corpus/decimal128-3-valid-050.phpt" role="test" />
<file md5sum="175917a95c4bb895a655dd34a5c45241" name="tests/bson-corpus/decimal128-3-valid-051.phpt" role="test" />
<file md5sum="da519fcd6365dfa317b47361ee5803aa" name="tests/bson-corpus/decimal128-3-valid-052.phpt" role="test" />
<file md5sum="d092cedcd919cdb4058bd3ae510fd1ad" name="tests/bson-corpus/decimal128-3-valid-053.phpt" role="test" />
<file md5sum="e850354f3236c861c6da9705f1486972" name="tests/bson-corpus/decimal128-3-valid-054.phpt" role="test" />
<file md5sum="bfe45e890c0fdb6ed790fb3a498d6af9" name="tests/bson-corpus/decimal128-3-valid-055.phpt" role="test" />
<file md5sum="5d501aee839b508cf2ef6295514ca94f" name="tests/bson-corpus/decimal128-3-valid-056.phpt" role="test" />
<file md5sum="12491275e5ec45c85a7b1df192bd4f3f" name="tests/bson-corpus/decimal128-3-valid-057.phpt" role="test" />
<file md5sum="14931a4e58c5ab8ac0fded043e177ea0" name="tests/bson-corpus/decimal128-3-valid-058.phpt" role="test" />
<file md5sum="89e0b5c575e0a05183d4083475a9e1e6" name="tests/bson-corpus/decimal128-3-valid-059.phpt" role="test" />
<file md5sum="1a1bcd12962fc1d18765b78d160cae45" name="tests/bson-corpus/decimal128-3-valid-060.phpt" role="test" />
<file md5sum="bff26b7bb5f5f026c1bef71daac5471a" name="tests/bson-corpus/decimal128-3-valid-061.phpt" role="test" />
<file md5sum="c424ce2eeb8b3e9d731268e2ecb586c8" name="tests/bson-corpus/decimal128-3-valid-062.phpt" role="test" />
<file md5sum="f9810126ba6338721bf810fc2f7df13c" name="tests/bson-corpus/decimal128-3-valid-063.phpt" role="test" />
<file md5sum="75dbcf3f9d389f3d01d3783d3a717312" name="tests/bson-corpus/decimal128-3-valid-064.phpt" role="test" />
<file md5sum="1962c74102261ec0275d1979f8b08a36" name="tests/bson-corpus/decimal128-3-valid-065.phpt" role="test" />
<file md5sum="4f880060a5188ef62155d868f1cfc1ed" name="tests/bson-corpus/decimal128-3-valid-066.phpt" role="test" />
<file md5sum="34dee229164dbb8d587755108dc3add6" name="tests/bson-corpus/decimal128-3-valid-067.phpt" role="test" />
<file md5sum="0481384bfb647021ec33ff435b5a16fc" name="tests/bson-corpus/decimal128-3-valid-068.phpt" role="test" />
<file md5sum="0ccf9fbb134c0f197c9427258ad9cf9a" name="tests/bson-corpus/decimal128-3-valid-069.phpt" role="test" />
<file md5sum="ebe453e7e8dafdb214cfbece655f3ba1" name="tests/bson-corpus/decimal128-3-valid-070.phpt" role="test" />
<file md5sum="e03aeca7a1854f872b573a6459237add" name="tests/bson-corpus/decimal128-3-valid-071.phpt" role="test" />
<file md5sum="ccc504adf424fa6c243daef5bbd14587" name="tests/bson-corpus/decimal128-3-valid-072.phpt" role="test" />
<file md5sum="cc1ad4185d5c5f656b0a897138532398" name="tests/bson-corpus/decimal128-3-valid-073.phpt" role="test" />
<file md5sum="c192e80107cd9d875fa116e476023243" name="tests/bson-corpus/decimal128-3-valid-074.phpt" role="test" />
<file md5sum="02156edeedc363f26d852f984f8212b4" name="tests/bson-corpus/decimal128-3-valid-075.phpt" role="test" />
<file md5sum="95aad9442987108e0b4cce2e4721899e" name="tests/bson-corpus/decimal128-3-valid-076.phpt" role="test" />
<file md5sum="8cb6067468db7aa9830d7e67b31e5049" name="tests/bson-corpus/decimal128-3-valid-077.phpt" role="test" />
<file md5sum="1d65b3edbf22c5db259eb2f3f03eb27c" name="tests/bson-corpus/decimal128-3-valid-078.phpt" role="test" />
<file md5sum="0feb8079732e1ad8a7c32976eb395a0f" name="tests/bson-corpus/decimal128-3-valid-079.phpt" role="test" />
<file md5sum="9c3a99144f631018d8bb67fd90fc11b0" name="tests/bson-corpus/decimal128-3-valid-080.phpt" role="test" />
<file md5sum="3f1a36b46cf7cc8a5cfe31d704f47c20" name="tests/bson-corpus/decimal128-3-valid-081.phpt" role="test" />
<file md5sum="93fe3ed288ee37162e75724e69258c3d" name="tests/bson-corpus/decimal128-3-valid-082.phpt" role="test" />
<file md5sum="857d01afef9513a561e89e65ecc3be65" name="tests/bson-corpus/decimal128-3-valid-083.phpt" role="test" />
<file md5sum="418e701672877a981f29a252d18649b7" name="tests/bson-corpus/decimal128-3-valid-084.phpt" role="test" />
<file md5sum="e0bd1763ce58b81b4b642ce7d847760d" name="tests/bson-corpus/decimal128-3-valid-085.phpt" role="test" />
<file md5sum="f8219f82f090ab31c72990f3e69f7de9" name="tests/bson-corpus/decimal128-3-valid-086.phpt" role="test" />
<file md5sum="135c5def9e53d1330e40d0c9db005f82" name="tests/bson-corpus/decimal128-3-valid-087.phpt" role="test" />
<file md5sum="eae1e8e58678ebc4900e1e76d8b707f7" name="tests/bson-corpus/decimal128-3-valid-088.phpt" role="test" />
<file md5sum="9da9ebdb272e62cd49ad55c953d2f585" name="tests/bson-corpus/decimal128-3-valid-089.phpt" role="test" />
<file md5sum="1b0308b459131414d4fdcbb83ce644be" name="tests/bson-corpus/decimal128-3-valid-090.phpt" role="test" />
<file md5sum="f6831b6281b8792c73c5e7e1a62f8d09" name="tests/bson-corpus/decimal128-3-valid-091.phpt" role="test" />
<file md5sum="f7f4ddb3747783588da39fcbbf877c7f" name="tests/bson-corpus/decimal128-3-valid-092.phpt" role="test" />
<file md5sum="9d931b0e25e8c506eb100ffcd40a81d2" name="tests/bson-corpus/decimal128-3-valid-093.phpt" role="test" />
<file md5sum="5569a2c40ab01148442a3e10317013f7" name="tests/bson-corpus/decimal128-3-valid-094.phpt" role="test" />
<file md5sum="6ded8b0607a78b0af47c70b5e40fa553" name="tests/bson-corpus/decimal128-3-valid-095.phpt" role="test" />
<file md5sum="87f2b78c9bde6247cd0e5df3b8974e13" name="tests/bson-corpus/decimal128-3-valid-096.phpt" role="test" />
<file md5sum="12c9214689823bd5e5185a9e70efc367" name="tests/bson-corpus/decimal128-3-valid-097.phpt" role="test" />
<file md5sum="a03dee4e37647a6d75d47e129c21e5ff" name="tests/bson-corpus/decimal128-3-valid-098.phpt" role="test" />
<file md5sum="1e40eaebd2f828048b3d2527cc28215a" name="tests/bson-corpus/decimal128-3-valid-099.phpt" role="test" />
<file md5sum="15f98c55d09d08ceefe37625e7968450" name="tests/bson-corpus/decimal128-3-valid-100.phpt" role="test" />
<file md5sum="86d1d02e3200ef3e6cb0ec6d56dffa7a" name="tests/bson-corpus/decimal128-3-valid-101.phpt" role="test" />
<file md5sum="ce2282f2a0b6a3a5dec57975a245a45e" name="tests/bson-corpus/decimal128-3-valid-102.phpt" role="test" />
<file md5sum="89ac6a9b7144480acf3a4d2e206d84a8" name="tests/bson-corpus/decimal128-3-valid-103.phpt" role="test" />
<file md5sum="7ee902971ee8a202a473da731afb9cfe" name="tests/bson-corpus/decimal128-3-valid-104.phpt" role="test" />
<file md5sum="aac8ebf753b56938213af2bc26bfe8e4" name="tests/bson-corpus/decimal128-3-valid-105.phpt" role="test" />
<file md5sum="77d21e1be55cc8a0455fb10831a345a5" name="tests/bson-corpus/decimal128-3-valid-106.phpt" role="test" />
<file md5sum="fc3e6cc66bf666004b1694d691fcef25" name="tests/bson-corpus/decimal128-3-valid-107.phpt" role="test" />
<file md5sum="c9857e3a53e2b492d4649fad34114fdc" name="tests/bson-corpus/decimal128-3-valid-108.phpt" role="test" />
<file md5sum="4acaf250c963be852e98e56858a02e0c" name="tests/bson-corpus/decimal128-3-valid-109.phpt" role="test" />
<file md5sum="086e06d076ced5b52258b2a33771c183" name="tests/bson-corpus/decimal128-3-valid-110.phpt" role="test" />
<file md5sum="8d91b9a7cb540d4387a505f58574108e" name="tests/bson-corpus/decimal128-3-valid-111.phpt" role="test" />
<file md5sum="34e1796deebbc24b7f5126d3fa76f492" name="tests/bson-corpus/decimal128-3-valid-112.phpt" role="test" />
<file md5sum="6876f7d97b31d9de1c5ef80cb2da3e46" name="tests/bson-corpus/decimal128-3-valid-113.phpt" role="test" />
<file md5sum="78db49b179f3aa2adf753ef414af4b07" name="tests/bson-corpus/decimal128-3-valid-114.phpt" role="test" />
<file md5sum="85077ceb495972ce1666ce2ca6bff241" name="tests/bson-corpus/decimal128-3-valid-115.phpt" role="test" />
<file md5sum="25d5f3a37400b59d830548d0b19f7167" name="tests/bson-corpus/decimal128-3-valid-116.phpt" role="test" />
<file md5sum="7bd291561573e8b297a283f71d0f833c" name="tests/bson-corpus/decimal128-3-valid-117.phpt" role="test" />
<file md5sum="3018d5985b433ad8327198371b274b69" name="tests/bson-corpus/decimal128-3-valid-118.phpt" role="test" />
<file md5sum="ab9e8e91b98e0f778fcdeb46ea0dba7a" name="tests/bson-corpus/decimal128-3-valid-119.phpt" role="test" />
<file md5sum="7245422896d49aa46f13d735bf1f0b60" name="tests/bson-corpus/decimal128-3-valid-120.phpt" role="test" />
<file md5sum="be7cc343096711e5c603aeb5bf9c8e1e" name="tests/bson-corpus/decimal128-3-valid-121.phpt" role="test" />
<file md5sum="fde4542bd5195f65a89f87fe592f5b68" name="tests/bson-corpus/decimal128-3-valid-122.phpt" role="test" />
<file md5sum="5784f8917972cf55088e0187fbee9eda" name="tests/bson-corpus/decimal128-3-valid-123.phpt" role="test" />
<file md5sum="4f8fbc6b7ddc23a24d9465cb3b65c935" name="tests/bson-corpus/decimal128-3-valid-124.phpt" role="test" />
<file md5sum="31740f132c125df94563a23df30f4062" name="tests/bson-corpus/decimal128-3-valid-125.phpt" role="test" />
<file md5sum="e905661301fb137f8e8af2022b094c8b" name="tests/bson-corpus/decimal128-3-valid-126.phpt" role="test" />
<file md5sum="d7f206136f1eeaa187435a8de879fe9b" name="tests/bson-corpus/decimal128-3-valid-127.phpt" role="test" />
<file md5sum="fd5d03e6d489d9483e0211e89d112db9" name="tests/bson-corpus/decimal128-3-valid-128.phpt" role="test" />
<file md5sum="1d8882fe77db8d8e9ff668d55c1aa7cc" name="tests/bson-corpus/decimal128-3-valid-129.phpt" role="test" />
<file md5sum="d192443cdd874b506af216c18260692e" name="tests/bson-corpus/decimal128-3-valid-130.phpt" role="test" />
<file md5sum="b9ebf345c533fe2fb31e3a976c5a2586" name="tests/bson-corpus/decimal128-3-valid-131.phpt" role="test" />
<file md5sum="2da4817354b049bf98d75f5cffb50df8" name="tests/bson-corpus/decimal128-3-valid-132.phpt" role="test" />
<file md5sum="c55b4edfaae4da641cbef9e43ae27749" name="tests/bson-corpus/decimal128-3-valid-133.phpt" role="test" />
<file md5sum="716b0e43ec01e9bdb8f1d07cb95d2d47" name="tests/bson-corpus/decimal128-3-valid-134.phpt" role="test" />
<file md5sum="4311a8f3f7f03b83bc8aa50c3b41a7b3" name="tests/bson-corpus/decimal128-3-valid-135.phpt" role="test" />
<file md5sum="f02d6dba5d13a1a553f4df0325ce8c95" name="tests/bson-corpus/decimal128-3-valid-136.phpt" role="test" />
<file md5sum="b427a8b34df8dfea8b658f0e397e6410" name="tests/bson-corpus/decimal128-3-valid-137.phpt" role="test" />
<file md5sum="412109a5ad9bace87a5e548320c95b63" name="tests/bson-corpus/decimal128-3-valid-138.phpt" role="test" />
<file md5sum="24b1923c0de2c035767ca0c2413a6877" name="tests/bson-corpus/decimal128-3-valid-139.phpt" role="test" />
<file md5sum="86d1daec5860decc7fed2c0d24a72010" name="tests/bson-corpus/decimal128-3-valid-140.phpt" role="test" />
<file md5sum="9df0580b1518470f5071f83d5b5907e4" name="tests/bson-corpus/decimal128-3-valid-141.phpt" role="test" />
<file md5sum="96d326ae41086e9e82a065ac0c2a5470" name="tests/bson-corpus/decimal128-3-valid-142.phpt" role="test" />
<file md5sum="dca7cd61fc27d3993dd2702d1078ccea" name="tests/bson-corpus/decimal128-3-valid-143.phpt" role="test" />
<file md5sum="2104f5bea79ea21b06ad36af1fef34f5" name="tests/bson-corpus/decimal128-3-valid-144.phpt" role="test" />
<file md5sum="db364e0176cd7bb05ca67aaea34c07ec" name="tests/bson-corpus/decimal128-3-valid-145.phpt" role="test" />
<file md5sum="041e861f5feabee285641bede7658962" name="tests/bson-corpus/decimal128-3-valid-146.phpt" role="test" />
<file md5sum="51277ab6f97e3f621cb44ce6ac3079b1" name="tests/bson-corpus/decimal128-3-valid-147.phpt" role="test" />
<file md5sum="9c0090cb83d66cb6779cfad5fbe2aeb5" name="tests/bson-corpus/decimal128-3-valid-148.phpt" role="test" />
<file md5sum="6b60295daa8dc395222a709fac2dbe69" name="tests/bson-corpus/decimal128-3-valid-149.phpt" role="test" />
<file md5sum="4848a67e7d194c36c2559bf4f16a75fa" name="tests/bson-corpus/decimal128-3-valid-150.phpt" role="test" />
<file md5sum="c7ab36909fd42b42ef9cfe62055ae48e" name="tests/bson-corpus/decimal128-3-valid-151.phpt" role="test" />
<file md5sum="8095127bc9738bdc43d73d620ec60085" name="tests/bson-corpus/decimal128-3-valid-152.phpt" role="test" />
<file md5sum="8c0516cd86dba89635450c4c2f16a1c8" name="tests/bson-corpus/decimal128-3-valid-153.phpt" role="test" />
<file md5sum="0b2d7af4fa199f375f7f7559e40c8437" name="tests/bson-corpus/decimal128-3-valid-154.phpt" role="test" />
<file md5sum="e4913bfa055eec06944d154c22254e34" name="tests/bson-corpus/decimal128-3-valid-155.phpt" role="test" />
<file md5sum="1bbb49f4acb8e747c671bec4ded1625b" name="tests/bson-corpus/decimal128-3-valid-156.phpt" role="test" />
<file md5sum="2055c345977112555436fd1032088550" name="tests/bson-corpus/decimal128-3-valid-157.phpt" role="test" />
<file md5sum="aee3703ff7f9d3574999ed4192ee5a7b" name="tests/bson-corpus/decimal128-3-valid-158.phpt" role="test" />
<file md5sum="6c44c9da5be7d14d7e1e64df0c05ab50" name="tests/bson-corpus/decimal128-3-valid-159.phpt" role="test" />
<file md5sum="fc733a47ea1bca924b7758b142feb60f" name="tests/bson-corpus/decimal128-3-valid-160.phpt" role="test" />
<file md5sum="9a1bc4666bf48a3f186158a275da92ee" name="tests/bson-corpus/decimal128-3-valid-161.phpt" role="test" />
<file md5sum="28ea08eae3926df32eac21f9c4fcf9f5" name="tests/bson-corpus/decimal128-3-valid-162.phpt" role="test" />
<file md5sum="c977800cce3174c016215be8b13895b8" name="tests/bson-corpus/decimal128-3-valid-163.phpt" role="test" />
<file md5sum="1205216679be2c1ef9701e5cdca89af3" name="tests/bson-corpus/decimal128-3-valid-164.phpt" role="test" />
<file md5sum="f5c5d28cb2c3e25959bcd8b8cfb18067" name="tests/bson-corpus/decimal128-3-valid-165.phpt" role="test" />
<file md5sum="57dfdcde16d01df36704cc544ccab7a9" name="tests/bson-corpus/decimal128-3-valid-166.phpt" role="test" />
<file md5sum="cb7888fb2fe79a6e4a4a24638ab3d6cb" name="tests/bson-corpus/decimal128-3-valid-167.phpt" role="test" />
<file md5sum="fc0ef710100ec9c010cab2b48bac6ad9" name="tests/bson-corpus/decimal128-3-valid-168.phpt" role="test" />
<file md5sum="ab255604f85bb4de07795ef64f5f52ff" name="tests/bson-corpus/decimal128-3-valid-169.phpt" role="test" />
<file md5sum="4c37d21a51e323aa2f5a9ce057370dfb" name="tests/bson-corpus/decimal128-3-valid-170.phpt" role="test" />
<file md5sum="e8004efddcf823a90d8866b01fe47484" name="tests/bson-corpus/decimal128-3-valid-171.phpt" role="test" />
<file md5sum="b5cd969bf4aa15beb8fd9d86da5e2c6b" name="tests/bson-corpus/decimal128-3-valid-172.phpt" role="test" />
<file md5sum="8e791e98d3e9d8b929aa776689060e73" name="tests/bson-corpus/decimal128-3-valid-173.phpt" role="test" />
<file md5sum="1a0aab89867a192127bee79116325b87" name="tests/bson-corpus/decimal128-3-valid-174.phpt" role="test" />
<file md5sum="92ee0cde9906482b7ba70af64b7db652" name="tests/bson-corpus/decimal128-3-valid-175.phpt" role="test" />
<file md5sum="47d81bd68b7d6cf7400e7bc7800b802f" name="tests/bson-corpus/decimal128-3-valid-176.phpt" role="test" />
<file md5sum="e9d3ecff8a2629451dfbd6ce8433ad16" name="tests/bson-corpus/decimal128-3-valid-177.phpt" role="test" />
<file md5sum="e2006319591744837f5c63c889a33a64" name="tests/bson-corpus/decimal128-3-valid-178.phpt" role="test" />
<file md5sum="31151203e48881eddcf122554c0066e2" name="tests/bson-corpus/decimal128-3-valid-179.phpt" role="test" />
<file md5sum="accf0f5388ceca4eeb1e353a58652381" name="tests/bson-corpus/decimal128-3-valid-180.phpt" role="test" />
<file md5sum="88889b93a559042a1d36b4613cb6e9d5" name="tests/bson-corpus/decimal128-3-valid-181.phpt" role="test" />
<file md5sum="8c394b5ae827d370d63336e610c82914" name="tests/bson-corpus/decimal128-3-valid-182.phpt" role="test" />
<file md5sum="37076846368569fc63d33fdb88a1b54d" name="tests/bson-corpus/decimal128-3-valid-183.phpt" role="test" />
<file md5sum="8eae26029ee22ecb86f41f180a5ca116" name="tests/bson-corpus/decimal128-3-valid-184.phpt" role="test" />
<file md5sum="31d3465dee3f4f873a2f07a9f7e5cbb1" name="tests/bson-corpus/decimal128-3-valid-185.phpt" role="test" />
<file md5sum="c20fffbdac614f64cdf9e0c0a4031ed5" name="tests/bson-corpus/decimal128-3-valid-186.phpt" role="test" />
<file md5sum="e661acef71d97e07e5e014db6b35882c" name="tests/bson-corpus/decimal128-3-valid-187.phpt" role="test" />
<file md5sum="868e5c102d17283c5d409860fccbfa4e" name="tests/bson-corpus/decimal128-3-valid-188.phpt" role="test" />
<file md5sum="bbea4f1602b3984917476d1e690ad295" name="tests/bson-corpus/decimal128-3-valid-189.phpt" role="test" />
<file md5sum="c4124a2fef2a6756a445119f5c9e87eb" name="tests/bson-corpus/decimal128-3-valid-190.phpt" role="test" />
<file md5sum="1947f48464ce9e2cf13063c8177c2242" name="tests/bson-corpus/decimal128-3-valid-191.phpt" role="test" />
<file md5sum="d18377558e6bd3ec8873415db1385f01" name="tests/bson-corpus/decimal128-3-valid-192.phpt" role="test" />
<file md5sum="4610f63580b90439588bafb24b7e3aec" name="tests/bson-corpus/decimal128-3-valid-193.phpt" role="test" />
<file md5sum="e2a0c6f4fca7db4fa4c246140e626dfa" name="tests/bson-corpus/decimal128-3-valid-194.phpt" role="test" />
<file md5sum="61fd9c77baa3e055a3dd1d583c735ad8" name="tests/bson-corpus/decimal128-3-valid-195.phpt" role="test" />
<file md5sum="a2dd41853291597b6e8a42659556f5ae" name="tests/bson-corpus/decimal128-3-valid-196.phpt" role="test" />
<file md5sum="fa0bf2f4dd8eef8f6e01fbc6ae34fbe4" name="tests/bson-corpus/decimal128-3-valid-197.phpt" role="test" />
<file md5sum="7d155cbc68bb1d0811799b8b956ea349" name="tests/bson-corpus/decimal128-3-valid-198.phpt" role="test" />
<file md5sum="8da630bd40cea241eaded08f2f0c85b7" name="tests/bson-corpus/decimal128-3-valid-199.phpt" role="test" />
<file md5sum="d18dada8921aa158fbd3c7f8ca7e5311" name="tests/bson-corpus/decimal128-3-valid-200.phpt" role="test" />
<file md5sum="d5c7a07be870a2ef38072661d54e96f8" name="tests/bson-corpus/decimal128-3-valid-201.phpt" role="test" />
<file md5sum="958fe772e4105738c3fdec3f12626e91" name="tests/bson-corpus/decimal128-3-valid-202.phpt" role="test" />
<file md5sum="7d26387b1ce9f36475e82b961132fe20" name="tests/bson-corpus/decimal128-3-valid-203.phpt" role="test" />
<file md5sum="10cff8b9ca7de0a9f65aa07637f1fbe1" name="tests/bson-corpus/decimal128-3-valid-204.phpt" role="test" />
<file md5sum="c48e34f0cd62955e21eb7eb4e91bc2e6" name="tests/bson-corpus/decimal128-3-valid-205.phpt" role="test" />
<file md5sum="d9756c9baeb4f4a380e06979e89ba8c6" name="tests/bson-corpus/decimal128-3-valid-206.phpt" role="test" />
<file md5sum="065368cc47839cb8f09fc29ef5be3356" name="tests/bson-corpus/decimal128-3-valid-207.phpt" role="test" />
<file md5sum="88e8a54b62e646b8f0018cebd13c91ce" name="tests/bson-corpus/decimal128-3-valid-208.phpt" role="test" />
<file md5sum="2a8907082d7e1562502089d3780da0da" name="tests/bson-corpus/decimal128-3-valid-209.phpt" role="test" />
<file md5sum="024b2807906b89941d8cb6cc7edcfa35" name="tests/bson-corpus/decimal128-3-valid-210.phpt" role="test" />
<file md5sum="a7a55d1d5240dfe00797f948a9b4ff14" name="tests/bson-corpus/decimal128-3-valid-211.phpt" role="test" />
<file md5sum="a90fa6dfcf451b906ef8dc4de0320e8c" name="tests/bson-corpus/decimal128-3-valid-212.phpt" role="test" />
<file md5sum="18e2d5bc2b07741bab2528993d781314" name="tests/bson-corpus/decimal128-3-valid-213.phpt" role="test" />
<file md5sum="37b0645de83b792bf815ad23103ab566" name="tests/bson-corpus/decimal128-3-valid-214.phpt" role="test" />
<file md5sum="4b9ffd465539a046a3cb246224d72f95" name="tests/bson-corpus/decimal128-3-valid-215.phpt" role="test" />
<file md5sum="984d8afafc82fad297461ba62cd8ac1d" name="tests/bson-corpus/decimal128-3-valid-216.phpt" role="test" />
<file md5sum="e3cc278118c21d942fc1ae11b687648b" name="tests/bson-corpus/decimal128-3-valid-217.phpt" role="test" />
<file md5sum="1173a48f6361e2de3dd61e6338ac788f" name="tests/bson-corpus/decimal128-3-valid-218.phpt" role="test" />
<file md5sum="96f2a2a5fe40e0c7c250b9ecc8348957" name="tests/bson-corpus/decimal128-3-valid-219.phpt" role="test" />
<file md5sum="dac9801678b61c05275f890be26ed6fa" name="tests/bson-corpus/decimal128-3-valid-220.phpt" role="test" />
<file md5sum="fa7d9008c0ce8501b8dd88c6f1979629" name="tests/bson-corpus/decimal128-3-valid-221.phpt" role="test" />
<file md5sum="7e4ebd6890f9f7a826fd305308d14391" name="tests/bson-corpus/decimal128-3-valid-222.phpt" role="test" />
<file md5sum="5062c83925f58f0a6862aa55b1a51ef3" name="tests/bson-corpus/decimal128-3-valid-223.phpt" role="test" />
<file md5sum="3bb84b7df212ca8940660ebe7d874a59" name="tests/bson-corpus/decimal128-3-valid-224.phpt" role="test" />
<file md5sum="74bf40280e720d2c4d2c4cac267fdad2" name="tests/bson-corpus/decimal128-3-valid-225.phpt" role="test" />
<file md5sum="b29d6344aa7230063e17e18a5a8afcdf" name="tests/bson-corpus/decimal128-3-valid-226.phpt" role="test" />
<file md5sum="534c33801721b90c1a05de585b27c346" name="tests/bson-corpus/decimal128-3-valid-227.phpt" role="test" />
<file md5sum="e8e1217c0cfcae77f1475428e2864833" name="tests/bson-corpus/decimal128-3-valid-228.phpt" role="test" />
<file md5sum="55c36373b5bb97d9458583e40c679154" name="tests/bson-corpus/decimal128-3-valid-229.phpt" role="test" />
<file md5sum="2b3a49f63c44e233a069c2cfc5ab6418" name="tests/bson-corpus/decimal128-3-valid-230.phpt" role="test" />
<file md5sum="7c7557f76a059b2702dd51658fb9b5fe" name="tests/bson-corpus/decimal128-3-valid-231.phpt" role="test" />
<file md5sum="b520fa6b84bd9f1ccae80fcb451d71b1" name="tests/bson-corpus/decimal128-3-valid-232.phpt" role="test" />
<file md5sum="9d29422ba6241564eaddded8d407dedf" name="tests/bson-corpus/decimal128-3-valid-233.phpt" role="test" />
<file md5sum="dacc33bbee339c26e7de1cda145afd02" name="tests/bson-corpus/decimal128-3-valid-234.phpt" role="test" />
<file md5sum="a70f999ff669cdba90b3010f0d6c3d88" name="tests/bson-corpus/decimal128-3-valid-235.phpt" role="test" />
<file md5sum="bc46984804f3efd6a5d727b012a4ef5c" name="tests/bson-corpus/decimal128-3-valid-236.phpt" role="test" />
<file md5sum="a4e1ecaa13dd625af1df3785ec5fb7d0" name="tests/bson-corpus/decimal128-3-valid-237.phpt" role="test" />
<file md5sum="a9563619eeb12e76dadb211e6e411096" name="tests/bson-corpus/decimal128-3-valid-238.phpt" role="test" />
<file md5sum="b2483a48520d01b99ee3782a545f620e" name="tests/bson-corpus/decimal128-3-valid-239.phpt" role="test" />
<file md5sum="beb70a804e04565272f7bcacdf106fdd" name="tests/bson-corpus/decimal128-3-valid-240.phpt" role="test" />
<file md5sum="0f3b075ad241dbb48003cc1ae4c5546d" name="tests/bson-corpus/decimal128-3-valid-241.phpt" role="test" />
<file md5sum="aa8d6423927cd6fa40dd0b0f750ab5cb" name="tests/bson-corpus/decimal128-3-valid-242.phpt" role="test" />
<file md5sum="d52a67c83822741cb3d4b3eef7c5bcb3" name="tests/bson-corpus/decimal128-3-valid-243.phpt" role="test" />
<file md5sum="fe2289f275359d280f1247ae727b842e" name="tests/bson-corpus/decimal128-3-valid-244.phpt" role="test" />
<file md5sum="9e5227bb6e0c2b52b6a466ac207c52ee" name="tests/bson-corpus/decimal128-3-valid-245.phpt" role="test" />
<file md5sum="7c7b2f334c3deb4c8520819a6a5c0753" name="tests/bson-corpus/decimal128-3-valid-246.phpt" role="test" />
<file md5sum="c2a4dee2ffb3ac99cf322056b216e1bf" name="tests/bson-corpus/decimal128-3-valid-247.phpt" role="test" />
<file md5sum="de365973ac696e0dbd2e920242bf7027" name="tests/bson-corpus/decimal128-3-valid-248.phpt" role="test" />
<file md5sum="2f2a7f8a47f0798bad07ff58d4f79cdd" name="tests/bson-corpus/decimal128-3-valid-249.phpt" role="test" />
<file md5sum="20bcbbdd59af956c90a49096feda241d" name="tests/bson-corpus/decimal128-3-valid-250.phpt" role="test" />
<file md5sum="4fc937ac01a41825a9de95a1aaef3626" name="tests/bson-corpus/decimal128-3-valid-251.phpt" role="test" />
<file md5sum="0bdd8aff5c0ecfff015e057ec783eb54" name="tests/bson-corpus/decimal128-3-valid-252.phpt" role="test" />
<file md5sum="8171b181ce1f3714b85fa4794a89f277" name="tests/bson-corpus/decimal128-3-valid-253.phpt" role="test" />
<file md5sum="d04d9efcc3f8855b83933dd3b3bc7048" name="tests/bson-corpus/decimal128-3-valid-254.phpt" role="test" />
<file md5sum="53ee0eaacdd78867ec0e7ed8971429a7" name="tests/bson-corpus/decimal128-3-valid-255.phpt" role="test" />
<file md5sum="3cee9acb77277efee148bdbe8d223dfa" name="tests/bson-corpus/decimal128-3-valid-256.phpt" role="test" />
<file md5sum="789c791120cc609ede0737b7c23c85c5" name="tests/bson-corpus/decimal128-3-valid-257.phpt" role="test" />
<file md5sum="3d98bb4cbf4deca3dbebca3c2dfd2172" name="tests/bson-corpus/decimal128-3-valid-258.phpt" role="test" />
<file md5sum="f236ad31e12561372e2eb1c5d422d433" name="tests/bson-corpus/decimal128-3-valid-259.phpt" role="test" />
<file md5sum="6b536b709b52a15a444876ba78d8386b" name="tests/bson-corpus/decimal128-3-valid-260.phpt" role="test" />
<file md5sum="977f9734739aa26baecfd42aa11d0563" name="tests/bson-corpus/decimal128-3-valid-261.phpt" role="test" />
<file md5sum="b20fadb42701697d312a405454d3897d" name="tests/bson-corpus/decimal128-3-valid-262.phpt" role="test" />
<file md5sum="cc1d280c45c19a0a4a99095ccb1057ee" name="tests/bson-corpus/decimal128-3-valid-263.phpt" role="test" />
<file md5sum="5396c314de1ee3d03222dd54730d8cea" name="tests/bson-corpus/decimal128-3-valid-264.phpt" role="test" />
<file md5sum="53355bc837a9e55bb89235c4a4dccebc" name="tests/bson-corpus/decimal128-3-valid-265.phpt" role="test" />
<file md5sum="b5f3ee35ca6330dc3fe7d36247329b19" name="tests/bson-corpus/decimal128-3-valid-266.phpt" role="test" />
<file md5sum="1caf657e84d75ec2da12cbdd694ed7cd" name="tests/bson-corpus/decimal128-3-valid-267.phpt" role="test" />
<file md5sum="91b7a0d88d47c52ff8c7fb90096ede50" name="tests/bson-corpus/decimal128-3-valid-268.phpt" role="test" />
<file md5sum="e8c6b1bff14070cb676c2f979b3b4e96" name="tests/bson-corpus/decimal128-3-valid-269.phpt" role="test" />
<file md5sum="c6146dad6e717e10b5bf49d19bd2db89" name="tests/bson-corpus/decimal128-3-valid-270.phpt" role="test" />
<file md5sum="a4209116538d9925a17136840c078d7e" name="tests/bson-corpus/decimal128-3-valid-271.phpt" role="test" />
<file md5sum="6410e5f72cfd14259830104c5c091139" name="tests/bson-corpus/decimal128-3-valid-272.phpt" role="test" />
<file md5sum="bd929e4791beeb33dbcae622f4626d04" name="tests/bson-corpus/decimal128-3-valid-273.phpt" role="test" />
<file md5sum="1760c2f0b0439badf8bea9d0c97b4bb9" name="tests/bson-corpus/decimal128-3-valid-274.phpt" role="test" />
<file md5sum="413c3fb29c57a6bb541a3208dfa5b0b5" name="tests/bson-corpus/decimal128-3-valid-275.phpt" role="test" />
<file md5sum="e94d822420eb0fcb1c4284555472f753" name="tests/bson-corpus/decimal128-3-valid-276.phpt" role="test" />
<file md5sum="851f35f08adee1669ee5aea2372bd1d3" name="tests/bson-corpus/decimal128-3-valid-277.phpt" role="test" />
<file md5sum="a5f96574b6b9757c43b66c78d8fd4192" name="tests/bson-corpus/decimal128-3-valid-278.phpt" role="test" />
<file md5sum="9a5b2ff83d46cea8ba921d741cab8ebd" name="tests/bson-corpus/decimal128-3-valid-279.phpt" role="test" />
<file md5sum="554928efc3695a2d4f5633d0b5d8ff1c" name="tests/bson-corpus/decimal128-3-valid-280.phpt" role="test" />
<file md5sum="beb3f30d75efb68b5f28bdea472f7de2" name="tests/bson-corpus/decimal128-3-valid-281.phpt" role="test" />
<file md5sum="cc5d33541c74b05f6baae0f9716cddfe" name="tests/bson-corpus/decimal128-3-valid-282.phpt" role="test" />
<file md5sum="ba3e10638dfebdb19cbd26a1a0f9fc8d" name="tests/bson-corpus/decimal128-3-valid-283.phpt" role="test" />
<file md5sum="2049b5bdb6e19ffb1596e99760be5910" name="tests/bson-corpus/decimal128-3-valid-284.phpt" role="test" />
<file md5sum="5c4dca60c9d1ade7ce30db60850d1462" name="tests/bson-corpus/decimal128-3-valid-285.phpt" role="test" />
<file md5sum="d4d643d1edee4c50e649692e26d7091a" name="tests/bson-corpus/decimal128-3-valid-286.phpt" role="test" />
<file md5sum="ad4a1ea5243f7c668fe1c709c7d35817" name="tests/bson-corpus/decimal128-3-valid-287.phpt" role="test" />
<file md5sum="8d8d837be562a71df83c5824e2f85d5d" name="tests/bson-corpus/decimal128-3-valid-288.phpt" role="test" />
<file md5sum="aede3884fcb665e586b415cabb1445c7" name="tests/bson-corpus/decimal128-3-valid-289.phpt" role="test" />
<file md5sum="382d05d15d18d9c982ee2bca7eb5c635" name="tests/bson-corpus/decimal128-3-valid-290.phpt" role="test" />
<file md5sum="f60413673f1660b677ae8266c8752d04" name="tests/bson-corpus/decimal128-3-valid-291.phpt" role="test" />
<file md5sum="04e0bf0b3d2e94c840709ee5b78e5c41" name="tests/bson-corpus/decimal128-3-valid-292.phpt" role="test" />
<file md5sum="ae8b9bea995be967a10013d3737e839b" name="tests/bson-corpus/decimal128-3-valid-293.phpt" role="test" />
<file md5sum="068c95a87a1fcf669a844e22295cae66" name="tests/bson-corpus/decimal128-3-valid-294.phpt" role="test" />
<file md5sum="e22e8042b8962529fe11556cdcf3f4bb" name="tests/bson-corpus/decimal128-3-valid-295.phpt" role="test" />
<file md5sum="cd3d4a2f108de6a94e832fc9f325b6b8" name="tests/bson-corpus/decimal128-3-valid-296.phpt" role="test" />
<file md5sum="722074da871f776a7963fbbe499d52b0" name="tests/bson-corpus/decimal128-3-valid-297.phpt" role="test" />
<file md5sum="a5bf581446b1e605ea2083eb87238d59" name="tests/bson-corpus/decimal128-3-valid-298.phpt" role="test" />
<file md5sum="7daf264958ffe34c085fa056b8f1fcde" name="tests/bson-corpus/decimal128-3-valid-299.phpt" role="test" />
<file md5sum="6c3b1b7b6475db6e258143c22cfdf823" name="tests/bson-corpus/decimal128-3-valid-300.phpt" role="test" />
<file md5sum="5696d287145bf434b3b4fa2b43e7519d" name="tests/bson-corpus/decimal128-3-valid-301.phpt" role="test" />
<file md5sum="4a7acee19c691e605b29a1ffe0d6d928" name="tests/bson-corpus/decimal128-3-valid-302.phpt" role="test" />
<file md5sum="1229842a762826af288b5ebdd895821b" name="tests/bson-corpus/decimal128-3-valid-303.phpt" role="test" />
<file md5sum="5680e250968906159a0379273ae5037e" name="tests/bson-corpus/decimal128-3-valid-304.phpt" role="test" />
<file md5sum="03d614a59d978304368b78eba1307bc2" name="tests/bson-corpus/decimal128-3-valid-305.phpt" role="test" />
<file md5sum="f56eda4c9bfb24077dff037a5fbdc971" name="tests/bson-corpus/decimal128-3-valid-306.phpt" role="test" />
<file md5sum="10c8c645114891728a44d4c55d3985ef" name="tests/bson-corpus/decimal128-3-valid-307.phpt" role="test" />
<file md5sum="d9d947e4778922f209b5164a63762252" name="tests/bson-corpus/decimal128-3-valid-308.phpt" role="test" />
<file md5sum="ba047e7921fca83be0bbf1ffb9ff32e6" name="tests/bson-corpus/decimal128-4-parseError-001.phpt" role="test" />
<file md5sum="96c4e11223d6a702ce7c160d7f33ec6e" name="tests/bson-corpus/decimal128-4-parseError-002.phpt" role="test" />
<file md5sum="2975e7043d01c304620a4a635c1df627" name="tests/bson-corpus/decimal128-4-parseError-003.phpt" role="test" />
<file md5sum="66ee3e45b68893588ae091b3da40b1c9" name="tests/bson-corpus/decimal128-4-parseError-004.phpt" role="test" />
<file md5sum="5f79cc977af6f42f0d16e23b6b78787a" name="tests/bson-corpus/decimal128-4-parseError-005.phpt" role="test" />
<file md5sum="905801853974398dd4df272c70db9f1f" name="tests/bson-corpus/decimal128-4-parseError-006.phpt" role="test" />
<file md5sum="930136040e99d94cac48f2dc1ea1b4ec" name="tests/bson-corpus/decimal128-4-parseError-007.phpt" role="test" />
<file md5sum="d200890cddd844aa3e417afdfaf66258" name="tests/bson-corpus/decimal128-4-parseError-008.phpt" role="test" />
<file md5sum="6929f5e4aa871b5568760bc96d01963f" name="tests/bson-corpus/decimal128-4-parseError-009.phpt" role="test" />
<file md5sum="14a207527ae35bbbf707219236f86f63" name="tests/bson-corpus/decimal128-4-parseError-010.phpt" role="test" />
<file md5sum="9828ca9e0e1d1af8bba3896ad969cbdc" name="tests/bson-corpus/decimal128-4-parseError-011.phpt" role="test" />
<file md5sum="eeb65b1dc4411a057e3437efd758cad5" name="tests/bson-corpus/decimal128-4-parseError-012.phpt" role="test" />
<file md5sum="ba731b0fd3b5e6f12980c65d3cd4c8c2" name="tests/bson-corpus/decimal128-4-parseError-013.phpt" role="test" />
<file md5sum="e185b77c3f7e11690bd948cff345f6a2" name="tests/bson-corpus/decimal128-4-parseError-014.phpt" role="test" />
<file md5sum="9c019336f3754089c347f727e81fa529" name="tests/bson-corpus/decimal128-4-parseError-015.phpt" role="test" />
<file md5sum="0eee95f4870d4d75daeba9d37a74a3da" name="tests/bson-corpus/decimal128-4-parseError-016.phpt" role="test" />
<file md5sum="9d327df701b1303cf8562508d1b73cc6" name="tests/bson-corpus/decimal128-4-parseError-017.phpt" role="test" />
<file md5sum="1ba071fa83d1712f9e18182a7c609d08" name="tests/bson-corpus/decimal128-4-parseError-018.phpt" role="test" />
<file md5sum="2e18b7b9617a104ca7944660cfbe7d31" name="tests/bson-corpus/decimal128-4-parseError-019.phpt" role="test" />
<file md5sum="54546dd203137c1ad0a58c5fd0144e7f" name="tests/bson-corpus/decimal128-4-parseError-020.phpt" role="test" />
<file md5sum="267a1f9db0dffd911c013dbdf7c1b7c3" name="tests/bson-corpus/decimal128-4-valid-001.phpt" role="test" />
<file md5sum="cb76c65de06c5493f91c2754bbaafe37" name="tests/bson-corpus/decimal128-4-valid-002.phpt" role="test" />
<file md5sum="632de2625b3d216e256d0ed592280201" name="tests/bson-corpus/decimal128-4-valid-003.phpt" role="test" />
<file md5sum="e49f627b6184b691e5bfe8e7abe13188" name="tests/bson-corpus/decimal128-4-valid-004.phpt" role="test" />
<file md5sum="29db50bbea92d96c66ee22b25937455c" name="tests/bson-corpus/decimal128-4-valid-005.phpt" role="test" />
<file md5sum="9c5d97a72c8d46d95fdd525fe4aa52aa" name="tests/bson-corpus/decimal128-4-valid-006.phpt" role="test" />
<file md5sum="4bdcc386968fb2f93abc39b0f9545d28" name="tests/bson-corpus/decimal128-4-valid-007.phpt" role="test" />
<file md5sum="c12b60332cdde3ee04f03e8850373696" name="tests/bson-corpus/decimal128-4-valid-008.phpt" role="test" />
<file md5sum="3d2d79a674331cfa01096813cac3b226" name="tests/bson-corpus/decimal128-4-valid-009.phpt" role="test" />
<file md5sum="5b142aac0ad0f00783cff7cbe7d996cb" name="tests/bson-corpus/decimal128-4-valid-010.phpt" role="test" />
<file md5sum="743051a9c45eefeb32cad44c6f9e9c91" name="tests/bson-corpus/decimal128-4-valid-011.phpt" role="test" />
<file md5sum="9d6f0169fd3f09984f3de067bebdba78" name="tests/bson-corpus/decimal128-4-valid-012.phpt" role="test" />
<file md5sum="943f97ece6a0843090c5baff1f2b730e" name="tests/bson-corpus/decimal128-4-valid-013.phpt" role="test" />
<file md5sum="a9981c958bf5491b6dae949026d66059" name="tests/bson-corpus/decimal128-5-valid-001.phpt" role="test" />
<file md5sum="a26800c0358caddea1d5b1dd9bd2ae23" name="tests/bson-corpus/decimal128-5-valid-002.phpt" role="test" />
<file md5sum="f4021d7ebe7eb3f6ee75091ce54a4f68" name="tests/bson-corpus/decimal128-5-valid-003.phpt" role="test" />
<file md5sum="e43383cbcb3d75e7cd967f3c9a159be8" name="tests/bson-corpus/decimal128-5-valid-004.phpt" role="test" />
<file md5sum="82d8c7463f9b98b6353f26b1a5ee030d" name="tests/bson-corpus/decimal128-5-valid-005.phpt" role="test" />
<file md5sum="f08c46d33cc7c52db54da0593e95a973" name="tests/bson-corpus/decimal128-5-valid-006.phpt" role="test" />
<file md5sum="8039d96c7d86bb021ab99e8ad40a0bff" name="tests/bson-corpus/decimal128-5-valid-007.phpt" role="test" />
<file md5sum="7e93f1c90e8a00bb6a3cd41da71fbd43" name="tests/bson-corpus/decimal128-5-valid-008.phpt" role="test" />
<file md5sum="338aaf0050fc9cb9236786de6b9095e7" name="tests/bson-corpus/decimal128-5-valid-009.phpt" role="test" />
<file md5sum="16673c8e4bd1edf82aafc281ba129efc" name="tests/bson-corpus/decimal128-5-valid-010.phpt" role="test" />
<file md5sum="1b0e168e873836f80595d1921ac43966" name="tests/bson-corpus/decimal128-5-valid-011.phpt" role="test" />
<file md5sum="ae4d358af4acaf73b54d796f9366d7c5" name="tests/bson-corpus/decimal128-5-valid-012.phpt" role="test" />
<file md5sum="e3e7a0daecdb0b5907859fe56431df3b" name="tests/bson-corpus/decimal128-5-valid-013.phpt" role="test" />
<file md5sum="b330fc71b0066b4e4c59a9fd564aa8fe" name="tests/bson-corpus/decimal128-5-valid-014.phpt" role="test" />
<file md5sum="a97fe0bb194ceeaa8de509adf29630e7" name="tests/bson-corpus/decimal128-5-valid-015.phpt" role="test" />
<file md5sum="cd2a754a2d5a82ed673e420b2d7b88f7" name="tests/bson-corpus/decimal128-5-valid-016.phpt" role="test" />
<file md5sum="1e6e680849fd7e36d378e728bbdb9b66" name="tests/bson-corpus/decimal128-5-valid-017.phpt" role="test" />
<file md5sum="ab93ba16758f68d9a3193911e6964e65" name="tests/bson-corpus/decimal128-5-valid-018.phpt" role="test" />
<file md5sum="80e5967f9738487686a86f10f15fa885" name="tests/bson-corpus/decimal128-5-valid-019.phpt" role="test" />
<file md5sum="f9e7a91beedf969e6df1a615e86558e6" name="tests/bson-corpus/decimal128-5-valid-020.phpt" role="test" />
<file md5sum="21d50833e7c999721d5d4306ad92a3fa" name="tests/bson-corpus/decimal128-5-valid-021.phpt" role="test" />
<file md5sum="909e2f48ca4706b4205a28e74d508b9e" name="tests/bson-corpus/decimal128-5-valid-022.phpt" role="test" />
<file md5sum="609cb491c2c160fb06497b0f23d96af7" name="tests/bson-corpus/decimal128-5-valid-023.phpt" role="test" />
<file md5sum="3e51831c477d2d2f943146e7ce786965" name="tests/bson-corpus/decimal128-5-valid-024.phpt" role="test" />
<file md5sum="942ed4fe72753a9ee4756afcb4fedba4" name="tests/bson-corpus/decimal128-5-valid-025.phpt" role="test" />
<file md5sum="5263e2388ae94ecbb529230d3b667717" name="tests/bson-corpus/decimal128-5-valid-026.phpt" role="test" />
<file md5sum="361cdf8640e57a9ac09c2b918f80f0b9" name="tests/bson-corpus/decimal128-5-valid-027.phpt" role="test" />
<file md5sum="698706c741e1d89a22b25eb8793fa3ce" name="tests/bson-corpus/decimal128-5-valid-028.phpt" role="test" />
<file md5sum="e08c868e027f85b3008abcc956f3b4a4" name="tests/bson-corpus/decimal128-5-valid-029.phpt" role="test" />
<file md5sum="ea64febefabfdbe88108852ab13201bb" name="tests/bson-corpus/decimal128-5-valid-030.phpt" role="test" />
<file md5sum="d82056149a3a7002513310b8a0632dc2" name="tests/bson-corpus/decimal128-5-valid-031.phpt" role="test" />
<file md5sum="e9fa637af0ebcb17267ae42644920bbb" name="tests/bson-corpus/decimal128-5-valid-032.phpt" role="test" />
<file md5sum="bc92c06a9cf332e2c730bb9f7c83268d" name="tests/bson-corpus/decimal128-5-valid-033.phpt" role="test" />
<file md5sum="5a59091bb3b1dedc267eaf79d38df0d3" name="tests/bson-corpus/decimal128-5-valid-034.phpt" role="test" />
<file md5sum="7af0fd92fc11417588602082e983ed83" name="tests/bson-corpus/decimal128-5-valid-035.phpt" role="test" />
<file md5sum="eae7b3bfba7cb6b5018f91cb6bf9c4da" name="tests/bson-corpus/decimal128-5-valid-036.phpt" role="test" />
<file md5sum="414c76669d00becc64246e97b2f70fb4" name="tests/bson-corpus/decimal128-5-valid-037.phpt" role="test" />
<file md5sum="e2941a8be7889c48461634da9f27c152" name="tests/bson-corpus/decimal128-5-valid-038.phpt" role="test" />
<file md5sum="d634cabc36938736e3fb5b1d5766c6c5" name="tests/bson-corpus/decimal128-5-valid-039.phpt" role="test" />
<file md5sum="1159c39b074979355f046ab2057576ea" name="tests/bson-corpus/decimal128-5-valid-040.phpt" role="test" />
<file md5sum="6b501682a22836cb221dc871d270227c" name="tests/bson-corpus/decimal128-5-valid-041.phpt" role="test" />
<file md5sum="ac354fc02b2c70cb3078f56a2e488761" name="tests/bson-corpus/decimal128-5-valid-042.phpt" role="test" />
<file md5sum="774b092064286ca4a12d87c2801a8f8c" name="tests/bson-corpus/decimal128-5-valid-043.phpt" role="test" />
<file md5sum="9498fcc098d04af6bc18ff3226421492" name="tests/bson-corpus/decimal128-5-valid-044.phpt" role="test" />
<file md5sum="d043cd280ec38491680b757f1095b2bc" name="tests/bson-corpus/decimal128-5-valid-045.phpt" role="test" />
<file md5sum="7e6fc4384daac7ba63fa15438487183e" name="tests/bson-corpus/decimal128-5-valid-046.phpt" role="test" />
<file md5sum="bf9017a27ab1056fd2156596fa5fa773" name="tests/bson-corpus/decimal128-5-valid-047.phpt" role="test" />
<file md5sum="d6e8383e3e9edbc8e3a9f7ea7880a29d" name="tests/bson-corpus/decimal128-5-valid-048.phpt" role="test" />
<file md5sum="518f3be51879acb708aadd12c0a4bc43" name="tests/bson-corpus/decimal128-5-valid-049.phpt" role="test" />
<file md5sum="9b815092dfc93cc3b95f5d613ec7edb1" name="tests/bson-corpus/decimal128-5-valid-050.phpt" role="test" />
<file md5sum="af44e5ac84c9bceff73bf490cd1a1f10" name="tests/bson-corpus/decimal128-5-valid-051.phpt" role="test" />
<file md5sum="7f039c3a7b0bcc30eeadebb7a88d7551" name="tests/bson-corpus/decimal128-5-valid-052.phpt" role="test" />
<file md5sum="ab8715e9de548d75ec5b634bfe09f983" name="tests/bson-corpus/decimal128-5-valid-053.phpt" role="test" />
<file md5sum="bf0236d0ef1475d10aaae9e5a781b2c2" name="tests/bson-corpus/decimal128-5-valid-054.phpt" role="test" />
<file md5sum="dc5c1657c93563731615c01fc00b20aa" name="tests/bson-corpus/decimal128-5-valid-055.phpt" role="test" />
<file md5sum="572c6bb3906cc8677d57a358a28a1eec" name="tests/bson-corpus/decimal128-5-valid-056.phpt" role="test" />
<file md5sum="10e8bd72db4fbf06371338e2156e020b" name="tests/bson-corpus/decimal128-5-valid-057.phpt" role="test" />
<file md5sum="29619b121f1e1cc80daf7b25e3c23734" name="tests/bson-corpus/decimal128-5-valid-058.phpt" role="test" />
<file md5sum="5fc14e28dd477b9760dff8c29e776327" name="tests/bson-corpus/decimal128-5-valid-059.phpt" role="test" />
<file md5sum="88585d3700d3313283f7ea87692c5314" name="tests/bson-corpus/decimal128-5-valid-060.phpt" role="test" />
<file md5sum="c2d8e3bd56e0bb7da2981c89a47f74dd" name="tests/bson-corpus/decimal128-5-valid-061.phpt" role="test" />
<file md5sum="dabbfbbb9c8a0dffe1190b6206414465" name="tests/bson-corpus/decimal128-5-valid-062.phpt" role="test" />
<file md5sum="f6e59ace820732da155936b82850c1ed" name="tests/bson-corpus/decimal128-5-valid-063.phpt" role="test" />
<file md5sum="45cc1964d3fd051a506b64c1bf145fb6" name="tests/bson-corpus/decimal128-5-valid-064.phpt" role="test" />
<file md5sum="bdb105435ff7bc5b5c900bbe02894c28" name="tests/bson-corpus/decimal128-5-valid-065.phpt" role="test" />
<file md5sum="9bdbed82d0a59f1200c405f7f06a2405" name="tests/bson-corpus/decimal128-5-valid-066.phpt" role="test" />
<file md5sum="bb317bfec39ac48ba2ee3671ecdd3c65" name="tests/bson-corpus/decimal128-5-valid-067.phpt" role="test" />
<file md5sum="9d619c3b0719e7e6075adddc0ea9dbfd" name="tests/bson-corpus/decimal128-6-parseError-001.phpt" role="test" />
<file md5sum="5e5e28715e20456528ad5de48bd7349e" name="tests/bson-corpus/decimal128-6-parseError-002.phpt" role="test" />
<file md5sum="0bcacd7da821fef56d8133be73d34e3f" name="tests/bson-corpus/decimal128-6-parseError-003.phpt" role="test" />
<file md5sum="b330cdf56d272be270e82e2341aff1f4" name="tests/bson-corpus/decimal128-6-parseError-004.phpt" role="test" />
<file md5sum="087821837bfc5cc35f93663233652f5e" name="tests/bson-corpus/decimal128-6-parseError-005.phpt" role="test" />
<file md5sum="b7ff0e65afd02d5000989e467d212c51" name="tests/bson-corpus/decimal128-6-parseError-006.phpt" role="test" />
<file md5sum="32b737ae134b0641800c408a9bc4f4fc" name="tests/bson-corpus/decimal128-6-parseError-007.phpt" role="test" />
<file md5sum="722f4553265a2f16492fedd8cadf5dea" name="tests/bson-corpus/decimal128-6-parseError-008.phpt" role="test" />
<file md5sum="2e6d342b33ad7b6fa79067ccf36a2a9e" name="tests/bson-corpus/decimal128-6-parseError-009.phpt" role="test" />
<file md5sum="da34bfaf1576dc9a3a0c7152ab17551e" name="tests/bson-corpus/decimal128-6-parseError-010.phpt" role="test" />
<file md5sum="86ce002a308067909f42b96eb21308b2" name="tests/bson-corpus/decimal128-6-parseError-011.phpt" role="test" />
<file md5sum="6addc588a3cbc00449082c46a2e121db" name="tests/bson-corpus/decimal128-6-parseError-012.phpt" role="test" />
<file md5sum="473b1b080710a4937c2d7b1586ee40b3" name="tests/bson-corpus/decimal128-6-parseError-013.phpt" role="test" />
<file md5sum="dd0898b2e0802cb47b30753e9da159e3" name="tests/bson-corpus/decimal128-6-parseError-014.phpt" role="test" />
<file md5sum="58eb765b37e2e284a67383aaf3359788" name="tests/bson-corpus/decimal128-6-parseError-015.phpt" role="test" />
<file md5sum="7f360fae68599d98fff6b09d9e2ea8d0" name="tests/bson-corpus/decimal128-6-parseError-016.phpt" role="test" />
<file md5sum="be7a3fadb14f640d88c8423932975813" name="tests/bson-corpus/decimal128-6-parseError-017.phpt" role="test" />
<file md5sum="7a0603436c1795a2a1613a83f90901b7" name="tests/bson-corpus/decimal128-6-parseError-018.phpt" role="test" />
<file md5sum="7d1dccee0bd183c2baf5c9e0c90e6fbb" name="tests/bson-corpus/decimal128-6-parseError-019.phpt" role="test" />
<file md5sum="b979e1cff5d7aac6ac47239fa21baa72" name="tests/bson-corpus/decimal128-6-parseError-020.phpt" role="test" />
<file md5sum="08834e4aa640b820ef329690c28ba6ca" name="tests/bson-corpus/decimal128-6-parseError-021.phpt" role="test" />
<file md5sum="df16fe00ed13b38e8d7c648bd6d89c97" name="tests/bson-corpus/decimal128-6-parseError-022.phpt" role="test" />
<file md5sum="26b48d1f949d0e3aed0b9dedfc185afd" name="tests/bson-corpus/decimal128-6-parseError-023.phpt" role="test" />
<file md5sum="1078595f5fac6bee1267b4d263c6c8cb" name="tests/bson-corpus/decimal128-6-parseError-024.phpt" role="test" />
<file md5sum="e047a839813f6d9e94bae49691dd6701" name="tests/bson-corpus/decimal128-6-parseError-025.phpt" role="test" />
<file md5sum="12a013fe95a88779c348c4cb773115ad" name="tests/bson-corpus/decimal128-6-parseError-026.phpt" role="test" />
<file md5sum="354ff6b5d986470794f59886b683ac70" name="tests/bson-corpus/decimal128-6-parseError-027.phpt" role="test" />
<file md5sum="3ef809210e108a7dc60645c4140f07f9" name="tests/bson-corpus/decimal128-6-parseError-028.phpt" role="test" />
<file md5sum="50f7c0c8c816658e51a3946671bc02b4" name="tests/bson-corpus/decimal128-6-parseError-029.phpt" role="test" />
<file md5sum="93988289538ba9bebb3c9130d0287dd0" name="tests/bson-corpus/decimal128-6-parseError-030.phpt" role="test" />
<file md5sum="6bd10e968b1852735c6047be0e22e523" name="tests/bson-corpus/decimal128-6-parseError-031.phpt" role="test" />
<file md5sum="739125a03b1d42ac4f928dfd98a3f306" name="tests/bson-corpus/decimal128-7-parseError-001.phpt" role="test" />
<file md5sum="3e70c7fd9860e1b557c951895227973b" name="tests/bson-corpus/decimal128-7-parseError-002.phpt" role="test" />
<file md5sum="5680032198806e7625acfcdb227dc67a" name="tests/bson-corpus/decimal128-7-parseError-003.phpt" role="test" />
<file md5sum="bf63ba62a9265425b447d7285f045b28" name="tests/bson-corpus/decimal128-7-parseError-004.phpt" role="test" />
<file md5sum="9319f1a49ec2f2449283c2fd44d8275a" name="tests/bson-corpus/decimal128-7-parseError-005.phpt" role="test" />
<file md5sum="770cd1d3f59b161db855c5838fad7390" name="tests/bson-corpus/decimal128-7-parseError-006.phpt" role="test" />
<file md5sum="0dd5f74d70bd4d09fefaccc0ae3b326c" name="tests/bson-corpus/decimal128-7-parseError-007.phpt" role="test" />
<file md5sum="aec5da5a25c84f34b33d65f347a83c10" name="tests/bson-corpus/decimal128-7-parseError-008.phpt" role="test" />
<file md5sum="ab4f84a31f21de6c7a5a75381d8a8760" name="tests/bson-corpus/decimal128-7-parseError-009.phpt" role="test" />
<file md5sum="e6c669fe4746f25af030f19ca2efe96f" name="tests/bson-corpus/decimal128-7-parseError-010.phpt" role="test" />
<file md5sum="1c512a25e6b3b5eeb7efb02607c01351" name="tests/bson-corpus/decimal128-7-parseError-011.phpt" role="test" />
<file md5sum="5ec3a512414e516a23691ed7ce9c8409" name="tests/bson-corpus/decimal128-7-parseError-012.phpt" role="test" />
<file md5sum="83e1d3549c3e354b4ef47b3a97a42304" name="tests/bson-corpus/decimal128-7-parseError-013.phpt" role="test" />
<file md5sum="d5a3fe0a6355b408d2b5b1e82164dc06" name="tests/bson-corpus/decimal128-7-parseError-014.phpt" role="test" />
<file md5sum="03c2144e7ed68d510609d1882a0d3fb5" name="tests/bson-corpus/decimal128-7-parseError-015.phpt" role="test" />
<file md5sum="5bc01966bae4d9965ca5ab8e64d55d21" name="tests/bson-corpus/decimal128-7-parseError-016.phpt" role="test" />
<file md5sum="19e0f71895b66144e92440e3dcd0ff23" name="tests/bson-corpus/decimal128-7-parseError-017.phpt" role="test" />
<file md5sum="2f9e63cdb60253c97b4a1b709a35b6be" name="tests/bson-corpus/decimal128-7-parseError-018.phpt" role="test" />
<file md5sum="aeaa29b049aae5916bb8cccc8d47e7e8" name="tests/bson-corpus/decimal128-7-parseError-019.phpt" role="test" />
<file md5sum="b103339bc111045d962a5da60907a954" name="tests/bson-corpus/decimal128-7-parseError-020.phpt" role="test" />
<file md5sum="77c0d904a85bc98f4c0d60637a167d59" name="tests/bson-corpus/decimal128-7-parseError-021.phpt" role="test" />
<file md5sum="526a91c29eedfb7e792e31284bce93c2" name="tests/bson-corpus/decimal128-7-parseError-022.phpt" role="test" />
<file md5sum="7fad1b695028cee5b3524ae7795671dd" name="tests/bson-corpus/decimal128-7-parseError-023.phpt" role="test" />
<file md5sum="a284eeae3ac0dc6913c5028765472178" name="tests/bson-corpus/decimal128-7-parseError-024.phpt" role="test" />
<file md5sum="de5e0cfba4ba4e4db4dc6f9bac610bf3" name="tests/bson-corpus/decimal128-7-parseError-025.phpt" role="test" />
<file md5sum="5e8f71033a1f75d2caad14db4806d8b7" name="tests/bson-corpus/decimal128-7-parseError-026.phpt" role="test" />
<file md5sum="3e9808fa4362a86083025c8418b6b300" name="tests/bson-corpus/decimal128-7-parseError-027.phpt" role="test" />
<file md5sum="46c182f2fb62174dbe5ad42d52b1230d" name="tests/bson-corpus/decimal128-7-parseError-028.phpt" role="test" />
<file md5sum="3df633a71755c619e70d3961f3ed778d" name="tests/bson-corpus/decimal128-7-parseError-029.phpt" role="test" />
<file md5sum="7f7590bd2c639fb10e553ea2f1e40a97" name="tests/bson-corpus/decimal128-7-parseError-030.phpt" role="test" />
<file md5sum="b827cc6fea8a64cc770452afa2cb45cb" name="tests/bson-corpus/decimal128-7-parseError-031.phpt" role="test" />
<file md5sum="98f885b5d4b9333ea213f4be4f8ddca6" name="tests/bson-corpus/decimal128-7-parseError-032.phpt" role="test" />
<file md5sum="546c9fa342e790e86e34f6b5c6de3b84" name="tests/bson-corpus/decimal128-7-parseError-033.phpt" role="test" />
<file md5sum="2b073b2ea1bc7fd605780f947ceac75e" name="tests/bson-corpus/decimal128-7-parseError-034.phpt" role="test" />
<file md5sum="9e92800972333c69386eb81e0e3d8ec9" name="tests/bson-corpus/decimal128-7-parseError-035.phpt" role="test" />
<file md5sum="ac308002b7f73ff45b68ce36b38a7275" name="tests/bson-corpus/decimal128-7-parseError-036.phpt" role="test" />
<file md5sum="a10da36d1c1c27079c245ad31d2bce08" name="tests/bson-corpus/decimal128-7-parseError-037.phpt" role="test" />
<file md5sum="c11703f2e41a1e40e993465cc1f5a865" name="tests/bson-corpus/decimal128-7-parseError-038.phpt" role="test" />
<file md5sum="ef094591196f8a16df0cfeb14d7fa8fd" name="tests/bson-corpus/decimal128-7-parseError-039.phpt" role="test" />
<file md5sum="d44551a47e6182cf4c22245df9a49863" name="tests/bson-corpus/decimal128-7-parseError-040.phpt" role="test" />
<file md5sum="bfd6aefac1a28c8f5a576f646d1c8f4b" name="tests/bson-corpus/decimal128-7-parseError-041.phpt" role="test" />
<file md5sum="5e667f745c3bf9dc68b4878a6de2ca7f" name="tests/bson-corpus/decimal128-7-parseError-042.phpt" role="test" />
<file md5sum="e8eb51d644cc1ad01df9f2fe5f8d615c" name="tests/bson-corpus/decimal128-7-parseError-043.phpt" role="test" />
<file md5sum="d0ab46feebf5f41b736c28c25be9c41d" name="tests/bson-corpus/decimal128-7-parseError-044.phpt" role="test" />
<file md5sum="5195470ca981d3b793e4dc7ae16c7b80" name="tests/bson-corpus/decimal128-7-parseError-045.phpt" role="test" />
<file md5sum="5ed083d6153fb2be44b2bdd69cb3ad66" name="tests/bson-corpus/decimal128-7-parseError-046.phpt" role="test" />
<file md5sum="b90aad87eb6e3fdc0f7069a6217bdeb6" name="tests/bson-corpus/decimal128-7-parseError-047.phpt" role="test" />
<file md5sum="24a773cfb9b0f6d19d2f5d23e2d4734f" name="tests/bson-corpus/decimal128-7-parseError-048.phpt" role="test" />
<file md5sum="d49c37b3be2913bbf9e94460aaa6dea5" name="tests/bson-corpus/decimal128-7-parseError-049.phpt" role="test" />
<file md5sum="a8e25353f491c8abcd83ecb445cdbef7" name="tests/bson-corpus/decimal128-7-parseError-050.phpt" role="test" />
<file md5sum="7d957b915a4677d1a743b82ed69b8399" name="tests/bson-corpus/decimal128-7-parseError-051.phpt" role="test" />
<file md5sum="a6c028651988ac5aef2583662d03606d" name="tests/bson-corpus/decimal128-7-parseError-052.phpt" role="test" />
<file md5sum="8b9d5a234c5003562c06a22a6055b9a9" name="tests/bson-corpus/decimal128-7-parseError-053.phpt" role="test" />
<file md5sum="db576d750b955b8133bc3a3ca17b268d" name="tests/bson-corpus/decimal128-7-parseError-054.phpt" role="test" />
<file md5sum="0fe5c131ea839136dbe43eb34956ddea" name="tests/bson-corpus/decimal128-7-parseError-055.phpt" role="test" />
<file md5sum="c8a6b9a6dc2b7fd0859748bf004444ad" name="tests/bson-corpus/decimal128-7-parseError-056.phpt" role="test" />
<file md5sum="e6317794fe425616e7384eaee73d508d" name="tests/bson-corpus/decimal128-7-parseError-057.phpt" role="test" />
<file md5sum="ae9adaf19631cf1b0fc10f5ef2d73fc9" name="tests/bson-corpus/decimal128-7-parseError-058.phpt" role="test" />
<file md5sum="de4ea2c89f6188610d9b754bbe699a64" name="tests/bson-corpus/decimal128-7-parseError-059.phpt" role="test" />
<file md5sum="2ab16b6b73a8fd7a26850ed267dc7839" name="tests/bson-corpus/decimal128-7-parseError-060.phpt" role="test" />
<file md5sum="e9243a30ec1d8601e3349c95a52bb281" name="tests/bson-corpus/decimal128-7-parseError-061.phpt" role="test" />
<file md5sum="deb3afb234ab883875f98adae9ac22c7" name="tests/bson-corpus/decimal128-7-parseError-062.phpt" role="test" />
<file md5sum="7f9efd9d04a8f1dc79a5b0b89fd01591" name="tests/bson-corpus/decimal128-7-parseError-063.phpt" role="test" />
<file md5sum="6e2d1fd08e5c5119473aec4a053a8b28" name="tests/bson-corpus/decimal128-7-parseError-064.phpt" role="test" />
<file md5sum="f01b69a5459752b843c52b2bfa3abe94" name="tests/bson-corpus/decimal128-7-parseError-065.phpt" role="test" />
<file md5sum="5f9f1ec42e3cb971c969c02e21861d35" name="tests/bson-corpus/decimal128-7-parseError-066.phpt" role="test" />
<file md5sum="5f35e09da70142bacb52211bc1c56723" name="tests/bson-corpus/decimal128-7-parseError-067.phpt" role="test" />
<file md5sum="670bba129ff3d44ebcaa75bb1eef54db" name="tests/bson-corpus/decimal128-7-parseError-068.phpt" role="test" />
<file md5sum="9822ce5f455adcb099fb8608ec00447e" name="tests/bson-corpus/decimal128-7-parseError-069.phpt" role="test" />
<file md5sum="3d91bc48b724ce35db3d8ee571201bef" name="tests/bson-corpus/decimal128-7-parseError-070.phpt" role="test" />
<file md5sum="4e27519c86e60695762547d22250a30d" name="tests/bson-corpus/decimal128-7-parseError-071.phpt" role="test" />
<file md5sum="2ad0c662a34e4860d591491568519e0c" name="tests/bson-corpus/decimal128-7-parseError-072.phpt" role="test" />
<file md5sum="8cb216dfac5cb18d1dc67b217b03a75f" name="tests/bson-corpus/decimal128-7-parseError-073.phpt" role="test" />
<file md5sum="102157c1968d887e482664937712f960" name="tests/bson-corpus/decimal128-7-parseError-074.phpt" role="test" />
<file md5sum="1383c9faaea4308830abf57c319d1416" name="tests/bson-corpus/decimal128-7-parseError-075.phpt" role="test" />
<file md5sum="bdc6b09eadb365c1ca90fa5abdcdcb72" name="tests/bson-corpus/decimal128-7-parseError-076.phpt" role="test" />
<file md5sum="fcb39e6d22bec7ae00715559c73d4021" name="tests/bson-corpus/decimal128-7-parseError-077.phpt" role="test" />
<file md5sum="883d74890811efba08b9bdcd00427933" name="tests/bson-corpus/decimal128-7-parseError-078.phpt" role="test" />
<file md5sum="b70276e215fe563edbb78b9ab826ac94" name="tests/bson-corpus/decimal128-7-parseError-079.phpt" role="test" />
<file md5sum="b566a55c4f0abf20272a8a5d7a7b0f86" name="tests/bson-corpus/decimal128-7-parseError-080.phpt" role="test" />
<file md5sum="87ad9d946c27e3f9dc0ce27d677603ee" name="tests/bson-corpus/document-decodeError-001.phpt" role="test" />
<file md5sum="19e200efa9c259f932e3b39b5414a9bd" name="tests/bson-corpus/document-decodeError-002.phpt" role="test" />
<file md5sum="4e0ee9b29c76b02780ac778f592a593a" name="tests/bson-corpus/document-decodeError-003.phpt" role="test" />
<file md5sum="4d54871d349fce471b2c04fb0315e283" name="tests/bson-corpus/document-decodeError-004.phpt" role="test" />
<file md5sum="c2afc444b968e7ed5206f630e7993387" name="tests/bson-corpus/document-valid-001.phpt" role="test" />
<file md5sum="9cb19864efff5132349002ceb3e91528" name="tests/bson-corpus/document-valid-002.phpt" role="test" />
<file md5sum="a0a053cd67c7dc2f17e5f7c78b2a8a3c" name="tests/bson-corpus/document-valid-003.phpt" role="test" />
<file md5sum="80bbe3b442ad0b02cb210ffdc084864c" name="tests/bson-corpus/document-valid-004.phpt" role="test" />
<file md5sum="5142ac41c9250459ba4f6d764e09f235" name="tests/bson-corpus/document-valid-005.phpt" role="test" />
<file md5sum="e15dd26f6396cae98bd71bc84b5e4485" name="tests/bson-corpus/document-valid-006.phpt" role="test" />
<file md5sum="dc115c6f84cfae3ee540db465c94d592" name="tests/bson-corpus/document-valid-007.phpt" role="test" />
<file md5sum="0e5e1939db94932d718a38b4ef0ab08a" name="tests/bson-corpus/double-decodeError-001.phpt" role="test" />
<file md5sum="cc38451861a9bdd440f141a9603d1c1e" name="tests/bson-corpus/double-valid-001.phpt" role="test" />
<file md5sum="695dd4b6ffe5752e635432f770112bbc" name="tests/bson-corpus/double-valid-002.phpt" role="test" />
<file md5sum="543c768616786e182f8a87808846c29d" name="tests/bson-corpus/double-valid-003.phpt" role="test" />
<file md5sum="3cf794c41b81ab6f675943418935fa74" name="tests/bson-corpus/double-valid-004.phpt" role="test" />
<file md5sum="fe3240831666b15e23036505dea59fa1" name="tests/bson-corpus/double-valid-005.phpt" role="test" />
<file md5sum="a224706dad0bf59ce12314a13678af78" name="tests/bson-corpus/double-valid-006.phpt" role="test" />
<file md5sum="8b867ea6bc23c98544e8257d7d8e4c92" name="tests/bson-corpus/double-valid-007.phpt" role="test" />
<file md5sum="804d48af76d2c76fd53627d49d7f2646" name="tests/bson-corpus/double-valid-008.phpt" role="test" />
<file md5sum="3e130f6f9ab3c4a0b6fd22cc2becefa6" name="tests/bson-corpus/double-valid-009.phpt" role="test" />
<file md5sum="604baeed341001363b5715e61056040a" name="tests/bson-corpus/double-valid-010.phpt" role="test" />
<file md5sum="fe54c7d3d75bdf528166ba26f76ef679" name="tests/bson-corpus/double-valid-011.phpt" role="test" />
<file md5sum="545898bdb556531e6f9d11da3ad5978b" name="tests/bson-corpus/double-valid-012.phpt" role="test" />
<file md5sum="c91a4bce14361c34ea741952eb2175be" name="tests/bson-corpus/int32-decodeError-001.phpt" role="test" />
<file md5sum="bd86a89e3e55ba3cc1bfc52f8d51c063" name="tests/bson-corpus/int32-valid-001.phpt" role="test" />
<file md5sum="a7f0ad32a306d3ff6a9e41243bbb1cf7" name="tests/bson-corpus/int32-valid-002.phpt" role="test" />
<file md5sum="5265e1dce0b39e9dd7d3eb28a2614cfe" name="tests/bson-corpus/int32-valid-003.phpt" role="test" />
<file md5sum="e860de8b786fc849832bb01181722e1d" name="tests/bson-corpus/int32-valid-004.phpt" role="test" />
<file md5sum="005f05207b42f0455548cc888b19d589" name="tests/bson-corpus/int32-valid-005.phpt" role="test" />
<file md5sum="0fe33cf3e05061a31ffc678969983d9c" name="tests/bson-corpus/int64-decodeError-001.phpt" role="test" />
<file md5sum="13bfcaf74f3aa1263c628e038ebf0ac6" name="tests/bson-corpus/int64-valid-001.phpt" role="test" />
<file md5sum="049fe2eaa155c9cb71d413c2f40b62b7" name="tests/bson-corpus/int64-valid-002.phpt" role="test" />
<file md5sum="fc58ac268c43443c5698d44bbf9986ac" name="tests/bson-corpus/int64-valid-003.phpt" role="test" />
<file md5sum="9e42448859f7314fcc95d46beb7b41ca" name="tests/bson-corpus/int64-valid-004.phpt" role="test" />
<file md5sum="7666e8e6e7cbc76a9ffcda2e8c41c972" name="tests/bson-corpus/int64-valid-005.phpt" role="test" />
<file md5sum="96c7d0d8dbfd8d3dbc184c71041bd085" name="tests/bson-corpus/maxkey-valid-001.phpt" role="test" />
<file md5sum="db4dfaef00c528351f9d0a79d49272c5" name="tests/bson-corpus/minkey-valid-001.phpt" role="test" />
<file md5sum="665af9df9c8f5436de98687e38505328" name="tests/bson-corpus/multi-type-deprecated-valid-001.phpt" role="test" />
<file md5sum="6575ecdd677d4e7d92da396f18004a36" name="tests/bson-corpus/multi-type-valid-001.phpt" role="test" />
<file md5sum="eecaba36153f53bde14086766ffa357b" name="tests/bson-corpus/null-valid-001.phpt" role="test" />
<file md5sum="fbacc7ed40542cb9572c2bb2a8493412" name="tests/bson-corpus/oid-decodeError-001.phpt" role="test" />
<file md5sum="d79850b753f362e9737a8e01d8a44f2f" name="tests/bson-corpus/oid-valid-001.phpt" role="test" />
<file md5sum="e523c3765b1c8911b90cc1d879926195" name="tests/bson-corpus/oid-valid-002.phpt" role="test" />
<file md5sum="af1f12a17a2ca6e4212a2b8380ea31e9" name="tests/bson-corpus/oid-valid-003.phpt" role="test" />
<file md5sum="3cf5f7b152a8003003b3c2d690c3303b" name="tests/bson-corpus/regex-decodeError-001.phpt" role="test" />
<file md5sum="e97a4abf7777aac9cb3ce9f8722d0453" name="tests/bson-corpus/regex-decodeError-002.phpt" role="test" />
<file md5sum="0e015c17579a3feed38e1e188dc7ff07" name="tests/bson-corpus/regex-valid-001.phpt" role="test" />
<file md5sum="9f3a43c96ad794fff3f75e0a6ecbdada" name="tests/bson-corpus/regex-valid-002.phpt" role="test" />
<file md5sum="a19498c0bc21109fd0ec0f810fc9ee2d" name="tests/bson-corpus/regex-valid-003.phpt" role="test" />
<file md5sum="46f7833cc33761cff91b356e4334463b" name="tests/bson-corpus/regex-valid-004.phpt" role="test" />
<file md5sum="7615e5b9e497d6e8456d375bc1b6910b" name="tests/bson-corpus/regex-valid-005.phpt" role="test" />
<file md5sum="4ffd5048962a95eb4562fce7501172f7" name="tests/bson-corpus/regex-valid-006.phpt" role="test" />
<file md5sum="86a99dccea9fd693a5b04ad5b2c01540" name="tests/bson-corpus/regex-valid-007.phpt" role="test" />
<file md5sum="802a0163c6f4fa8d95e94dc16f94f960" name="tests/bson-corpus/regex-valid-008.phpt" role="test" />
<file md5sum="6557f635e166a9c648e6b75dc5f843e0" name="tests/bson-corpus/regex-valid-009.phpt" role="test" />
<file md5sum="4898fc40b2f51bbba71363a14daab010" name="tests/bson-corpus/string-decodeError-001.phpt" role="test" />
<file md5sum="280e883246a2fc2c030af330a8c4da96" name="tests/bson-corpus/string-decodeError-002.phpt" role="test" />
<file md5sum="71c126e1ee7dd0bb5d9d45946cf121f4" name="tests/bson-corpus/string-decodeError-003.phpt" role="test" />
<file md5sum="73afd75be29fecc6e512f5d7e07010d9" name="tests/bson-corpus/string-decodeError-004.phpt" role="test" />
<file md5sum="9e98c7b6d20ef1dec8fd719435c6cdfd" name="tests/bson-corpus/string-decodeError-005.phpt" role="test" />
<file md5sum="123a6dcad2408ad25b64e22001c86dde" name="tests/bson-corpus/string-decodeError-006.phpt" role="test" />
<file md5sum="f87222f2d3962ee60d538b7cd3309826" name="tests/bson-corpus/string-decodeError-007.phpt" role="test" />
<file md5sum="cd090432ec5b22617da3c15fae13be95" name="tests/bson-corpus/string-valid-001.phpt" role="test" />
<file md5sum="61d943d946c7727fa1939033f388a11b" name="tests/bson-corpus/string-valid-002.phpt" role="test" />
<file md5sum="3ac03f27d856eee9ad8937fdcfc899d2" name="tests/bson-corpus/string-valid-003.phpt" role="test" />
<file md5sum="d52070fed1cb99e9afd091c80bca6a1c" name="tests/bson-corpus/string-valid-004.phpt" role="test" />
<file md5sum="695929957ffb4fe7947e575d5235c8b5" name="tests/bson-corpus/string-valid-005.phpt" role="test" />
<file md5sum="2df5ab655b2a343ff9d742de3dbfe976" name="tests/bson-corpus/string-valid-006.phpt" role="test" />
<file md5sum="e84799c6f81901ac9d3ddf95a60df0fb" name="tests/bson-corpus/string-valid-007.phpt" role="test" />
<file md5sum="830eb608ffd3b6585639f518eeed862b" name="tests/bson-corpus/symbol-decodeError-001.phpt" role="test" />
<file md5sum="0ab4d25eb7621d0a3da5a0d7d00359c5" name="tests/bson-corpus/symbol-decodeError-002.phpt" role="test" />
<file md5sum="b3a8d860d2a1836a8ebbb608e1193283" name="tests/bson-corpus/symbol-decodeError-003.phpt" role="test" />
<file md5sum="bd5f73305b311b05e59e75423648dbb1" name="tests/bson-corpus/symbol-decodeError-004.phpt" role="test" />
<file md5sum="3b9ae0fb4b4f1dc2b9ea00ef617de89f" name="tests/bson-corpus/symbol-decodeError-005.phpt" role="test" />
<file md5sum="6890f411db7f5ea2c4c49efd9208a396" name="tests/bson-corpus/symbol-decodeError-006.phpt" role="test" />
<file md5sum="4fd326563d72bbd45b0e00c82f353a7b" name="tests/bson-corpus/symbol-decodeError-007.phpt" role="test" />
<file md5sum="7d95d4e791eadb0a4046aae7f03f5bbe" name="tests/bson-corpus/symbol-valid-001.phpt" role="test" />
<file md5sum="b0bb8ae42ee2cf53e4cda0c89fd1bda0" name="tests/bson-corpus/symbol-valid-002.phpt" role="test" />
<file md5sum="142070c493226d39a9841548057b9267" name="tests/bson-corpus/symbol-valid-003.phpt" role="test" />
<file md5sum="44002e1290f035dd5fa28105b0dd2151" name="tests/bson-corpus/symbol-valid-004.phpt" role="test" />
<file md5sum="ee611d73c4222f696e08d5e0165ca062" name="tests/bson-corpus/symbol-valid-005.phpt" role="test" />
<file md5sum="30d1b68d8dff83d027dc4fd701223f22" name="tests/bson-corpus/symbol-valid-006.phpt" role="test" />
<file md5sum="a1543108e6f297ee2f7cf6381339309a" name="tests/bson-corpus/timestamp-decodeError-001.phpt" role="test" />
<file md5sum="77004f6708d4f044c123334ab683fee3" name="tests/bson-corpus/timestamp-valid-001.phpt" role="test" />
<file md5sum="e5045dceeea21b4557008b944d2f8456" name="tests/bson-corpus/timestamp-valid-002.phpt" role="test" />
<file md5sum="46d59f37bff62adeba220a24c4f40444" name="tests/bson-corpus/timestamp-valid-003.phpt" role="test" />
<file md5sum="0f24703e16e6d58a54e0d1458421ed04" name="tests/bson-corpus/timestamp-valid-004.phpt" role="test" />
<file md5sum="a5746762b1f83f18dd08b3af2a79bd82" name="tests/bson-corpus/top-decodeError-001.phpt" role="test" />
<file md5sum="5a74dcc8e1f00e3d61b8d532e394fa4a" name="tests/bson-corpus/top-decodeError-002.phpt" role="test" />
<file md5sum="2eebd24618df5f979d21bc03000ec9fb" name="tests/bson-corpus/top-decodeError-003.phpt" role="test" />
<file md5sum="fdcc239654abfb36fdf13b1098c77130" name="tests/bson-corpus/top-decodeError-004.phpt" role="test" />
<file md5sum="711fea55b27b2786267454fda85ff66c" name="tests/bson-corpus/top-decodeError-005.phpt" role="test" />
<file md5sum="67ca5cd050fc16f6be3b3414368c2e0c" name="tests/bson-corpus/top-decodeError-006.phpt" role="test" />
<file md5sum="93ad41d55ec7e4f707f3d14b42f8e547" name="tests/bson-corpus/top-decodeError-007.phpt" role="test" />
<file md5sum="31dc1b6892344a4d37f32cb103631b91" name="tests/bson-corpus/top-decodeError-008.phpt" role="test" />
<file md5sum="1ac72fa2caa70252323a7390e90f4af9" name="tests/bson-corpus/top-decodeError-009.phpt" role="test" />
<file md5sum="2953c32452de2afa6cd31d8377a7eafb" name="tests/bson-corpus/top-decodeError-010.phpt" role="test" />
<file md5sum="6fc36bb32a3209c6218c2240de2eb15f" name="tests/bson-corpus/top-decodeError-011.phpt" role="test" />
<file md5sum="abf592b4ca9282c12a83de8a8da98409" name="tests/bson-corpus/top-decodeError-012.phpt" role="test" />
<file md5sum="ee5382fc1a0b4f995464f3976b98760f" name="tests/bson-corpus/top-decodeError-013.phpt" role="test" />
<file md5sum="2b2a3ba8d74fc26bbc451ea95e8961c9" name="tests/bson-corpus/top-decodeError-014.phpt" role="test" />
<file md5sum="48020b621a91d5798a64a3093002e4cb" name="tests/bson-corpus/top-decodeError-015.phpt" role="test" />
<file md5sum="e4fae2f12a561bd3ffb82ef693900a72" name="tests/bson-corpus/top-parseError-001.phpt" role="test" />
<file md5sum="9cd08fb16dfb481d6a30391b521d6926" name="tests/bson-corpus/top-parseError-002.phpt" role="test" />
<file md5sum="6767ba1deaad7cc658ebdb9d34b35ccd" name="tests/bson-corpus/top-parseError-003.phpt" role="test" />
<file md5sum="203ca09e6fcd6186e025fdf713529773" name="tests/bson-corpus/top-parseError-004.phpt" role="test" />
<file md5sum="14907ac9f9578344f895e192a3072cf4" name="tests/bson-corpus/top-parseError-005.phpt" role="test" />
<file md5sum="57f4f24b244817c15cf329e985905e35" name="tests/bson-corpus/top-parseError-006.phpt" role="test" />
<file md5sum="d51577a319f459bb1ca2d5e8974f2b0a" name="tests/bson-corpus/top-parseError-007.phpt" role="test" />
<file md5sum="5003d0478689f52a901bdb5c8f97a7ab" name="tests/bson-corpus/top-parseError-008.phpt" role="test" />
<file md5sum="ec23c3b3fa83d23338f1225b4ff97266" name="tests/bson-corpus/top-parseError-009.phpt" role="test" />
<file md5sum="b162f2cb67f78f60dc2be04d7e1850a3" name="tests/bson-corpus/top-parseError-010.phpt" role="test" />
<file md5sum="f6c561717161fef888831a004208b889" name="tests/bson-corpus/top-parseError-011.phpt" role="test" />
<file md5sum="6c203c59e320c264bd8a77dcad85c78f" name="tests/bson-corpus/top-parseError-012.phpt" role="test" />
<file md5sum="e0aa94e3b0d53dea52514e97d81bb533" name="tests/bson-corpus/top-parseError-013.phpt" role="test" />
<file md5sum="355204a85d99f71ba5191d6ab3d4c25a" name="tests/bson-corpus/top-parseError-014.phpt" role="test" />
<file md5sum="eb8e0bc7482afd8d028d242b7eed55a1" name="tests/bson-corpus/top-parseError-015.phpt" role="test" />
<file md5sum="21a6da95073beac6597ec25a1e8f1f50" name="tests/bson-corpus/top-parseError-016.phpt" role="test" />
<file md5sum="ef3937e1fac5136b3fb5b89d4b84e58b" name="tests/bson-corpus/top-parseError-017.phpt" role="test" />
<file md5sum="1fa01faebe457ce15d2fa145a1387b16" name="tests/bson-corpus/top-parseError-018.phpt" role="test" />
<file md5sum="4fb0b73c21bc7759ea406486d7af54eb" name="tests/bson-corpus/top-parseError-019.phpt" role="test" />
<file md5sum="aaafb808ced03bf16d7b459b2c03b513" name="tests/bson-corpus/top-parseError-020.phpt" role="test" />
<file md5sum="3585b33df743cd164de84bab95887006" name="tests/bson-corpus/top-parseError-021.phpt" role="test" />
<file md5sum="a0d66550a5fe08352448e581c841e820" name="tests/bson-corpus/top-parseError-022.phpt" role="test" />
<file md5sum="5a572d1c94b46570970c8e24362a680b" name="tests/bson-corpus/top-parseError-023.phpt" role="test" />
<file md5sum="972d38422efd928c9a0abe7fa6ec3bbc" name="tests/bson-corpus/top-parseError-024.phpt" role="test" />
<file md5sum="0b91fe79c2fae913a941179a7d4637ac" name="tests/bson-corpus/top-parseError-025.phpt" role="test" />
<file md5sum="ff22a84cb2cd8a79eb737e2cf891a028" name="tests/bson-corpus/top-parseError-026.phpt" role="test" />
<file md5sum="a4baa8f4b94c682bc97fefa232ccda88" name="tests/bson-corpus/top-parseError-027.phpt" role="test" />
<file md5sum="e11c66523dc4c6c4cb145ef20d93648d" name="tests/bson-corpus/top-parseError-028.phpt" role="test" />
<file md5sum="a604b56dbbd486175ea60d2d3d012ba2" name="tests/bson-corpus/top-parseError-029.phpt" role="test" />
<file md5sum="8a13c440f47575e00d3236e12adcce7c" name="tests/bson-corpus/top-parseError-030.phpt" role="test" />
<file md5sum="e334df950ab8061f120169f73f7df38a" name="tests/bson-corpus/top-parseError-031.phpt" role="test" />
<file md5sum="0444895204cdd4fb7c9a0b9205e6771b" name="tests/bson-corpus/top-parseError-032.phpt" role="test" />
<file md5sum="ad149adbdb84c23e408b8ee48a18682d" name="tests/bson-corpus/top-parseError-033.phpt" role="test" />
<file md5sum="8e523e50fdab6b4f9c234f2da8dee443" name="tests/bson-corpus/top-parseError-034.phpt" role="test" />
<file md5sum="5c548ed88b10bd221e005d716fe3838b" name="tests/bson-corpus/top-parseError-035.phpt" role="test" />
<file md5sum="3728c8281b5ad85fa8061144c9c16248" name="tests/bson-corpus/top-parseError-036.phpt" role="test" />
<file md5sum="710b55a4cbb613984b6e7e363a73d5ee" name="tests/bson-corpus/top-parseError-037.phpt" role="test" />
<file md5sum="44bcdd8c877aa1edb9912bdf7a41177c" name="tests/bson-corpus/top-parseError-038.phpt" role="test" />
<file md5sum="9913de14e00404a200e386ff25b1737f" name="tests/bson-corpus/top-parseError-039.phpt" role="test" />
<file md5sum="518e955449095c0064f8ae0ce6c61d17" name="tests/bson-corpus/top-parseError-040.phpt" role="test" />
<file md5sum="879e82251a2d8f6696947af913df789c" name="tests/bson-corpus/top-parseError-041.phpt" role="test" />
<file md5sum="5194cd6fc21f532371f0b6d3579af422" name="tests/bson-corpus/top-parseError-042.phpt" role="test" />
<file md5sum="582edbb14368ab63af4329ddbf5532c1" name="tests/bson-corpus/top-parseError-043.phpt" role="test" />
<file md5sum="f3bd75e918f0ba2b3d63ce05fafd30d3" name="tests/bson-corpus/top-parseError-044.phpt" role="test" />
<file md5sum="d127bb81fc985a32b18f4fbf562ca6e8" name="tests/bson-corpus/top-valid-001.phpt" role="test" />
<file md5sum="8a40ba6371deed0938490606bf3efe55" name="tests/bson-corpus/top-valid-002.phpt" role="test" />
<file md5sum="d5a07aa241ff80ff6d6558c3ecbe0425" name="tests/bson-corpus/top-valid-003.phpt" role="test" />
<file md5sum="f11a8a52803e238ce58fbc7ed7973927" name="tests/bson-corpus/top-valid-004.phpt" role="test" />
<file md5sum="a5c0bf78a37a5b4cc6b4c766f5720315" name="tests/bson-corpus/undefined-valid-001.phpt" role="test" />
<file md5sum="e0f562832e47bd59cecc7e99aa443e5a" name="tests/bson/bson-binary-001.phpt" role="test" />
<file md5sum="8e80fa7d54ec086c48315cac29f9e739" name="tests/bson/bson-binary-clone-001.phpt" role="test" />
<file md5sum="78c016cd924e363fb8433ce673a76b6a" name="tests/bson/bson-binary-compare-001.phpt" role="test" />
<file md5sum="6eb6c83707dd7be5c718fa13b0427d6c" name="tests/bson/bson-binary-compare-002.phpt" role="test" />
<file md5sum="58e5df014bd86dd8f1313b3fb734a7ce" name="tests/bson/bson-binary-get_properties-001.phpt" role="test" />
<file md5sum="c61e1c8e4c5327f87674314fde6b5d2f" name="tests/bson/bson-binary-get_properties-002.phpt" role="test" />
<file md5sum="a89324b72c9dbfffca5008d9563565c8" name="tests/bson/bson-binary-jsonserialize-001.phpt" role="test" />
<file md5sum="f09168841e8c1c8c75f785705ea5867d" name="tests/bson/bson-binary-jsonserialize-002.phpt" role="test" />
<file md5sum="3bf4748a5513a5aa255a38ada3f49cf6" name="tests/bson/bson-binary-serialization-001.phpt" role="test" />
<file md5sum="1c5030867786be34d289e795e28003c3" name="tests/bson/bson-binary-serialization-002.phpt" role="test" />
<file md5sum="2f8b8545ec69b155f55d1195187a4cd2" name="tests/bson/bson-binary-serialization_error-001.phpt" role="test" />
<file md5sum="423c959fe88b78ade73303c8467779b6" name="tests/bson/bson-binary-serialization_error-002.phpt" role="test" />
<file md5sum="f0e0c245cad638edebd3b4d50c890d93" name="tests/bson/bson-binary-serialization_error-003.phpt" role="test" />
<file md5sum="dc34ba6f912c1684bc6873e3a13c12fb" name="tests/bson/bson-binary-serialization_error-004.phpt" role="test" />
<file md5sum="2bd6ceb365ce5548ce1694081584cd7c" name="tests/bson/bson-binary-serialization_error-005.phpt" role="test" />
<file md5sum="11d3d828f528c119653974af5973baaf" name="tests/bson/bson-binary-serialization_error-006.phpt" role="test" />
<file md5sum="4a4275ac852b7457302ddcb2fdce7544" name="tests/bson/bson-binary-set_state-001.phpt" role="test" />
<file md5sum="b7e5915d1450ca8cb5a5e547ca9160b5" name="tests/bson/bson-binary-set_state_error-001.phpt" role="test" />
<file md5sum="4afee01d63968922b4a6642e7bbb401f" name="tests/bson/bson-binary-set_state_error-002.phpt" role="test" />
<file md5sum="ede14af86e066f7e7a2e1f8fb95deef5" name="tests/bson/bson-binary-set_state_error-003.phpt" role="test" />
<file md5sum="2079c2a8ebed8e51c12a0fab40e42ab3" name="tests/bson/bson-binary-tostring-001.phpt" role="test" />
<file md5sum="07d22be75bb9a7f92a0a70f3e517f43d" name="tests/bson/bson-binary_error-001.phpt" role="test" />
<file md5sum="e19b6d29cb9a0b089ec60d677518b336" name="tests/bson/bson-binary_error-002.phpt" role="test" />
<file md5sum="81379b32b0d5a89ab8a6ff0ac0adadba" name="tests/bson/bson-binary_error-003.phpt" role="test" />
<file md5sum="c06ae96a6cc67f60cbf53231b7a2143f" name="tests/bson/bson-binary_error-004.phpt" role="test" />
<file md5sum="fe638f713510cf803847a14a9109e6e7" name="tests/bson/bson-binaryinterface-001.phpt" role="test" />
<file md5sum="27af38a0c4f8c69764813d35839bf850" name="tests/bson/bson-dbpointer-001.phpt" role="test" />
<file md5sum="a9eb173b6168b52f6f36a3c1ad230e03" name="tests/bson/bson-dbpointer-002.phpt" role="test" />
<file md5sum="3b065984d845826addd19b9a6af03f61" name="tests/bson/bson-dbpointer-clone-001.phpt" role="test" />
<file md5sum="d583aaa6c756bd85fbc18a1aea0c8375" name="tests/bson/bson-dbpointer-compare-001.phpt" role="test" />
<file md5sum="54a92286eef293b765b118e13c4c35c6" name="tests/bson/bson-dbpointer-get_properties-001.phpt" role="test" />
<file md5sum="7eb0a24e6d9fdb5ba682ed5b56d4e903" name="tests/bson/bson-dbpointer-get_properties-002.phpt" role="test" />
<file md5sum="080fc12205c5e3b7faac905c1492d430" name="tests/bson/bson-dbpointer-jsonserialize-001.phpt" role="test" />
<file md5sum="b95771b72feed9e472fe3e8a208c6dc6" name="tests/bson/bson-dbpointer-jsonserialize-003.phpt" role="test" />
<file md5sum="0f8f37f38dc30236b58b2678bdabe8af" name="tests/bson/bson-dbpointer-serialization-001.phpt" role="test" />
<file md5sum="28bc72c2fc1f76d9ce4dca837b0467a9" name="tests/bson/bson-dbpointer-serialization-002.phpt" role="test" />
<file md5sum="572f5c184c8048a12f9a633a4f5b5161" name="tests/bson/bson-dbpointer-serialization_error-001.phpt" role="test" />
<file md5sum="6fcad6bde701b86b793b70d802110843" name="tests/bson/bson-dbpointer-serialization_error-002.phpt" role="test" />
<file md5sum="058d75bfbff3fcb9960c59165ff3f0fe" name="tests/bson/bson-dbpointer-serialization_error-003.phpt" role="test" />
<file md5sum="820c28cd63ded636b5b94d5e7734c201" name="tests/bson/bson-dbpointer-serialization_error-004.phpt" role="test" />
<file md5sum="9967c68c7c6be7228d00469feb0a1a44" name="tests/bson/bson-dbpointer-tostring-001.phpt" role="test" />
<file md5sum="8586d0a798025c589314ec96271f8ee1" name="tests/bson/bson-dbpointer_error-002.phpt" role="test" />
<file md5sum="1b07dc40c0327eaa948a01415e80156e" name="tests/bson/bson-decimal128-001.phpt" role="test" />
<file md5sum="aa1a54f32962e51878159b0b3f25a83a" name="tests/bson/bson-decimal128-002.phpt" role="test" />
<file md5sum="b17b174c54b38e37a407f8fb35aff65e" name="tests/bson/bson-decimal128-003.phpt" role="test" />
<file md5sum="b6d96feed66dfb73e8220e48e58337a1" name="tests/bson/bson-decimal128-004.phpt" role="test" />
<file md5sum="0f6988e90559d6d9f1a55d433bd02e8a" name="tests/bson/bson-decimal128-clone-001.phpt" role="test" />
<file md5sum="49024c33887fe583b96d02a37d826015" name="tests/bson/bson-decimal128-get_properties-001.phpt" role="test" />
<file md5sum="2078cc54b51b316910e7724a9fd6a346" name="tests/bson/bson-decimal128-get_properties-002.phpt" role="test" />
<file md5sum="b82e77c47a326ab042f1e35ec4725e51" name="tests/bson/bson-decimal128-jsonserialize-001.phpt" role="test" />
<file md5sum="cb0996f5695a326193b01373d57a81fb" name="tests/bson/bson-decimal128-jsonserialize-002.phpt" role="test" />
<file md5sum="f890cf6437b01948782d18fe3ecba422" name="tests/bson/bson-decimal128-serialization-001.phpt" role="test" />
<file md5sum="04decbf536c9fb60e5fcce1619ffc27b" name="tests/bson/bson-decimal128-serialization-002.phpt" role="test" />
<file md5sum="c21c6db23fc38a3c0de719c18aba9ed2" name="tests/bson/bson-decimal128-serialization_error-001.phpt" role="test" />
<file md5sum="cdb1ef626a0bc629ba8816d145055383" name="tests/bson/bson-decimal128-serialization_error-002.phpt" role="test" />
<file md5sum="90b4715e5ccade6479572b1cbd4e3fff" name="tests/bson/bson-decimal128-serialization_error-003.phpt" role="test" />
<file md5sum="d79ccabd6541bb758d0848bfe7e8fd7d" name="tests/bson/bson-decimal128-serialization_error-004.phpt" role="test" />
<file md5sum="3a8bcad13be933556fd0967a643293ac" name="tests/bson/bson-decimal128-set_state-001.phpt" role="test" />
<file md5sum="067e89686f1af0fc9281ae7b7fa55559" name="tests/bson/bson-decimal128-set_state_error-001.phpt" role="test" />
<file md5sum="95f6be0b00844003690b270087c7e8e0" name="tests/bson/bson-decimal128-set_state_error-002.phpt" role="test" />
<file md5sum="38e7320acc411dc19c200dcf4cf9fb24" name="tests/bson/bson-decimal128_error-001.phpt" role="test" />
<file md5sum="0f4dea68cea5e1b9ec5ea0bbb7e407e1" name="tests/bson/bson-decimal128_error-002.phpt" role="test" />
<file md5sum="a7dbd531a5dace1341acdf77d3821da3" name="tests/bson/bson-decimal128interface-001.phpt" role="test" />
<file md5sum="5b89a145ad1ee8e366a33c3728b1c1d3" name="tests/bson/bson-decode-001.phpt" role="test" />
<file md5sum="905e2cad0ed091633aa74ea6b3d74368" name="tests/bson/bson-decode-002.phpt" role="test" />
<file md5sum="20d31f08c1bde121119b5643be855f54" name="tests/bson/bson-encode-001.phpt" role="test" />
<file md5sum="6eefc04d2279aa541e60a1bf5a41191a" name="tests/bson/bson-encode-002.phpt" role="test" />
<file md5sum="72beb42baef8a97bb7d58355c916ceeb" name="tests/bson/bson-encode-003.phpt" role="test" />
<file md5sum="1fef8ca07ced691be09475c7726dbfcc" name="tests/bson/bson-encode-004.phpt" role="test" />
<file md5sum="abdb12bec880f1f67021fd671fd59b64" name="tests/bson/bson-encode-005.phpt" role="test" />
<file md5sum="e78affed774e0b3614d96c5455d064d1" name="tests/bson/bson-fromJSON-001.phpt" role="test" />
<file md5sum="cd3f89d1b4b926f9508c1f004244a677" name="tests/bson/bson-fromJSON-002.phpt" role="test" />
+ <file md5sum="5c1d857130788502f6e046a4e5594fba" name="tests/bson/bson-fromJSON-003.phpt" role="test" />
<file md5sum="0235d0d88aa6b8fe6959933b36285145" name="tests/bson/bson-fromJSON_error-001.phpt" role="test" />
<file md5sum="862d5db78dee4d2e6595d2a689d62ef1" name="tests/bson/bson-fromPHP-001.phpt" role="test" />
<file md5sum="e58fb5b6e7c422388074f9841cebd526" name="tests/bson/bson-fromPHP-002.phpt" role="test" />
<file md5sum="6b7dbfd1365adb626abb6a7b22c2e947" name="tests/bson/bson-fromPHP-003.phpt" role="test" />
<file md5sum="76871342b7809aa430fe465dd43361ca" name="tests/bson/bson-fromPHP-005.phpt" role="test" />
<file md5sum="46e2008dccd4677d517ad689ecdb2026" name="tests/bson/bson-fromPHP-006.phpt" role="test" />
<file md5sum="bbadfc7ced5da4ba1bd6652e924f96f1" name="tests/bson/bson-fromPHP_error-001.phpt" role="test" />
<file md5sum="5c886d755cd88364f0c8db69fbf3c940" name="tests/bson/bson-fromPHP_error-002.phpt" role="test" />
<file md5sum="e98523783e7330f32c8201f73c6dcc28" name="tests/bson/bson-fromPHP_error-003.phpt" role="test" />
<file md5sum="f68179caed6ca457d1da808d14cd6c65" name="tests/bson/bson-fromPHP_error-004.phpt" role="test" />
<file md5sum="9b9f0a2f33494c53a9b2ae310a58c005" name="tests/bson/bson-fromPHP_error-005.phpt" role="test" />
<file md5sum="88cad2d0e67050d76fb23a190d7a0e98" name="tests/bson/bson-fromPHP_error-006.phpt" role="test" />
<file md5sum="f73ab14963ae08f0dc674c3b5590ede5" name="tests/bson/bson-fromPHP_error-007.phpt" role="test" />
<file md5sum="247839625266088bbe2470e69cba29b6" name="tests/bson/bson-fromPHP_error-008.phpt" role="test" />
<file md5sum="3f7453d6f12a51683d5378cea4a3c920" name="tests/bson/bson-generate-document-id.phpt" role="test" />
<file md5sum="5bfed445a47856619e5e4ee5966bd531" name="tests/bson/bson-int64-001.phpt" role="test" />
<file md5sum="905baa0034820cce55b12c0fed1ac310" name="tests/bson/bson-int64-002.phpt" role="test" />
<file md5sum="4931c15064094b59d41951e0f2b63bc8" name="tests/bson/bson-int64-003.phpt" role="test" />
<file md5sum="5c9d668ca892566a55d86240786397fa" name="tests/bson/bson-int64-clone-001.phpt" role="test" />
<file md5sum="3e9447dc7f3c1f1d40741b8585fe7807" name="tests/bson/bson-int64-compare-001.phpt" role="test" />
<file md5sum="c213fa3095e2825c4743677d746b1439" name="tests/bson/bson-int64-debug-001.phpt" role="test" />
<file md5sum="9cf48adc54bdbcbcecb5a2d9fd7c83c5" name="tests/bson/bson-int64-get_properties-001.phpt" role="test" />
<file md5sum="4900dd4d57070508e00217e51f470024" name="tests/bson/bson-int64-get_properties-002.phpt" role="test" />
<file md5sum="3e267e9d9f2bd1c6e3cf496dc153291c" name="tests/bson/bson-int64-jsonserialize-001.phpt" role="test" />
<file md5sum="63787c977cac21d00f57d7c280b7ab7e" name="tests/bson/bson-int64-jsonserialize-002.phpt" role="test" />
<file md5sum="2195d40c9cf84278e7182207908c664f" name="tests/bson/bson-int64-serialization-001.phpt" role="test" />
<file md5sum="d949a276c2060299628270411eb360f0" name="tests/bson/bson-int64-serialization-002.phpt" role="test" />
<file md5sum="bc9c651613dac4502de4a08d990e3351" name="tests/bson/bson-int64-serialization_error-001.phpt" role="test" />
<file md5sum="dbb974929ac4bc20457bf78398539883" name="tests/bson/bson-int64-serialization_error-002.phpt" role="test" />
<file md5sum="3a1a4984bb7403742709524fca696869" name="tests/bson/bson-int64-serialization_error-003.phpt" role="test" />
<file md5sum="c80708f2b1967d38447882afbb649820" name="tests/bson/bson-int64-serialization_error-004.phpt" role="test" />
<file md5sum="d3d5527a1ed2efe91fa1772c9f4b9698" name="tests/bson/bson-int64-tostring-001.phpt" role="test" />
<file md5sum="a5e58f843937879d0919b476d879644a" name="tests/bson/bson-int64_error-001.phpt" role="test" />
<file md5sum="a46d3047cc8115fcccb300a9ccab9247" name="tests/bson/bson-javascript-001.phpt" role="test" />
<file md5sum="9c91bd749fd0ab27a36d14394a5e424b" name="tests/bson/bson-javascript-002.phpt" role="test" />
<file md5sum="04404d6096ed38ec3796730bbb5261c3" name="tests/bson/bson-javascript-clone-001.phpt" role="test" />
<file md5sum="97e60e9d937e0545fdd93efbc9f78c7f" name="tests/bson/bson-javascript-compare-001.phpt" role="test" />
<file md5sum="6fa03185f5a88f493df843621065aeb9" name="tests/bson/bson-javascript-compare-002.phpt" role="test" />
<file md5sum="3567bceb79c30dfd50838a0267a69c62" name="tests/bson/bson-javascript-getCode-001.phpt" role="test" />
<file md5sum="540de5d9a88362eb9f00555a1fb35597" name="tests/bson/bson-javascript-getScope-001.phpt" role="test" />
<file md5sum="e25c7ca28f41bf8785962a44c62b2159" name="tests/bson/bson-javascript-get_properties-001.phpt" role="test" />
<file md5sum="d422d8249db5a52a19a9fb2bf3e2b631" name="tests/bson/bson-javascript-get_properties-002.phpt" role="test" />
<file md5sum="b56136e8638788b0e72210ae82293c4a" name="tests/bson/bson-javascript-jsonserialize-001.phpt" role="test" />
<file md5sum="08155bf6625a0317d0daebba81670fcc" name="tests/bson/bson-javascript-jsonserialize-002.phpt" role="test" />
<file md5sum="bcb35c9e2daccee18c6fca9c8008712c" name="tests/bson/bson-javascript-jsonserialize-003.phpt" role="test" />
<file md5sum="e41434375ce47d77b71716fadf06c735" name="tests/bson/bson-javascript-jsonserialize-004.phpt" role="test" />
<file md5sum="84d099b0a16b379db8bbc4776a6610a9" name="tests/bson/bson-javascript-serialization-001.phpt" role="test" />
<file md5sum="14689ce4b1ba7f8b8105efb1598acb21" name="tests/bson/bson-javascript-serialization-002.phpt" role="test" />
<file md5sum="e377451b43f8831e68bfaf694a077789" name="tests/bson/bson-javascript-serialization_error-001.phpt" role="test" />
<file md5sum="a36384592b77821182cf5e7dac8623d8" name="tests/bson/bson-javascript-serialization_error-002.phpt" role="test" />
<file md5sum="3b9e8d0e09c9ca728a33ad59e5f2aaf6" name="tests/bson/bson-javascript-serialization_error-003.phpt" role="test" />
<file md5sum="08d397211436ce1bec9279a6921e3d58" name="tests/bson/bson-javascript-serialization_error-004.phpt" role="test" />
<file md5sum="c74d17bca1b3648fcaef53c5358d4f6e" name="tests/bson/bson-javascript-serialization_error-005.phpt" role="test" />
<file md5sum="a52c6ffac00f34fb356481a38aa50931" name="tests/bson/bson-javascript-serialization_error-006.phpt" role="test" />
<file md5sum="8b7ae41cc5888baaa121061c665ba301" name="tests/bson/bson-javascript-set_state-001.phpt" role="test" />
<file md5sum="d649a395f0abcd4c41dc59f9344f0a89" name="tests/bson/bson-javascript-set_state_error-001.phpt" role="test" />
<file md5sum="e43106245c7f106bc8b60b5a2249980d" name="tests/bson/bson-javascript-set_state_error-002.phpt" role="test" />
<file md5sum="64930970a2085d8c4d5e43d267dc5b13" name="tests/bson/bson-javascript-set_state_error-003.phpt" role="test" />
<file md5sum="4a853962f168d677f3e9c2087766fa29" name="tests/bson/bson-javascript-tostring-001.phpt" role="test" />
<file md5sum="d33b6fabee6b27aa845112710e0f043e" name="tests/bson/bson-javascript_error-001.phpt" role="test" />
<file md5sum="ebee3faf0213cdf7df62dd289a481297" name="tests/bson/bson-javascript_error-002.phpt" role="test" />
<file md5sum="be5b6f9751e312da5ff4d4331e307642" name="tests/bson/bson-javascript_error-003.phpt" role="test" />
<file md5sum="91e37d158699b239d09f45bac8b3a237" name="tests/bson/bson-javascriptinterface-001.phpt" role="test" />
<file md5sum="8443b87ea871db9861558e6979ff0db6" name="tests/bson/bson-maxkey-001.phpt" role="test" />
<file md5sum="e1179648520ecb6cf347e2e82826b4df" name="tests/bson/bson-maxkey-clone-001.phpt" role="test" />
<file md5sum="1640c877e8ffab77ca2a49939721f325" name="tests/bson/bson-maxkey-compare-001.phpt" role="test" />
<file md5sum="4314312c271b5c33f53a4d3887a683b0" name="tests/bson/bson-maxkey-jsonserialize-001.phpt" role="test" />
<file md5sum="b21da8686270aac6b81ec28467ed1144" name="tests/bson/bson-maxkey-jsonserialize-002.phpt" role="test" />
<file md5sum="352380ab948329003bccd5c12397be34" name="tests/bson/bson-maxkey-serialization-001.phpt" role="test" />
<file md5sum="2c7974d5284754b25e129f32b2700dfa" name="tests/bson/bson-maxkey-serialization-002.phpt" role="test" />
<file md5sum="ea86c16672ce4ca92a750eb7de2837e5" name="tests/bson/bson-maxkey-set_state-001.phpt" role="test" />
<file md5sum="d4a47acb431463b7f01c83e5db2f2d3d" name="tests/bson/bson-maxkey_error-001.phpt" role="test" />
<file md5sum="d9a42b06a0a7d9b8103ffee8a638c7b5" name="tests/bson/bson-maxkeyinterface-001.phpt" role="test" />
<file md5sum="a472b29a2cbc7ae8065ca1129ec5f699" name="tests/bson/bson-minkey-001.phpt" role="test" />
<file md5sum="2215a249b4334d774b4d9ab2e075ce72" name="tests/bson/bson-minkey-clone-001.phpt" role="test" />
<file md5sum="cab9d17b350f7ff0fb3930aa298f626a" name="tests/bson/bson-minkey-compare-001.phpt" role="test" />
<file md5sum="6b2c6c29ac2dbc4f91392779b99d562c" name="tests/bson/bson-minkey-jsonserialize-001.phpt" role="test" />
<file md5sum="2f29f939846864d23b0bd7fd3896301a" name="tests/bson/bson-minkey-jsonserialize-002.phpt" role="test" />
<file md5sum="dbc4b2a7f6d42a017a0004bc95552ac3" name="tests/bson/bson-minkey-serialization-001.phpt" role="test" />
<file md5sum="98b0d2775839d019bbaaae5abafa63cb" name="tests/bson/bson-minkey-serialization-002.phpt" role="test" />
<file md5sum="74201982485a724a0822cc2f2093cb75" name="tests/bson/bson-minkey-set_state-001.phpt" role="test" />
<file md5sum="64d66ab2ebc01d4b1c271079bb94db72" name="tests/bson/bson-minkey_error-001.phpt" role="test" />
<file md5sum="0a45023579316c69f78806f230ba106c" name="tests/bson/bson-minkeyinterface-001.phpt" role="test" />
<file md5sum="2f8619f0b382f91b183575db2a09fa68" name="tests/bson/bson-objectid-001.phpt" role="test" />
<file md5sum="d1eae72097de3d1e1bd0ef60f4e35cd6" name="tests/bson/bson-objectid-002.phpt" role="test" />
<file md5sum="c994597716974e44d2586b1fd6abe4a8" name="tests/bson/bson-objectid-003.phpt" role="test" />
<file md5sum="b9a3a09dd645ff06e975d192c34ad587" name="tests/bson/bson-objectid-004.phpt" role="test" />
<file md5sum="75e3621029ca645e2a5bfc69f32f2fd8" name="tests/bson/bson-objectid-clone-001.phpt" role="test" />
<file md5sum="a777ad1f36f9f3ab61a31848e29fbda3" name="tests/bson/bson-objectid-compare-001.phpt" role="test" />
<file md5sum="45a5c909f831527ec527dc6dff83a41d" name="tests/bson/bson-objectid-compare-002.phpt" role="test" />
<file md5sum="5f4fc31b72fbf2946cabfbe801e1f8e5" name="tests/bson/bson-objectid-getTimestamp-001.phpt" role="test" />
<file md5sum="04c2bfef7d149d82b796f8257ae8d1ee" name="tests/bson/bson-objectid-getTimestamp-002.phpt" role="test" />
<file md5sum="cae2d6ff62f134db503c739f79da7516" name="tests/bson/bson-objectid-get_properties-001.phpt" role="test" />
<file md5sum="ce20450b15ec7489bc67392e0af50231" name="tests/bson/bson-objectid-get_properties-002.phpt" role="test" />
<file md5sum="2927bb3a1e8581dada0e53f8c701f30d" name="tests/bson/bson-objectid-jsonserialize-001.phpt" role="test" />
<file md5sum="582dc76cd110aac0e0cb8c299e70d076" name="tests/bson/bson-objectid-jsonserialize-002.phpt" role="test" />
<file md5sum="664772c1486cea5290f9365595b7dd19" name="tests/bson/bson-objectid-serialization-001.phpt" role="test" />
<file md5sum="e75f9416725745ea9a3890a3519f8ff3" name="tests/bson/bson-objectid-serialization-002.phpt" role="test" />
<file md5sum="8cd579253bc676cc7d159dd1bb05b950" name="tests/bson/bson-objectid-serialization_error-001.phpt" role="test" />
<file md5sum="50e1b000a0b30447487e3b3f7dd055db" name="tests/bson/bson-objectid-serialization_error-002.phpt" role="test" />
<file md5sum="9a62434ef2614a0da99c6202fa0e3e4c" name="tests/bson/bson-objectid-serialization_error-003.phpt" role="test" />
<file md5sum="ff253046c0960900411875db4800a0bd" name="tests/bson/bson-objectid-serialization_error-004.phpt" role="test" />
<file md5sum="5d2fd4b95c5120b2f79599dab1d8611f" name="tests/bson/bson-objectid-set_state-001.phpt" role="test" />
<file md5sum="3667bbb9e3faffc2665641488e24cb93" name="tests/bson/bson-objectid-set_state_error-001.phpt" role="test" />
<file md5sum="4d7026a6b49e6f5d40d51a1003a251b6" name="tests/bson/bson-objectid-set_state_error-002.phpt" role="test" />
<file md5sum="dc3e069b4e1039311345171358f3d795" name="tests/bson/bson-objectid-tostring_error-001.phpt" role="test" />
<file md5sum="76ef9f4ba753e7ff3cbbf1a7181a70f1" name="tests/bson/bson-objectid_error-001.phpt" role="test" />
<file md5sum="cdb174d464441a4a3ab142b0d27429ec" name="tests/bson/bson-objectid_error-002.phpt" role="test" />
<file md5sum="556a89c07ebc69c629010a8381f918d3" name="tests/bson/bson-objectid_error-003.phpt" role="test" />
<file md5sum="94512cbf7a26273ee3b7191601600674" name="tests/bson/bson-objectidinterface-001.phpt" role="test" />
<file md5sum="6794691cba0bd0a8d005c10c46c670a3" name="tests/bson/bson-regex-001.phpt" role="test" />
<file md5sum="c6d502bd80b12b49bb86ca15cd80cb5d" name="tests/bson/bson-regex-002.phpt" role="test" />
<file md5sum="4eeeb040d3e3d2e90011e4d82ffadf5c" name="tests/bson/bson-regex-003.phpt" role="test" />
<file md5sum="511347e513bdf3bc2ae37aa34b146c01" name="tests/bson/bson-regex-004.phpt" role="test" />
<file md5sum="c5aeef20912e9660c5b9b9916e6061ed" name="tests/bson/bson-regex-005.phpt" role="test" />
<file md5sum="a785e64f4e65f7497852e29719da7e1c" name="tests/bson/bson-regex-clone-001.phpt" role="test" />
<file md5sum="6f0accb9c2f47fd13f287b115e1fdb69" name="tests/bson/bson-regex-compare-001.phpt" role="test" />
<file md5sum="78e0fcaa87dc451f34f9ef119e1bd274" name="tests/bson/bson-regex-compare-002.phpt" role="test" />
<file md5sum="7b006f20fc2ac164fb4bdce2846da38b" name="tests/bson/bson-regex-get_properties-001.phpt" role="test" />
<file md5sum="6324a488905bb05b3d2e75375c69d88a" name="tests/bson/bson-regex-get_properties-002.phpt" role="test" />
<file md5sum="6fa2a0677b01b0c63ac9e75d7189de73" name="tests/bson/bson-regex-jsonserialize-001.phpt" role="test" />
<file md5sum="b74df13ee5230ede71e1c6dab4439d2f" name="tests/bson/bson-regex-jsonserialize-002.phpt" role="test" />
<file md5sum="8a6b9554bdd5e55d0e7854e439d18925" name="tests/bson/bson-regex-jsonserialize-003.phpt" role="test" />
<file md5sum="ccb43fb3fe648baec71fc2ec79dcbbf4" name="tests/bson/bson-regex-jsonserialize-004.phpt" role="test" />
<file md5sum="34f6961089d1acb9e5d314d2f6a81262" name="tests/bson/bson-regex-serialization-001.phpt" role="test" />
<file md5sum="25b4eb60c948d48451d6d6ce0998f260" name="tests/bson/bson-regex-serialization-002.phpt" role="test" />
<file md5sum="f406a56c1cf8016d5fd0d0ecd6604bd0" name="tests/bson/bson-regex-serialization-003.phpt" role="test" />
<file md5sum="9a37fd5ae1e62311bd1e1fea9a9a84bd" name="tests/bson/bson-regex-serialization-004.phpt" role="test" />
<file md5sum="d986deafead8ca9b484dcc0eed24a934" name="tests/bson/bson-regex-serialization-005.phpt" role="test" />
<file md5sum="8a5a3cb2f10225728a903c66dcd47eb1" name="tests/bson/bson-regex-serialization-006.phpt" role="test" />
<file md5sum="5dd1e154925bebbe66ead1fe352f77bf" name="tests/bson/bson-regex-serialization_error-001.phpt" role="test" />
<file md5sum="66256509949ea548032fe13a35feafa5" name="tests/bson/bson-regex-serialization_error-002.phpt" role="test" />
<file md5sum="bfe0313e242a67e11776d51c2c953b2d" name="tests/bson/bson-regex-serialization_error-003.phpt" role="test" />
<file md5sum="d573dfe08ae5a6abc5e49492714b61d3" name="tests/bson/bson-regex-serialization_error-004.phpt" role="test" />
<file md5sum="1761af9218ff1583f51133d4f0cdcb19" name="tests/bson/bson-regex-set_state-001.phpt" role="test" />
<file md5sum="ab56bd68ecf9ea5717facbaa141db1b5" name="tests/bson/bson-regex-set_state-002.phpt" role="test" />
<file md5sum="fdd23b37dd05d0c7b626bf7192073a26" name="tests/bson/bson-regex-set_state_error-001.phpt" role="test" />
<file md5sum="780b53cc64a01a8d0a74f3cd49563d2e" name="tests/bson/bson-regex-set_state_error-002.phpt" role="test" />
<file md5sum="f86befb012d028c7552ea505725dd6e9" name="tests/bson/bson-regex_error-001.phpt" role="test" />
<file md5sum="009697ca0ba2befc6b308d59fd304b11" name="tests/bson/bson-regex_error-002.phpt" role="test" />
<file md5sum="e8851dee3b4a2cb27016935a7c4fe549" name="tests/bson/bson-regex_error-003.phpt" role="test" />
<file md5sum="b3c02b3eb309f7bbf5a33523a120b43f" name="tests/bson/bson-regexinterface-001.phpt" role="test" />
<file md5sum="b5f7d02fbf62cf6d5bece75e3f82359d" name="tests/bson/bson-symbol-001.phpt" role="test" />
<file md5sum="c49005d1f3a31ba63334439927aa8842" name="tests/bson/bson-symbol-clone-001.phpt" role="test" />
<file md5sum="a55dbbc77a3a9221810c032f38d25005" name="tests/bson/bson-symbol-compare-001.phpt" role="test" />
<file md5sum="e0b90e25e3507d77a97b7463ab76c0d4" name="tests/bson/bson-symbol-get_properties-001.phpt" role="test" />
<file md5sum="0648e9bf022072d2eb9343fb99f30a0a" name="tests/bson/bson-symbol-get_properties-002.phpt" role="test" />
<file md5sum="218eba280d32b6bbe135d24fb530ecb1" name="tests/bson/bson-symbol-jsonserialize-001.phpt" role="test" />
<file md5sum="890793b8dfd3ef59c89b90b5f063acaf" name="tests/bson/bson-symbol-jsonserialize-002.phpt" role="test" />
<file md5sum="403d81de0a50fbb4d660b2c065771906" name="tests/bson/bson-symbol-serialization-001.phpt" role="test" />
<file md5sum="2be0f0a6d09b6e4107616bf4670e5637" name="tests/bson/bson-symbol-serialization-002.phpt" role="test" />
<file md5sum="555b678e5bbe48dbfb15bb93347d4417" name="tests/bson/bson-symbol-serialization_error-001.phpt" role="test" />
<file md5sum="b7237ee2d7d9f6b613a48c502199c2ea" name="tests/bson/bson-symbol-serialization_error-002.phpt" role="test" />
<file md5sum="f9e39cd91cf14f5d0dbc126334a83200" name="tests/bson/bson-symbol-serialization_error-003.phpt" role="test" />
<file md5sum="a61f0474d24c9949b187722437dc2b5c" name="tests/bson/bson-symbol-serialization_error-004.phpt" role="test" />
<file md5sum="5753cdf389e2e3cb769eaa272f4a285e" name="tests/bson/bson-symbol-tostring-001.phpt" role="test" />
<file md5sum="92583aa0415496caf1876468b4814b84" name="tests/bson/bson-symbol_error-001.phpt" role="test" />
<file md5sum="5b5b7584c59afc95c82f798c4405d0e9" name="tests/bson/bson-timestamp-001.phpt" role="test" />
<file md5sum="94cee14f3d06ab8085f06c241a976589" name="tests/bson/bson-timestamp-002.phpt" role="test" />
<file md5sum="a0763909d65abab501df3471d9cf0009" name="tests/bson/bson-timestamp-003.phpt" role="test" />
<file md5sum="3932a3692389d969ee55de22034324b1" name="tests/bson/bson-timestamp-004.phpt" role="test" />
<file md5sum="db926cded84f832c39e527d5fcdadcbb" name="tests/bson/bson-timestamp-005.phpt" role="test" />
<file md5sum="d537ba65e693c20ae7ef9373a10c7b9a" name="tests/bson/bson-timestamp-clone-001.phpt" role="test" />
<file md5sum="bf27f37b85d838f7f3601f1733674ebe" name="tests/bson/bson-timestamp-compare-001.phpt" role="test" />
<file md5sum="8d390960f78a0d4c874f1a9bea6f60e1" name="tests/bson/bson-timestamp-getIncrement-001.phpt" role="test" />
<file md5sum="dbc98d4c863f2edbd470a744569b8ebc" name="tests/bson/bson-timestamp-getTimestamp-001.phpt" role="test" />
<file md5sum="70cbe569659d4cd104ded6f0b3954697" name="tests/bson/bson-timestamp-get_properties-001.phpt" role="test" />
<file md5sum="1cb51102b60c196d34c7c1588b91ae78" name="tests/bson/bson-timestamp-get_properties-002.phpt" role="test" />
<file md5sum="4ff5e264bb118d99302fb918e2b54ea4" name="tests/bson/bson-timestamp-jsonserialize-001.phpt" role="test" />
<file md5sum="c4ed3bdd884202c20cf3dfb199f765a2" name="tests/bson/bson-timestamp-jsonserialize-002.phpt" role="test" />
<file md5sum="5828245cb8bc389dbcc1625087637662" name="tests/bson/bson-timestamp-serialization-001.phpt" role="test" />
<file md5sum="b8c8c61075957d65caab2df3b217c4bd" name="tests/bson/bson-timestamp-serialization-002.phpt" role="test" />
<file md5sum="417881d8826b15f7c2e0df3dd386efef" name="tests/bson/bson-timestamp-serialization-003.phpt" role="test" />
<file md5sum="e4ffb218da3ca4e4947c577eb9ac7b1b" name="tests/bson/bson-timestamp-serialization-004.phpt" role="test" />
<file md5sum="6187a9a761acda7f751591d944dd890f" name="tests/bson/bson-timestamp-serialization_error-001.phpt" role="test" />
<file md5sum="7b0f7e61ca04c299c65b9c7861d61e01" name="tests/bson/bson-timestamp-serialization_error-002.phpt" role="test" />
<file md5sum="ddbdf01400527236bc45326ec0558c5d" name="tests/bson/bson-timestamp-serialization_error-003.phpt" role="test" />
<file md5sum="cb50b8e81cae55ecec85b029dc91b124" name="tests/bson/bson-timestamp-serialization_error-004.phpt" role="test" />
<file md5sum="359692a518cea16106f34a999305c280" name="tests/bson/bson-timestamp-serialization_error-005.phpt" role="test" />
<file md5sum="bc0dd3d46bff61f1b84a18a70dabe480" name="tests/bson/bson-timestamp-serialization_error-006.phpt" role="test" />
<file md5sum="b3774e8fb79913b09eaec9294ae00128" name="tests/bson/bson-timestamp-serialization_error-007.phpt" role="test" />
<file md5sum="8533a6a30fa1ee5e6be11c81b2629f95" name="tests/bson/bson-timestamp-serialization_error-008.phpt" role="test" />
<file md5sum="7a13dad169f79e7cda4ab3c7a8e2dc1f" name="tests/bson/bson-timestamp-set_state-001.phpt" role="test" />
<file md5sum="2137458362aca8c1a3d8f6224c438d9e" name="tests/bson/bson-timestamp-set_state-002.phpt" role="test" />
<file md5sum="8baeba2ddc938df88ba34a03ba47d1d1" name="tests/bson/bson-timestamp-set_state_error-001.phpt" role="test" />
<file md5sum="73a5d3cebea540001cba1b80f1febc52" name="tests/bson/bson-timestamp-set_state_error-002.phpt" role="test" />
<file md5sum="c37df82f2051521242f1dbc7ae1a9ecd" name="tests/bson/bson-timestamp-set_state_error-003.phpt" role="test" />
<file md5sum="d7176a251bfc6af5b814cc7a52a8f4b3" name="tests/bson/bson-timestamp-set_state_error-004.phpt" role="test" />
<file md5sum="6ca746014810084f9fe6cc45bb431ed6" name="tests/bson/bson-timestamp_error-001.phpt" role="test" />
<file md5sum="69daf6c7b6567dfbce4f64a6a77075a5" name="tests/bson/bson-timestamp_error-002.phpt" role="test" />
<file md5sum="c6a934138c3573ae650ea666baa809c5" name="tests/bson/bson-timestamp_error-003.phpt" role="test" />
<file md5sum="6b62f4f50fb29c882e769710d62b1f72" name="tests/bson/bson-timestamp_error-004.phpt" role="test" />
<file md5sum="4345c7e61bb3f6eadf294f1d29d5c4df" name="tests/bson/bson-timestamp_error-005.phpt" role="test" />
<file md5sum="a708297bd4537aecac1efe8868cabf7e" name="tests/bson/bson-timestamp_error-006.phpt" role="test" />
<file md5sum="304b9fe634cafb1fb611d793197f60ec" name="tests/bson/bson-timestampinterface-001.phpt" role="test" />
<file md5sum="a82ec1fe251bc4a7ce713735ae9a28b2" name="tests/bson/bson-toCanonicalJSON-001.phpt" role="test" />
<file md5sum="22321d5aa441679bfb9f60ea930228a6" name="tests/bson/bson-toCanonicalJSON-002.phpt" role="test" />
<file md5sum="5b5fa3d5a61d2646ff9f82003e83f222" name="tests/bson/bson-toCanonicalJSON_error-001.phpt" role="test" />
<file md5sum="7349eb21455138d4d5d40891a0f9f837" name="tests/bson/bson-toCanonicalJSON_error-002.phpt" role="test" />
<file md5sum="47b89324f7c19952f8fa6e977a0a0e75" name="tests/bson/bson-toCanonicalJSON_error-003.phpt" role="test" />
<file md5sum="acf0303d524300ae52812f4c04c446a5" name="tests/bson/bson-toJSON-001.phpt" role="test" />
<file md5sum="44357d5f0079f8c53f3b5d0d1671d0b4" name="tests/bson/bson-toJSON-002.phpt" role="test" />
+ <file md5sum="4680a3b31b66615db2875e3d794dcffd" name="tests/bson/bson-toJSON-003.phpt" role="test" />
<file md5sum="1534bb66792c42334a3ccf580da1c97b" name="tests/bson/bson-toJSON_error-001.phpt" role="test" />
<file md5sum="47271f6e4dded5ff20f04c88b2e53b8f" name="tests/bson/bson-toJSON_error-002.phpt" role="test" />
<file md5sum="3c2ca8258b3b64d53a74040675a9ead7" name="tests/bson/bson-toJSON_error-003.phpt" role="test" />
<file md5sum="c2c8b44aec6dbc4a7649394607b7aed4" name="tests/bson/bson-toPHP-001.phpt" role="test" />
<file md5sum="902453975c62deb1601d90f88778f45b" name="tests/bson/bson-toPHP-002.phpt" role="test" />
<file md5sum="28758ff54b0ba60b172bceb762710e60" name="tests/bson/bson-toPHP-003.phpt" role="test" />
<file md5sum="f1528de440af64af3ad2c64680b5d24f" name="tests/bson/bson-toPHP-004.phpt" role="test" />
<file md5sum="429cf2a3dd16f54a2688043e97598348" name="tests/bson/bson-toPHP-006.phpt" role="test" />
<file md5sum="a0b49d8b87a293efe7aa38950455b894" name="tests/bson/bson-toPHP-007.phpt" role="test" />
<file md5sum="d25d75d37d7252171a7349a3c9103760" name="tests/bson/bson-toPHP-008.phpt" role="test" />
<file md5sum="8dea2bcca14169ded2315c3c69986465" name="tests/bson/bson-toPHP-009.phpt" role="test" />
<file md5sum="1f4802a3e561debbb3ae5e08125bfb86" name="tests/bson/bson-toPHP-010.phpt" role="test" />
<file md5sum="138a7e09fdce8d44d6719a76d95d6baa" name="tests/bson/bson-toPHP-011.phpt" role="test" />
+ <file md5sum="b4c90232aff25ed3b7e28f1ba052c35d" name="tests/bson/bson-toPHP-012.phpt" role="test" />
<file md5sum="aeb50a7ff8e6e5e241630ca2d6835536" name="tests/bson/bson-toPHP_error-001.phpt" role="test" />
<file md5sum="26629fc4af47f1878838edb4f4b161f3" name="tests/bson/bson-toPHP_error-002.phpt" role="test" />
<file md5sum="8df28633d423cf82f5f4b08b65395b78" name="tests/bson/bson-toPHP_error-003.phpt" role="test" />
<file md5sum="a4c73580f29357adf4c4cff62f265d2a" name="tests/bson/bson-toPHP_error-004.phpt" role="test" />
<file md5sum="f6e156c4ae00827bc071e1f039e83b3d" name="tests/bson/bson-toPHP_error-005.phpt" role="test" />
<file md5sum="393e6cd0dc25441afd9802e361ffb900" name="tests/bson/bson-toPHP_error-006.phpt" role="test" />
<file md5sum="28afbfd1d34a8531e28c70c1d1b8c277" name="tests/bson/bson-toRelaxedJSON-001.phpt" role="test" />
<file md5sum="53e31eb8338e3fbfc680fa7561c9cba3" name="tests/bson/bson-toRelaxedJSON-002.phpt" role="test" />
<file md5sum="05af402e9c41fdc20e1840183dfc3ead" name="tests/bson/bson-toRelaxedJSON_error-001.phpt" role="test" />
<file md5sum="7e5f4a45d2bbb48e823ae6ee1b244c6c" name="tests/bson/bson-toRelaxedJSON_error-002.phpt" role="test" />
<file md5sum="6832130f3ad0ff88be298675a6ac2fd8" name="tests/bson/bson-toRelaxedJSON_error-003.phpt" role="test" />
<file md5sum="522c1e36a572c3a8a9835683b3fb4d60" name="tests/bson/bson-undefined-001.phpt" role="test" />
<file md5sum="2e2f8ed13b02d8631b8137568ae5b50b" name="tests/bson/bson-undefined-clone-001.phpt" role="test" />
<file md5sum="dc74e078f67345758dbb837e9d1f0f6e" name="tests/bson/bson-undefined-compare-001.phpt" role="test" />
<file md5sum="286eaff5b548beb827ac4e7641bf0cf8" name="tests/bson/bson-undefined-jsonserialize-001.phpt" role="test" />
<file md5sum="8c8a718f141b1a455d12e3e4395b638f" name="tests/bson/bson-undefined-jsonserialize-002.phpt" role="test" />
<file md5sum="e8f9d2ea7cfa8130a5e2370a89dd4bad" name="tests/bson/bson-undefined-serialization-001.phpt" role="test" />
<file md5sum="81eac679b3b83eec0f290d9724ea9856" name="tests/bson/bson-undefined-serialization-002.phpt" role="test" />
<file md5sum="efc4ba473c747b5b0dc5b5ac7fbeb8c4" name="tests/bson/bson-undefined-tostring-001.phpt" role="test" />
<file md5sum="40d8bb19b4d396749f94324a6e21cbcb" name="tests/bson/bson-undefined_error-001.phpt" role="test" />
<file md5sum="44f4e512930061f4c42daa0b0a60bfe3" name="tests/bson/bson-unknown-001.phpt" role="test" />
<file md5sum="4319ea68e884e60f54e36bb2c82b699d" name="tests/bson/bson-utcdatetime-001.phpt" role="test" />
<file md5sum="de22f1e3d63048ab3db3b3514ce45bf2" name="tests/bson/bson-utcdatetime-002.phpt" role="test" />
<file md5sum="4a7ceed02905927b3e2df8c5cc957d98" name="tests/bson/bson-utcdatetime-003.phpt" role="test" />
<file md5sum="de4188f960c7fd6debed280d2ce4da02" name="tests/bson/bson-utcdatetime-004.phpt" role="test" />
<file md5sum="ebcbd881098aeef861090012f341282d" name="tests/bson/bson-utcdatetime-005.phpt" role="test" />
<file md5sum="982f7f8d65d0f7f222f9b2512786dc4c" name="tests/bson/bson-utcdatetime-006.phpt" role="test" />
<file md5sum="322715ac6f412974a9dacb1dc7a1ebc9" name="tests/bson/bson-utcdatetime-007.phpt" role="test" />
<file md5sum="d254384c4d47ea4242c61ded0e391d66" name="tests/bson/bson-utcdatetime-clone-001.phpt" role="test" />
<file md5sum="6728e628d6cd1def65b21b5d58c477b4" name="tests/bson/bson-utcdatetime-compare-001.phpt" role="test" />
<file md5sum="8272da2bda9a4289184e655f6822550c" name="tests/bson/bson-utcdatetime-get_properties-001.phpt" role="test" />
<file md5sum="334df91a905a2ca36f77b385271e77ab" name="tests/bson/bson-utcdatetime-get_properties-002.phpt" role="test" />
<file md5sum="87a0dfcedd4205a3da922c2f10a05e7e" name="tests/bson/bson-utcdatetime-int-size-001.phpt" role="test" />
<file md5sum="56191c433baac3e51c249dec24a34a5e" name="tests/bson/bson-utcdatetime-int-size-002.phpt" role="test" />
<file md5sum="a93b633b97ec16f0b7707205f4709d12" name="tests/bson/bson-utcdatetime-jsonserialize-001.phpt" role="test" />
<file md5sum="69cf474f8b42d60ddea971ea57a092bc" name="tests/bson/bson-utcdatetime-jsonserialize-002.phpt" role="test" />
<file md5sum="ae56b03f19d04e0f0e6159220830dcd4" name="tests/bson/bson-utcdatetime-serialization-001.phpt" role="test" />
<file md5sum="1f5cca24baa36821a313dbcabf70846f" name="tests/bson/bson-utcdatetime-serialization-002.phpt" role="test" />
<file md5sum="83425ce215a17789ba2cd09d9c272224" name="tests/bson/bson-utcdatetime-serialization-003.phpt" role="test" />
<file md5sum="953a3066ecbfb702bab335eee8fa2bea" name="tests/bson/bson-utcdatetime-serialization-004.phpt" role="test" />
<file md5sum="a8f6d095646ba51b3fd9788f6be3dd23" name="tests/bson/bson-utcdatetime-serialization_error-001.phpt" role="test" />
<file md5sum="bb9575e11adaeda47d544a78e5cede26" name="tests/bson/bson-utcdatetime-serialization_error-002.phpt" role="test" />
<file md5sum="53fdeaf7c37bd0a410d2ba04a0a1e884" name="tests/bson/bson-utcdatetime-serialization_error-003.phpt" role="test" />
<file md5sum="9d764d6fea3f1414b967e7aa9a20e02b" name="tests/bson/bson-utcdatetime-serialization_error-004.phpt" role="test" />
<file md5sum="5f4ac622d87e508604308b21ae43f835" name="tests/bson/bson-utcdatetime-set_state-001.phpt" role="test" />
<file md5sum="cdbb4d6a6cd72816568163b8f54a0b9f" name="tests/bson/bson-utcdatetime-set_state-002.phpt" role="test" />
<file md5sum="ddd4b46bb4a6912b2d4f089f0d661cc4" name="tests/bson/bson-utcdatetime-set_state_error-001.phpt" role="test" />
<file md5sum="d5e321205232b014070cb2f4986e2f86" name="tests/bson/bson-utcdatetime-set_state_error-002.phpt" role="test" />
<file md5sum="1b9dd88668a06f402a8567d13d47dea7" name="tests/bson/bson-utcdatetime-todatetime-001.phpt" role="test" />
<file md5sum="8a6c7f3a7120a6135e4d8153da1fe675" name="tests/bson/bson-utcdatetime-todatetime-002.phpt" role="test" />
<file md5sum="71574612145585e471c5777f97b4721e" name="tests/bson/bson-utcdatetime-tostring-001.phpt" role="test" />
<file md5sum="ccc05d6334ea2bfebe4f35f9cc9a47dc" name="tests/bson/bson-utcdatetime_error-001.phpt" role="test" />
<file md5sum="d87151a333e0bbdb938955184366451e" name="tests/bson/bson-utcdatetime_error-002.phpt" role="test" />
<file md5sum="2e08d89b5ae15ad631aa99ab75374a9c" name="tests/bson/bson-utcdatetime_error-003.phpt" role="test" />
<file md5sum="d1aea5ef2f3fd0eb229ee2d5d83b5f2c" name="tests/bson/bson-utcdatetime_error-004.phpt" role="test" />
<file md5sum="a67824badfe3e9a6cfb5aea0577edaad" name="tests/bson/bson-utcdatetimeinterface-001.phpt" role="test" />
<file md5sum="d3e4cf8c1076daa382830ce04144bccc" name="tests/bson/bug0274.phpt" role="test" />
<file md5sum="703c3782b42782bbb822a94aa3c2d121" name="tests/bson/bug0325.phpt" role="test" />
<file md5sum="83c306e8ce09efc5d522f828243736c7" name="tests/bson/bug0334-001.phpt" role="test" />
<file md5sum="210085eaff5b9efea56a5b1ce1a5710c" name="tests/bson/bug0334-002.phpt" role="test" />
<file md5sum="2040b00df19f44645120f86708a6bbb6" name="tests/bson/bug0341.phpt" role="test" />
<file md5sum="0cdeba17452a000dab636ae0ee32f9d9" name="tests/bson/bug0347.phpt" role="test" />
<file md5sum="1eb798c06998f02912ece8b791d8366f" name="tests/bson/bug0528.phpt" role="test" />
<file md5sum="3813fc4b5a63c2d33d8b3cffaca0e8d5" name="tests/bson/bug0531-001.phpt" role="test" />
<file md5sum="e099504467387df42af07a35a74fcd31" name="tests/bson/bug0544.phpt" role="test" />
<file md5sum="2f82e244799d87c8d65772a78ecbacbf" name="tests/bson/bug0592.phpt" role="test" />
<file md5sum="6881f25614a80996fa9edaa608abb5bc" name="tests/bson/bug0623.phpt" role="test" />
<file md5sum="da12dca645be8512da84fde89ebc893a" name="tests/bson/bug0631.phpt" role="test" />
<file md5sum="b982dd73d598f1466905d11fdf43bdb2" name="tests/bson/bug0672.phpt" role="test" />
<file md5sum="9264b5948771b436ed31cf559ade001a" name="tests/bson/bug0894-001.phpt" role="test" />
<file md5sum="d0c1fd240ccf37b9af58f7e892278b60" name="tests/bson/bug0923-001.phpt" role="test" />
<file md5sum="8f38c32d045e96c06538bec87e8e7dcd" name="tests/bson/bug0923-002.phpt" role="test" />
<file md5sum="455a94f4f8a0ff8fd27e52d96438fd59" name="tests/bson/bug0939-001.phpt" role="test" />
<file md5sum="ec18f7aa32d251859f5ecae309a7da6c" name="tests/bson/bug0974-001.phpt" role="test" />
<file md5sum="a69437b114d2d538b5bb591598ca3493" name="tests/bson/bug1006-001.phpt" role="test" />
<file md5sum="38e1666dc67a7ca49646a9d787400e2e" name="tests/bson/bug1006-002.phpt" role="test" />
<file md5sum="22c30ca9d73e86406d2d6f74861366b7" name="tests/bson/bug1053.phpt" role="test" />
<file md5sum="b32de2d6a5a540a853ad9ae92b466e63" name="tests/bson/bug1067.phpt" role="test" />
<file md5sum="6e4cd77ba6ba82ebf68c6a366733094e" name="tests/bson/bug1266.phpt" role="test" />
<file md5sum="2cf98072672acfd21d0da25bad891ac6" name="tests/bson/bug1598-001.phpt" role="test" />
<file md5sum="14399bc891511ef249b27b2a377e7319" name="tests/bson/bug1598-002.phpt" role="test" />
<file md5sum="cbd0992c9a32e8c1777f75256ec30ade" name="tests/bson/bug1839-001.phpt" role="test" />
<file md5sum="e95661dcc62bf6e6d287187b0e00a151" name="tests/bson/bug1839-002.phpt" role="test" />
<file md5sum="aa36dbea2e9c29d58b15f0a3ed5211cd" name="tests/bson/bug1839-003.phpt" role="test" />
<file md5sum="9dcb7cfdee07ae5e41bffd58ac7b48a1" name="tests/bson/bug1839-004.phpt" role="test" />
<file md5sum="f71c4bb04f368828e4371ebf9b68f4e2" name="tests/bson/bug1839-005.phpt" role="test" />
<file md5sum="637bf7ef46dbb397aa0bb17f1712a698" name="tests/bson/bug1839-006.phpt" role="test" />
<file md5sum="9f35b64bb1bff9746febd2ec22c8dc06" name="tests/bson/bug1839-007.phpt" role="test" />
<file md5sum="b689bc7a94b208aff702848e5dbf9416" name="tests/bson/bug1839-008.phpt" role="test" />
<file md5sum="334d9e27adf0080811c164edc4a09604" name="tests/bson/typemap-001.phpt" role="test" />
<file md5sum="7d45dc9c4e491d5405fdb3bdc1eaa84b" name="tests/bson/typemap-002.phpt" role="test" />
<file md5sum="20fb7177932f34e5d3bb02791c1e4530" name="tests/bson/typemap-003.phpt" role="test" />
<file md5sum="0ce89d13ac86a496bf018b656a6b6ec8" name="tests/bson/typemap-004.phpt" role="test" />
<file md5sum="588aefd123e8ae0d1a4d4e2c4cfa1e9c" name="tests/bson/typemap-005.phpt" role="test" />
<file md5sum="6e028e5000a0609a96478a8d955c8b42" name="tests/bson/typemap-006.phpt" role="test" />
<file md5sum="907a18be6ca57629a5c5222dcc61fce2" name="tests/bson/typemap-007.phpt" role="test" />
<file md5sum="55f4be2106b3f9222216570cb4e53df8" name="tests/bulk/bug0667.phpt" role="test" />
<file md5sum="e64d115fba82e356ad50e008520a491f" name="tests/bulk/bulkwrite-count-001.phpt" role="test" />
<file md5sum="0a96053f6e2e81ba25f21c62ab6512fa" name="tests/bulk/bulkwrite-countable-001.phpt" role="test" />
<file md5sum="d82fab930893ce11122510d6f27380c3" name="tests/bulk/bulkwrite-debug-001.phpt" role="test" />
- <file md5sum="7df42fa709668303eed8443f9c8e3280" name="tests/bulk/bulkwrite-debug-002.phpt" role="test" />
+ <file md5sum="1b437c5f96c7e0b7e58adee71d5c9477" name="tests/bulk/bulkwrite-debug-002.phpt" role="test" />
<file md5sum="258ae0a1c622c643e8f8872ad7fc47a9" name="tests/bulk/bulkwrite-delete-001.phpt" role="test" />
<file md5sum="1ccd740b537c38b2c63e287ef7c59b61" name="tests/bulk/bulkwrite-delete-002.phpt" role="test" />
<file md5sum="455cebe9732350024cafd321188e1f44" name="tests/bulk/bulkwrite-delete_error-001.phpt" role="test" />
<file md5sum="8b72f9f86c38e21f2c62a529ac39dfd4" name="tests/bulk/bulkwrite-delete_error-002.phpt" role="test" />
<file md5sum="5c2928e7429cd633e042e59561ff4f00" name="tests/bulk/bulkwrite-delete_error-003.phpt" role="test" />
- <file md5sum="091b2b29fc68445f8c361a407806126e" name="tests/bulk/bulkwrite-delete_error-004.phpt" role="test" />
- <file md5sum="4e7668029bccdd86971290850dc9f0c5" name="tests/bulk/bulkwrite-delete_error-005.phpt" role="test" />
+ <file md5sum="e1ac1619f3114f9175e1d0249dbfafb7" name="tests/bulk/bulkwrite-delete_error-005.phpt" role="test" />
<file md5sum="a0f4f9800e1215bd5ae006a8b4ce93e7" name="tests/bulk/bulkwrite-insert-001.phpt" role="test" />
<file md5sum="5b0444ab63abf63403518d4e91af4e89" name="tests/bulk/bulkwrite-insert-004.phpt" role="test" />
<file md5sum="f78b72d1cf92e87ae55c01f387e349ff" name="tests/bulk/bulkwrite-insert_error-001.phpt" role="test" />
<file md5sum="a20b0d320adf61d20988b8dcda9580ae" name="tests/bulk/bulkwrite-insert_error-002.phpt" role="test" />
<file md5sum="59c60a17514366c03448112a41fbe726" name="tests/bulk/bulkwrite-insert_error-003.phpt" role="test" />
<file md5sum="90f30610837b3c4dacf3121bdbdfe680" name="tests/bulk/bulkwrite-update-001.phpt" role="test" />
- <file md5sum="f00e82f676f1062bc6d28d232e254291" name="tests/bulk/bulkwrite-update-002.phpt" role="test" />
+ <file md5sum="8257aa4b9b034288c463fa67c72a78e1" name="tests/bulk/bulkwrite-update-002.phpt" role="test" />
<file md5sum="72717aa03bbb8050feebc3bd78747035" name="tests/bulk/bulkwrite-update-003.phpt" role="test" />
<file md5sum="f377f9003530d52b5eef96cccd1e042d" name="tests/bulk/bulkwrite-update-004.phpt" role="test" />
<file md5sum="d9e18f23a4604f922ac662c01782614b" name="tests/bulk/bulkwrite-update_error-001.phpt" role="test" />
<file md5sum="40e78e07b505520a85a69a1fd9f01cae" name="tests/bulk/bulkwrite-update_error-002.phpt" role="test" />
<file md5sum="83fdd3168f859cb31b0afdac24d46dfe" name="tests/bulk/bulkwrite-update_error-003.phpt" role="test" />
<file md5sum="08abf78018bdd6d3bb652f86f5653905" name="tests/bulk/bulkwrite-update_error-004.phpt" role="test" />
<file md5sum="9a7d39da76a5c30b106dc891da1f55f7" name="tests/bulk/bulkwrite-update_error-005.phpt" role="test" />
- <file md5sum="8478ad8893e451dfae0dd0d665149344" name="tests/bulk/bulkwrite-update_error-006.phpt" role="test" />
- <file md5sum="3139e2a481a93685dc2209ccc9cb0314" name="tests/bulk/bulkwrite-update_error-007.phpt" role="test" />
- <file md5sum="df6def7111dbb80c39553ac389110e03" name="tests/bulk/bulkwrite-update_error-008.phpt" role="test" />
+ <file md5sum="d83616a08c8691c84b3f155f7809d18b" name="tests/bulk/bulkwrite-update_error-008.phpt" role="test" />
<file md5sum="bd5f1f654b138089ea753c5e20d589f2" name="tests/bulk/bulkwrite_error-001.phpt" role="test" />
<file md5sum="2b2784e0a4fa3c6628a932ee53126946" name="tests/bulk/bulkwrite_error-002.phpt" role="test" />
<file md5sum="9620e8719fb39c100f23862926e2d9ce" name="tests/bulk/write-0001.phpt" role="test" />
<file md5sum="39c8e831ed0f1566c5dd8ebd4edf4bd3" name="tests/bulk/write-0002.phpt" role="test" />
- <file md5sum="b620d094ffff2bb42da9382cf6e8e267" name="tests/causal-consistency/causal-consistency-001.phpt" role="test" />
- <file md5sum="0563a7274286a9f0c84d22341e6e79c3" name="tests/causal-consistency/causal-consistency-002.phpt" role="test" />
- <file md5sum="7aba2223bef5d14be15dbbfd06199021" name="tests/causal-consistency/causal-consistency-003.phpt" role="test" />
- <file md5sum="c48e9170f7099a368553d87fee098b65" name="tests/causal-consistency/causal-consistency-004.phpt" role="test" />
- <file md5sum="5137a93609e0f3dbea217ed6c822b70a" name="tests/causal-consistency/causal-consistency-005.phpt" role="test" />
- <file md5sum="c10864a9752367de9185ac0a0bfd8193" name="tests/causal-consistency/causal-consistency-006.phpt" role="test" />
- <file md5sum="ba657c6fa09189b992b912e51d59b7ff" name="tests/causal-consistency/causal-consistency-007.phpt" role="test" />
- <file md5sum="9d730f12d0472eebe0bd6d0e4223f850" name="tests/causal-consistency/causal-consistency-008.phpt" role="test" />
- <file md5sum="7126df34b4f3445b7bb31425bfce576e" name="tests/causal-consistency/causal-consistency-009.phpt" role="test" />
- <file md5sum="4a4393f334267880359bf883d45f4854" name="tests/causal-consistency/causal-consistency-010.phpt" role="test" />
- <file md5sum="589d21cea2dd8379c96fe99a1dde50c6" name="tests/causal-consistency/causal-consistency-011.phpt" role="test" />
- <file md5sum="1b0252e79dff94527a7716ea4d1b990c" name="tests/causal-consistency/causal-consistency-012.phpt" role="test" />
+ <file md5sum="8a59042397146a6403b05d49d19927fc" name="tests/causal-consistency/causal-consistency-001.phpt" role="test" />
+ <file md5sum="d3e9eae691d9574829c6ac4fc15679cc" name="tests/causal-consistency/causal-consistency-002.phpt" role="test" />
+ <file md5sum="7b9976bef2af039a9fd8c6e92a681533" name="tests/causal-consistency/causal-consistency-003.phpt" role="test" />
+ <file md5sum="d0a3779ae5032b82cfd007fac79d66d7" name="tests/causal-consistency/causal-consistency-004.phpt" role="test" />
+ <file md5sum="08d0f259d8c3d9d30d45592ee12d7ef3" name="tests/causal-consistency/causal-consistency-005.phpt" role="test" />
+ <file md5sum="f846641c4b1f23847d7e9ed24bc2fda1" name="tests/causal-consistency/causal-consistency-006.phpt" role="test" />
+ <file md5sum="8939f754bbda25f29dec934c71aa6436" name="tests/causal-consistency/causal-consistency-007.phpt" role="test" />
+ <file md5sum="94d13af15b1f05867936624a980c5af6" name="tests/causal-consistency/causal-consistency-008.phpt" role="test" />
+ <file md5sum="39354f752f54b2dd511a726e72eb197e" name="tests/causal-consistency/causal-consistency-009.phpt" role="test" />
+ <file md5sum="91098da345011767e321e75deef99a1a" name="tests/causal-consistency/causal-consistency-010.phpt" role="test" />
+ <file md5sum="c4ce8b5d2f34064ab19f21e2f7049e2f" name="tests/causal-consistency/causal-consistency-011.phpt" role="test" />
+ <file md5sum="2528cc9b914cd2e641f673a8bff58c17" name="tests/causal-consistency/causal-consistency-012.phpt" role="test" />
<file md5sum="f4f472cc8b013465c3fbb600ceaecc53" name="tests/clientEncryption/clientEncryption-constants.phpt" role="test" />
<file md5sum="14746b6a0288ff389bcd8b147f8b22de" name="tests/clientEncryption/clientEncryption-createDataKey-001.phpt" role="test" />
<file md5sum="0143c3a0ce8c2faea1accbef594e1dd8" name="tests/clientEncryption/clientEncryption-createDataKey_error-001.phpt" role="test" />
- <file md5sum="e9ba3acdb344a6f0d7086b395722fb1d" name="tests/clientEncryption/clientEncryption-decrypt-001.phpt" role="test" />
- <file md5sum="88a9d64f4c4088a469b329cdecc645c5" name="tests/clientEncryption/clientEncryption-encrypt-001.phpt" role="test" />
+ <file md5sum="34f12363170f2783a4841a5b2113c299" name="tests/clientEncryption/clientEncryption-decrypt-001.phpt" role="test" />
+ <file md5sum="7509d4f9bed0416d757ae0d932a1cc67" name="tests/clientEncryption/clientEncryption-encrypt-001.phpt" role="test" />
<file md5sum="ef68cd61887cefb041597f5d81a7b673" name="tests/command/command-ctor-001.phpt" role="test" />
<file md5sum="81fbf19cf9cd5f5383c49d9fd3f177e8" name="tests/command/command_error-001.phpt" role="test" />
<file md5sum="4933197dd276292bc02bae8d3bce1728" name="tests/command/cursor-batchsize-001.phpt" role="test" />
<file md5sum="a783f1f889f4ba7a819ed1e55fd8a989" name="tests/command/cursor-batchsize-002.phpt" role="test" />
- <file md5sum="783c985b8f289a262ba60570a09f3562" name="tests/command/cursor-tailable-001.phpt" role="test" />
- <file md5sum="6b7a33995d8015ce4e8259b79f05c713" name="tests/command/findAndModify-001.phpt" role="test" />
- <file md5sum="7ffe8aceda81907e9adb2945f0a93852" name="tests/command/update-001.phpt" role="test" />
- <file md5sum="7416c4a7cea6e730849bae6af8388a32" name="tests/connect/bug0720.phpt" role="test" />
+ <file md5sum="dbbcfc4b838dcf02fac66f4e7aa1ffdc" name="tests/command/cursor-tailable-001.phpt" role="test" />
+ <file md5sum="e1994473378fa4935533460deec15f5b" name="tests/command/findAndModify-001.phpt" role="test" />
+ <file md5sum="0f0c8d871b716d4b0311b846d98b684c" name="tests/command/update-001.phpt" role="test" />
+ <file md5sum="007ea6228ce0a8dc4ed9ca6201facec7" name="tests/connect/bug0720.phpt" role="test" />
<file md5sum="ad508af588e129119d0e9a4f6b82c890" name="tests/connect/bug1015.phpt" role="test" />
- <file md5sum="fe5f23f2534eb5da575d76f1070e1fd2" name="tests/connect/bug1045.phpt" role="test" />
+ <file md5sum="0ebcb8e508d1978211d1fe84732360cf" name="tests/connect/bug1045.phpt" role="test" />
<file md5sum="556c4d26da417b73c82bcb0ed9ab41e0" name="tests/connect/compression_error-001.phpt" role="test" />
<file md5sum="341af7c42107c40210903b7cb57070b2" name="tests/connect/compression_error-002.phpt" role="test" />
<file md5sum="83ff07823c743c67c76d808bac72bdd3" name="tests/connect/replicaset-seedlist-001.phpt" role="test" />
<file md5sum="689439f028c731f0daca49ae282096e2" name="tests/connect/replicaset-seedlist-002.phpt" role="test" />
<file md5sum="a4fc8812cf174d4c5d216704fce536ca" name="tests/connect/standalone-auth-001.phpt" role="test" />
<file md5sum="ab62017c209508bcc9cdb1dc4cde8c3b" name="tests/connect/standalone-auth_error-001.phpt" role="test" />
<file md5sum="c678e843cf60d1363dfd1195531f8a86" name="tests/connect/standalone-plain-0001.phpt" role="test" />
<file md5sum="36c31dca4f718a0162c118c50196877a" name="tests/connect/standalone-plain-0002.phpt" role="test" />
- <file md5sum="2df2decf58ee9f08c59795ffb2965f05" name="tests/connect/standalone-ssl-no_verify-001.phpt" role="test" />
- <file md5sum="945c393861bcf606176a9c970893f08f" name="tests/connect/standalone-ssl-no_verify-002.phpt" role="test" />
- <file md5sum="604e88d71fb28d363410af528f97d90c" name="tests/connect/standalone-ssl-verify_cert-001.phpt" role="test" />
- <file md5sum="fafad629b56ea82bad464fba23f4bd9c" name="tests/connect/standalone-ssl-verify_cert-002.phpt" role="test" />
- <file md5sum="6e4b30c175f61caa891ccd8920e328ef" name="tests/connect/standalone-ssl-verify_cert-error-001.phpt" role="test" />
+ <file md5sum="f57b8f13c14f0098bab50c5af6eb386a" name="tests/connect/standalone-ssl-no_verify-001.phpt" role="test" />
+ <file md5sum="afb6291e139049ced590708ec4c524de" name="tests/connect/standalone-ssl-no_verify-002.phpt" role="test" />
+ <file md5sum="5bd2e78cc438937ba63f4ebdcc7c09b7" name="tests/connect/standalone-ssl-no_verify-003.phpt" role="test" />
+ <file md5sum="a34af3798467d094259a52dfacd12c27" name="tests/connect/standalone-ssl-verify_cert-001.phpt" role="test" />
+ <file md5sum="64fa53c106def6b1fb64936d4815c1f4" name="tests/connect/standalone-ssl-verify_cert-002.phpt" role="test" />
+ <file md5sum="240022b71966207b7b3a7336cba3a0e3" name="tests/connect/standalone-ssl-verify_cert-003.phpt" role="test" />
+ <file md5sum="3f0b35cfea9bc855d3637e39dc28c590" name="tests/connect/standalone-ssl-verify_cert-error-001.phpt" role="test" />
<file md5sum="b76eb381dbf0e69a1aa17521717e5228" name="tests/connect/standalone-ssl-verify_cert-error-002.phpt" role="test" />
+ <file md5sum="36a7dfc2fa0f2841086845a0dc514a92" name="tests/connect/standalone-ssl-verify_cert-error-003.phpt" role="test" />
<file md5sum="6f1ccb813ebceec352a3dcdf94e903db" name="tests/connect/standalone-x509-auth-001.phpt" role="test" />
<file md5sum="72b1b75461b4ddeeae1e3bd447d01201" name="tests/connect/standalone-x509-auth-002.phpt" role="test" />
<file md5sum="fed7282c9290a51a9409de4f15ceef6f" name="tests/connect/standalone-x509-error-0001.phpt" role="test" />
<file md5sum="b9d9eb16149f4334b7207d57c6819a9b" name="tests/connect/standalone-x509-extract_username-001.phpt" role="test" />
<file md5sum="edb99d7994524c07755b6b24ad6f30ba" name="tests/connect/standalone-x509-extract_username-002.phpt" role="test" />
<file md5sum="be75a888807351e00540edebf19c921b" name="tests/cursor/bug0671-001.phpt" role="test" />
<file md5sum="de71b16365183778e7d3386f2c077470" name="tests/cursor/bug0732-001.phpt" role="test" />
<file md5sum="034b4c5be16697c07400868165f6a410" name="tests/cursor/bug0849-001.phpt" role="test" />
<file md5sum="c70dca73cab9c3883a5995f0f26f149e" name="tests/cursor/bug0924-001.phpt" role="test" />
<file md5sum="c6433cc5a09c138bf717fa58da889b68" name="tests/cursor/bug0924-002.phpt" role="test" />
- <file md5sum="47e190c23ce7bf4e3dcac73ddcf32067" name="tests/cursor/bug1050-001.phpt" role="test" />
- <file md5sum="14171cd8655bab3a2256a2199a1a4965" name="tests/cursor/bug1050-002.phpt" role="test" />
- <file md5sum="1b538495c1357eb2fbb08dc8b57527f9" name="tests/cursor/bug1151-001.phpt" role="test" />
- <file md5sum="04035a6cefd168fc934fe358ca50af59" name="tests/cursor/bug1151-002.phpt" role="test" />
- <file md5sum="0a69ad035054abcdea77736940888599" name="tests/cursor/bug1151-003.phpt" role="test" />
- <file md5sum="638e0247cc08c808c872f43ecaea8514" name="tests/cursor/bug1151-004.phpt" role="test" />
- <file md5sum="a235a69f859cc30621ba072939cea9f7" name="tests/cursor/bug1152-001.phpt" role="test" />
- <file md5sum="a44905f6c373e4e6dc1b43e022d0ca68" name="tests/cursor/bug1152-002.phpt" role="test" />
+ <file md5sum="a8fd3482471b5872f1be4807eba87196" name="tests/cursor/bug1050-001.phpt" role="test" />
+ <file md5sum="979b627261c140a612f9700f65344f68" name="tests/cursor/bug1050-002.phpt" role="test" />
+ <file md5sum="963697c64f74660a5adf28d1ad23ff4f" name="tests/cursor/bug1151-001.phpt" role="test" />
+ <file md5sum="121a051c3f32dda640c00d7b60025fac" name="tests/cursor/bug1151-002.phpt" role="test" />
+ <file md5sum="25f41f7dee1132a7354f21b8fa0f0119" name="tests/cursor/bug1151-003.phpt" role="test" />
+ <file md5sum="739f511357f2205d495da8dd59c17cd2" name="tests/cursor/bug1151-004.phpt" role="test" />
+ <file md5sum="b164823899b354b7ab8183b027d9207e" name="tests/cursor/bug1152-001.phpt" role="test" />
+ <file md5sum="cd34d162e92b07b7c5cf016532f4cd45" name="tests/cursor/bug1152-002.phpt" role="test" />
<file md5sum="1d2e6bd077d3d59cdec119361fa53b27" name="tests/cursor/bug1162-001.phpt" role="test" />
<file md5sum="a67938c9bc4c584c654d0f98659f72a0" name="tests/cursor/bug1274-001.phpt" role="test" />
- <file md5sum="39a13ee900852192f4e1cc6983299ca2" name="tests/cursor/bug1274-002.phpt" role="test" />
+ <file md5sum="4574073e5ad7f2a7306912c1b93a2312" name="tests/cursor/bug1274-002.phpt" role="test" />
<file md5sum="f56bde35dc916acfc3cba7c0ae77d93a" name="tests/cursor/bug1274-003.phpt" role="test" />
<file md5sum="b7e0f253d88d86e087d6118eb58c4651" name="tests/cursor/bug1274-004.phpt" role="test" />
- <file md5sum="0b3beb7838519caaa6c4e7765d26f8e9" name="tests/cursor/bug1274-005.phpt" role="test" />
+ <file md5sum="10baa2d2575ad212500b244b7a3f17f2" name="tests/cursor/bug1274-005.phpt" role="test" />
<file md5sum="b413244ca68fe63c6165a6590c91a6de" name="tests/cursor/bug1274-006.phpt" role="test" />
<file md5sum="efedd67316e0098a7f504cc9bc88f4d0" name="tests/cursor/bug1419-001.phpt" role="test" />
- <file md5sum="d25c34b7f215c34795726a48fa406f5e" name="tests/cursor/bug1529-001.phpt" role="test" />
+ <file md5sum="052f67e9ee173efd4ee000d30870a7ae" name="tests/cursor/bug1529-001.phpt" role="test" />
<file md5sum="0287863386284b368c94796c8563818b" name="tests/cursor/bug1713-001.phpt" role="test" />
<file md5sum="03bc65d514988acceecd8b830c41f152" name="tests/cursor/cursor-001.phpt" role="test" />
<file md5sum="bf69deaf6361488462540564d8a8b657" name="tests/cursor/cursor-IteratorIterator-001.phpt" role="test" />
<file md5sum="67cadd0d7513523b7b83f0fffb5d2c67" name="tests/cursor/cursor-IteratorIterator-002.phpt" role="test" />
- <file md5sum="a92296b15c0cde51640d422322b34a24" name="tests/cursor/cursor-IteratorIterator-003.phpt" role="test" />
- <file md5sum="4be5a1fbc9c0b5662f997cd953c15cfe" name="tests/cursor/cursor-IteratorIterator-004.phpt" role="test" />
+ <file md5sum="c099283c71f289238f24febdf4e91a02" name="tests/cursor/cursor-IteratorIterator-003.phpt" role="test" />
<file md5sum="ce2b204d53dde74e4f820cef9ebcf283" name="tests/cursor/cursor-NoRewindIterator-001.phpt" role="test" />
<file md5sum="55ac0cb41e23fd4d7cfafec98db222a9" name="tests/cursor/cursor-destruct-001.phpt" role="test" />
<file md5sum="007dfe8e75d7a3b53f17cba2155544f4" name="tests/cursor/cursor-getmore-001.phpt" role="test" />
<file md5sum="43dc536482d1d475ca02ad3818b99b9f" name="tests/cursor/cursor-getmore-002.phpt" role="test" />
<file md5sum="b18d1c583fc853cd30e933b67a7106c1" name="tests/cursor/cursor-getmore-003.phpt" role="test" />
<file md5sum="1b3d6811a9036c2118bc8fa8d07d3996" name="tests/cursor/cursor-getmore-004.phpt" role="test" />
- <file md5sum="1f63bb3962c8d77695d6c31bdb54ff81" name="tests/cursor/cursor-getmore-005.phpt" role="test" />
- <file md5sum="1c9f5595269be9bd6df95df35700f1f4" name="tests/cursor/cursor-getmore-006.phpt" role="test" />
- <file md5sum="e612f53f96e9e329c9c18dd26f368a97" name="tests/cursor/cursor-getmore-007.phpt" role="test" />
- <file md5sum="223b0ee0b1b667a2453226d01b413a87" name="tests/cursor/cursor-getmore-008.phpt" role="test" />
- <file md5sum="84c3c45fa468ba663e4ab2aa223d04b7" name="tests/cursor/cursor-isDead-001.phpt" role="test" />
- <file md5sum="5c8af3a571788caf0f1b16f53c2f3ff7" name="tests/cursor/cursor-isDead-002.phpt" role="test" />
- <file md5sum="3d7527637b92c62e64d0fa42da38cd82" name="tests/cursor/cursor-isDead-003.phpt" role="test" />
- <file md5sum="d8da9e30a5c38fb28b4abdc974b16bb5" name="tests/cursor/cursor-isDead-004.phpt" role="test" />
+ <file md5sum="34ce76ce804bb6033cd494128ee0fcc7" name="tests/cursor/cursor-getmore-005.phpt" role="test" />
+ <file md5sum="a777fda21b29aa1a7971eb582cecec1b" name="tests/cursor/cursor-getmore-006.phpt" role="test" />
+ <file md5sum="6a28996e14074c84f2c98392786503b8" name="tests/cursor/cursor-isDead-001.phpt" role="test" />
+ <file md5sum="30d5decc604a425560270049a5ee695b" name="tests/cursor/cursor-isDead-002.phpt" role="test" />
<file md5sum="a587b8ffaf32c40cf2cd6e541b0fbbf1" name="tests/cursor/cursor-iterator-001.phpt" role="test" />
<file md5sum="7415ad3c7ac10d6052686ee1a5169dca" name="tests/cursor/cursor-iterator-002.phpt" role="test" />
<file md5sum="cd965b5a7e8a1037ef83cb2a6dd139b1" name="tests/cursor/cursor-iterator-003.phpt" role="test" />
<file md5sum="8fb2fbf644c00ee7e0bf977f8a1f211a" name="tests/cursor/cursor-iterator_handlers-001.phpt" role="test" />
<file md5sum="9ee993379dae963fa0d04f2311f20f35" name="tests/cursor/cursor-rewind-001.phpt" role="test" />
- <file md5sum="94b44f1ff4f46b6ebca63d23e177b7c4" name="tests/cursor/cursor-session-001.phpt" role="test" />
- <file md5sum="66f78363eebb13d838a3ca6d11331fcc" name="tests/cursor/cursor-session-002.phpt" role="test" />
- <file md5sum="2fc56983651a210be6258a4a472ef0b1" name="tests/cursor/cursor-session-003.phpt" role="test" />
- <file md5sum="cf6b8718d1fa9e65cc161e1565a59de3" name="tests/cursor/cursor-session-004.phpt" role="test" />
+ <file md5sum="f36441689efbf83b3d3b8268bcbe8771" name="tests/cursor/cursor-session-001.phpt" role="test" />
+ <file md5sum="a313da7bb52134b2bf9e099afdef50af" name="tests/cursor/cursor-session-002.phpt" role="test" />
+ <file md5sum="df735d7c9d38a25949a369df84d5eb0b" name="tests/cursor/cursor-session-003.phpt" role="test" />
+ <file md5sum="e96c4ca6aa15446f99ee6507188c4204" name="tests/cursor/cursor-session-004.phpt" role="test" />
<file md5sum="2cdda5f635087458d91722cb829357c1" name="tests/cursor/cursor-setTypeMap_error-001.phpt" role="test" />
<file md5sum="8610f9892fb81dde0b9031042cd6d3c5" name="tests/cursor/cursor-setTypeMap_error-002.phpt" role="test" />
<file md5sum="7f470a3db7be533cf0a2049a0e1adb26" name="tests/cursor/cursor-setTypeMap_error-003.phpt" role="test" />
<file md5sum="22cfc18c129aed3a0ea3b62277ba69ff" name="tests/cursor/cursor-setTypeMap_error-004.phpt" role="test" />
<file md5sum="b84aece5c9dbc1284e9200e75b63713d" name="tests/cursor/cursor-tailable-001.phpt" role="test" />
<file md5sum="b91df472b35c89949aab04c55b91999d" name="tests/cursor/cursor-tailable-002.phpt" role="test" />
- <file md5sum="dac7feefb3481fbac92b55a904a65686" name="tests/cursor/cursor-tailable-003.phpt" role="test" />
+ <file md5sum="60a670668cf45f8e2ad86a58ddd4ed8b" name="tests/cursor/cursor-tailable-003.phpt" role="test" />
<file md5sum="fb143952fe649c057eb164922963ea39" name="tests/cursor/cursor-tailable_error-001.phpt" role="test" />
- <file md5sum="fdaebf447452e30aa2438cc97671b893" name="tests/cursor/cursor-tailable_error-002.phpt" role="test" />
+ <file md5sum="9a11f5ea30986c1ab3d7a72397fe417e" name="tests/cursor/cursor-tailable_error-002.phpt" role="test" />
<file md5sum="b5bda059f5a97bb8b3b012891ba29460" name="tests/cursor/cursor-toArray-001.phpt" role="test" />
<file md5sum="eafd09d1e9e8eed41e4efa188f1f4750" name="tests/cursor/cursor-toArray-002.phpt" role="test" />
<file md5sum="11ce7d49c58b1efbef42e52612f2ed3e" name="tests/cursor/cursor_error-001.phpt" role="test" />
<file md5sum="74ee254ba8edcea3575d523499bc542a" name="tests/cursor/cursorinterface-001.phpt" role="test" />
<file md5sum="d35e1eff5ad7b32efb76838dd4345d0e" name="tests/cursor/cursorinterface-002.phpt" role="test" />
<file md5sum="edc4273b932edaa535af383ec047ad31" name="tests/cursor/cursorinterface-003.phpt" role="test" />
<file md5sum="fb4f47efe165b4a8ab62c9a1c52419ba" name="tests/cursorid/cursorid-001.phpt" role="test" />
- <file md5sum="e34d7d2c2488c756d820bf2d8d347ccf" name="tests/cursorid/cursorid-002.phpt" role="test" />
+ <file md5sum="1011840881ca3b8ef05dacdd5b6d4ece" name="tests/cursorid/cursorid-002.phpt" role="test" />
<file md5sum="6ed65377ec9bbc81ab150ddfeb46f6da" name="tests/cursorid/cursorid-debug-001.phpt" role="test" />
<file md5sum="a2a84e7cbab924addae7560d92d40d93" name="tests/cursorid/cursorid-debug-002.phpt" role="test" />
<file md5sum="50a9a5368994bd5d8535529423f829e3" name="tests/cursorid/cursorid-debug-003.phpt" role="test" />
<file md5sum="730abb0e89433ef5d8a42012cc89d5f9" name="tests/cursorid/cursorid-serialization-001.phpt" role="test" />
<file md5sum="533a1cf52e30959e59c5ae53cb7d64a2" name="tests/cursorid/cursorid-serialization-002.phpt" role="test" />
<file md5sum="a76f1ca7cee09b8823fc2e09e661c2d2" name="tests/cursorid/cursorid-serialization_error-001.phpt" role="test" />
<file md5sum="9e166a70145710c11e86a29b45dbd054" name="tests/cursorid/cursorid-serialization_error-002.phpt" role="test" />
<file md5sum="0afe67043b96fca72dda54ec7f61986c" name="tests/cursorid/cursorid-set_state-001.phpt" role="test" />
<file md5sum="0c5d91a8e0ebfdf67f6e67ec86affc4c" name="tests/cursorid/cursorid-set_state_error-001.phpt" role="test" />
<file md5sum="f8f9533dc57a5175c028bffb66af1b16" name="tests/cursorid/cursorid-tostring-001.phpt" role="test" />
<file md5sum="c1e706da3f7795132d8a2b15beadb9bb" name="tests/cursorid/cursorid-var_export-001.phpt" role="test" />
<file md5sum="dfd23c235da73521f540440dfdd942f6" name="tests/cursorid/cursorid_error-001.phpt" role="test" />
<file md5sum="e9d41f8bd860cf7bc7aecf888a6e5f03" name="tests/exception/bulkwriteexception-getwriteresult-001.phpt" role="test" />
<file md5sum="0c742d44e6e7d6cc44043ff7c7d52dfd" name="tests/exception/bulkwriteexception-haserrorlabel-001.phpt" role="test" />
<file md5sum="107d048dac2bfeb88038407043231966" name="tests/exception/bulkwriteexception-haserrorlabel-002.phpt" role="test" />
<file md5sum="9affde6e5226e248967e3ee33a5feef0" name="tests/exception/bulkwriteexception-haserrorlabel_error-001.phpt" role="test" />
<file md5sum="9b577a17a9a125ab32ad48010d3b7909" name="tests/exception/commandexception-getresultdocument-001.phpt" role="test" />
<file md5sum="f517ae8a8ad62e3fa2fe69d282367ea4" name="tests/exception/commandexception-haserrorlabel-001.phpt" role="test" />
<file md5sum="69b64eec21ec54c479dfe557269598ab" name="tests/exception/commandexception-haserrorlabel_error-001.phpt" role="test" />
<file md5sum="6bcc1ed27df3ddbe16f549c82803d0cf" name="tests/exception/exception-001.phpt" role="test" />
<file md5sum="0f64ba7a9c355b2ee9a30d5f3f2241b8" name="tests/exception/runtimeexception-haserrorlabel-001.phpt" role="test" />
<file md5sum="98fe8f2b6fc815b91199a9d9fb9320f3" name="tests/exception/runtimeexception-haserrorlabel_error-001.phpt" role="test" />
<file md5sum="d078443aa427bf7a9b9fa31383027c38" name="tests/functional/cursor-001.phpt" role="test" />
<file md5sum="c617d75116254e986cfb55680329fdf7" name="tests/functional/cursorid-001.phpt" role="test" />
<file md5sum="e2ec8630d72d7056d7e354dfa7c8ceea" name="tests/functional/query-sort-001.phpt" role="test" />
<file md5sum="70eadbd23fde7c9fe3e47c0660019662" name="tests/functional/query-sort-002.phpt" role="test" />
<file md5sum="5ebf5ea95564a7e037329ded2b56a48e" name="tests/functional/query-sort-003.phpt" role="test" />
<file md5sum="9ff28a88ea444b1e2fdb93cb9d57a042" name="tests/functional/query-sort-004.phpt" role="test" />
<file md5sum="6bbd8a73a4ddc363257f26a055744e05" name="tests/ini/ini-debug-ini_get-001.phpt" role="test" />
<file md5sum="329a0fb960668dfb38b5d59a221c39f5" name="tests/ini/ini-debug-ini_get-002.phpt" role="test" />
<file md5sum="8eb3c43b6e36a4ddb9df1e05439ae08d" name="tests/ini/ini-debug-phpinfo-001.phpt" role="test" />
<file md5sum="09aca68640353346b8794e157930e547" name="tests/ini/ini-debug-phpinfo-002.phpt" role="test" />
<file md5sum="cc08d1004d1ab7608990fff4451f9f69" name="tests/ini/ini-mock_service_id-ini_get-001.phpt" role="test" />
<file md5sum="dcaeb7fde859686df50b77a3a0242960" name="tests/ini/ini-mock_service_id-ini_get-002.phpt" role="test" />
<file md5sum="451ece5646c829209d0fb03f5dfb1d5d" name="tests/ini/ini-mock_service_id-phpinfo-001.phpt" role="test" />
<file md5sum="2b4777e59a0ffb0103ed998f9c7a10a1" name="tests/ini/ini-mock_service_id-phpinfo-002.phpt" role="test" />
- <file md5sum="a93f8bea1ce1c6c47a11c833ae0da495" name="tests/manager/bug0572.phpt" role="test" />
+ <file md5sum="4c270b3a7c57500dba85a79938df1495" name="tests/manager/bug0572.phpt" role="test" />
<file md5sum="f0346e6cd2ba9520eef5021167879c4e" name="tests/manager/bug0851-001.phpt" role="test" />
<file md5sum="d5af337dd2aa7220b61b71deacb2a0ef" name="tests/manager/bug0851-002.phpt" role="test" />
<file md5sum="eb1c288def3ad2711f856313fabd08ee" name="tests/manager/bug0912-001.phpt" role="test" />
<file md5sum="f6de9f3ae346da76b6a0f777ed1bb04a" name="tests/manager/bug0913-001.phpt" role="test" />
<file md5sum="581f3f676bb14c8f81e76890e69864f4" name="tests/manager/bug0940-001.phpt" role="test" />
<file md5sum="4a8161bfdfd6cc6611c33d7c22323e35" name="tests/manager/bug0940-002.phpt" role="test" />
- <file md5sum="77ab4a0e9fb4919d1a22e3c6bb448254" name="tests/manager/bug1163-001.phpt" role="test" />
+ <file md5sum="499aaafa901f396dea56ef1dd94887be" name="tests/manager/bug1163-001.phpt" role="test" />
<file md5sum="3b75a0aded454ff7a0b1d602db1ece5f" name="tests/manager/bug1701-001.phpt" role="test" />
<file md5sum="5e03095c0330adf9c2a8207f861eb31f" name="tests/manager/manager-addSubscriber-001.phpt" role="test" />
<file md5sum="b82b18aae62824212cbea901095d6891" name="tests/manager/manager-addSubscriber-002.phpt" role="test" />
<file md5sum="69f21c1b26508112f80b5795264bfd6e" name="tests/manager/manager-addSubscriber-003.phpt" role="test" />
<file md5sum="df4637bb253994b085da23cb7c2baf02" name="tests/manager/manager-addSubscriber-004.phpt" role="test" />
<file md5sum="dffea1ba61ff80a301a251c7266353f5" name="tests/manager/manager-addSubscriber-005.phpt" role="test" />
<file md5sum="11c7dd46d560091cb685cfa96509f887" name="tests/manager/manager-addSubscriber-006.phpt" role="test" />
<file md5sum="2787ed29d23447eead4f2e5b5fcbf3f5" name="tests/manager/manager-createClientEncryption-001.phpt" role="test" />
<file md5sum="cc2ec9dedc92e65426c43fa6e3446b88" name="tests/manager/manager-createClientEncryption-error-001.phpt" role="test" />
<file md5sum="117f989d4a45f417b318ef64b061c1a6" name="tests/manager/manager-createClientEncryption-error-002.phpt" role="test" />
<file md5sum="d582d6ff744cdbf6f65a37e63faac924" name="tests/manager/manager-ctor-001.phpt" role="test" />
<file md5sum="ddb6ad56c0bddfdcddc28eac459c2ec7" name="tests/manager/manager-ctor-002.phpt" role="test" />
<file md5sum="bf482d24f1467be19b603557a6cb8e6c" name="tests/manager/manager-ctor-003.phpt" role="test" />
<file md5sum="cd62592a5c1c3b6c855b698735a1b9eb" name="tests/manager/manager-ctor-004.phpt" role="test" />
<file md5sum="23db0653a78cb7318c9978f1fc87bba9" name="tests/manager/manager-ctor-005.phpt" role="test" />
<file md5sum="7747cbf6bee84e93ed0ca1bb249af376" name="tests/manager/manager-ctor-006.phpt" role="test" />
<file md5sum="63826ceaf67ba68e92278c9f212ea931" name="tests/manager/manager-ctor-007.phpt" role="test" />
<file md5sum="5114f45044457fc9fa9b6913bb412a7b" name="tests/manager/manager-ctor-008.phpt" role="test" />
<file md5sum="7ee075e78215384bc775165f5bcaecc2" name="tests/manager/manager-ctor-appname-001.phpt" role="test" />
<file md5sum="407f236f707abcb938e7f065dd1346fc" name="tests/manager/manager-ctor-appname_error-001.phpt" role="test" />
<file md5sum="0f29f362757476ecaa36f936d16a7c20" name="tests/manager/manager-ctor-auth_mechanism-001.phpt" role="test" />
<file md5sum="7e334d9c4f17adc4ec5be12d461207b6" name="tests/manager/manager-ctor-auth_mechanism-002.phpt" role="test" />
- <file md5sum="0ac8ac98d24ae6d9eb710f11606db8e0" name="tests/manager/manager-ctor-auth_mechanism-error-001.phpt" role="test" />
+ <file md5sum="2e7cfd7ab77f97ab8261f464f84fb030" name="tests/manager/manager-ctor-auth_mechanism-error-001.phpt" role="test" />
<file md5sum="b36422d0897ec7f315fdb5f3391d7341" name="tests/manager/manager-ctor-auth_source-001.phpt" role="test" />
<file md5sum="85b83ea4ac48a57132906b006c01d8de" name="tests/manager/manager-ctor-auto_encryption-001.phpt" role="test" />
<file md5sum="aab3b7de7b4834fd3d93f0ca5a8b79cd" name="tests/manager/manager-ctor-auto_encryption-error-001.phpt" role="test" />
<file md5sum="78ec79aeb3fb1e221759a0632dafe0be" name="tests/manager/manager-ctor-auto_encryption-error-002.phpt" role="test" />
<file md5sum="95745423b41e3b940a46a33dbf55b111" name="tests/manager/manager-ctor-auto_encryption-error-003.phpt" role="test" />
<file md5sum="bbd66e27c8ae892d3ba42417a0bc0fd7" name="tests/manager/manager-ctor-directconnection-001.phpt" role="test" />
- <file md5sum="5b00f659c08122e9c629f525e47f0dba" name="tests/manager/manager-ctor-directconnection-error-001.phpt" role="test" />
- <file md5sum="c464aceed78505d1516029976817e26c" name="tests/manager/manager-ctor-directconnection-error-002.phpt" role="test" />
+ <file md5sum="e85a2529c8de114992f22289800615fc" name="tests/manager/manager-ctor-directconnection-error-001.phpt" role="test" />
+ <file md5sum="b3680d5e2c654cba916f7e523b04ee9c" name="tests/manager/manager-ctor-directconnection-error-002.phpt" role="test" />
<file md5sum="0a4c7fdb304b664df108aa9a6fa54e82" name="tests/manager/manager-ctor-disableClientPersistence-001.phpt" role="test" />
<file md5sum="2e3bbe239f1aba35a1c6ba9589f8ee76" name="tests/manager/manager-ctor-disableClientPersistence-002.phpt" role="test" />
- <file md5sum="244b8165a26dbe8b54fe1181d8473e28" name="tests/manager/manager-ctor-disableClientPersistence-003.phpt" role="test" />
+ <file md5sum="10c3c2d46b5447b1a7c1b446cef8f5d4" name="tests/manager/manager-ctor-disableClientPersistence-003.phpt" role="test" />
<file md5sum="220dfefa93b81ded8cf90c1be371a6d5" name="tests/manager/manager-ctor-disableClientPersistence-004.phpt" role="test" />
<file md5sum="5f46a29a8e3b5c36a013946b19d0f22a" name="tests/manager/manager-ctor-disableClientPersistence-005.phpt" role="test" />
<file md5sum="5cce6589b645b6cdf775facb76805dc3" name="tests/manager/manager-ctor-disableClientPersistence-006.phpt" role="test" />
<file md5sum="9c6f8ae4606f7c6d09c3150426ccc144" name="tests/manager/manager-ctor-disableClientPersistence-007.phpt" role="test" />
<file md5sum="9af2ff3c80a4511cd0e30d445dd681aa" name="tests/manager/manager-ctor-disableClientPersistence-008.phpt" role="test" />
<file md5sum="3f629511676dda931a85988f7fab2f53" name="tests/manager/manager-ctor-disableClientPersistence-009.phpt" role="test" />
<file md5sum="891cb09a2517e005b2f568f976f06cb5" name="tests/manager/manager-ctor-disableClientPersistence-010.phpt" role="test" />
<file md5sum="d8f9cef48b537b356664ea15b17eb55e" name="tests/manager/manager-ctor-disableClientPersistence-011.phpt" role="test" />
<file md5sum="01c99b2ff9bbc25b0bc3c6d74552710f" name="tests/manager/manager-ctor-disableClientPersistence_error-001.phpt" role="test" />
<file md5sum="684d21bfb847f1d4f949c55ada08c349" name="tests/manager/manager-ctor-driver-metadata-001.phpt" role="test" />
<file md5sum="620dd66d04240a1cbfbc33373117085c" name="tests/manager/manager-ctor-duplicate-option-001.phpt" role="test" />
<file md5sum="9311bb62f8740436ef91ef7a0fe5c97a" name="tests/manager/manager-ctor-duplicate-option-002.phpt" role="test" />
<file md5sum="d6b52ffcafa9ceaf363ebdb07c10cc75" name="tests/manager/manager-ctor-duplicate-option-003.phpt" role="test" />
<file md5sum="7538039ec421e2ae634e91ba24999408" name="tests/manager/manager-ctor-duplicate-option-004.phpt" role="test" />
+ <file md5sum="b5a10d899434b9deef074274da9e6259" name="tests/manager/manager-ctor-loadBalanced_error-001.phpt" role="test" />
<file md5sum="ee7822e3b58b7abb5ccee0a87dc86e4d" name="tests/manager/manager-ctor-read_concern-001.phpt" role="test" />
<file md5sum="c3050181118743d791b3ed29bdb4dd03" name="tests/manager/manager-ctor-read_concern-error-001.phpt" role="test" />
<file md5sum="79e97d46bf35dde168a2b2c8b304d259" name="tests/manager/manager-ctor-read_preference-001.phpt" role="test" />
<file md5sum="a68f0249fa21dc829486e9b349d5835a" name="tests/manager/manager-ctor-read_preference-002.phpt" role="test" />
<file md5sum="a542b958f8d6382715bc565c70ad6f34" name="tests/manager/manager-ctor-read_preference-error-001.phpt" role="test" />
<file md5sum="168b9448ba25614c452395a7801acd2d" name="tests/manager/manager-ctor-read_preference-error-002.phpt" role="test" />
<file md5sum="27ca549dbb89c00049059ec7aa61e080" name="tests/manager/manager-ctor-read_preference-error-004.phpt" role="test" />
<file md5sum="15ff7aaa3b2ccb96efac1fd5817e7496" name="tests/manager/manager-ctor-server.phpt" role="test" />
<file md5sum="e012ca65947f9a4fb9f07c6194a7ddb0" name="tests/manager/manager-ctor-serverApi-001.phpt" role="test" />
<file md5sum="fd58121e4d808d98a6ab5e723fb0948b" name="tests/manager/manager-ctor-serverApi-error-001.phpt" role="test" />
+ <file md5sum="189f7b0da30ee877dd930d11b14b6a1a" name="tests/manager/manager-ctor-srvMaxHosts_error-001.phpt" role="test" />
+ <file md5sum="d3c81af87b476fadf7ab31a0830a750e" name="tests/manager/manager-ctor-srvServiceName_error-001.phpt" role="test" />
<file md5sum="0f5384a769df66ede31e0c1bcd91db3b" name="tests/manager/manager-ctor-ssl-001.phpt" role="test" />
<file md5sum="5b0ee7ee781a81ef427fcc42d0af2441" name="tests/manager/manager-ctor-ssl-002.phpt" role="test" />
<file md5sum="80664e19f82704d7f9fbb9973d34bd4b" name="tests/manager/manager-ctor-ssl-003.phpt" role="test" />
<file md5sum="5acad9aa9837e9e164e90fea64608727" name="tests/manager/manager-ctor-ssl-deprecated-001.phpt" role="test" />
<file md5sum="31a9a1a525cd162eefcd61443a10ce72" name="tests/manager/manager-ctor-ssl-deprecated-002.phpt" role="test" />
- <file md5sum="e5f0cf0bcddc8f8f597134f69b2b555b" name="tests/manager/manager-ctor-tls-error-001.phpt" role="test" />
+ <file md5sum="485381d433a7d2df4e2864183167783d" name="tests/manager/manager-ctor-tls-error-001.phpt" role="test" />
<file md5sum="78fd7230fed15c73d514a4f5bb6b28db" name="tests/manager/manager-ctor-wireversion.phpt" role="test" />
<file md5sum="f5f725515b3e0d3000a190ca90a48902" name="tests/manager/manager-ctor-write_concern-001.phpt" role="test" />
<file md5sum="f57f8e8063d723e1cd9e01a7e65cdcf6" name="tests/manager/manager-ctor-write_concern-002.phpt" role="test" />
<file md5sum="a795c0a05f3f14eee39dc899c6b8b353" name="tests/manager/manager-ctor-write_concern-003.phpt" role="test" />
<file md5sum="243320fdfc028f0156dab89e0a4111fd" name="tests/manager/manager-ctor-write_concern-004.phpt" role="test" />
<file md5sum="3082087d08245cfd506d8e9c065552eb" name="tests/manager/manager-ctor-write_concern-005.phpt" role="test" />
<file md5sum="19a3af22d908692a494ff19407488831" name="tests/manager/manager-ctor-write_concern-006.phpt" role="test" />
<file md5sum="5d28e6043e9e02f5cb9d8cf1888467be" name="tests/manager/manager-ctor-write_concern-error-001.phpt" role="test" />
<file md5sum="90ccf4bb2ee95f53ffbb1e9fb28c77c0" name="tests/manager/manager-ctor-write_concern-error-002.phpt" role="test" />
<file md5sum="e5da84659c4d520d3b4136e0d269bbc6" name="tests/manager/manager-ctor-write_concern-error-003.phpt" role="test" />
<file md5sum="b673d755c80327aa2ad66909956a6edb" name="tests/manager/manager-ctor-write_concern-error-005.phpt" role="test" />
<file md5sum="b84a33ba0c7e0ffbc2d281a260891c96" name="tests/manager/manager-ctor-write_concern-error-006.phpt" role="test" />
<file md5sum="2ad014b8f8dfde5313342d05f0d8198a" name="tests/manager/manager-ctor-write_concern-error-007.phpt" role="test" />
<file md5sum="3ad6b15c16b8d14633b5f677b94a0050" name="tests/manager/manager-ctor_error-001.phpt" role="test" />
<file md5sum="ad3bd333cd908ee4c406c7b110e97f61" name="tests/manager/manager-ctor_error-002.phpt" role="test" />
<file md5sum="2be80650701a83ae0b95140279131df4" name="tests/manager/manager-ctor_error-003.phpt" role="test" />
<file md5sum="3626db363099e33cd39331fde78f46c3" name="tests/manager/manager-ctor_error-004.phpt" role="test" />
<file md5sum="1ea3fe7629cdebd837254fd1b0730514" name="tests/manager/manager-ctor_error-005.phpt" role="test" />
<file md5sum="be738dc790fc658a6ce32235b04b1d4b" name="tests/manager/manager-debug-001.phpt" role="test" />
<file md5sum="fed182f4305d260702f56990d7977c91" name="tests/manager/manager-debug-002.phpt" role="test" />
<file md5sum="b99cf3e782d7e1fba6a320e7815305f5" name="tests/manager/manager-debug-003.phpt" role="test" />
<file md5sum="4259a7b351904d6953d98b315be1ae65" name="tests/manager/manager-destruct-001.phpt" role="test" />
<file md5sum="9858166f195e0b105301c23b6436fdea" name="tests/manager/manager-executeBulkWrite-001.phpt" role="test" />
<file md5sum="9206434f496fb925d1b0a499f4f5b790" name="tests/manager/manager-executeBulkWrite-002.phpt" role="test" />
<file md5sum="d677e3dbe915d7799541477aeb4ea377" name="tests/manager/manager-executeBulkWrite-003.phpt" role="test" />
<file md5sum="3c8bc99af44c66e6c3d36a5a4d5bd8ba" name="tests/manager/manager-executeBulkWrite-004.phpt" role="test" />
<file md5sum="9e2e4162b402edd002462bb5125df34e" name="tests/manager/manager-executeBulkWrite-005.phpt" role="test" />
<file md5sum="795731bd50229fee29f2f80356f9df66" name="tests/manager/manager-executeBulkWrite-006.phpt" role="test" />
<file md5sum="65087ac5e6795aec5235055a07b42d5d" name="tests/manager/manager-executeBulkWrite-007.phpt" role="test" />
<file md5sum="ea6d63c6200730caf72ab5985375bc23" name="tests/manager/manager-executeBulkWrite-008.phpt" role="test" />
<file md5sum="22eecd73ad4e7f112efb4f91dcde274c" name="tests/manager/manager-executeBulkWrite-009.phpt" role="test" />
<file md5sum="1e4b2286bc8e60d3000a70c555857d55" name="tests/manager/manager-executeBulkWrite-010.phpt" role="test" />
- <file md5sum="c991dabde0bd8435444ddd56c443bab1" name="tests/manager/manager-executeBulkWrite-011.phpt" role="test" />
+ <file md5sum="7ab463e67470819d06afba936154682d" name="tests/manager/manager-executeBulkWrite-011.phpt" role="test" />
<file md5sum="09cce0f9669e62dade4ec2f527cccac6" name="tests/manager/manager-executeBulkWrite-012.phpt" role="test" />
<file md5sum="4a08d8ca47b6634ac392e8551282cd50" name="tests/manager/manager-executeBulkWrite-013.phpt" role="test" />
<file md5sum="d518608f1d6ba9e787603aa42e95a87a" name="tests/manager/manager-executeBulkWrite-014.phpt" role="test" />
<file md5sum="17edeebb5d2d6fe81f16ff75186ecb14" name="tests/manager/manager-executeBulkWrite_error-001.phpt" role="test" />
<file md5sum="055caec5920283895721528c49541692" name="tests/manager/manager-executeBulkWrite_error-002.phpt" role="test" />
<file md5sum="a71df0ff298839d4b40c4791fd9d36ed" name="tests/manager/manager-executeBulkWrite_error-003.phpt" role="test" />
<file md5sum="88da3b97b15660e6185a1e9a1bc993ef" name="tests/manager/manager-executeBulkWrite_error-004.phpt" role="test" />
<file md5sum="25e5cd8215e8cbe5e8e54a2568296075" name="tests/manager/manager-executeBulkWrite_error-005.phpt" role="test" />
<file md5sum="78bf40680ecc66aa370a9bd96e4aa8f9" name="tests/manager/manager-executeBulkWrite_error-006.phpt" role="test" />
<file md5sum="b3ace17b87a0ff9a38535aab0735318f" name="tests/manager/manager-executeBulkWrite_error-007.phpt" role="test" />
<file md5sum="4fc2ff48edb6d3b24c055a79c3768528" name="tests/manager/manager-executeBulkWrite_error-008.phpt" role="test" />
<file md5sum="7c989b5bd98732cfecc3bc46488e76ed" name="tests/manager/manager-executeBulkWrite_error-009.phpt" role="test" />
- <file md5sum="1183fd1485be67dfe470dcf7efcb833d" name="tests/manager/manager-executeBulkWrite_error-010.phpt" role="test" />
+ <file md5sum="0230472d8a9e6e5f979972a5296447e0" name="tests/manager/manager-executeBulkWrite_error-010.phpt" role="test" />
<file md5sum="2e16b236ed0b9d83c4dbdd460678d664" name="tests/manager/manager-executeBulkWrite_error-011.phpt" role="test" />
<file md5sum="ec99c21e5928121af04ce66bf708f252" name="tests/manager/manager-executeCommand-001.phpt" role="test" />
<file md5sum="e6bfa30363f74cc2ca3b6fb94556cef8" name="tests/manager/manager-executeCommand-002.phpt" role="test" />
<file md5sum="8b42bf17bf134bb02b95a04345ba26e8" name="tests/manager/manager-executeCommand-003.phpt" role="test" />
- <file md5sum="8176814493a8cd4f1e4ef3397cfaafa7" name="tests/manager/manager-executeCommand-004.phpt" role="test" />
+ <file md5sum="824027c39963dc2ab0a6998722f6b62b" name="tests/manager/manager-executeCommand-004.phpt" role="test" />
<file md5sum="eb54735876d5b2cfa2254f36dee96fcb" name="tests/manager/manager-executeCommand-005.phpt" role="test" />
<file md5sum="25703dba306cfa484ea7c7fe150d9a86" name="tests/manager/manager-executeCommand-006.phpt" role="test" />
- <file md5sum="8521c80d8ae029879d2b0a574bfc1684" name="tests/manager/manager-executeCommand-007.phpt" role="test" />
+ <file md5sum="c77cc61748533707a12f5fd68839fe9b" name="tests/manager/manager-executeCommand-007.phpt" role="test" />
<file md5sum="414cb9ff3e5179fd483cd2a9d1d5c6c5" name="tests/manager/manager-executeCommand_error-001.phpt" role="test" />
<file md5sum="3a6361131801e5716a8ceacc11632924" name="tests/manager/manager-executeCommand_error-002.phpt" role="test" />
<file md5sum="ac72ebf6080b999ac922854f877c0896" name="tests/manager/manager-executeCommand_error-003.phpt" role="test" />
<file md5sum="609298cc6697cfa6303b3a16ad29fbf2" name="tests/manager/manager-executeCommand_error-004.phpt" role="test" />
- <file md5sum="e54bfcc91322a08183ab16b79b64ab6d" name="tests/manager/manager-executeCommand_error-005.phpt" role="test" />
- <file md5sum="159ef1e67ffd60b421afebd9a8f8d35b" name="tests/manager/manager-executeQuery-001.phpt" role="test" />
- <file md5sum="14a6fde807ba3ae2836eb6d4075e67b3" name="tests/manager/manager-executeQuery-002.phpt" role="test" />
+ <file md5sum="7f2ac9637e5fea5e5a796dffa612ad7b" name="tests/manager/manager-executeCommand_error-005.phpt" role="test" />
+ <file md5sum="a4bd4054f9e33874b706920dacee6ecf" name="tests/manager/manager-executeQuery-002.phpt" role="test" />
<file md5sum="ceec6777086895ff43b3618b203809d8" name="tests/manager/manager-executeQuery-003.phpt" role="test" />
<file md5sum="72528bc2e1f521b5f490893616cfe893" name="tests/manager/manager-executeQuery-004.phpt" role="test" />
<file md5sum="539863b58b1307304c52d9d9760f29e5" name="tests/manager/manager-executeQuery-005.phpt" role="test" />
<file md5sum="d2b957d04be0f84243425f051329a30c" name="tests/manager/manager-executeQuery-006.phpt" role="test" />
- <file md5sum="527e82c94c86730005168d3749dcfbff" name="tests/manager/manager-executeQuery-007.phpt" role="test" />
+ <file md5sum="4397e3a049cf85e53f15beea02220ddc" name="tests/manager/manager-executeQuery-007.phpt" role="test" />
<file md5sum="18e9275267d96345a2365a618bf09ada" name="tests/manager/manager-executeQuery_error-001.phpt" role="test" />
<file md5sum="77de256019cf2c997e2dab1f5bc3a9e0" name="tests/manager/manager-executeQuery_error-002.phpt" role="test" />
- <file md5sum="9b05d5f1529ea7f4b798a95bfffa3b2a" name="tests/manager/manager-executeQuery_error-003.phpt" role="test" />
- <file md5sum="af8133ebf77a3c026777ce324a7b1924" name="tests/manager/manager-executeReadCommand-001.phpt" role="test" />
+ <file md5sum="3c9dbb9e16de715ecd2f14d46afe8d0b" name="tests/manager/manager-executeQuery_error-003.phpt" role="test" />
+ <file md5sum="7dbc24d4236d40e4ab7701ebffb5e2f5" name="tests/manager/manager-executeReadCommand-001.phpt" role="test" />
<file md5sum="a0b869caad05b5965cce7cf826904f3c" name="tests/manager/manager-executeReadCommand-002.phpt" role="test" />
- <file md5sum="4b055e8d8224a0d48b0475eaabd1806a" name="tests/manager/manager-executeReadCommand-003.phpt" role="test" />
+ <file md5sum="5c93e515f5a14d09fc062d959d105b08" name="tests/manager/manager-executeReadCommand-003.phpt" role="test" />
<file md5sum="10bf137557e0d4db82110694c981d5c6" name="tests/manager/manager-executeReadCommand_error-001.phpt" role="test" />
- <file md5sum="3fa4be18f6fe6c656ce36955d6cf3c17" name="tests/manager/manager-executeReadWriteCommand-001.phpt" role="test" />
+ <file md5sum="4764835d6787201f3457712cf4282f04" name="tests/manager/manager-executeReadWriteCommand-001.phpt" role="test" />
<file md5sum="c813dd43cd5321f0af87763f6b1d9b80" name="tests/manager/manager-executeReadWriteCommand-002.phpt" role="test" />
- <file md5sum="3061d55b33d6779ca69b5f0d2da7f664" name="tests/manager/manager-executeReadWriteCommand-003.phpt" role="test" />
+ <file md5sum="4969e1c51e63c5de7dae2228323f51d2" name="tests/manager/manager-executeReadWriteCommand-003.phpt" role="test" />
<file md5sum="7c1a531a50d4abdda38e30aecb95cb28" name="tests/manager/manager-executeReadWriteCommand_error-001.phpt" role="test" />
- <file md5sum="ffad7bec2eb77d297748bbcc27bfc5f1" name="tests/manager/manager-executeReadWriteCommand_error-002.phpt" role="test" />
- <file md5sum="6c562feec1eeef7a98fbee5852e4f616" name="tests/manager/manager-executeWriteCommand-001.phpt" role="test" />
+ <file md5sum="c9399ff2f0afba6d4f6eddeef157a0d2" name="tests/manager/manager-executeReadWriteCommand_error-002.phpt" role="test" />
+ <file md5sum="60e8d449b9e05e92f7bd388728a49fa3" name="tests/manager/manager-executeWriteCommand-001.phpt" role="test" />
<file md5sum="1ad68515d769c576adedc214870fec71" name="tests/manager/manager-executeWriteCommand-002.phpt" role="test" />
- <file md5sum="e8d6c66ed9df42cc9be13b860c2a360d" name="tests/manager/manager-executeWriteCommand-003.phpt" role="test" />
+ <file md5sum="caa13ad0a35b45393296fee760c8624e" name="tests/manager/manager-executeWriteCommand-003.phpt" role="test" />
<file md5sum="3ae03d1aff8ebbc34f63713fc61a3871" name="tests/manager/manager-executeWriteCommand_error-001.phpt" role="test" />
- <file md5sum="96e8fd344ac27f0267ffbe66dc3b5146" name="tests/manager/manager-executeWriteCommand_error-002.phpt" role="test" />
- <file md5sum="13f5cb0b26b7450121ecf6fc4b844c28" name="tests/manager/manager-executeWriteCommand_error-003.phpt" role="test" />
- <file md5sum="ed5d434c2b04639149c5f0d5ec599ef7" name="tests/manager/manager-executeWriteCommand_error-004.phpt" role="test" />
+ <file md5sum="d0786f10e106a21127d5fffdaac12d90" name="tests/manager/manager-executeWriteCommand_error-002.phpt" role="test" />
+ <file md5sum="3552239623dd45961c879ac52a69ec17" name="tests/manager/manager-executeWriteCommand_error-003.phpt" role="test" />
+ <file md5sum="209ae7fa335c75ccbd98deed9d4719f7" name="tests/manager/manager-executeWriteCommand_error-004.phpt" role="test" />
<file md5sum="0c869cc5b61b1891fb9860b5c631797f" name="tests/manager/manager-getreadconcern-001.phpt" role="test" />
<file md5sum="f01ca8d5ec0497d3c83c20fbfbd78df9" name="tests/manager/manager-getreadpreference-001.phpt" role="test" />
<file md5sum="03b5f6a61ced57942d19e3179196e2f3" name="tests/manager/manager-getservers-001.phpt" role="test" />
- <file md5sum="744ca6f9eb3935ed0e7aa16aefbe2c7a" name="tests/manager/manager-getservers-002.phpt" role="test" />
+ <file md5sum="ecd5cca20434921ed49475e5bf0a9264" name="tests/manager/manager-getservers-002.phpt" role="test" />
<file md5sum="5cb96f5b8c994e360692ef80b430085d" name="tests/manager/manager-getwriteconcern-001.phpt" role="test" />
<file md5sum="56dac5c4a4ee50a9c4fd1d8d818bf61a" name="tests/manager/manager-invalidnamespace.phpt" role="test" />
<file md5sum="7611f59a99a3162f15f8b284b87018ca" name="tests/manager/manager-removeSubscriber-001.phpt" role="test" />
<file md5sum="97919b0457d262d662abe995a9a07f1e" name="tests/manager/manager-removeSubscriber-002.phpt" role="test" />
<file md5sum="59cf29ecacb6f5d625af2b0f72a65445" name="tests/manager/manager-selectServer-001.phpt" role="test" />
<file md5sum="2041bf47ba3d52885998335f0fa3f103" name="tests/manager/manager-selectServer-002.phpt" role="test" />
<file md5sum="afb93c16286dc405a8eca6d0e6c52aef" name="tests/manager/manager-selectserver_error-001.phpt" role="test" />
<file md5sum="8e039926e7293962b4b2fbe1f4b4b02b" name="tests/manager/manager-set-uri-options-001.phpt" role="test" />
- <file md5sum="a63464172d8f5a7d018711fc6be664b7" name="tests/manager/manager-set-uri-options-002.phpt" role="test" />
+ <file md5sum="4da747c692390c6ea147ecb6e09f5bd8" name="tests/manager/manager-set-uri-options-002.phpt" role="test" />
<file md5sum="1845b7c3854d5664f89e56717b122139" name="tests/manager/manager-set-uri-options-003.phpt" role="test" />
- <file md5sum="26cffe2e18c637883fdb2d7bf6472e0f" name="tests/manager/manager-startSession_error-001.phpt" role="test" />
- <file md5sum="895adb6f2b0d1532a2de11e5685aa6d5" name="tests/manager/manager-startSession_error-002.phpt" role="test" />
+ <file md5sum="78e7c65e46fb7e80e2e6bba7663636bb" name="tests/manager/manager-startSession_error-001.phpt" role="test" />
+ <file md5sum="e7e0836d2bfd71c6f2d8f89a7705ad27" name="tests/manager/manager-startSession_error-002.phpt" role="test" />
<file md5sum="da2ad1d3d56ad8751c548c3790b56841" name="tests/manager/manager-var-dump-001.phpt" role="test" />
<file md5sum="4866b19eb11b9ad4a9afc8ecb16dee9e" name="tests/manager/manager-wakeup.phpt" role="test" />
<file md5sum="9fbed7bd60817812ebb3ad0c1554082c" name="tests/manager/manager_error-001.phpt" role="test" />
<file md5sum="2dd9863434c753dd55242243d48091c9" name="tests/query/bug0430-001.phpt" role="test" />
<file md5sum="6cfbe0ca5de33e4402bf779a44d64b4e" name="tests/query/bug0430-002.phpt" role="test" />
<file md5sum="6004d177d8ffc04a0a295eb824697e4a" name="tests/query/bug0430-003.phpt" role="test" />
- <file md5sum="d91cf9c5cb79b9a05c4d4403c1fc34d2" name="tests/query/bug0705-001.phpt" role="test" />
- <file md5sum="ba20420414f19bee71f874d362ed6fac" name="tests/query/bug0705-002.phpt" role="test" />
<file md5sum="1cb4b1ce61547c8a149732444808d884" name="tests/query/query-ctor-001.phpt" role="test" />
<file md5sum="1cf3ecf0a05cc2c305042b47e712e351" name="tests/query/query-ctor-002.phpt" role="test" />
<file md5sum="739343c4dd6b03ab5c3dfec995fe6bff" name="tests/query/query-ctor-003.phpt" role="test" />
<file md5sum="c78b0601cac5a186e6e7c386f89ee4ef" name="tests/query/query-ctor-004.phpt" role="test" />
<file md5sum="71f1fa84dbf281b67d942863248f7e31" name="tests/query/query-ctor-005.phpt" role="test" />
<file md5sum="64bda823995da00efceed4b07627f18f" name="tests/query/query-ctor-006.phpt" role="test" />
<file md5sum="a8feb530a36c277f0c0e29bb9972f88c" name="tests/query/query-ctor_error-001.phpt" role="test" />
<file md5sum="5becf772e73317d13feb71669b09ca74" name="tests/query/query-ctor_error-002.phpt" role="test" />
<file md5sum="2ac2f168d04925cff53e63ec1454ea95" name="tests/query/query-ctor_error-003.phpt" role="test" />
<file md5sum="cd5bf5c6f72e4e1edb89a2fc560a3900" name="tests/query/query-ctor_error-004.phpt" role="test" />
<file md5sum="d535216394d0c494d16c1b3314a9a84c" name="tests/query/query-ctor_error-005.phpt" role="test" />
<file md5sum="771c2de819fa84ec3f8d89336beb1e14" name="tests/query/query-ctor_error-006.phpt" role="test" />
<file md5sum="8cf658f5cd18c7b5fc9b71e668699910" name="tests/query/query-debug-001.phpt" role="test" />
<file md5sum="872a288691976f48f0f5c0b03e5cd2ed" name="tests/query/query_error-001.phpt" role="test" />
<file md5sum="a235c15b6d12006dd86cd3fc9d364abd" name="tests/readConcern/bug1598-001.phpt" role="test" />
<file md5sum="5b87f36784f6bfaf2d80fd5cd79c4571" name="tests/readConcern/bug1598-002.phpt" role="test" />
<file md5sum="f1fbd66fd9c60d9285188b66d445db7f" name="tests/readConcern/readconcern-bsonserialize-001.phpt" role="test" />
<file md5sum="39158d99f0278d6471a58bac33619583" name="tests/readConcern/readconcern-bsonserialize-002.phpt" role="test" />
<file md5sum="d964c2eae3f1a7ec5daf4296a9429e0c" name="tests/readConcern/readconcern-constants.phpt" role="test" />
<file md5sum="673f3d6d7729381139502491fd69dda4" name="tests/readConcern/readconcern-ctor-001.phpt" role="test" />
<file md5sum="c1f4a3040b96c582e164b9d6aa50e12c" name="tests/readConcern/readconcern-ctor_error-001.phpt" role="test" />
<file md5sum="a745c3afbb8fe5d09d7207d0d0b4934d" name="tests/readConcern/readconcern-ctor_error-002.phpt" role="test" />
<file md5sum="d0389718048d152dd41da2168e340354" name="tests/readConcern/readconcern-debug-001.phpt" role="test" />
<file md5sum="c6ecab3439c2b4249bedd2c6dc299dcf" name="tests/readConcern/readconcern-getlevel-001.phpt" role="test" />
<file md5sum="7bc12b0529eef007f25068e8a410d755" name="tests/readConcern/readconcern-isdefault-001.phpt" role="test" />
<file md5sum="5de358d3debd897a124379358f7a5e0b" name="tests/readConcern/readconcern-serialization-001.phpt" role="test" />
<file md5sum="9fa914142b00f41ba75dd34ffdabc917" name="tests/readConcern/readconcern-serialization-002.phpt" role="test" />
<file md5sum="d8d54e56154f941e7459801886d77c32" name="tests/readConcern/readconcern-serialization_error-001.phpt" role="test" />
<file md5sum="9eac2093a5a8d08fb4bccb9c7aee98c6" name="tests/readConcern/readconcern-serialization_error-002.phpt" role="test" />
<file md5sum="d2fa9df1d03888e6b7d56e076730d645" name="tests/readConcern/readconcern-set_state-001.phpt" role="test" />
<file md5sum="324870d2b3da8a4730a2684ffb878724" name="tests/readConcern/readconcern-set_state_error-001.phpt" role="test" />
<file md5sum="8fff1e579d6d65883c570d0d1deafa5a" name="tests/readConcern/readconcern-var_export-001.phpt" role="test" />
<file md5sum="626fe59437a671f6c480e6a813dcf777" name="tests/readConcern/readconcern_error-001.phpt" role="test" />
- <file md5sum="8522ebd1f23ccbdfccddad42d95a5e40" name="tests/readPreference/bug0146-001.phpt" role="test" />
- <file md5sum="3ad2e5bb6476a3716971dddc573c48a8" name="tests/readPreference/bug0146-002.phpt" role="test" />
+ <file md5sum="a80a89eb47df461d92dddac847792979" name="tests/readPreference/bug0146-001.phpt" role="test" />
<file md5sum="5bbbd73884d0d64989109201e7e1bf3f" name="tests/readPreference/bug0851-001.phpt" role="test" />
<file md5sum="bdc1634fe23391ae15928e87da27e5dc" name="tests/readPreference/bug1598-001.phpt" role="test" />
<file md5sum="fd65990a31032d72fd2a97e4d9425ea4" name="tests/readPreference/bug1598-002.phpt" role="test" />
<file md5sum="20d09af75e7eb7eda7844ad5bb0de8e4" name="tests/readPreference/bug1698-001.phpt" role="test" />
<file md5sum="4306e546d698e0aab6805c3f6132ca91" name="tests/readPreference/readpreference-bsonserialize-001.phpt" role="test" />
<file md5sum="b46b5fd1a651f731ffcb052491b75afc" name="tests/readPreference/readpreference-bsonserialize-002.phpt" role="test" />
<file md5sum="961998132bc79161663699fd64b369b2" name="tests/readPreference/readpreference-constants.phpt" role="test" />
<file md5sum="d8641784d6b9e66b8b44dfaa0328abd6" name="tests/readPreference/readpreference-ctor-001.phpt" role="test" />
<file md5sum="221ff341be838431d0b6aa95e1680e16" name="tests/readPreference/readpreference-ctor-002.phpt" role="test" />
<file md5sum="956253c23bd1901c67ae7268dd48cdc7" name="tests/readPreference/readpreference-ctor_error-001.phpt" role="test" />
<file md5sum="8de3ed037e390f8098ddf490b29e2efb" name="tests/readPreference/readpreference-ctor_error-002.phpt" role="test" />
<file md5sum="c5078470f13c591d8c18afc7df2d70ed" name="tests/readPreference/readpreference-ctor_error-003.phpt" role="test" />
<file md5sum="a27b9291c564dddb16ac7483e57e25d2" name="tests/readPreference/readpreference-ctor_error-004.phpt" role="test" />
<file md5sum="18f7711b47781d30db39b6bd166edf57" name="tests/readPreference/readpreference-ctor_error-005.phpt" role="test" />
<file md5sum="f0b9407f58356bb69079e1f9a43624d4" name="tests/readPreference/readpreference-ctor_error-006.phpt" role="test" />
<file md5sum="54296349ca6f684ae2b562b20b42b5c3" name="tests/readPreference/readpreference-ctor_error-007.phpt" role="test" />
<file md5sum="a77bcca3541615a47d80c3704075cb58" name="tests/readPreference/readpreference-debug-001.phpt" role="test" />
<file md5sum="1c1e56ded53731dba637bb13d90a1a55" name="tests/readPreference/readpreference-getHedge-001.phpt" role="test" />
<file md5sum="aa4a310fc1d92319cd41f84838974a65" name="tests/readPreference/readpreference-getMaxStalenessMS-001.phpt" role="test" />
<file md5sum="917131aadbd26697fbc3ac5923fa46bf" name="tests/readPreference/readpreference-getMaxStalenessMS-002.phpt" role="test" />
<file md5sum="2300bc05051a0d0dc183ebe1d699190a" name="tests/readPreference/readpreference-getMode-001.phpt" role="test" />
<file md5sum="8114a801f07aafd9330c9143bb02672a" name="tests/readPreference/readpreference-getModeString-001.phpt" role="test" />
<file md5sum="2a58ca560ca933e763397fdecd6e1c22" name="tests/readPreference/readpreference-getTagSets-001.phpt" role="test" />
<file md5sum="74a95fd229d950e7116b5ff0fd78db56" name="tests/readPreference/readpreference-getTagSets-002.phpt" role="test" />
<file md5sum="5c062e9eb9ece5c8967d62178c0d6a04" name="tests/readPreference/readpreference-serialization-001.phpt" role="test" />
<file md5sum="b5394883c72067d2a5772f44c9b1a5eb" name="tests/readPreference/readpreference-serialization-002.phpt" role="test" />
<file md5sum="ba5157287a7a47945c70c95f3ceb7f4a" name="tests/readPreference/readpreference-serialization_error-001.phpt" role="test" />
<file md5sum="85301553f88548b69ced7b3cdfb51853" name="tests/readPreference/readpreference-serialization_error-002.phpt" role="test" />
<file md5sum="e0af4202d10db8f83c89490880038d93" name="tests/readPreference/readpreference-set_state-001.phpt" role="test" />
<file md5sum="b03909a4a689849dc38bcac0dfa3291f" name="tests/readPreference/readpreference-set_state_error-001.phpt" role="test" />
<file md5sum="862edb823e451326954908c96fa3337d" name="tests/readPreference/readpreference-set_state_error-002.phpt" role="test" />
<file md5sum="429144cec33308148cf1025b9dd65c3d" name="tests/readPreference/readpreference-var_export-001.phpt" role="test" />
<file md5sum="b2df8c5d8346e04359efa29eaab86f3c" name="tests/readPreference/readpreference_error-001.phpt" role="test" />
<file md5sum="7b9704e8f22a7f21c6bea50af2fdc2c1" name="tests/replicaset/bug0155.phpt" role="test" />
- <file md5sum="5058c0cc909744465c50c01c1cec0560" name="tests/replicaset/bug0898-001.phpt" role="test" />
- <file md5sum="f5763e47fd7218291463d08b3b3148b1" name="tests/replicaset/bug0898-002.phpt" role="test" />
- <file md5sum="3bf800ddd4502e09af52e41daf896140" name="tests/replicaset/manager-getservers-001.phpt" role="test" />
+ <file md5sum="10bda8d50276bcea0dc8ab4e1b0e07fa" name="tests/replicaset/bug0898-001.phpt" role="test" />
+ <file md5sum="3055fdc9202aedd4e2ed6c49dd0343c4" name="tests/replicaset/bug0898-002.phpt" role="test" />
<file md5sum="044c6ba1198a0424e3fff63672ed47cf" name="tests/replicaset/manager-selectserver-001.phpt" role="test" />
- <file md5sum="1bfbbbec0fa03ec7e17f6764e39d72cc" name="tests/replicaset/readconcern-001.phpt" role="test" />
- <file md5sum="ad005a49014a70eb349b8820696ff7bc" name="tests/replicaset/readconcern-002.phpt" role="test" />
- <file md5sum="a8d8777bbe06d8639cd73544cc1fd416" name="tests/replicaset/server-001.phpt" role="test" />
- <file md5sum="e4a51325ac9d8c393dfa0645b68e8897" name="tests/replicaset/server-002.phpt" role="test" />
+ <file md5sum="2d4284bfa26035c5dd491f19b1bebd29" name="tests/replicaset/readconcern-001.phpt" role="test" />
<file md5sum="a1de1b9494b169e78f99a1f39c1fd398" name="tests/replicaset/writeconcernerror-001.phpt" role="test" />
<file md5sum="0e20788b5f4f6622a2b31818a02fa654" name="tests/replicaset/writeconcernerror-002.phpt" role="test" />
<file md5sum="42e2d59aa909b6596f4ccb42f7e0b766" name="tests/replicaset/writeresult-getserver-001.phpt" role="test" />
- <file md5sum="d453c4af37c326164bceb49f4d7f6e5f" name="tests/replicaset/writeresult-getserver-002.phpt" role="test" />
+ <file md5sum="4061e3b29126ff0b33bc2c801832f015" name="tests/replicaset/writeresult-getserver-002.phpt" role="test" />
<file md5sum="ac1b65aa5b5c0456805a416a786d3853" name="tests/retryable-reads/retryable-reads-001.phpt" role="test" />
<file md5sum="d8ce7be28b1ab665c10d8bb8820b05c6" name="tests/retryable-reads/retryable-reads-002.phpt" role="test" />
<file md5sum="14de621ed64577f72173b257b87bacc8" name="tests/retryable-reads/retryable-reads_error-001.phpt" role="test" />
<file md5sum="8bdd3d167752e7fd68781f2b6d2b22a2" name="tests/retryable-reads/retryable-reads_error-002.phpt" role="test" />
- <file md5sum="50d8db0c66a81326ab632f04bf926001" name="tests/retryable-writes/retryable-writes-001.phpt" role="test" />
- <file md5sum="947ea1949dfb01b6cf1ad41d9ded76ee" name="tests/retryable-writes/retryable-writes-002.phpt" role="test" />
- <file md5sum="a11c4c0896384062b162aa12f9e3bda8" name="tests/retryable-writes/retryable-writes-003.phpt" role="test" />
- <file md5sum="e70c4c36e6114c502c7327be6d9cfd8c" name="tests/retryable-writes/retryable-writes-004.phpt" role="test" />
- <file md5sum="af7aeb00cc54ab613d98dacf02080b82" name="tests/retryable-writes/retryable-writes-005.phpt" role="test" />
- <file md5sum="c992fb80c3d298f76cd7689c2763f5b9" name="tests/retryable-writes/retryable-writes_error-001.phpt" role="test" />
+ <file md5sum="b86269868a56f8e9417de735ab85f336" name="tests/retryable-writes/retryable-writes-001.phpt" role="test" />
+ <file md5sum="7b8a14e05f8c3913e83ce9ce2bf77602" name="tests/retryable-writes/retryable-writes-002.phpt" role="test" />
+ <file md5sum="3f010d40a6d741b594f4f9cb238fd264" name="tests/retryable-writes/retryable-writes-003.phpt" role="test" />
+ <file md5sum="716542a9bed46b7c70259b160b58fb02" name="tests/retryable-writes/retryable-writes-004.phpt" role="test" />
+ <file md5sum="2ac8fa15762869e31b47b743b346a18d" name="tests/retryable-writes/retryable-writes-005.phpt" role="test" />
+ <file md5sum="f73fcc5beca298ed93cfbb920be52a51" name="tests/retryable-writes/retryable-writes_error-001.phpt" role="test" />
<file md5sum="04e696099a0d8845402c7a388e98e1aa" name="tests/server/bug0671-002.phpt" role="test" />
<file md5sum="48b01991b47cc25751a6cf7796aeddaf" name="tests/server/server-constants.phpt" role="test" />
- <file md5sum="bd50fcc093e04d6ddaf9a37907f883ea" name="tests/server/server-construct-001.phpt" role="test" />
+ <file md5sum="118b30ef453ec6253600d76cdd450803" name="tests/server/server-construct-001.phpt" role="test" />
<file md5sum="b3317c5a9c1822a706abd8380ad39b96" name="tests/server/server-debug.phpt" role="test" />
<file md5sum="7b1c205df7700100ddd510fe1c02bfa6" name="tests/server/server-errors.phpt" role="test" />
<file md5sum="a3c68c2927886b94de39b084c8fbc4d8" name="tests/server/server-executeBulkWrite-001.phpt" role="test" />
<file md5sum="4011b0e8fc004882a109ab4a38b578e1" name="tests/server/server-executeBulkWrite-002.phpt" role="test" />
<file md5sum="e2cee1b0a112c818cdcaeca6090f04f6" name="tests/server/server-executeBulkWrite-003.phpt" role="test" />
<file md5sum="29a12e54466a36faaa535f04bd5e92de" name="tests/server/server-executeBulkWrite-004.phpt" role="test" />
<file md5sum="e07a73cf6359944cbfa0447604577158" name="tests/server/server-executeBulkWrite-005.phpt" role="test" />
<file md5sum="43fe553e0a8c0d6bf7d3c9b88903490a" name="tests/server/server-executeBulkWrite-006.phpt" role="test" />
<file md5sum="0a6b753ae3c4c7ac989abd4e3639fdfe" name="tests/server/server-executeBulkWrite-007.phpt" role="test" />
<file md5sum="8febec6c2f0d437d0ec29caf8a1bda06" name="tests/server/server-executeBulkWrite-008.phpt" role="test" />
<file md5sum="8e8c4e7c00f1db9cc303003d29b95693" name="tests/server/server-executeBulkWrite-009.phpt" role="test" />
<file md5sum="cc438e01de7f07dc121dcd437db0bf21" name="tests/server/server-executeBulkWrite_error-001.phpt" role="test" />
<file md5sum="d26c83bab1f51da481f749441588a788" name="tests/server/server-executeBulkWrite_error-002.phpt" role="test" />
<file md5sum="c6b762d00285a92cb2ca9d5582bb78fc" name="tests/server/server-executeCommand-001.phpt" role="test" />
- <file md5sum="c6224f062dee4ea2ae3b053e7b9178d0" name="tests/server/server-executeCommand-002.phpt" role="test" />
+ <file md5sum="d3106f7b4c539fcb68943b81ae359a14" name="tests/server/server-executeCommand-002.phpt" role="test" />
<file md5sum="e867fd6de4d48341eb04052d8c3abe6c" name="tests/server/server-executeCommand-003.phpt" role="test" />
<file md5sum="3a3566ebf6c370cd3dd90006b5704622" name="tests/server/server-executeCommand-004.phpt" role="test" />
<file md5sum="323185711766653ac8feec208bfb5290" name="tests/server/server-executeCommand-005.phpt" role="test" />
- <file md5sum="d48e7a8a8ad64c159947e13775433c24" name="tests/server/server-executeCommand-006.phpt" role="test" />
+ <file md5sum="2a25e3913470653deaa12187b4cc3130" name="tests/server/server-executeCommand-006.phpt" role="test" />
<file md5sum="b1a79ead9ea13c33b6cf3c88ea3a63a9" name="tests/server/server-executeCommand-007.phpt" role="test" />
- <file md5sum="0a06bd37ccd8c2442e9b6dc77802bc89" name="tests/server/server-executeCommand-008.phpt" role="test" />
+ <file md5sum="b57c30db64e71a0394be9894434c0391" name="tests/server/server-executeCommand-008.phpt" role="test" />
<file md5sum="34ba337b799b4d9ac1f6de03ee8c4847" name="tests/server/server-executeCommand-009.phpt" role="test" />
- <file md5sum="ee9f9642001bd42d27290fddea2e76fa" name="tests/server/server-executeCommand-010.phpt" role="test" />
+ <file md5sum="cb2851e0b80b29bec23b3d87244f6fb5" name="tests/server/server-executeCommand-010.phpt" role="test" />
<file md5sum="ea1e0ec450e478317d828026c3e86f80" name="tests/server/server-executeCommand_error-001.phpt" role="test" />
<file md5sum="0fba40ada9f345ba296a11e771a4fa28" name="tests/server/server-executeQuery-001.phpt" role="test" />
<file md5sum="7d6abfb7e95373573fbf6fa59e721734" name="tests/server/server-executeQuery-002.phpt" role="test" />
<file md5sum="4ecb73a09f7235029478726ec577be85" name="tests/server/server-executeQuery-003.phpt" role="test" />
<file md5sum="786fb95ad650d21a3738b31654d6db09" name="tests/server/server-executeQuery-004.phpt" role="test" />
- <file md5sum="87e78f9980c9e28c78c739ce65d20b9b" name="tests/server/server-executeQuery-005.phpt" role="test" />
- <file md5sum="44e2b38be1ea0a765ed82ac3d829dc7a" name="tests/server/server-executeQuery-006.phpt" role="test" />
+ <file md5sum="c5d8945fac786607c94d46310e17d17b" name="tests/server/server-executeQuery-006.phpt" role="test" />
<file md5sum="6963aebb29068bce72a8beea91e61cf8" name="tests/server/server-executeQuery-007.phpt" role="test" />
<file md5sum="7537ffc55664b14a250232fc0fd518c8" name="tests/server/server-executeQuery-008.phpt" role="test" />
<file md5sum="6500fb13222358652861ca10c4ce7146" name="tests/server/server-executeQuery-009.phpt" role="test" />
<file md5sum="8a38e31a280aa3fed36b36c3b0a8d931" name="tests/server/server-executeQuery-010.phpt" role="test" />
<file md5sum="6acd6ddda6ea8aa46921b3e5eed81c5e" name="tests/server/server-executeQuery-011.phpt" role="test" />
- <file md5sum="70627156bf8447754259f4ec54a33ca8" name="tests/server/server-executeQuery-012.phpt" role="test" />
- <file md5sum="8b02525e585ef4016d070a1127714f7a" name="tests/server/server-executeQuery-013.phpt" role="test" />
+ <file md5sum="56345d55c13ffde2693d42d1b23cdbf9" name="tests/server/server-executeQuery-012.phpt" role="test" />
+ <file md5sum="b82554034b4271053bbe208858cda081" name="tests/server/server-executeQuery-013.phpt" role="test" />
<file md5sum="eb481ae7199a421ce81145f4d0c006ea" name="tests/server/server-executeQuery_error-001.phpt" role="test" />
- <file md5sum="18fd9da375761736e37539547f6d2629" name="tests/server/server-executeReadCommand-001.phpt" role="test" />
+ <file md5sum="91eb77d6bff81a929cbb1d55bd90101a" name="tests/server/server-executeReadCommand-001.phpt" role="test" />
<file md5sum="8b6fc02521a1901f05e353370e7f8ee5" name="tests/server/server-executeReadCommand-002.phpt" role="test" />
- <file md5sum="38170d85b2d04c1f1570c04a8e1b3559" name="tests/server/server-executeReadCommand-003.phpt" role="test" />
+ <file md5sum="8fc7bcc947d50d6fccf64fdb34b01e5d" name="tests/server/server-executeReadCommand-003.phpt" role="test" />
<file md5sum="f57782a263590833f8c5bd5a58f30f17" name="tests/server/server-executeReadCommand_error-001.phpt" role="test" />
- <file md5sum="f4bd59c8961259286332d38e021d45b1" name="tests/server/server-executeReadWriteCommand-001.phpt" role="test" />
+ <file md5sum="62ca987f8a6a03cdc25e0fc0bb28525e" name="tests/server/server-executeReadWriteCommand-001.phpt" role="test" />
<file md5sum="d1fe71cee62f9491a73b09551840825c" name="tests/server/server-executeReadWriteCommand-002.phpt" role="test" />
- <file md5sum="f80e38693df12e914edcd4201cf66adc" name="tests/server/server-executeReadWriteCommand-003.phpt" role="test" />
+ <file md5sum="b6350951e4aeb9270d940b551cf5145e" name="tests/server/server-executeReadWriteCommand-003.phpt" role="test" />
<file md5sum="16db14f702d8d12e9e457e4fbe889a60" name="tests/server/server-executeReadWriteCommand_error-001.phpt" role="test" />
- <file md5sum="48a36e9c7b4420c6ddcfd54d09c2ecb5" name="tests/server/server-executeWriteCommand-001.phpt" role="test" />
+ <file md5sum="1c54f99b3627a37c0f36be8eff4cb025" name="tests/server/server-executeWriteCommand-001.phpt" role="test" />
<file md5sum="97b1c9cf42fbf431702c78183c6571db" name="tests/server/server-executeWriteCommand-002.phpt" role="test" />
- <file md5sum="71fca8bb2af8356a642a3a48b5d00b4a" name="tests/server/server-executeWriteCommand-003.phpt" role="test" />
+ <file md5sum="2f93789872e1453422986a2ed7052f26" name="tests/server/server-executeWriteCommand-003.phpt" role="test" />
<file md5sum="ac22aefe6d4f07faa75c8a0b938bfc78" name="tests/server/server-executeWriteCommand_error-001.phpt" role="test" />
<file md5sum="6daab74c8cc8188626f6659df04c30a2" name="tests/server/server-getInfo-001.phpt" role="test" />
<file md5sum="a0c7cbf92555d8c8a961edbfdac92685" name="tests/server/server-getLatency-001.phpt" role="test" />
- <file md5sum="5987e67b9b88a723b85083813b560b73" name="tests/server/server-getLatency-002.phpt" role="test" />
+ <file md5sum="d48bdb590104928b42ace95b62f7ed0a" name="tests/server/server-getLatency-002.phpt" role="test" />
+ <file md5sum="53d08da4a63f4b403a592c0c4b29526a" name="tests/server/server-getServerDescription-001.phpt" role="test" />
<file md5sum="8c836609ad6a434770df70781ff73dfa" name="tests/server/server-getTags-001.phpt" role="test" />
<file md5sum="93d1818b704c415bb309c58044b299c4" name="tests/server/server-getTags-002.phpt" role="test" />
<file md5sum="eed3333d1956c2ec13d99ad095c5e91c" name="tests/server/server_error-001.phpt" role="test" />
<file md5sum="47317cff71d468ebe61d741d71a2e499" name="tests/serverApi/serverApi-bsonserialize-001.phpt" role="test" />
<file md5sum="afde498a7cdeae0f161a7b130f1c4d8c" name="tests/serverApi/serverApi-bsonserialize-002.phpt" role="test" />
<file md5sum="a2392cc37aa1d30469140b791cc8ed84" name="tests/serverApi/serverApi-construct-001.phpt" role="test" />
<file md5sum="abf58c35668375559c6268ae126efe6d" name="tests/serverApi/serverApi-debug.phpt" role="test" />
<file md5sum="bdb265aef44a27c94c0cf12cde912ad9" name="tests/serverApi/serverApi-serialization-001.phpt" role="test" />
<file md5sum="75592b40a340f12455f9c8e3c0fa3721" name="tests/serverApi/serverApi-serialization-002.phpt" role="test" />
<file md5sum="2a910b096a80f610866743257752fd87" name="tests/serverApi/serverApi-serialization_error-001.phpt" role="test" />
<file md5sum="68e6b4f290def40b8c9821ac19faf65e" name="tests/serverApi/serverApi-serialization_error-002.phpt" role="test" />
<file md5sum="7a06c82daaaf45e17dc0cc29a0332331" name="tests/serverApi/serverApi-set_state-001.phpt" role="test" />
<file md5sum="8e58f2fb54c09f56da57773a188a1c73" name="tests/serverApi/serverApi-set_state_error-001.phpt" role="test" />
<file md5sum="ee3d952d72cb7109d370d125e280c609" name="tests/serverApi/serverApi-var_export-001.phpt" role="test" />
+ <file md5sum="ee1b9429abdc682a0dab5810d5065a49" name="tests/serverDescription/serverDescription-constants.phpt" role="test" />
+ <file md5sum="0720df3be175bba730376d3dfcc562e0" name="tests/serverDescription/serverDescription-debug-001.phpt" role="test" />
+ <file md5sum="ee5fcc26ac6494d62d213df062118079" name="tests/serverDescription/serverDescription-getHelloResponse-001.phpt" role="test" />
+ <file md5sum="85a5f91600730b9909cebef3263269fe" name="tests/serverDescription/serverDescription-getHost-001.phpt" role="test" />
+ <file md5sum="6260e17daf2ed937773a019b560c0628" name="tests/serverDescription/serverDescription-getLastUpdateTime-001.phpt" role="test" />
+ <file md5sum="ee367002592bead6eb0f38a96d59fc17" name="tests/serverDescription/serverDescription-getLastUpdateTime-002.phpt" role="test" />
+ <file md5sum="6da7822ec082fd74c42095dbf0c705ac" name="tests/serverDescription/serverDescription-getPort-001.phpt" role="test" />
+ <file md5sum="07a5cf52ad8e035fc2ca6e0ed4e08654" name="tests/serverDescription/serverDescription-getRoundTripTime-001.phpt" role="test" />
+ <file md5sum="00fa91c208967234609f1c70f51b8f4b" name="tests/serverDescription/serverDescription-getType-001.phpt" role="test" />
+ <file md5sum="5ca27edd77b32610b16217a1115a1cf8" name="tests/serverDescription/serverDescription-var_export-001.phpt" role="test" />
<file md5sum="88d6b70b08d0499be1df22f03ffe33fd" name="tests/session/bug1274-001.phpt" role="test" />
- <file md5sum="22a7a9192ec967ced58ebf64eff821af" name="tests/session/bug1274-002.phpt" role="test" />
- <file md5sum="c2f3158fdde998225c34c755a9499454" name="tests/session/bug1274-003.phpt" role="test" />
+ <file md5sum="f033ecdb9f9e8b47690540bec04c6a35" name="tests/session/bug1274-002.phpt" role="test" />
+ <file md5sum="0bfd943e10668b0cadc1356fd6064f73" name="tests/session/bug1274-003.phpt" role="test" />
<file md5sum="77e7a7474ad07ab60895238d17dab331" name="tests/session/bug1274-004.phpt" role="test" />
- <file md5sum="1e68e0ed8296b0ec867e20434c0d60c5" name="tests/session/bug1274-005.phpt" role="test" />
- <file md5sum="e7fef9fc1fec9cffe4b341ad9fe7f0c8" name="tests/session/bug1274-006.phpt" role="test" />
- <file md5sum="8f44f547eb1fe11ff6855c7b2739f569" name="tests/session/session-001.phpt" role="test" />
- <file md5sum="acace46349e4435e434d935103c0ec39" name="tests/session/session-002.phpt" role="test" />
- <file md5sum="19dba4a40b7355b3aea63b9989b89fb9" name="tests/session/session-003.phpt" role="test" />
+ <file md5sum="e71c67dd24c0f8fd77c6920cc11f6122" name="tests/session/bug1274-005.phpt" role="test" />
+ <file md5sum="775888594331e6b95ff5e15b91a8108e" name="tests/session/bug1274-006.phpt" role="test" />
+ <file md5sum="896e2c257f1ff67f40decad2eae240f1" name="tests/session/session-001.phpt" role="test" />
+ <file md5sum="d9c39708e7b704bff2d55e04dc289623" name="tests/session/session-002.phpt" role="test" />
+ <file md5sum="bacf01b37692d00170fa99fdf9740b78" name="tests/session/session-003.phpt" role="test" />
<file md5sum="50d18fb03e0c133f58a48ac0567cce0b" name="tests/session/session-004.phpt" role="test" />
- <file md5sum="6b53aaf0a07689b8829a3739287c7391" name="tests/session/session-005.phpt" role="test" />
- <file md5sum="e7af566dca7fc99e6fe7a30552ef9e1b" name="tests/session/session-advanceClusterTime-001.phpt" role="test" />
- <file md5sum="1b551672c978b4d5004a13140d2e0bf7" name="tests/session/session-advanceOperationTime-001.phpt" role="test" />
- <file md5sum="84788bb5dae3bb833432cc6b01ead989" name="tests/session/session-advanceOperationTime-002.phpt" role="test" />
- <file md5sum="da8634a889affa83e402455b76df87a2" name="tests/session/session-advanceOperationTime-003.phpt" role="test" />
- <file md5sum="486bc9b29ed1854b1ca430bebe28fe74" name="tests/session/session-advanceOperationTime_error-001.phpt" role="test" />
+ <file md5sum="55028dc0255b302ea1e48b70d9c84633" name="tests/session/session-005.phpt" role="test" />
+ <file md5sum="a1534efa6e4be70889ce4e3cdd5bfeb4" name="tests/session/session-advanceClusterTime-001.phpt" role="test" />
+ <file md5sum="1f64cf2fc890b0cddf04b0a0694fd2c2" name="tests/session/session-advanceOperationTime-001.phpt" role="test" />
+ <file md5sum="35cc4f4df8c4f6823d639be1e1d3f5d0" name="tests/session/session-advanceOperationTime-002.phpt" role="test" />
+ <file md5sum="6f76a36f7de08f9d8928b425ca388223" name="tests/session/session-advanceOperationTime-003.phpt" role="test" />
+ <file md5sum="5dc2a52220fb2e0147197a20dbe80e34" name="tests/session/session-advanceOperationTime_error-001.phpt" role="test" />
<file md5sum="9d6bd97bb6d06b11ffbee3897619fbf4" name="tests/session/session-commitTransaction-001.phpt" role="test" />
<file md5sum="ae4075d8629d54ce74448dc56562af31" name="tests/session/session-constants.phpt" role="test" />
- <file md5sum="97a09a2fc53170bd025325e61e45d9d9" name="tests/session/session-debug-001.phpt" role="test" />
- <file md5sum="a29f1c016c2dc1931670481275bf4b1a" name="tests/session/session-debug-002.phpt" role="test" />
- <file md5sum="1632f3a81e5c0c8a265fbde2ae974c8b" name="tests/session/session-debug-003.phpt" role="test" />
- <file md5sum="8746ef628c13cbb2b9d638e8b544d809" name="tests/session/session-debug-004.phpt" role="test" />
- <file md5sum="0a50f51031b18a66f862b0d693d9e1a9" name="tests/session/session-debug-005.phpt" role="test" />
- <file md5sum="0f4b6f5d107b3b2b1fdc66c8f24b71bb" name="tests/session/session-debug-006.phpt" role="test" />
- <file md5sum="decc58bf9dee27ef40826ecd1c1cd4e5" name="tests/session/session-debug-007.phpt" role="test" />
+ <file md5sum="364e7846648fa0d2442d8a787b89f5bc" name="tests/session/session-debug-001.phpt" role="test" />
+ <file md5sum="bb1f735378f1e0cb8abb4bea4438e5c3" name="tests/session/session-debug-002.phpt" role="test" />
+ <file md5sum="24417c11eedcf8ce4f777201a249a807" name="tests/session/session-debug-003.phpt" role="test" />
+ <file md5sum="b8428d2436e019d424a16f1e64ae8fe5" name="tests/session/session-debug-004.phpt" role="test" />
+ <file md5sum="ae285b35b2f4f0a2c615611ffab7fdbb" name="tests/session/session-debug-005.phpt" role="test" />
+ <file md5sum="64fbca8cff0dfd7fc2d000578de4d48a" name="tests/session/session-debug-006.phpt" role="test" />
+ <file md5sum="ba684bae99a0d29fd195dc20a97cd621" name="tests/session/session-debug-007.phpt" role="test" />
<file md5sum="007301127176ed86d3717a4a120fcabf" name="tests/session/session-endSession-001.phpt" role="test" />
- <file md5sum="104ee3c9e396852bc3a2b6f7255c7ec8" name="tests/session/session-endSession-002.phpt" role="test" />
- <file md5sum="2f652ed026dfc6365c59b8248df0d74c" name="tests/session/session-getClusterTime-001.phpt" role="test" />
- <file md5sum="2765dbc40c1152c5e0cf37b2d84dc13c" name="tests/session/session-getLogicalSessionId-001.phpt" role="test" />
- <file md5sum="e9228794dcf032fbe002dfc0b04115f6" name="tests/session/session-getOperationTime-001.phpt" role="test" />
+ <file md5sum="be157fd514c0e54b02ddd0d001e9b733" name="tests/session/session-endSession-002.phpt" role="test" />
+ <file md5sum="047663a229a1398ddf09580af0b1065f" name="tests/session/session-getClusterTime-001.phpt" role="test" />
+ <file md5sum="dd1b4d449e49ff4ad12b7dcae787a045" name="tests/session/session-getLogicalSessionId-001.phpt" role="test" />
+ <file md5sum="c7731b7bb01087a5a302e193d4d4de04" name="tests/session/session-getOperationTime-001.phpt" role="test" />
<file md5sum="4f144ae06868c02faddbeaf7a3c99a85" name="tests/session/session-getTransactionOptions-001.phpt" role="test" />
<file md5sum="d8861674e657c7f538bfec79587d8daa" name="tests/session/session-getTransactionState-001.phpt" role="test" />
+ <file md5sum="98249ded70f51f54fb0dc937ac016c8c" name="tests/session/session-isDirty-001.phpt" role="test" />
<file md5sum="79abf68b491c002b36c67b1485dcea20" name="tests/session/session-isInTransaction-001.phpt" role="test" />
<file md5sum="d2e85244ca1595ea1aea216ce74cb3b0" name="tests/session/session-startTransaction-001.phpt" role="test" />
<file md5sum="66b3d2185152fed858c46a333cf7cfb4" name="tests/session/session-startTransaction_error-001.phpt" role="test" />
<file md5sum="1038a9b5241b4813d8e96c0faa6077f6" name="tests/session/session-startTransaction_error-002.phpt" role="test" />
<file md5sum="527836016953f63af235bcf561df0b14" name="tests/session/session-startTransaction_error-004.phpt" role="test" />
<file md5sum="42b86984fefc51b3d42b108fde6ab12e" name="tests/session/session-startTransaction_error-005.phpt" role="test" />
- <file md5sum="a1b9b896257f29c300df8baf01b71a0a" name="tests/session/session-startTransaction_error-006.phpt" role="test" />
- <file md5sum="be41c4abbfd4de054108b01fdbdb6907" name="tests/session/session-startTransaction_error-007.phpt" role="test" />
+ <file md5sum="b8c07f225df0eae46ed4d8a33916327d" name="tests/session/session-startTransaction_error-006.phpt" role="test" />
+ <file md5sum="ab46db00e6f8fb756a7f98309033472f" name="tests/session/session-startTransaction_error-007.phpt" role="test" />
<file md5sum="cf9cb4bd8e63acaad16ffb6a1b3cf4e1" name="tests/session/transaction-integration-001.phpt" role="test" />
<file md5sum="0e8b366aa9781103bb1fc37fc685b9ab" name="tests/session/transaction-integration-002.phpt" role="test" />
<file md5sum="c0a958f2da4e0e64e946b2d21a391475" name="tests/session/transaction-integration-003.phpt" role="test" />
<file md5sum="2205a55501e7d1b51873749f6f73380b" name="tests/session/transaction-integration_error-001.phpt" role="test" />
<file md5sum="8f80677316e350aa0f839263120d32df" name="tests/session/transaction-integration_error-002.phpt" role="test" />
<file md5sum="005c410b5eae4853c8181e9da9dfe9d9" name="tests/session/transaction-integration_error-003.phpt" role="test" />
<file md5sum="8d57f720d8c54d0a09ed8dd5c3b57998" name="tests/session/transaction-integration_error-004.phpt" role="test" />
<file md5sum="8dd43ac797e59ffd3386b81f97f63795" name="tests/standalone/bug0166.phpt" role="test" />
<file md5sum="f8500fd70f234db2c5b176de9768fc18" name="tests/standalone/bug0231.phpt" role="test" />
<file md5sum="d3780db83fa5dd757b2fa14e6e8cee69" name="tests/standalone/bug0357.phpt" role="test" />
<file md5sum="a52e716f71c0399292a9ce6086279e26" name="tests/standalone/bug0545.phpt" role="test" />
<file md5sum="7ec0be606371d41790ba43b1de8fc308" name="tests/standalone/bug0655.phpt" role="test" />
<file md5sum="ec3c0bb4e15c9c29e46f84c4b0189794" name="tests/standalone/command-aggregate-001.phpt" role="test" />
<file md5sum="545faf9d019b2c579f0cebc65e78927a" name="tests/standalone/connectiontimeoutexception-001.phpt" role="test" />
- <file md5sum="f4d918dbecb78a360391addb25706ed9" name="tests/standalone/executiontimeoutexception-001.phpt" role="test" />
- <file md5sum="4e25eb76fb434946a0a1ad06d336aef0" name="tests/standalone/executiontimeoutexception-002.phpt" role="test" />
+ <file md5sum="514f314c056df7faec52e42ba5f20dc9" name="tests/standalone/executiontimeoutexception-001.phpt" role="test" />
+ <file md5sum="4d78ffda28c4d6ec4201ad9c7311bd9d" name="tests/standalone/executiontimeoutexception-002.phpt" role="test" />
<file md5sum="859da0ba6f58581e57e0ae594c1244b0" name="tests/standalone/manager-as-singleton.phpt" role="test" />
<file md5sum="54dc16a86c37e04384e2c6454ef056b7" name="tests/standalone/query-errors.phpt" role="test" />
<file md5sum="bb25fc25c134935d184b9f5dff5a9a79" name="tests/standalone/update-multi-001.phpt" role="test" />
<file md5sum="4c04398fae3e97c595c2b2c6d48b5586" name="tests/standalone/write-error-001.phpt" role="test" />
<file md5sum="ca8f516beab9a92fd2b3c4dcbc45a6cb" name="tests/standalone/writeresult-isacknowledged-001.phpt" role="test" />
<file md5sum="4f4e56bd6416741285c1972bec97f3d2" name="tests/standalone/writeresult-isacknowledged-002.phpt" role="test" />
<file md5sum="07c512735db3b178e4ff36a431a75be2" name="tests/standalone/writeresult-isacknowledged-003.phpt" role="test" />
+ <file md5sum="3add3334968577e9622a91649d79c63a" name="tests/topologyDescription/topologyDescription-constants.phpt" role="test" />
+ <file md5sum="0f25ad220b80ad5aca349816149e7480" name="tests/topologyDescription/topologyDescription-debug-001.phpt" role="test" />
+ <file md5sum="e89dfd665169fbbe7ed036501d596257" name="tests/topologyDescription/topologyDescription-getServers-001.phpt" role="test" />
+ <file md5sum="291dfdadfdc642294374718279a2b036" name="tests/topologyDescription/topologyDescription-getType-001.phpt" role="test" />
+ <file md5sum="938f51370502bf9dee250c99d16b5bf3" name="tests/topologyDescription/topologyDescription-hasReadableServer-001.phpt" role="test" />
+ <file md5sum="ea94018ffe9dfd249fc47d3fc90ef1fc" name="tests/topologyDescription/topologyDescription-hasReadableServer-002.phpt" role="test" />
+ <file md5sum="a3a27c569f84e1b42affdf3276d8eddb" name="tests/topologyDescription/topologyDescription-hasReadableServer_error-001.phpt" role="test" />
+ <file md5sum="43e93f52f18c7a4150d64b7bfbbc12fb" name="tests/topologyDescription/topologyDescription-hasWritableServer-001.phpt" role="test" />
<file md5sum="59adebd29ef983f00c4d55cfc4b2d10d" name="tests/utils/PHONGO-FIXTURES.json.gz" role="test" />
<file md5sum="20bcdb186e464bebff08400730d55afd" name="tests/utils/basic-skipif.inc" role="test" />
<file md5sum="97e5555e09949a5c3807a3d11dc3f0f0" name="tests/utils/basic.inc" role="test" />
<file md5sum="d45f34ff6fd0f526099f3131d5d17b11" name="tests/utils/classes.inc" role="test" />
<file md5sum="4134acafdc5eb51800213b41043116ba" name="tests/utils/observer.php" role="test" />
- <file md5sum="15289726413fdbb6d1faf1b2279566ce" name="tests/utils/skipif.php" role="test" />
- <file md5sum="d6f7af7c585d3617c082477b15cb8415" name="tests/utils/tools.php" role="test" />
+ <file md5sum="ab4a44a9c4d270b02b7c68cf1cad873c" name="tests/utils/skipif.php" role="test" />
+ <file md5sum="662bc4ba852dccb67ca53d2b4028deb7" name="tests/utils/tools.php" role="test" />
<file md5sum="64ee8e2ef24e46d681df686739aa4e69" name="tests/writeConcern/bug1598-001.phpt" role="test" />
<file md5sum="2627d7f0df83428223b79249b0223243" name="tests/writeConcern/bug1598-002.phpt" role="test" />
<file md5sum="47c5356af82d44e77f1ed1a19dee9915" name="tests/writeConcern/writeconcern-bsonserialize-001.phpt" role="test" />
<file md5sum="073e73d11253900ad6d1e3e1b0656d20" name="tests/writeConcern/writeconcern-bsonserialize-002.phpt" role="test" />
<file md5sum="a02e1015d4bc797ff8a68613342f28c5" name="tests/writeConcern/writeconcern-bsonserialize-003.phpt" role="test" />
<file md5sum="64c7fb44e466938561d753546b82c22f" name="tests/writeConcern/writeconcern-bsonserialize-004.phpt" role="test" />
<file md5sum="08cc65bfe3d89314eca5a43616e12202" name="tests/writeConcern/writeconcern-constants.phpt" role="test" />
<file md5sum="3dbbdae846359bf00358aad47b0b7ae6" name="tests/writeConcern/writeconcern-ctor-001.phpt" role="test" />
<file md5sum="1f9f66d9446fa0f5ce954d88abe56e70" name="tests/writeConcern/writeconcern-ctor-002.phpt" role="test" />
<file md5sum="04b1a413620234518b86f7ce3d5c7be0" name="tests/writeConcern/writeconcern-ctor_error-001.phpt" role="test" />
<file md5sum="406313ae1d92e1e1f55eb223a4128012" name="tests/writeConcern/writeconcern-ctor_error-002.phpt" role="test" />
<file md5sum="727cc4fe9885dc11716446782384160f" name="tests/writeConcern/writeconcern-ctor_error-003.phpt" role="test" />
<file md5sum="be881f8e0077d593ce05110808600265" name="tests/writeConcern/writeconcern-ctor_error-004.phpt" role="test" />
<file md5sum="6ff4840ca262801e9e58c69253f45ae8" name="tests/writeConcern/writeconcern-ctor_error-005.phpt" role="test" />
<file md5sum="22dfaec3917fe798f71c15d857a36921" name="tests/writeConcern/writeconcern-debug-001.phpt" role="test" />
<file md5sum="56555f30c1e42233cb65ef12a0fb870b" name="tests/writeConcern/writeconcern-debug-002.phpt" role="test" />
<file md5sum="7feb66ce332c7b57016aa3f40e157480" name="tests/writeConcern/writeconcern-debug-003.phpt" role="test" />
<file md5sum="544bc7904161390cd99e1603b71eb0c6" name="tests/writeConcern/writeconcern-getjournal-001.phpt" role="test" />
<file md5sum="c64faac6dd9eeb55bb27b2d82acb7d86" name="tests/writeConcern/writeconcern-getw-001.phpt" role="test" />
<file md5sum="9ec2c850fc6202678ea402e96a56e530" name="tests/writeConcern/writeconcern-getwtimeout-001.phpt" role="test" />
<file md5sum="c63e6a803d425dd751247d43f24b3525" name="tests/writeConcern/writeconcern-getwtimeout-002.phpt" role="test" />
<file md5sum="7ac2556e20b9fda6524d291b695f9241" name="tests/writeConcern/writeconcern-isdefault-001.phpt" role="test" />
<file md5sum="fa9b7c79b76f3be41e38eb3268b90b4b" name="tests/writeConcern/writeconcern-serialization-001.phpt" role="test" />
<file md5sum="4e7ddcacb814ab0585f8a523530c722a" name="tests/writeConcern/writeconcern-serialization-002.phpt" role="test" />
<file md5sum="629db53508eb8c174e1113c8896dfb9d" name="tests/writeConcern/writeconcern-serialization_error-001.phpt" role="test" />
<file md5sum="745107ee996786aaa39efa12836ed56b" name="tests/writeConcern/writeconcern-serialization_error-002.phpt" role="test" />
<file md5sum="d114d86a919cd387a4f16d9c2f1308db" name="tests/writeConcern/writeconcern-set_state-001.phpt" role="test" />
<file md5sum="6866ee01eeb3334135ae6daf61f1463d" name="tests/writeConcern/writeconcern-set_state_error-001.phpt" role="test" />
<file md5sum="898c846d82ef5860cad45d52ff82e31c" name="tests/writeConcern/writeconcern-var_export-001.phpt" role="test" />
<file md5sum="17b4be0b8f641686cbfa42b324101697" name="tests/writeConcern/writeconcern_error-001.phpt" role="test" />
- <file md5sum="a0b087c850216762fe79b10bf3edb06e" name="tests/writeConcernError/writeconcernerror-debug-001.phpt" role="test" />
- <file md5sum="a96946c741eec4773017afef61bbdd45" name="tests/writeConcernError/writeconcernerror-debug-002.phpt" role="test" />
- <file md5sum="0973c8443a7a12f35240389dd961c5a5" name="tests/writeConcernError/writeconcernerror-getcode-001.phpt" role="test" />
- <file md5sum="63c9d69257468ead81287d171fe29999" name="tests/writeConcernError/writeconcernerror-getinfo-001.phpt" role="test" />
- <file md5sum="d612901b5e46c8cc5404346b57614bab" name="tests/writeConcernError/writeconcernerror-getinfo-002.phpt" role="test" />
- <file md5sum="554eaf0c77f53b8ab00715d446106839" name="tests/writeConcernError/writeconcernerror-getinfo-003.phpt" role="test" />
- <file md5sum="adc65fb5c7f3970c0acad3789366ff29" name="tests/writeConcernError/writeconcernerror-getmessage-001.phpt" role="test" />
+ <file md5sum="430f003448f59e4f09350361df0d0a64" name="tests/writeConcernError/writeconcernerror-debug-001.phpt" role="test" />
+ <file md5sum="0207b3ca1ce7331ac9070db62dd5f975" name="tests/writeConcernError/writeconcernerror-getcode-001.phpt" role="test" />
+ <file md5sum="b7ddc77b7dfab4eea7ebf4f17f26a067" name="tests/writeConcernError/writeconcernerror-getinfo-001.phpt" role="test" />
+ <file md5sum="ec2da2427cf424b319c87857cdf9ad08" name="tests/writeConcernError/writeconcernerror-getmessage-001.phpt" role="test" />
<file md5sum="3aca836caa673a3a3f636679f5216839" name="tests/writeConcernError/writeconcernerror_error-001.phpt" role="test" />
<file md5sum="5e4dafe8f5dbe27f4628ad27c597d4b9" name="tests/writeError/writeerror-debug-001.phpt" role="test" />
<file md5sum="0bd364116e4769f2267bc4957eec4b26" name="tests/writeError/writeerror-getCode-001.phpt" role="test" />
<file md5sum="239052e89e6a23ff9ad83cb504e84115" name="tests/writeError/writeerror-getIndex-001.phpt" role="test" />
<file md5sum="b2a070ca4c4ecb4655b9e26a8b42d1bd" name="tests/writeError/writeerror-getInfo-001.phpt" role="test" />
<file md5sum="c838ad909ca5988e9f09ccea7387a1ff" name="tests/writeError/writeerror-getInfo-002.phpt" role="test" />
<file md5sum="8f029a6c06d58a0ba358b281589e3712" name="tests/writeError/writeerror-getMessage-001.phpt" role="test" />
<file md5sum="8c4a875920ce58be5d2b2bd54329f277" name="tests/writeError/writeerror_error-001.phpt" role="test" />
<file md5sum="b018cf23e251de1fbafba2e1afef0d85" name="tests/writeResult/bug0671-003.phpt" role="test" />
<file md5sum="c6837064d64637aed3931a7645db441d" name="tests/writeResult/writeresult-debug-001.phpt" role="test" />
<file md5sum="95dda8392be9692e9a40baa976b4641a" name="tests/writeResult/writeresult-debug-002.phpt" role="test" />
<file md5sum="528005c11553cf65c27292a21c846eed" name="tests/writeResult/writeresult-getdeletedcount-001.phpt" role="test" />
<file md5sum="48174d244bb948935bd9f2a6b6dab367" name="tests/writeResult/writeresult-getdeletedcount-002.phpt" role="test" />
<file md5sum="77194d0db2a6c41f1e449ccebf5bb8c3" name="tests/writeResult/writeresult-getinsertedcount-001.phpt" role="test" />
<file md5sum="4be749561c8ea4f2699ff8b6c200dc03" name="tests/writeResult/writeresult-getinsertedcount-002.phpt" role="test" />
<file md5sum="ba801c202cd4376858f2bb6cbf80dd2a" name="tests/writeResult/writeresult-getmatchedcount-001.phpt" role="test" />
<file md5sum="4d61dde1268b3b907cb81632f11d6094" name="tests/writeResult/writeresult-getmatchedcount-002.phpt" role="test" />
<file md5sum="5d5e9abd30c4abb7847c1de3419c28c7" name="tests/writeResult/writeresult-getmodifiedcount-001.phpt" role="test" />
<file md5sum="585bdc0f2a8ae1dcb53856cb14e37663" name="tests/writeResult/writeresult-getmodifiedcount-002.phpt" role="test" />
<file md5sum="d7048d2116d38c5e32fa1b81cfac1221" name="tests/writeResult/writeresult-getserver-001.phpt" role="test" />
<file md5sum="7713f25147d7307652fccf53314438b4" name="tests/writeResult/writeresult-getupsertedcount-001.phpt" role="test" />
<file md5sum="406ad88c641c58d3d155767d1bd5f33f" name="tests/writeResult/writeresult-getupsertedcount-002.phpt" role="test" />
<file md5sum="394e1ffea610e9132248ca78a99a4a34" name="tests/writeResult/writeresult-getupsertedids-001.phpt" role="test" />
- <file md5sum="012823b3abfabdb5ea52b8db1d8f7954" name="tests/writeResult/writeresult-getupsertedids-002.phpt" role="test" />
+ <file md5sum="7c57183e3aee5d65e7c40313042ac91c" name="tests/writeResult/writeresult-getupsertedids-002.phpt" role="test" />
<file md5sum="3eb2168110c0d9eda93dab94d1f659d7" name="tests/writeResult/writeresult-getwriteconcernerror-001.phpt" role="test" />
<file md5sum="0d2bc8d0be8bd62a0a1c098aa342c936" name="tests/writeResult/writeresult-getwriteerrors-001.phpt" role="test" />
<file md5sum="6c58b57bc400142dc88ce373dacdc1f5" name="tests/writeResult/writeresult-getwriteerrors-002.phpt" role="test" />
<file md5sum="97f22e293b467de65fce989d9ee0f227" name="tests/writeResult/writeresult-isacknowledged-001.phpt" role="test" />
<file md5sum="089e1618e09d5e4ba4b79eb4c1f54ea3" name="tests/writeResult/writeresult_error-001.phpt" role="test" />
- <file md5sum="384ec6b4229a6ffba7a2c607cb339c94" name="CONTRIBUTING.md" role="doc" />
+ <file md5sum="7803ac4d804109b882c4c8591405dd32" name="CONTRIBUTING.md" role="doc" />
<file md5sum="198d0ffaabbd88f77e9b9067b694ca10" name="CREDITS" role="doc" />
<file md5sum="b1e01b26bacfc2232046c90a330332b3" name="LICENSE" role="doc" />
<file md5sum="362fa5548c9527dac7da5d7c27d05444" name="Makefile.frag" role="src" />
<file md5sum="eda1e5a174576bf6e8d51d4293f41236" name="README.md" role="doc" />
<file md5sum="eadbe8ccffa540f5ac53ffc59e36a727" name="THIRD_PARTY_NOTICES" role="doc" />
<file md5sum="0962c850da28d6d16b471cc9e9c976d9" name="Vagrantfile" role="test" />
- <file md5sum="00413ac72feb7a9680262eae80f0ceb0" name="config.m4" role="src" />
- <file md5sum="794eb20e68c00f7b3a99eb32b6313846" name="config.w32" role="src" />
- <file md5sum="36558e38151cdd9c6b759d34426a1502" name="phongo_compat.c" role="src" />
- <file md5sum="a65d649052b51cab756cf4316844518d" name="phongo_compat.h" role="src" />
- <file md5sum="83716638a1592796b6de5710aa5f3242" name="phongo_version.h" role="src" />
- <file md5sum="0f71e03bd801cbbd018df0eb6dbb3773" name="php_bson.h" role="src" />
- <file md5sum="e630095e67f76e525e94f562d088ac40" name="php_phongo.c" role="src" />
- <file md5sum="3c126e28066811d7269276a72ae5cfb0" name="php_phongo.h" role="src" />
- <file md5sum="c42366320251ab963a91803674c0f851" name="php_phongo_classes.h" role="src" />
- <file md5sum="e538d3efd32ad86ce6af9f6a3ada17ba" name="php_phongo_structs.h" role="src" />
+ <file md5sum="18ea7643965f36d7589eb3611fbf3e0b" name="config.m4" role="src" />
+ <file md5sum="2798243a4062157db91bdb0a43f82160" name="config.w32" role="src" />
+ <file md5sum="8175849dff2928ca833bb0779e53adcc" name="php_phongo.c" role="src" />
+ <file md5sum="d5a9061f36ea5e4d8b1ea162cea26c3b" name="php_phongo.h" role="src" />
</dir>
</contents>
<dependencies>
<required>
<php>
<min>7.2.0</min>
<max>8.99.99</max>
</php>
<pearinstaller>
<min>1.4.8</min>
</pearinstaller>
</required>
</dependencies>
<providesextension>mongodb</providesextension>
<extsrcrelease />
</package>

File Metadata

Mime Type
application/octet-stream
Expires
Fri, Sep 12, 1:16 PM (1 d, 23 h)
Storage Engine
chunks
Storage Format
Chunks
Storage Handle
KUQcWR1Z5i49
Default Alt Text
(6 MB)

Event Timeline