Page MenuHomePhabricator (Chris)

No OneTemporary

Authored By
Unknown
Size
363 KB
Referenced Files
None
Subscribers
None
This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/debian/patches/0001-Try-linking-with-public-libmongoc-1.0-library-and-sl.patch b/debian/patches/0001-Try-linking-with-public-libmongoc-1.0-library-and-sl.patch
deleted file mode 100644
index ac9216cb..00000000
--- a/debian/patches/0001-Try-linking-with-public-libmongoc-1.0-library-and-sl.patch
+++ /dev/null
@@ -1,10013 +0,0 @@
-From: =?utf-8?q?Ond=C5=99ej_Sur=C3=BD?= <ondrej@sury.org>
-Date: Mon, 18 Jan 2016 11:52:58 +0100
-Subject: Try linking with public libmongoc-1.0 library and slowly resolve the
- internal dependencies
-
----
- mongodb-1.1.4/config.m4 | 26 +-
- .../src/mongoc/mongoc-array-private.h | 60 +
- .../src/mongoc/mongoc-async-cmd-private.h | 103 ++
- .../src/mongoc/mongoc-async-private.h | 83 ++
- .../src/mongoc/mongoc-buffer-private.h | 85 ++
- .../src/mongoc/mongoc-bulk-operation-private.h | 55 +
- .../src/mongoc/mongoc-client-private.h | 137 ++
- .../src/mongoc/mongoc-cluster-private.h | 152 ++
- .../src/mongoc/mongoc-cursor-cursorid-private.h | 51 +
- .../src/mongoc/mongoc-cursor-cursorid.c | 300 ++++
- .../src/mongoc/mongoc-cursor-private.h | 132 ++
- .../src/mongoc/mongoc-host-list-private.h | 41 +
- .../src/mongoc/mongoc-list-private.h | 55 +
- .../libmongoc-priv/src/mongoc/mongoc-log-private.h | 50 +
- .../src/libmongoc-priv/src/mongoc/mongoc-log.c | 327 ++++
- .../src/mongoc/mongoc-read-concern-private.h | 44 +
- .../src/mongoc/mongoc-read-prefs-private.h | 61 +
- .../libmongoc-priv/src/mongoc/mongoc-rpc-private.h | 117 ++
- .../src/mongoc/mongoc-server-description-private.h | 124 ++
- .../src/mongoc/mongoc-server-description.c | 651 ++++++++
- .../src/mongoc/mongoc-server-stream-private.h | 62 +
- .../libmongoc-priv/src/mongoc/mongoc-set-private.h | 101 ++
- .../src/libmongoc-priv/src/mongoc/mongoc-set.c | 217 +++
- .../src/mongoc/mongoc-thread-private.h | 126 ++
- .../mongoc/mongoc-topology-description-private.h | 98 ++
- .../src/mongoc/mongoc-topology-description.c | 1402 ++++++++++++++++++
- .../src/mongoc/mongoc-topology-private.h | 102 ++
- .../src/mongoc/mongoc-topology-scanner-private.h | 152 ++
- .../libmongoc-priv/src/mongoc/mongoc-topology.c | 915 ++++++++++++
- .../libmongoc-priv/src/mongoc/mongoc-uri-private.h | 87 ++
- .../src/libmongoc-priv/src/mongoc/mongoc-uri.c | 1559 ++++++++++++++++++++
- .../src/mongoc/mongoc-util-private.h | 56 +
- .../src/mongoc/mongoc-write-command-private.h | 147 ++
- .../src/mongoc/mongoc-write-command.c | 1527 +++++++++++++++++++
- .../src/mongoc/mongoc-write-concern-private.h | 55 +
- .../src/mongoc/mongoc-write-concern.c | 436 ++++++
- 36 files changed, 9691 insertions(+), 5 deletions(-)
- create mode 100644 mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-array-private.h
- create mode 100644 mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-async-cmd-private.h
- create mode 100644 mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-async-private.h
- create mode 100644 mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-buffer-private.h
- create mode 100644 mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-bulk-operation-private.h
- create mode 100644 mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-client-private.h
- create mode 100644 mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-cluster-private.h
- create mode 100644 mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-cursor-cursorid-private.h
- create mode 100644 mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-cursor-cursorid.c
- create mode 100644 mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-cursor-private.h
- create mode 100644 mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-host-list-private.h
- create mode 100644 mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-list-private.h
- create mode 100644 mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-log-private.h
- create mode 100644 mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-log.c
- create mode 100644 mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-read-concern-private.h
- create mode 100644 mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-read-prefs-private.h
- create mode 100644 mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-rpc-private.h
- create mode 100644 mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-server-description-private.h
- create mode 100644 mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-server-description.c
- create mode 100644 mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-server-stream-private.h
- create mode 100644 mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-set-private.h
- create mode 100644 mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-set.c
- create mode 100644 mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-thread-private.h
- create mode 100644 mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-topology-description-private.h
- create mode 100644 mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-topology-description.c
- create mode 100644 mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-topology-private.h
- create mode 100644 mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-topology-scanner-private.h
- create mode 100644 mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-topology.c
- create mode 100644 mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-uri-private.h
- create mode 100644 mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-uri.c
- create mode 100644 mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-util-private.h
- create mode 100644 mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-write-command-private.h
- create mode 100644 mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-write-command.c
- create mode 100644 mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-write-concern-private.h
- create mode 100644 mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-write-concern.c
-
-diff --git a/mongodb-1.1.4/config.m4 b/mongodb-1.1.4/config.m4
-index 52e84c0..32cd4ae 100644
---- a/mongodb-1.1.4/config.m4
-+++ b/mongodb-1.1.4/config.m4
-@@ -287,6 +287,18 @@ MONGOC_SOURCES_SSL="\
- MONGOC_SOURCES_SASL=mongoc-sasl.c
-
-
-+MONGOC_PRIV_SOURCES="\
-+ mongoc-cursor-cursorid.c \
-+ mongoc-log.c \
-+ mongoc-server-description.c \
-+ mongoc-set.c \
-+ mongoc-topology.c \
-+ mongoc-topology-description.c \
-+ mongoc-uri.c \
-+ mongoc-write-command.c \
-+ mongoc-write-concern.c \
-+ ";
-+
- if test "$ext_shared" = "no"; then
- PHP_ADD_SOURCES(PHP_EXT_DIR(mongodb), $MONGODB_BSON)
- PHP_ADD_SOURCES(PHP_EXT_DIR(mongodb), $MONGODB_BSON_CLASSES)
-@@ -339,14 +351,15 @@ PHP_ARG_WITH(libmongoc, whether to use system libmongoc,
- if test "$PHP_LIBMONGOC" != "no"; then
- AC_PATH_PROG(PKG_CONFIG, pkg-config, no)
- AC_MSG_CHECKING(for libmongoc)
-- if test -x "$PKG_CONFIG" && $PKG_CONFIG --exists libmongoc-1.0 && $PKG_CONFIG --exists libmongoc-priv; then
-+ if test -x "$PKG_CONFIG" && $PKG_CONFIG --exists libmongoc-1.0; then
- if $PKG_CONFIG libmongoc-1.0 --atleast-version 1.3.3; then
-- LIBMONGOC_INC=`$PKG_CONFIG libmongoc-priv --cflags`
-- LIBMONGOC_LIB=`$PKG_CONFIG libmongoc-priv --libs`
-- LIBMONGOC_VER=`$PKG_CONFIG libmongoc-priv --modversion`
-+ LIBMONGOC_INC=`$PKG_CONFIG libmongoc-1.0 --cflags`
-+ LIBMONGOC_LIB=`$PKG_CONFIG libmongoc-1.0 --libs`
-+ LIBMONGOC_VER=`$PKG_CONFIG libmongoc-1.0 --modversion`
- AC_MSG_RESULT(version $LIBMONGOC_VER found)
- CFLAGS="$CFLAGS -DMONGOC_I_AM_A_DRIVER"
--
-+ PHP_ADD_SOURCES_X(PHP_EXT_DIR(mongodb)[src/libmongoc-priv/src/mongoc], $MONGOC_PRIV_SOURCES, [$STD_CFLAGS], shared_objects_mongodb, yes)
-+ CPPFLAGS="$CPPFLAGS -DMONGOC_COMPILATION -DMONGOC_TRACE"
- else
- AC_MSG_ERROR(system libmongoc must be upgraded to version >= 1.3.3)
- fi
-@@ -472,6 +485,9 @@ dnl }}}
- if test "$PHP_LIBMONGOC" == "no"; then
- PHP_ADD_INCLUDE([$ext_srcdir/src/libmongoc/src/mongoc/])
- PHP_ADD_BUILD_DIR([$ext_builddir/src/libmongoc/src/mongoc/])
-+ else
-+ PHP_ADD_INCLUDE([$ext_srcdir/src/libmongoc-priv/src/mongoc/])
-+ PHP_ADD_BUILD_DIR([$ext_builddir/src/libmongoc-priv/src/mongoc/])
- fi
- if test "$PHP_LIBBSON" == "no"; then
- m4_include(src/libbson/build/autotools/CheckAtomics.m4)
-diff --git a/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-array-private.h b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-array-private.h
-new file mode 100644
-index 0000000..5674a0b
---- /dev/null
-+++ b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-array-private.h
-@@ -0,0 +1,60 @@
-+/*
-+ * 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.
-+ */
-+
-+#ifndef MONGOC_ARRAY_PRIVATE_H
-+#define MONGOC_ARRAY_PRIVATE_H
-+
-+#if !defined (MONGOC_I_AM_A_DRIVER) && !defined (MONGOC_COMPILATION)
-+#error "Only <mongoc.h> can be included directly."
-+#endif
-+
-+#include <bson.h>
-+
-+
-+BSON_BEGIN_DECLS
-+
-+
-+typedef struct _mongoc_array_t mongoc_array_t;
-+
-+
-+struct _mongoc_array_t
-+{
-+ size_t len;
-+ size_t element_size;
-+ size_t allocated;
-+ void *data;
-+};
-+
-+
-+#define _mongoc_array_append_val(a, v) _mongoc_array_append_vals(a, &v, 1)
-+#define _mongoc_array_index(a, t, i) (((t*)(a)->data)[i])
-+#define _mongoc_array_clear(a) (a)->len = 0
-+
-+
-+void _mongoc_array_init (mongoc_array_t *array,
-+ size_t element_size);
-+void _mongoc_array_copy (mongoc_array_t *dst,
-+ const mongoc_array_t *src);
-+void _mongoc_array_append_vals (mongoc_array_t *array,
-+ const void *data,
-+ uint32_t n_elements);
-+void _mongoc_array_destroy (mongoc_array_t *array);
-+
-+
-+BSON_END_DECLS
-+
-+
-+#endif /* MONGOC_ARRAY_PRIVATE_H */
-diff --git a/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-async-cmd-private.h b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-async-cmd-private.h
-new file mode 100644
-index 0000000..30a82f2
---- /dev/null
-+++ b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-async-cmd-private.h
-@@ -0,0 +1,103 @@
-+/*
-+ * 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.
-+ */
-+
-+#ifndef MONGOC_ASYNC_CMD_PRIVATE_H
-+#define MONGOC_ASYNC_CMD_PRIVATE_H
-+
-+#if !defined (MONGOC_I_AM_A_DRIVER) && !defined (MONGOC_COMPILATION)
-+#error "Only <mongoc.h> can be included directly."
-+#endif
-+
-+#include <bson.h>
-+
-+#include "mongoc-client.h"
-+#include "mongoc-async-private.h"
-+#include "mongoc-array-private.h"
-+#include "mongoc-buffer-private.h"
-+#include "mongoc-rpc-private.h"
-+#include "mongoc-stream.h"
-+
-+BSON_BEGIN_DECLS
-+
-+typedef enum
-+{
-+ MONGOC_ASYNC_CMD_SETUP,
-+ MONGOC_ASYNC_CMD_SEND,
-+ MONGOC_ASYNC_CMD_RECV_LEN,
-+ MONGOC_ASYNC_CMD_RECV_RPC,
-+ MONGOC_ASYNC_CMD_ERROR_STATE,
-+ MONGOC_ASYNC_CMD_CANCELED_STATE,
-+} mongoc_async_cmd_state_t;
-+
-+typedef struct _mongoc_async_cmd
-+{
-+ mongoc_stream_t *stream;
-+
-+ mongoc_async_t *async;
-+ mongoc_async_cmd_state_t state;
-+ int events;
-+ mongoc_async_cmd_setup_t setup;
-+ void *setup_ctx;
-+ mongoc_async_cmd_cb_t cb;
-+ void *data;
-+ bson_error_t error;
-+ int64_t start_time;
-+ int64_t expire_at;
-+ bson_t cmd;
-+ mongoc_buffer_t buffer;
-+ mongoc_array_t array;
-+ mongoc_iovec_t *iovec;
-+ size_t niovec;
-+ size_t bytes_to_read;
-+ mongoc_rpc_t rpc;
-+ bson_t reply;
-+ bool reply_needs_cleanup;
-+ char ns[MONGOC_NAMESPACE_MAX];
-+
-+ struct _mongoc_async_cmd *next;
-+ struct _mongoc_async_cmd *prev;
-+} mongoc_async_cmd_t;
-+
-+mongoc_async_cmd_t *
-+mongoc_async_cmd_new (mongoc_async_t *async,
-+ mongoc_stream_t *stream,
-+ mongoc_async_cmd_setup_t setup,
-+ void *setup_ctx,
-+ const char *dbname,
-+ const bson_t *cmd,
-+ mongoc_async_cmd_cb_t cb,
-+ void *cb_data,
-+ int32_t timeout_msec);
-+
-+void
-+mongoc_async_cmd_destroy (mongoc_async_cmd_t *acmd);
-+
-+bool
-+mongoc_async_cmd_run (mongoc_async_cmd_t *acmd);
-+
-+#ifdef MONGOC_ENABLE_SSL
-+int
-+mongoc_async_cmd_tls_setup (mongoc_stream_t *stream,
-+ int *events,
-+ void *ctx,
-+ int32_t timeout_msec,
-+ bson_error_t *error);
-+#endif
-+
-+BSON_END_DECLS
-+
-+
-+#endif /* MONGOC_ASYNC_CMD_PRIVATE_H */
-diff --git a/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-async-private.h b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-async-private.h
-new file mode 100644
-index 0000000..663f819
---- /dev/null
-+++ b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-async-private.h
-@@ -0,0 +1,83 @@
-+/*
-+ * 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.
-+ */
-+
-+#ifndef MONGOC_ASYNC_PRIVATE_H
-+#define MONGOC_ASYNC_PRIVATE_H
-+
-+#if !defined (MONGOC_I_AM_A_DRIVER) && !defined (MONGOC_COMPILATION)
-+#error "Only <mongoc.h> can be included directly."
-+#endif
-+
-+#include <bson.h>
-+#include "mongoc-stream.h"
-+
-+BSON_BEGIN_DECLS
-+
-+struct _mongoc_async_cmd;
-+
-+typedef struct _mongoc_async
-+{
-+ struct _mongoc_async_cmd *cmds;
-+ size_t ncmds;
-+ uint32_t request_id;
-+} mongoc_async_t;
-+
-+typedef enum
-+{
-+ MONGOC_ASYNC_CMD_IN_PROGRESS,
-+ MONGOC_ASYNC_CMD_SUCCESS,
-+ MONGOC_ASYNC_CMD_ERROR,
-+ MONGOC_ASYNC_CMD_TIMEOUT,
-+} mongoc_async_cmd_result_t;
-+
-+typedef void (*mongoc_async_cmd_cb_t)(mongoc_async_cmd_result_t result,
-+ const bson_t *bson,
-+ int64_t rtt_msec,
-+ void *data,
-+ bson_error_t *error);
-+
-+typedef int
-+(*mongoc_async_cmd_setup_t)(mongoc_stream_t *stream,
-+ int *events,
-+ void *ctx,
-+ int32_t timeout_msec,
-+ bson_error_t *error);
-+
-+
-+mongoc_async_t *
-+mongoc_async_new ();
-+
-+void
-+mongoc_async_destroy (mongoc_async_t *async);
-+
-+bool
-+mongoc_async_run (mongoc_async_t *async,
-+ int32_t timeout_msec);
-+
-+struct _mongoc_async_cmd *
-+mongoc_async_cmd (mongoc_async_t *async,
-+ mongoc_stream_t *stream,
-+ mongoc_async_cmd_setup_t setup,
-+ void *setup_ctx,
-+ const char *dbname,
-+ const bson_t *cmd,
-+ mongoc_async_cmd_cb_t cb,
-+ void *cb_data,
-+ int32_t timeout_msec);
-+
-+BSON_END_DECLS
-+
-+#endif /* MONGOC_ASYNC_PRIVATE_H */
-diff --git a/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-buffer-private.h b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-buffer-private.h
-new file mode 100644
-index 0000000..b42eb7d
---- /dev/null
-+++ b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-buffer-private.h
-@@ -0,0 +1,85 @@
-+/*
-+ * 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.
-+ */
-+
-+#ifndef MONGOC_BUFFER_PRIVATE_H
-+#define MONGOC_BUFFER_PRIVATE_H
-+
-+#if !defined (MONGOC_I_AM_A_DRIVER) && !defined (MONGOC_COMPILATION)
-+#error "Only <mongoc.h> can be included directly."
-+#endif
-+
-+#include <bson.h>
-+
-+#include "mongoc-stream.h"
-+
-+
-+BSON_BEGIN_DECLS
-+
-+
-+typedef struct _mongoc_buffer_t mongoc_buffer_t;
-+
-+
-+struct _mongoc_buffer_t
-+{
-+ uint8_t *data;
-+ size_t datalen;
-+ off_t off;
-+ size_t len;
-+ bson_realloc_func realloc_func;
-+ void *realloc_data;
-+};
-+
-+
-+void
-+_mongoc_buffer_init (mongoc_buffer_t *buffer,
-+ uint8_t *buf,
-+ size_t buflen,
-+ bson_realloc_func realloc_func,
-+ void *realloc_data);
-+
-+bool
-+_mongoc_buffer_append_from_stream (mongoc_buffer_t *buffer,
-+ mongoc_stream_t *stream,
-+ size_t size,
-+ int32_t timeout_msec,
-+ bson_error_t *error);
-+
-+ssize_t
-+_mongoc_buffer_try_append_from_stream (mongoc_buffer_t *buffer,
-+ mongoc_stream_t *stream,
-+ size_t size,
-+ int32_t timeout_msec,
-+ bson_error_t *error);
-+
-+ssize_t
-+_mongoc_buffer_fill (mongoc_buffer_t *buffer,
-+ mongoc_stream_t *stream,
-+ size_t min_bytes,
-+ int32_t timeout_msec,
-+ bson_error_t *error);
-+
-+void
-+_mongoc_buffer_destroy (mongoc_buffer_t *buffer);
-+
-+void
-+_mongoc_buffer_clear (mongoc_buffer_t *buffer,
-+ bool zero);
-+
-+
-+BSON_END_DECLS
-+
-+
-+#endif /* MONGOC_BUFFER_PRIVATE_H */
-diff --git a/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-bulk-operation-private.h b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-bulk-operation-private.h
-new file mode 100644
-index 0000000..0b9b890
---- /dev/null
-+++ b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-bulk-operation-private.h
-@@ -0,0 +1,55 @@
-+/*
-+ * 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.
-+ */
-+
-+#ifndef MONGOC_BULK_OPERATION_PRIVATE_H
-+#define MONGOC_BULK_OPERATION_PRIVATE_H
-+
-+#if !defined (MONGOC_I_AM_A_DRIVER) && !defined (MONGOC_COMPILATION)
-+#error "Only <mongoc.h> can be included directly."
-+#endif
-+
-+#include "mongoc-array-private.h"
-+#include "mongoc-client.h"
-+#include "mongoc-write-command-private.h"
-+
-+
-+BSON_BEGIN_DECLS
-+
-+struct _mongoc_bulk_operation_t
-+{
-+ char *database;
-+ char *collection;
-+ mongoc_client_t *client;
-+ mongoc_write_concern_t *write_concern;
-+ mongoc_bulk_write_flags_t flags;
-+ uint32_t hint;
-+ mongoc_array_t commands;
-+ mongoc_write_result_t result;
-+ bool executed;
-+};
-+
-+
-+mongoc_bulk_operation_t *_mongoc_bulk_operation_new (mongoc_client_t *client,
-+ const char *database,
-+ const char *collection,
-+ mongoc_bulk_write_flags_t flags,
-+ const mongoc_write_concern_t *write_concern);
-+
-+
-+BSON_END_DECLS
-+
-+
-+#endif /* MONGOC_BULK_OPERATION_PRIVATE_H */
-diff --git a/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-client-private.h b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-client-private.h
-new file mode 100644
-index 0000000..88e8b68
---- /dev/null
-+++ b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-client-private.h
-@@ -0,0 +1,137 @@
-+/*
-+ * 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.
-+ */
-+
-+#ifndef MONGOC_CLIENT_PRIVATE_H
-+#define MONGOC_CLIENT_PRIVATE_H
-+
-+#if !defined (MONGOC_I_AM_A_DRIVER) && !defined (MONGOC_COMPILATION)
-+#error "Only <mongoc.h> can be included directly."
-+#endif
-+
-+#include <bson.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"
-+
-+
-+BSON_BEGIN_DECLS
-+
-+/* protocol versions this driver can speak */
-+#define WIRE_VERSION_MIN 0
-+#define WIRE_VERSION_MAX 4
-+
-+/* first version that supported aggregation cursors */
-+#define WIRE_VERSION_AGG_CURSOR 1
-+/* first version that supported "insert", "update", "delete" commands */
-+#define WIRE_VERSION_WRITE_CMD 2
-+/* first version when SCRAM-SHA-1 replaced MONGODB-CR as default auth mech */
-+#define WIRE_VERSION_SCRAM_DEFAULT 3
-+/* 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
-+
-+
-+struct _mongoc_client_t
-+{
-+ uint32_t request_id;
-+ mongoc_list_t *conns;
-+ mongoc_uri_t *uri;
-+ mongoc_cluster_t cluster;
-+ bool in_exhaust;
-+
-+ mongoc_stream_initiator_t initiator;
-+ void *initiator_data;
-+
-+#ifdef MONGOC_ENABLE_SSL
-+ bool use_ssl;
-+ mongoc_ssl_opt_t ssl_opts;
-+ char *pem_subject;
-+#endif
-+
-+ mongoc_topology_t *topology;
-+
-+ mongoc_read_prefs_t *read_prefs;
-+ mongoc_read_concern_t *read_concern;
-+ mongoc_write_concern_t *write_concern;
-+};
-+
-+
-+mongoc_client_t *
-+_mongoc_client_new_from_uri (const mongoc_uri_t *uri,
-+ mongoc_topology_t *topology);
-+
-+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);
-+
-+bool
-+_mongoc_client_recv_gle (mongoc_client_t *client,
-+ mongoc_server_stream_t *server_stream,
-+ bson_t **gle_doc,
-+ bson_error_t *error);
-+
-+void
-+_mongoc_topology_background_thread_start (mongoc_topology_t *topology);
-+
-+void
-+_mongoc_topology_background_thread_stop (mongoc_topology_t *topology);
-+
-+mongoc_server_description_t *
-+_mongoc_client_get_server_description (mongoc_client_t *client,
-+ uint32_t server_id);
-+
-+void
-+_mongoc_client_kill_cursor (mongoc_client_t *client,
-+ uint32_t server_id,
-+ int64_t cursor_id,
-+ const char *db,
-+ const char *collection);
-+
-+BSON_END_DECLS
-+
-+
-+#endif /* MONGOC_CLIENT_PRIVATE_H */
-diff --git a/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-cluster-private.h b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-cluster-private.h
-new file mode 100644
-index 0000000..b9ae36b
---- /dev/null
-+++ b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-cluster-private.h
-@@ -0,0 +1,152 @@
-+/*
-+ * 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.
-+ */
-+
-+#ifndef MONGOC_CLUSTER_PRIVATE_H
-+#define MONGOC_CLUSTER_PRIVATE_H
-+
-+#if !defined (MONGOC_I_AM_A_DRIVER) && !defined (MONGOC_COMPILATION)
-+#error "Only <mongoc.h> can be included directly."
-+#endif
-+
-+#include <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-read-prefs.h"
-+#include "mongoc-rpc-private.h"
-+#include "mongoc-server-stream-private.h"
-+#include "mongoc-set-private.h"
-+#include "mongoc-stream.h"
-+#include "mongoc-topology-description-private.h"
-+#include "mongoc-uri.h"
-+#include "mongoc-write-concern.h"
-+
-+
-+BSON_BEGIN_DECLS
-+
-+
-+typedef struct _mongoc_cluster_node_t
-+{
-+ mongoc_stream_t *stream;
-+
-+ int32_t max_wire_version;
-+ int32_t min_wire_version;
-+ int32_t max_write_batch_size;
-+ int32_t max_bson_obj_size;
-+ int32_t max_msg_size;
-+
-+ int64_t timestamp;
-+} mongoc_cluster_node_t;
-+
-+typedef struct _mongoc_cluster_t
-+{
-+ 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_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);
-+
-+int32_t
-+mongoc_cluster_node_max_wire_version (mongoc_cluster_t *cluster,
-+ uint32_t server_id);
-+
-+int32_t
-+mongoc_cluster_node_min_wire_version (mongoc_cluster_t *cluster,
-+ uint32_t server_id);
-+
-+bool
-+mongoc_cluster_sendv_to_server (mongoc_cluster_t *cluster,
-+ mongoc_rpc_t *rpcs,
-+ size_t rpcs_len,
-+ mongoc_server_stream_t *server_stream,
-+ const mongoc_write_concern_t *write_concern,
-+ 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);
-+
-+mongoc_server_stream_t *
-+mongoc_cluster_stream_for_reads (mongoc_cluster_t *cluster,
-+ const mongoc_read_prefs_t *read_prefs,
-+ bson_error_t *error);
-+
-+mongoc_server_stream_t *
-+mongoc_cluster_stream_for_writes (mongoc_cluster_t *cluster,
-+ bson_error_t *error);
-+
-+mongoc_server_stream_t *
-+mongoc_cluster_stream_for_server (mongoc_cluster_t *cluster,
-+ uint32_t server_id,
-+ bool reconnect_ok,
-+ bson_error_t *error);
-+
-+bool
-+mongoc_cluster_run_command_rpc (mongoc_cluster_t *cluster,
-+ mongoc_stream_t *stream,
-+ uint32_t server_id,
-+ const char *command_name,
-+ mongoc_rpc_t *rpc,
-+ mongoc_rpc_t *reply_rpc,
-+ mongoc_buffer_t *buffer,
-+ bson_error_t *error);
-+
-+bool
-+mongoc_cluster_run_command (mongoc_cluster_t *cluster,
-+ mongoc_stream_t *stream,
-+ uint32_t server_id,
-+ mongoc_query_flags_t flags,
-+ const char *db_name,
-+ const bson_t *command,
-+ bson_t *reply,
-+ bson_error_t *error);
-+
-+
-+BSON_END_DECLS
-+
-+
-+#endif /* MONGOC_CLUSTER_PRIVATE_H */
-diff --git a/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-cursor-cursorid-private.h b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-cursor-cursorid-private.h
-new file mode 100644
-index 0000000..9147822
---- /dev/null
-+++ b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-cursor-cursorid-private.h
-@@ -0,0 +1,51 @@
-+/*
-+ * 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.
-+ */
-+
-+#ifndef MONGOC_CURSOR_CURSORID_PRIVATE_H
-+#define MONGOC_CURSOR_CURSORID_PRIVATE_H
-+
-+#if !defined (MONGOC_I_AM_A_DRIVER) && !defined (MONGOC_COMPILATION)
-+#error "Only <mongoc.h> can be included directly."
-+#endif
-+
-+#include <bson.h>
-+
-+#include "mongoc-cursor-private.h"
-+
-+
-+BSON_BEGIN_DECLS
-+
-+
-+typedef struct
-+{
-+ bool in_batch;
-+ bool in_reader;
-+ bson_iter_t batch_iter;
-+ bson_t current_doc;
-+} mongoc_cursor_cursorid_t;
-+
-+
-+bool _mongoc_cursor_cursorid_prime (mongoc_cursor_t *cursor);
-+bool _mongoc_cursor_cursorid_next (mongoc_cursor_t *cursor,
-+ const bson_t **bson);
-+void _mongoc_cursor_cursorid_init (mongoc_cursor_t *cursor,
-+ const bson_t *command);
-+
-+
-+BSON_END_DECLS
-+
-+
-+#endif /* MONGOC_CURSOR_CURSORID_PRIVATE_H */
-diff --git a/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-cursor-cursorid.c b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-cursor-cursorid.c
-new file mode 100644
-index 0000000..4d93164
---- /dev/null
-+++ b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-cursor-cursorid.c
-@@ -0,0 +1,300 @@
-+/*
-+ * 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-cursor-cursorid-private.h"
-+#include "mongoc-log.h"
-+#include "mongoc-trace.h"
-+#include "mongoc-error.h"
-+#include "mongoc-util-private.h"
-+
-+
-+#undef MONGOC_LOG_DOMAIN
-+#define MONGOC_LOG_DOMAIN "cursor-cursorid"
-+
-+
-+static void *
-+_mongoc_cursor_cursorid_new (void)
-+{
-+ mongoc_cursor_cursorid_t *cid;
-+
-+ ENTRY;
-+
-+ cid = (mongoc_cursor_cursorid_t *)bson_malloc0 (sizeof *cid);
-+
-+ RETURN (cid);
-+}
-+
-+
-+static void
-+_mongoc_cursor_cursorid_destroy (mongoc_cursor_t *cursor)
-+{
-+ ENTRY;
-+
-+ bson_free (cursor->iface_data);
-+ _mongoc_cursor_destroy (cursor);
-+
-+ EXIT;
-+}
-+
-+
-+static bool
-+_mongoc_cursor_cursorid_refresh_from_command (mongoc_cursor_t *cursor,
-+ const bson_t *command)
-+{
-+ mongoc_cursor_cursorid_t *cid;
-+ const bson_t *bson;
-+ bson_iter_t iter, child;
-+ const char *ns;
-+
-+ ENTRY;
-+
-+ cid = (mongoc_cursor_cursorid_t *)cursor->iface_data;
-+ BSON_ASSERT (cid);
-+
-+ /* 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) &&
-+ _mongoc_read_from_buffer (cursor, &bson) &&
-+ bson_iter_init_find (&iter, bson, "cursor") &&
-+ BSON_ITER_HOLDS_DOCUMENT (&iter) &&
-+ bson_iter_recurse (&iter, &child)) {
-+
-+ while (bson_iter_next (&child)) {
-+ if (BSON_ITER_IS_KEY (&child, "id")) {
-+ cursor->rpc.reply.cursor_id = bson_iter_as_int64 (&child);
-+ } else if (BSON_ITER_IS_KEY (&child, "ns")) {
-+ ns = bson_iter_utf8 (&child, &cursor->nslen);
-+ bson_strncpy (cursor->ns, ns, sizeof cursor->ns);
-+ } else if (BSON_ITER_IS_KEY (&child, "firstBatch") ||
-+ BSON_ITER_IS_KEY (&child, "nextBatch")) {
-+ if (BSON_ITER_HOLDS_ARRAY (&child) &&
-+ bson_iter_recurse (&child, &cid->batch_iter)) {
-+ cid->in_batch = true;
-+ }
-+ }
-+ }
-+
-+ RETURN (true);
-+ } else {
-+ 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));
-+ }
-+
-+ RETURN (false);
-+ }
-+}
-+
-+
-+static void
-+_mongoc_cursor_cursorid_read_from_batch (mongoc_cursor_t *cursor,
-+ const bson_t **bson)
-+{
-+ mongoc_cursor_cursorid_t *cid;
-+ const uint8_t *data = NULL;
-+ uint32_t data_len = 0;
-+
-+ ENTRY;
-+
-+ cid = (mongoc_cursor_cursorid_t *)cursor->iface_data;
-+ BSON_ASSERT (cid);
-+
-+ if (bson_iter_next (&cid->batch_iter) &&
-+ BSON_ITER_HOLDS_DOCUMENT (&cid->batch_iter)) {
-+ bson_iter_document (&cid->batch_iter, &data_len, &data);
-+
-+ if (bson_init_static (&cid->current_doc, data, data_len)) {
-+ *bson = &cid->current_doc;
-+ }
-+ }
-+}
-+
-+
-+bool
-+_mongoc_cursor_cursorid_prime (mongoc_cursor_t *cursor)
-+{
-+ cursor->sent = true;
-+ return _mongoc_cursor_cursorid_refresh_from_command (cursor, &cursor->query);
-+}
-+
-+
-+static void
-+_mongoc_cursor_prepare_getmore_command (mongoc_cursor_t *cursor,
-+ bson_t *command)
-+{
-+ const char *collection;
-+ int collection_len;
-+ mongoc_cursor_cursorid_t *cid;
-+
-+ cid = (mongoc_cursor_cursorid_t *)cursor->iface_data;
-+ BSON_ASSERT (cid);
-+
-+ _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);
-+
-+ if (cursor->batch_size) {
-+ bson_append_int32 (command, "batchSize", 9, cursor->batch_size);
-+ }
-+
-+ /* 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."
-+ */
-+ if (cursor->flags & MONGOC_QUERY_TAILABLE_CURSOR &&
-+ cursor->flags & MONGOC_QUERY_AWAIT_DATA &&
-+ cursor->max_await_time_ms) {
-+ bson_append_int32 (command, "maxTimeMS", 9, cursor->max_await_time_ms);
-+ }
-+}
-+
-+
-+static bool
-+_mongoc_cursor_cursorid_get_more (mongoc_cursor_t *cursor)
-+{
-+ mongoc_cursor_cursorid_t *cid;
-+ mongoc_server_stream_t *server_stream;
-+ bson_t command;
-+ bool ret;
-+
-+ ENTRY;
-+
-+ cid = (mongoc_cursor_cursorid_t *)cursor->iface_data;
-+ BSON_ASSERT (cid);
-+
-+ server_stream = _mongoc_cursor_fetch_stream (cursor);
-+
-+ if (!server_stream) {
-+ RETURN (false);
-+ }
-+
-+ if (_use_find_command (cursor, server_stream)) {
-+ _mongoc_cursor_prepare_getmore_command (cursor, &command);
-+ ret = _mongoc_cursor_cursorid_refresh_from_command (cursor, &command);
-+ bson_destroy (&command);
-+ } else {
-+ ret = _mongoc_cursor_op_getmore (cursor, server_stream);
-+ cid->in_reader = ret;
-+ }
-+
-+ mongoc_server_stream_cleanup (server_stream);
-+ RETURN (ret);
-+}
-+
-+
-+bool
-+_mongoc_cursor_cursorid_next (mongoc_cursor_t *cursor,
-+ const bson_t **bson)
-+{
-+ mongoc_cursor_cursorid_t *cid;
-+ bool refreshed = false;
-+
-+ ENTRY;
-+
-+ *bson = NULL;
-+
-+ cid = (mongoc_cursor_cursorid_t *)cursor->iface_data;
-+ BSON_ASSERT (cid);
-+
-+ if (!cursor->sent) {
-+ if (!_mongoc_cursor_cursorid_prime (cursor)) {
-+ GOTO (done);
-+ }
-+ }
-+
-+again:
-+
-+ if (cid->in_batch) {
-+ _mongoc_cursor_cursorid_read_from_batch (cursor, bson);
-+
-+ if (*bson) {
-+ GOTO (done);
-+ }
-+
-+ cid->in_batch = false;
-+ } else if (cid->in_reader) {
-+ _mongoc_read_from_buffer (cursor, bson);
-+
-+ if (*bson) {
-+ GOTO (done);
-+ }
-+
-+ cid->in_reader = false;
-+ }
-+
-+ if (!refreshed && mongoc_cursor_get_id (cursor)) {
-+ if (!_mongoc_cursor_cursorid_get_more (cursor)) {
-+ GOTO (done);
-+ }
-+
-+ refreshed = true;
-+ GOTO (again);
-+ }
-+
-+done:
-+ RETURN (*bson ? true : false);
-+}
-+
-+
-+static mongoc_cursor_t *
-+_mongoc_cursor_cursorid_clone (const mongoc_cursor_t *cursor)
-+{
-+ mongoc_cursor_t *clone_;
-+
-+ ENTRY;
-+
-+ clone_ = _mongoc_cursor_clone (cursor);
-+ _mongoc_cursor_cursorid_init (clone_, &cursor->query);
-+
-+ RETURN (clone_);
-+}
-+
-+
-+static mongoc_cursor_interface_t gMongocCursorCursorid = {
-+ _mongoc_cursor_cursorid_clone,
-+ _mongoc_cursor_cursorid_destroy,
-+ NULL,
-+ _mongoc_cursor_cursorid_next,
-+};
-+
-+
-+void
-+_mongoc_cursor_cursorid_init (mongoc_cursor_t *cursor,
-+ const bson_t *command)
-+{
-+ ENTRY;
-+
-+ bson_destroy (&cursor->query);
-+ bson_copy_to (command, &cursor->query);
-+
-+ cursor->iface_data = _mongoc_cursor_cursorid_new ();
-+
-+ memcpy (&cursor->iface, &gMongocCursorCursorid,
-+ sizeof (mongoc_cursor_interface_t));
-+
-+ EXIT;
-+}
-diff --git a/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-cursor-private.h b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-cursor-private.h
-new file mode 100644
-index 0000000..8c7e38c
---- /dev/null
-+++ b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-cursor-private.h
-@@ -0,0 +1,132 @@
-+/*
-+ * 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.
-+ */
-+
-+#ifndef MONGOC_CURSOR_PRIVATE_H
-+#define MONGOC_CURSOR_PRIVATE_H
-+
-+#if !defined (MONGOC_I_AM_A_DRIVER) && !defined (MONGOC_COMPILATION)
-+#error "Only <mongoc.h> can be included directly."
-+#endif
-+
-+#include <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
-+
-+typedef struct _mongoc_cursor_interface_t mongoc_cursor_interface_t;
-+
-+
-+struct _mongoc_cursor_interface_t
-+{
-+ mongoc_cursor_t *(*clone) (const mongoc_cursor_t *cursor);
-+ void (*destroy) (mongoc_cursor_t *cursor);
-+ bool (*more) (mongoc_cursor_t *cursor);
-+ bool (*next) (mongoc_cursor_t *cursor,
-+ const bson_t **bson);
-+ bool (*error) (mongoc_cursor_t *cursor,
-+ bson_error_t *error);
-+ void (*get_host) (mongoc_cursor_t *cursor,
-+ mongoc_host_list_t *host);
-+};
-+
-+
-+struct _mongoc_cursor_t
-+{
-+ mongoc_client_t *client;
-+
-+ uint32_t hint;
-+ uint32_t stamp;
-+
-+ unsigned is_command : 1;
-+ unsigned sent : 1;
-+ unsigned done : 1;
-+ unsigned end_of_event : 1;
-+ unsigned has_fields : 1;
-+ unsigned in_exhaust : 1;
-+
-+ bson_t query;
-+ bson_t fields;
-+
-+ mongoc_read_concern_t *read_concern;
-+ mongoc_read_prefs_t *read_prefs;
-+
-+ mongoc_query_flags_t flags;
-+ uint32_t skip;
-+ int32_t limit;
-+ uint32_t count;
-+ uint32_t batch_size;
-+ uint32_t max_await_time_ms;
-+
-+ char ns [140];
-+ uint32_t nslen;
-+ uint32_t dblen;
-+
-+ bson_error_t error;
-+
-+ mongoc_rpc_t rpc;
-+ mongoc_buffer_t buffer;
-+ bson_reader_t *reader;
-+
-+ const bson_t *current;
-+
-+ mongoc_cursor_interface_t iface;
-+ void *iface_data;
-+};
-+
-+
-+mongoc_cursor_t * _mongoc_cursor_new (mongoc_client_t *client,
-+ const char *db_and_collection,
-+ mongoc_query_flags_t flags,
-+ uint32_t skip,
-+ int32_t limit,
-+ uint32_t batch_size,
-+ bool is_command,
-+ const bson_t *query,
-+ const bson_t *fields,
-+ const mongoc_read_prefs_t *read_prefs,
-+ const mongoc_read_concern_t *read_concern);
-+mongoc_cursor_t *_mongoc_cursor_clone (const mongoc_cursor_t *cursor);
-+void _mongoc_cursor_destroy (mongoc_cursor_t *cursor);
-+bool _mongoc_read_from_buffer (mongoc_cursor_t *cursor,
-+ const bson_t **bson);
-+bool _use_find_command (const mongoc_cursor_t *cursor,
-+ const mongoc_server_stream_t *server_stream);
-+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_op_getmore (mongoc_cursor_t *cursor,
-+ mongoc_server_stream_t *server_stream);
-+bool _mongoc_cursor_run_command (mongoc_cursor_t *cursor,
-+ const bson_t *command);
-+bool _mongoc_cursor_more (mongoc_cursor_t *cursor);
-+bool _mongoc_cursor_next (mongoc_cursor_t *cursor,
-+ const bson_t **bson);
-+bool _mongoc_cursor_error (mongoc_cursor_t *cursor,
-+ bson_error_t *error);
-+void _mongoc_cursor_get_host (mongoc_cursor_t *cursor,
-+ mongoc_host_list_t *host);
-+
-+
-+BSON_END_DECLS
-+
-+
-+#endif /* MONGOC_CURSOR_PRIVATE_H */
-diff --git a/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-host-list-private.h b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-host-list-private.h
-new file mode 100644
-index 0000000..9cf93fd
---- /dev/null
-+++ b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-host-list-private.h
-@@ -0,0 +1,41 @@
-+/*
-+ * 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.
-+ */
-+
-+#ifndef MONGOC_HOST_LIST_PRIVATE_H
-+#define MONGOC_HOST_LIST_PRIVATE_H
-+
-+#if !defined (MONGOC_I_AM_A_DRIVER) && !defined (MONGOC_COMPILATION)
-+#error "Only <mongoc.h> can be included directly."
-+#endif
-+
-+#include "mongoc-host-list.h"
-+
-+
-+BSON_BEGIN_DECLS
-+
-+
-+bool _mongoc_host_list_from_string (mongoc_host_list_t *host_list,
-+ const char *host_and_port);
-+
-+bool _mongoc_host_list_equal (const mongoc_host_list_t *host_a,
-+ const mongoc_host_list_t *host_b);
-+
-+void _mongoc_host_list_destroy_all (mongoc_host_list_t *host);
-+
-+BSON_END_DECLS
-+
-+
-+#endif /* MONGOC_HOST_LIST_PRIVATE_H */
-diff --git a/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-list-private.h b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-list-private.h
-new file mode 100644
-index 0000000..5a6c431
---- /dev/null
-+++ b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-list-private.h
-@@ -0,0 +1,55 @@
-+/*
-+ * 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.
-+ */
-+
-+#ifndef MONGOC_LIST_H
-+#define MONGOC_LIST_H
-+
-+#if !defined (MONGOC_I_AM_A_DRIVER) && !defined (MONGOC_COMPILATION)
-+#error "Only <mongoc.h> can be included directly."
-+#endif
-+
-+#include <bson.h>
-+
-+
-+BSON_BEGIN_DECLS
-+
-+
-+typedef struct _mongoc_list_t mongoc_list_t;
-+
-+
-+struct _mongoc_list_t
-+{
-+ mongoc_list_t *next;
-+ void *data;
-+};
-+
-+
-+mongoc_list_t *_mongoc_list_append (mongoc_list_t *list,
-+ void *data);
-+mongoc_list_t *_mongoc_list_prepend (mongoc_list_t *list,
-+ void *data);
-+mongoc_list_t *_mongoc_list_remove (mongoc_list_t *list,
-+ void *data);
-+void _mongoc_list_foreach (mongoc_list_t *list,
-+ void (*func) (void *data, void *user_data),
-+ void * user_data);
-+void _mongoc_list_destroy (mongoc_list_t *list);
-+
-+
-+BSON_END_DECLS
-+
-+
-+#endif /* MONGOC_LIST_H */
-diff --git a/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-log-private.h b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-log-private.h
-new file mode 100644
-index 0000000..49bf1cc
---- /dev/null
-+++ b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-log-private.h
-@@ -0,0 +1,50 @@
-+/*
-+ * 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.
-+ */
-+
-+#ifndef MONGOC_LOG_PRIVATE_H
-+#define MONGOC_LOG_PRIVATE_H
-+
-+#if !defined (MONGOC_INSIDE) && !defined (MONGOC_COMPILATION) && !defined (MONGOC_I_AM_A_DRIVER)
-+# error "Only <mongoc.h> can be included directly."
-+#endif
-+
-+#include "mongoc-iovec.h"
-+
-+/* just for testing */
-+void _mongoc_log_get_handler (mongoc_log_func_t *log_func,
-+ void **user_data);
-+
-+bool _mongoc_log_trace_is_enabled (void);
-+
-+void
-+mongoc_log_trace_bytes (const char *domain,
-+ const uint8_t *_b,
-+ size_t _l);
-+
-+void
-+mongoc_log_trace_iovec (const char *domain,
-+ const mongoc_iovec_t *_iov,
-+ size_t _iovcnt);
-+
-+void
-+mongoc_log_trace_enable (void);
-+
-+void
-+mongoc_log_trace_disable (void);
-+
-+
-+
-+#endif /* MONGOC_LOG_PRIVATE_H */
-diff --git a/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-log.c b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-log.c
-new file mode 100644
-index 0000000..47e13f3
---- /dev/null
-+++ b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-log.c
-@@ -0,0 +1,327 @@
-+/*
-+ * 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>
-+#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 mongoc_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 MONGOC_ONCE_FUN( _mongoc_ensure_mutex_once)
-+{
-+ mongoc_mutex_init(&gLogMutex);
-+
-+ MONGOC_ONCE_RETURN;
-+}
-+
-+void
-+mongoc_log_set_handler (mongoc_log_func_t log_func,
-+ void *user_data)
-+{
-+ static mongoc_once_t once = MONGOC_ONCE_INIT;
-+ mongoc_once(&once, &_mongoc_ensure_mutex_once);
-+
-+ mongoc_mutex_lock(&gLogMutex);
-+ gLogFunc = log_func;
-+ gLogData = user_data;
-+ mongoc_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;
-+ static mongoc_once_t once = MONGOC_ONCE_INIT;
-+ int stop_logging;
-+
-+ mongoc_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);
-+
-+ mongoc_mutex_lock(&gLogMutex);
-+ gLogFunc(log_level, log_domain, message, gLogData);
-+ mongoc_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 ();
-+#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.1.4/src/libmongoc-priv/src/mongoc/mongoc-read-concern-private.h b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-read-concern-private.h
-new file mode 100644
-index 0000000..3de75a1
---- /dev/null
-+++ b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-read-concern-private.h
-@@ -0,0 +1,44 @@
-+/*
-+ * 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.
-+ */
-+
-+#ifndef MONGOC_READ_CONCERN_PRIVATE_H
-+#define MONGOC_READ_CONCERN_PRIVATE_H
-+
-+#if !defined (MONGOC_I_AM_A_DRIVER) && !defined (MONGOC_COMPILATION)
-+#error "Only <mongoc.h> can be included directly."
-+#endif
-+
-+#include <bson.h>
-+#include "mongoc-read-concern.h"
-+
-+
-+BSON_BEGIN_DECLS
-+
-+
-+struct _mongoc_read_concern_t
-+{
-+ char *level;
-+ bool frozen;
-+ bson_t compiled;
-+};
-+
-+
-+const bson_t *_mongoc_read_concern_get_bson (mongoc_read_concern_t *read_concern);
-+
-+BSON_END_DECLS
-+
-+
-+#endif /* MONGOC_READ_CONCERN_PRIVATE_H */
-diff --git a/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-read-prefs-private.h b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-read-prefs-private.h
-new file mode 100644
-index 0000000..4983500
---- /dev/null
-+++ b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-read-prefs-private.h
-@@ -0,0 +1,61 @@
-+/*
-+ * 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.
-+ */
-+
-+#ifndef MONGOC_READ_PREFS_PRIVATE_H
-+#define MONGOC_READ_PREFS_PRIVATE_H
-+
-+#if !defined (MONGOC_I_AM_A_DRIVER) && !defined (MONGOC_COMPILATION)
-+#error "Only <mongoc.h> can be included directly."
-+#endif
-+
-+#include <bson.h>
-+
-+#include "mongoc-cluster-private.h"
-+#include "mongoc-read-prefs.h"
-+
-+
-+BSON_BEGIN_DECLS
-+
-+struct _mongoc_read_prefs_t
-+{
-+ mongoc_read_mode_t mode;
-+ bson_t tags;
-+};
-+
-+
-+typedef struct _mongoc_apply_read_prefs_result_t {
-+ bson_t *query_with_read_prefs;
-+ bool query_owned;
-+ mongoc_query_flags_t flags;
-+} mongoc_apply_read_prefs_result_t;
-+
-+
-+#define READ_PREFS_RESULT_INIT { NULL, false, MONGOC_QUERY_NONE }
-+
-+void
-+apply_read_preferences (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_apply_read_prefs_result_t *result);
-+
-+void
-+apply_read_prefs_result_cleanup (mongoc_apply_read_prefs_result_t *result);
-+
-+BSON_END_DECLS
-+
-+
-+#endif /* MONGOC_READ_PREFS_PRIVATE_H */
-diff --git a/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-rpc-private.h b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-rpc-private.h
-new file mode 100644
-index 0000000..f742db3
---- /dev/null
-+++ b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-rpc-private.h
-@@ -0,0 +1,117 @@
-+/*
-+ * 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.
-+ */
-+
-+#ifndef MONGOC_RPC_PRIVATE_H
-+#define MONGOC_RPC_PRIVATE_H
-+
-+#if !defined (MONGOC_I_AM_A_DRIVER) && !defined (MONGOC_COMPILATION)
-+#error "Only <mongoc.h> can be included directly."
-+#endif
-+
-+#include <bson.h>
-+#include <stddef.h>
-+
-+#include "mongoc-array-private.h"
-+#include "mongoc-iovec.h"
-+#include "mongoc-write-concern.h"
-+#include "mongoc-flags.h"
-+
-+
-+BSON_BEGIN_DECLS
-+
-+
-+#define RPC(_name, _code) typedef struct { _code } mongoc_rpc_##_name##_t;
-+#define ENUM_FIELD(_name) uint32_t _name;
-+#define INT32_FIELD(_name) int32_t _name;
-+#define INT64_FIELD(_name) int64_t _name;
-+#define INT64_ARRAY_FIELD(_len, _name) int32_t _len; int64_t *_name;
-+#define CSTRING_FIELD(_name) const char *_name;
-+#define BSON_FIELD(_name) const uint8_t *_name;
-+#define BSON_ARRAY_FIELD(_name) const uint8_t *_name; int32_t _name##_len;
-+#define IOVEC_ARRAY_FIELD(_name) const mongoc_iovec_t *_name; int32_t n_##_name; mongoc_iovec_t _name##_recv;
-+#define RAW_BUFFER_FIELD(_name) const uint8_t *_name; int32_t _name##_len;
-+#define BSON_OPTIONAL(_check, _code) _code
-+
-+
-+#include "op-delete.def"
-+#include "op-get-more.def"
-+#include "op-header.def"
-+#include "op-insert.def"
-+#include "op-kill-cursors.def"
-+#include "op-msg.def"
-+#include "op-query.def"
-+#include "op-reply.def"
-+#include "op-update.def"
-+
-+
-+typedef union
-+{
-+ mongoc_rpc_delete_t delete_;
-+ mongoc_rpc_get_more_t get_more;
-+ mongoc_rpc_header_t header;
-+ mongoc_rpc_insert_t insert;
-+ mongoc_rpc_kill_cursors_t kill_cursors;
-+ mongoc_rpc_msg_t msg;
-+ mongoc_rpc_query_t query;
-+ mongoc_rpc_reply_t reply;
-+ mongoc_rpc_update_t update;
-+} mongoc_rpc_t;
-+
-+
-+BSON_STATIC_ASSERT (sizeof (mongoc_rpc_header_t) == 16);
-+BSON_STATIC_ASSERT (offsetof (mongoc_rpc_header_t, opcode) ==
-+ offsetof (mongoc_rpc_reply_t, opcode));
-+
-+
-+#undef RPC
-+#undef ENUM_FIELD
-+#undef INT32_FIELD
-+#undef INT64_FIELD
-+#undef INT64_ARRAY_FIELD
-+#undef CSTRING_FIELD
-+#undef BSON_FIELD
-+#undef BSON_ARRAY_FIELD
-+#undef IOVEC_ARRAY_FIELD
-+#undef BSON_OPTIONAL
-+#undef RAW_BUFFER_FIELD
-+
-+
-+void _mongoc_rpc_gather (mongoc_rpc_t *rpc,
-+ mongoc_array_t *array);
-+bool _mongoc_rpc_needs_gle (mongoc_rpc_t *rpc,
-+ const mongoc_write_concern_t *write_concern);
-+void _mongoc_rpc_swab_to_le (mongoc_rpc_t *rpc);
-+void _mongoc_rpc_swab_from_le (mongoc_rpc_t *rpc);
-+void _mongoc_rpc_printf (mongoc_rpc_t *rpc);
-+bool _mongoc_rpc_scatter (mongoc_rpc_t *rpc,
-+ const uint8_t *buf,
-+ size_t buflen);
-+bool _mongoc_rpc_reply_get_first (mongoc_rpc_reply_t *reply,
-+ bson_t *bson);
-+void _mongoc_rpc_prep_command (mongoc_rpc_t *rpc,
-+ const char *cmd_ns,
-+ const bson_t *command,
-+ mongoc_query_flags_t flags);
-+bool _mongoc_rpc_parse_command_error(mongoc_rpc_t *rpc,
-+ bson_error_t *error);
-+bool _mongoc_rpc_parse_query_error (mongoc_rpc_t *rpc,
-+ bson_error_t *error);
-+
-+
-+BSON_END_DECLS
-+
-+
-+#endif /* MONGOC_RPC_PRIVATE_H */
-diff --git a/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-server-description-private.h b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-server-description-private.h
-new file mode 100644
-index 0000000..b8b5962
---- /dev/null
-+++ b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-server-description-private.h
-@@ -0,0 +1,124 @@
-+/*
-+ * 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.
-+ */
-+
-+#ifndef MONGOC_SERVER_DESCRIPTION_PRIVATE_H
-+#define MONGOC_SERVER_DESCRIPTION_PRIVATE_H
-+
-+#include "mongoc-server-description.h"
-+
-+
-+#define MONGOC_DEFAULT_WIRE_VERSION 0
-+#define MONGOC_DEFAULT_WRITE_BATCH_SIZE 1000
-+#define MONGOC_DEFAULT_BSON_OBJ_SIZE 16 * 1024 * 1024
-+#define MONGOC_DEFAULT_MAX_MSG_SIZE 48000000
-+
-+/* represent a server or topology with no replica set config version */
-+#define MONGOC_NO_SET_VERSION -1
-+
-+typedef enum
-+ {
-+ MONGOC_SERVER_UNKNOWN,
-+ MONGOC_SERVER_STANDALONE,
-+ MONGOC_SERVER_MONGOS,
-+ MONGOC_SERVER_POSSIBLE_PRIMARY,
-+ MONGOC_SERVER_RS_PRIMARY,
-+ MONGOC_SERVER_RS_SECONDARY,
-+ MONGOC_SERVER_RS_ARBITER,
-+ MONGOC_SERVER_RS_OTHER,
-+ MONGOC_SERVER_RS_GHOST,
-+ MONGOC_SERVER_DESCRIPTION_TYPES,
-+ } mongoc_server_description_type_t;
-+
-+struct _mongoc_server_description_t
-+{
-+ uint32_t id;
-+ mongoc_host_list_t host;
-+ int64_t round_trip_time;
-+ bson_t last_is_master;
-+ bool has_is_master;
-+ const char *connection_address;
-+ const char *me;
-+
-+ /* The following fields are filled from the last_is_master and are zeroed on
-+ * parse. So order matters here. DON'T move set_name */
-+ const char *set_name;
-+ bson_error_t error;
-+ mongoc_server_description_type_t type;
-+
-+ int32_t min_wire_version;
-+ int32_t max_wire_version;
-+ int32_t max_msg_size;
-+ int32_t max_bson_obj_size;
-+ int32_t max_write_batch_size;
-+
-+ bson_t hosts;
-+ bson_t passives;
-+ bson_t arbiters;
-+
-+ bson_t tags;
-+ const char *current_primary;
-+ int64_t set_version;
-+ bson_oid_t election_id;
-+};
-+
-+void
-+mongoc_server_description_init (mongoc_server_description_t *sd,
-+ const char *address,
-+ uint32_t id);
-+bool
-+mongoc_server_description_has_rs_member (mongoc_server_description_t *description,
-+ const char *address);
-+
-+
-+bool
-+mongoc_server_description_has_set_version (mongoc_server_description_t *description);
-+
-+bool
-+mongoc_server_description_has_election_id (mongoc_server_description_t *description);
-+
-+void
-+mongoc_server_description_cleanup (mongoc_server_description_t *sd);
-+
-+void
-+mongoc_server_description_reset (mongoc_server_description_t *sd);
-+
-+void
-+mongoc_server_description_set_state (mongoc_server_description_t *description,
-+ mongoc_server_description_type_t type);
-+void
-+mongoc_server_description_set_set_version (mongoc_server_description_t *description,
-+ int64_t set_version);
-+void
-+mongoc_server_description_set_election_id (mongoc_server_description_t *description,
-+ const bson_oid_t *election_id);
-+void
-+mongoc_server_description_update_rtt (mongoc_server_description_t *server,
-+ int64_t new_time);
-+
-+void
-+mongoc_server_description_handle_ismaster (
-+ mongoc_server_description_t *sd,
-+ const bson_t *reply,
-+ int64_t rtt_msec,
-+ bson_error_t *error);
-+
-+size_t
-+mongoc_server_description_filter_eligible (
-+ mongoc_server_description_t **descriptions,
-+ size_t description_len,
-+ const mongoc_read_prefs_t *read_prefs);
-+
-+#endif
-diff --git a/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-server-description.c b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-server-description.c
-new file mode 100644
-index 0000000..2341e4f
---- /dev/null
-+++ b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-server-description.c
-@@ -0,0 +1,651 @@
-+/*
-+ * 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-host-list.h"
-+#include "mongoc-host-list-private.h"
-+#include "mongoc-read-prefs.h"
-+#include "mongoc-server-description-private.h"
-+#include "mongoc-trace.h"
-+#include "mongoc-uri.h"
-+#include "mongoc-util-private.h"
-+
-+#include <stdio.h>
-+
-+#define ALPHA 0.2
-+
-+
-+static uint8_t kMongocEmptyBson[] = { 5, 0, 0, 0, 0 };
-+
-+static bson_oid_t kObjectIdZero = { {0} };
-+
-+/* Destroy allocated resources within @description, but don't free it */
-+void
-+mongoc_server_description_cleanup (mongoc_server_description_t *sd)
-+{
-+ BSON_ASSERT(sd);
-+
-+ bson_destroy (&sd->last_is_master);
-+}
-+
-+/* Reset fields inside this sd, but keep same id, host information, and RTT,
-+ and leave ismaster in empty inited state */
-+void
-+mongoc_server_description_reset (mongoc_server_description_t *sd)
-+{
-+ BSON_ASSERT(sd);
-+
-+ /* set other fields to default or empty states. election_id is zeroed. */
-+ memset (&sd->set_name, 0, sizeof (*sd) - ((char*)&sd->set_name - (char*)sd));
-+ sd->set_name = NULL;
-+ sd->type = MONGOC_SERVER_UNKNOWN;
-+
-+ sd->min_wire_version = MONGOC_DEFAULT_WIRE_VERSION;
-+ sd->max_wire_version = MONGOC_DEFAULT_WIRE_VERSION;
-+ sd->max_msg_size = MONGOC_DEFAULT_MAX_MSG_SIZE;
-+ sd->max_bson_obj_size = MONGOC_DEFAULT_BSON_OBJ_SIZE;
-+ sd->max_write_batch_size = MONGOC_DEFAULT_WRITE_BATCH_SIZE;
-+
-+ /* always leave last ismaster in an init-ed state until we destroy sd */
-+ bson_destroy (&sd->last_is_master);
-+ bson_init (&sd->last_is_master);
-+ sd->has_is_master = false;
-+}
-+
-+/*
-+ *--------------------------------------------------------------------------
-+ *
-+ * mongoc_server_description_init --
-+ *
-+ * Initialize a new server_description_t.
-+ *
-+ * Returns:
-+ * None.
-+ *
-+ * Side effects:
-+ * None.
-+ *
-+ *--------------------------------------------------------------------------
-+ */
-+void
-+mongoc_server_description_init (mongoc_server_description_t *sd,
-+ const char *address,
-+ uint32_t id)
-+{
-+ ENTRY;
-+
-+ BSON_ASSERT (sd);
-+ BSON_ASSERT (address);
-+
-+ memset (sd, 0, sizeof *sd);
-+
-+ sd->id = id;
-+ sd->type = MONGOC_SERVER_UNKNOWN;
-+ sd->round_trip_time = -1;
-+
-+ sd->set_name = NULL;
-+ sd->set_version = MONGOC_NO_SET_VERSION;
-+ sd->current_primary = NULL;
-+
-+ if (!_mongoc_host_list_from_string(&sd->host, address)) {
-+ MONGOC_WARNING("Failed to parse uri for %s", address);
-+ return;
-+ }
-+
-+ sd->connection_address = sd->host.host_and_port;
-+
-+ sd->me = NULL;
-+ sd->min_wire_version = MONGOC_DEFAULT_WIRE_VERSION;
-+ sd->max_wire_version = MONGOC_DEFAULT_WIRE_VERSION;
-+ sd->max_msg_size = MONGOC_DEFAULT_MAX_MSG_SIZE;
-+ sd->max_bson_obj_size = MONGOC_DEFAULT_BSON_OBJ_SIZE;
-+ sd->max_write_batch_size = MONGOC_DEFAULT_WRITE_BATCH_SIZE;
-+
-+ bson_init_static (&sd->hosts, kMongocEmptyBson, sizeof (kMongocEmptyBson));
-+ bson_init_static (&sd->passives, kMongocEmptyBson, sizeof (kMongocEmptyBson));
-+ bson_init_static (&sd->arbiters, kMongocEmptyBson, sizeof (kMongocEmptyBson));
-+ bson_init_static (&sd->tags, kMongocEmptyBson, sizeof (kMongocEmptyBson));
-+
-+ bson_init (&sd->last_is_master);
-+
-+ EXIT;
-+}
-+
-+/*
-+ *--------------------------------------------------------------------------
-+ *
-+ * mongoc_server_description_destroy --
-+ *
-+ * Destroy allocated resources within @description and free
-+ * @description.
-+ *
-+ * Returns:
-+ * None.
-+ *
-+ * Side effects:
-+ * None.
-+ *
-+ *--------------------------------------------------------------------------
-+ */
-+void
-+mongoc_server_description_destroy (mongoc_server_description_t *description)
-+{
-+ ENTRY;
-+
-+ mongoc_server_description_cleanup(description);
-+
-+ bson_free(description);
-+
-+ EXIT;
-+}
-+
-+/*
-+ *--------------------------------------------------------------------------
-+ *
-+ * mongoc_server_description_has_rs_member --
-+ *
-+ * Return true if this address is included in server's list of rs
-+ * members, false otherwise.
-+ *
-+ * Returns:
-+ * true, false
-+ *
-+ * Side effects:
-+ * None
-+ *
-+ *--------------------------------------------------------------------------
-+ */
-+bool
-+mongoc_server_description_has_rs_member(mongoc_server_description_t *server,
-+ const char *address)
-+{
-+ bson_iter_t member_iter;
-+ const bson_t *rs_members[3];
-+ int i;
-+
-+ if (server->type != MONGOC_SERVER_UNKNOWN) {
-+ rs_members[0] = &server->hosts;
-+ rs_members[1] = &server->arbiters;
-+ rs_members[2] = &server->passives;
-+
-+ for (i = 0; i < 3; i++) {
-+ bson_iter_init (&member_iter, rs_members[i]);
-+
-+ while (bson_iter_next (&member_iter)) {
-+ if (strcasecmp (address, bson_iter_utf8 (&member_iter, NULL)) == 0) {
-+ return true;
-+ }
-+ }
-+ }
-+ }
-+
-+ return false;
-+}
-+
-+/*
-+ *--------------------------------------------------------------------------
-+ *
-+ * mongoc_server_description_has_set_version --
-+ *
-+ * Did this server's ismaster response have a "setVersion" field?
-+ *
-+ * Returns:
-+ * True if the server description's setVersion is set.
-+ *
-+ *--------------------------------------------------------------------------
-+ */
-+
-+bool
-+mongoc_server_description_has_set_version (mongoc_server_description_t *description)
-+{
-+ return description->set_version != MONGOC_NO_SET_VERSION;
-+}
-+
-+/*
-+ *--------------------------------------------------------------------------
-+ *
-+ * mongoc_server_description_has_election_id --
-+ *
-+ * Did this server's ismaster response have an "electionId" field?
-+ *
-+ * Returns:
-+ * True if the server description's electionId is set.
-+ *
-+ *--------------------------------------------------------------------------
-+ */
-+
-+bool
-+mongoc_server_description_has_election_id (mongoc_server_description_t *description)
-+{
-+ return 0 != bson_oid_compare (&description->election_id, &kObjectIdZero);
-+}
-+
-+/*
-+ *--------------------------------------------------------------------------
-+ *
-+ * mongoc_server_description_id --
-+ *
-+ * Get the id of this server.
-+ *
-+ * Returns:
-+ * Server's id.
-+ *
-+ *--------------------------------------------------------------------------
-+ */
-+
-+uint32_t
-+mongoc_server_description_id (mongoc_server_description_t *description)
-+{
-+ return description->id;
-+}
-+
-+/*
-+ *--------------------------------------------------------------------------
-+ *
-+ * mongoc_server_description_host --
-+ *
-+ * Return a reference to the host associated with this server description.
-+ *
-+ * Returns:
-+ * A mongoc_host_list_t *, this server description's host.
-+ *
-+ *--------------------------------------------------------------------------
-+ */
-+
-+mongoc_host_list_t *
-+mongoc_server_description_host (mongoc_server_description_t *description)
-+{
-+ return &description->host;
-+}
-+
-+/*
-+ *--------------------------------------------------------------------------
-+ *
-+ * mongoc_server_description_set_state --
-+ *
-+ * Set the server description's server type.
-+ *
-+ *--------------------------------------------------------------------------
-+ */
-+void
-+mongoc_server_description_set_state (mongoc_server_description_t *description,
-+ mongoc_server_description_type_t type)
-+{
-+ description->type = type;
-+}
-+
-+
-+/*
-+ *--------------------------------------------------------------------------
-+ *
-+ * mongoc_server_description_set_set_version --
-+ *
-+ * Set the replica set version of this server.
-+ *
-+ * Side effects:
-+ * None.
-+ *
-+ *--------------------------------------------------------------------------
-+ */
-+void
-+mongoc_server_description_set_set_version (mongoc_server_description_t *description,
-+ int64_t set_version)
-+{
-+ description->set_version = set_version;
-+}
-+
-+/*
-+ *--------------------------------------------------------------------------
-+ *
-+ * mongoc_server_description_set_election_id --
-+ *
-+ * Set the election_id of this server. Copies the given ObjectId or,
-+ * if it is NULL, zeroes description's election_id.
-+ *
-+ * Side effects:
-+ * None.
-+ *
-+ *--------------------------------------------------------------------------
-+ */
-+void
-+mongoc_server_description_set_election_id (mongoc_server_description_t *description,
-+ const bson_oid_t *election_id)
-+{
-+ if (election_id) {
-+ bson_oid_copy_unsafe (election_id, &description->election_id);
-+ } else {
-+ bson_oid_copy_unsafe (&kObjectIdZero, &description->election_id);
-+ }
-+}
-+
-+
-+/*
-+ *-------------------------------------------------------------------------
-+ *
-+ * mongoc_server_description_update_rtt --
-+ *
-+ * Calculate this server's rtt calculation using an exponentially-
-+ * weighted moving average formula.
-+ *
-+ * Side effects:
-+ * None.
-+ *
-+ *-------------------------------------------------------------------------
-+ */
-+void
-+mongoc_server_description_update_rtt (mongoc_server_description_t *server,
-+ int64_t new_time)
-+{
-+ if (server->round_trip_time == -1) {
-+ server->round_trip_time = new_time;
-+ } else {
-+ server->round_trip_time = ALPHA * new_time + (1 - ALPHA) * server->round_trip_time;
-+ }
-+}
-+
-+/*
-+ *-------------------------------------------------------------------------
-+ *
-+ * Called during SDAM, from topology description's ismaster handler.
-+ *
-+ *-------------------------------------------------------------------------
-+ */
-+
-+void
-+mongoc_server_description_handle_ismaster (
-+ mongoc_server_description_t *sd,
-+ const bson_t *ismaster_response,
-+ int64_t rtt_msec,
-+ bson_error_t *error)
-+{
-+ bson_iter_t iter;
-+ bool is_master = false;
-+ bool is_shard = false;
-+ bool is_secondary = false;
-+ bool is_arbiter = false;
-+ bool is_replicaset = false;
-+ bool is_hidden = false;
-+ const uint8_t *bytes;
-+ uint32_t len;
-+ int num_keys = 0;
-+ ENTRY;
-+
-+ BSON_ASSERT (sd);
-+
-+ mongoc_server_description_reset (sd);
-+ if (!ismaster_response) {
-+ EXIT;
-+ }
-+
-+ bson_destroy (&sd->last_is_master);
-+ bson_copy_to (ismaster_response, &sd->last_is_master);
-+ sd->has_is_master = true;
-+
-+ bson_iter_init (&iter, &sd->last_is_master);
-+
-+ while (bson_iter_next (&iter)) {
-+ num_keys++;
-+ if (strcmp ("ok", bson_iter_key (&iter)) == 0) {
-+ /* ismaster responses never have ok: 0, but spec requires we check */
-+ if (! bson_iter_as_bool (&iter)) goto failure;
-+ } else if (strcmp ("ismaster", bson_iter_key (&iter)) == 0) {
-+ if (! BSON_ITER_HOLDS_BOOL (&iter)) goto failure;
-+ is_master = bson_iter_bool (&iter);
-+ } else if (strcmp ("me", bson_iter_key (&iter)) == 0) {
-+ if (! BSON_ITER_HOLDS_UTF8 (&iter)) goto failure;
-+ sd->me = bson_iter_utf8 (&iter, NULL);
-+ } else if (strcmp ("maxMessageSizeBytes", bson_iter_key (&iter)) == 0) {
-+ if (! BSON_ITER_HOLDS_INT32 (&iter)) goto failure;
-+ sd->max_msg_size = bson_iter_int32 (&iter);
-+ } else if (strcmp ("maxBsonObjectSize", bson_iter_key (&iter)) == 0) {
-+ if (! BSON_ITER_HOLDS_INT32 (&iter)) goto failure;
-+ sd->max_bson_obj_size = bson_iter_int32 (&iter);
-+ } else if (strcmp ("maxWriteBatchSize", bson_iter_key (&iter)) == 0) {
-+ if (! BSON_ITER_HOLDS_INT32 (&iter)) goto failure;
-+ sd->max_write_batch_size = bson_iter_int32 (&iter);
-+ } else if (strcmp ("minWireVersion", bson_iter_key (&iter)) == 0) {
-+ if (! BSON_ITER_HOLDS_INT32 (&iter)) goto failure;
-+ sd->min_wire_version = bson_iter_int32 (&iter);
-+ } else if (strcmp ("maxWireVersion", bson_iter_key (&iter)) == 0) {
-+ if (! BSON_ITER_HOLDS_INT32 (&iter)) goto failure;
-+ sd->max_wire_version = bson_iter_int32 (&iter);
-+ } else if (strcmp ("msg", bson_iter_key (&iter)) == 0) {
-+ if (! BSON_ITER_HOLDS_UTF8 (&iter)) goto failure;
-+ is_shard = !!bson_iter_utf8 (&iter, NULL);
-+ } else if (strcmp ("setName", bson_iter_key (&iter)) == 0) {
-+ if (! BSON_ITER_HOLDS_UTF8 (&iter)) goto failure;
-+ sd->set_name = bson_iter_utf8 (&iter, NULL);
-+ } else if (strcmp ("setVersion", bson_iter_key (&iter)) == 0) {
-+ mongoc_server_description_set_set_version (sd,
-+ bson_iter_as_int64 (&iter));
-+ } else if (strcmp ("electionId", bson_iter_key (&iter)) == 0) {
-+ if (! BSON_ITER_HOLDS_OID (&iter)) goto failure;
-+ mongoc_server_description_set_election_id (sd, bson_iter_oid (&iter));
-+ } else if (strcmp ("secondary", bson_iter_key (&iter)) == 0) {
-+ if (! BSON_ITER_HOLDS_BOOL (&iter)) goto failure;
-+ is_secondary = bson_iter_bool (&iter);
-+ } else if (strcmp ("hosts", bson_iter_key (&iter)) == 0) {
-+ if (! BSON_ITER_HOLDS_ARRAY (&iter)) goto failure;
-+ bson_iter_array (&iter, &len, &bytes);
-+ bson_init_static (&sd->hosts, bytes, len);
-+ } else if (strcmp ("passives", bson_iter_key (&iter)) == 0) {
-+ if (! BSON_ITER_HOLDS_ARRAY (&iter)) goto failure;
-+ bson_iter_array (&iter, &len, &bytes);
-+ bson_init_static (&sd->passives, bytes, len);
-+ } else if (strcmp ("arbiters", bson_iter_key (&iter)) == 0) {
-+ if (! BSON_ITER_HOLDS_ARRAY (&iter)) goto failure;
-+ bson_iter_array (&iter, &len, &bytes);
-+ bson_init_static (&sd->arbiters, bytes, len);
-+ } else if (strcmp ("primary", bson_iter_key (&iter)) == 0) {
-+ if (! BSON_ITER_HOLDS_UTF8 (&iter)) goto failure;
-+ sd->current_primary = bson_iter_utf8 (&iter, NULL);
-+ } else if (strcmp ("arbiterOnly", bson_iter_key (&iter)) == 0) {
-+ if (! BSON_ITER_HOLDS_BOOL (&iter)) goto failure;
-+ is_arbiter = bson_iter_bool (&iter);
-+ } else if (strcmp ("isreplicaset", bson_iter_key (&iter)) == 0) {
-+ if (! BSON_ITER_HOLDS_BOOL (&iter)) goto failure;
-+ is_replicaset = bson_iter_bool (&iter);
-+ } else if (strcmp ("tags", bson_iter_key (&iter)) == 0) {
-+ if (! BSON_ITER_HOLDS_DOCUMENT (&iter)) goto failure;
-+ bson_iter_document (&iter, &len, &bytes);
-+ bson_init_static (&sd->tags, bytes, len);
-+ } else if (strcmp ("hidden", bson_iter_key (&iter)) == 0) {
-+ is_hidden = bson_iter_bool (&iter);
-+ }
-+ }
-+
-+ if (is_shard) {
-+ sd->type = MONGOC_SERVER_MONGOS;
-+ } else if (sd->set_name) {
-+ if (is_hidden) {
-+ sd->type = MONGOC_SERVER_RS_OTHER;
-+ } else if (is_master) {
-+ sd->type = MONGOC_SERVER_RS_PRIMARY;
-+ } else if (is_secondary) {
-+ sd->type = MONGOC_SERVER_RS_SECONDARY;
-+ } else if (is_arbiter) {
-+ sd->type = MONGOC_SERVER_RS_ARBITER;
-+ } else {
-+ sd->type = MONGOC_SERVER_RS_OTHER;
-+ }
-+ } else if (is_replicaset) {
-+ sd->type = MONGOC_SERVER_RS_GHOST;
-+ } else if (num_keys > 0) {
-+ sd->type = MONGOC_SERVER_STANDALONE;
-+ } else {
-+ sd->type = MONGOC_SERVER_UNKNOWN;
-+ }
-+
-+ mongoc_server_description_update_rtt(sd, rtt_msec);
-+
-+ EXIT;
-+
-+failure:
-+ sd->type = MONGOC_SERVER_UNKNOWN;
-+ sd->round_trip_time = -1;
-+
-+ EXIT;
-+}
-+
-+/*
-+ *-------------------------------------------------------------------------
-+ *
-+ * mongoc_server_description_new_copy --
-+ *
-+ * A copy of a server description that you must destroy, or NULL.
-+ *
-+ *-------------------------------------------------------------------------
-+ */
-+mongoc_server_description_t *
-+mongoc_server_description_new_copy (const mongoc_server_description_t *description)
-+{
-+ mongoc_server_description_t *copy;
-+
-+ if (!description) {
-+ return NULL;
-+ }
-+
-+ copy = (mongoc_server_description_t *)bson_malloc0(sizeof (*copy));
-+
-+ copy->id = description->id;
-+ memcpy (&copy->host, &description->host, sizeof (copy->host));
-+ copy->round_trip_time = -1;
-+
-+ copy->connection_address = copy->host.host_and_port;
-+
-+ /* wait for handle_ismaster to fill these in properly */
-+ copy->has_is_master = false;
-+ copy->set_version = MONGOC_NO_SET_VERSION;
-+ bson_init_static (&copy->hosts, kMongocEmptyBson, sizeof (kMongocEmptyBson));
-+ bson_init_static (&copy->passives, kMongocEmptyBson, sizeof (kMongocEmptyBson));
-+ bson_init_static (&copy->arbiters, kMongocEmptyBson, sizeof (kMongocEmptyBson));
-+ bson_init_static (&copy->tags, kMongocEmptyBson, sizeof (kMongocEmptyBson));
-+
-+ bson_init (&copy->last_is_master);
-+
-+ if (description->has_is_master) {
-+ mongoc_server_description_handle_ismaster (copy, &description->last_is_master,
-+ description->round_trip_time, NULL);
-+ }
-+ /* Preserve the error */
-+ memcpy (&copy->error, &description->error, sizeof copy->error);
-+ return copy;
-+}
-+
-+/*
-+ *-------------------------------------------------------------------------
-+ *
-+ * mongoc_server_description_filter_eligible --
-+ *
-+ * Given a set of server descriptions, determine which are eligible
-+ * as per the Server Selection spec. Determines the number of
-+ * eligible servers, and sets any servers that are NOT eligible to
-+ * NULL in the descriptions set.
-+ *
-+ * Returns:
-+ * Number of eligible servers found.
-+ *
-+ *-------------------------------------------------------------------------
-+ */
-+
-+size_t
-+mongoc_server_description_filter_eligible (
-+ mongoc_server_description_t **descriptions,
-+ size_t description_len,
-+ const mongoc_read_prefs_t *read_prefs)
-+{
-+ const bson_t *rp_tags;
-+ bson_iter_t rp_tagset_iter;
-+ bson_iter_t rp_iter;
-+ bson_iter_t sd_iter;
-+ uint32_t rp_len;
-+ uint32_t sd_len;
-+ const char *rp_val;
-+ const char *sd_val;
-+ bool *sd_matched = NULL;
-+ size_t found;
-+ size_t i;
-+ size_t rval = 0;
-+
-+ if (!read_prefs) {
-+ /* NULL read_prefs is PRIMARY, no tags to filter by */
-+ return description_len;
-+ }
-+
-+ rp_tags = mongoc_read_prefs_get_tags (read_prefs);
-+
-+ if (bson_count_keys (rp_tags) == 0) {
-+ return description_len;
-+ }
-+
-+ sd_matched = (bool *) bson_malloc0 (sizeof(bool) * description_len);
-+
-+ bson_iter_init (&rp_tagset_iter, rp_tags);
-+
-+ /* for each read preference tagset */
-+ while (bson_iter_next (&rp_tagset_iter)) {
-+ found = description_len;
-+
-+ for (i = 0; i < description_len; i++) {
-+ sd_matched[i] = true;
-+
-+ bson_iter_recurse (&rp_tagset_iter, &rp_iter);
-+
-+ while (bson_iter_next (&rp_iter)) {
-+ /* TODO: can we have non-utf8 tags? */
-+ rp_val = bson_iter_utf8 (&rp_iter, &rp_len);
-+
-+ if (bson_iter_init_find (&sd_iter, &descriptions[i]->tags, bson_iter_key (&rp_iter))) {
-+
-+ /* If the server description has that key */
-+ sd_val = bson_iter_utf8 (&sd_iter, &sd_len);
-+
-+ if (! (sd_len == rp_len && (0 == memcmp(rp_val, sd_val, rp_len)))) {
-+ /* If the key value doesn't match, no match */
-+ sd_matched[i] = false;
-+ found--;
-+ }
-+ } else {
-+ /* If the server description doesn't have that key, no match */
-+ sd_matched[i] = false;
-+ found--;
-+ break;
-+ }
-+ }
-+ }
-+
-+ if (found) {
-+ for (i = 0; i < description_len; i++) {
-+ if (! sd_matched[i]) {
-+ descriptions[i] = NULL;
-+ }
-+ }
-+
-+ rval = found;
-+ goto CLEANUP;
-+ }
-+ }
-+
-+ for (i = 0; i < description_len; i++) {
-+ if (! sd_matched[i]) {
-+ descriptions[i] = NULL;
-+ }
-+ }
-+
-+CLEANUP:
-+ bson_free (sd_matched);
-+
-+ return rval;
-+}
-diff --git a/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-server-stream-private.h b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-server-stream-private.h
-new file mode 100644
-index 0000000..0a2cde3
---- /dev/null
-+++ b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-server-stream-private.h
-@@ -0,0 +1,62 @@
-+/*
-+ * 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.
-+ */
-+
-+#ifndef MONGOC_SERVER_STREAM_H
-+#define MONGOC_SERVER_STREAM_H
-+
-+#include "mongoc-config.h"
-+
-+#if !defined (MONGOC_I_AM_A_DRIVER) && !defined (MONGOC_COMPILATION)
-+#error "Only <mongoc.h> can be included directly."
-+#endif
-+
-+#include <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 */
-+ mongoc_stream_t *stream; /* borrowed */
-+} mongoc_server_stream_t;
-+
-+
-+mongoc_server_stream_t *
-+mongoc_server_stream_new (mongoc_topology_description_type_t topology_type,
-+ 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.1.4/src/libmongoc-priv/src/mongoc/mongoc-set-private.h b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-set-private.h
-new file mode 100644
-index 0000000..896dfe3
---- /dev/null
-+++ b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-set-private.h
-@@ -0,0 +1,101 @@
-+/*
-+ * 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.
-+ */
-+
-+#ifndef MONGOC_SET_PRIVATE_H
-+#define MONGOC_SET_PRIVATE_H
-+
-+#if !defined (MONGOC_I_AM_A_DRIVER) && !defined (MONGOC_COMPILATION)
-+#error "Only <mongoc.h> can be included directly."
-+#endif
-+
-+#include <bson.h>
-+
-+BSON_BEGIN_DECLS
-+
-+typedef void (*mongoc_set_item_dtor)(void *item,
-+ void *ctx);
-+
-+/* return true to continue iteration, false to stop */
-+typedef bool (*mongoc_set_for_each_cb_t)(void *item,
-+ void *ctx);
-+
-+typedef struct
-+{
-+ uint32_t id;
-+ void *item;
-+} mongoc_set_item_t;
-+
-+typedef struct
-+{
-+ mongoc_set_item_t *items;
-+ size_t items_len;
-+ size_t items_allocated;
-+ mongoc_set_item_dtor dtor;
-+ void *dtor_ctx;
-+} mongoc_set_t;
-+
-+mongoc_set_t *
-+mongoc_set_new (size_t nitems,
-+ mongoc_set_item_dtor dtor,
-+ void *dtor_ctx);
-+
-+void
-+mongoc_set_add (mongoc_set_t *set,
-+ uint32_t id,
-+ void *item);
-+
-+void
-+mongoc_set_rm (mongoc_set_t *set,
-+ uint32_t id);
-+
-+void *
-+mongoc_set_get (mongoc_set_t *set,
-+ uint32_t id);
-+
-+void *
-+mongoc_set_get_item (mongoc_set_t *set,
-+ int idx);
-+
-+void
-+mongoc_set_destroy (mongoc_set_t *set);
-+
-+/* loops over the set safe-ish.
-+ *
-+ * Caveats:
-+ * - you can add items at any iteration
-+ * - if you remove elements other than the one you're currently looking at,
-+ * you may see it later in the iteration
-+ */
-+void
-+mongoc_set_for_each (mongoc_set_t *set,
-+ mongoc_set_for_each_cb_t cb,
-+ void *ctx);
-+
-+/* first item in set for which "cb" returns true */
-+void *
-+mongoc_set_find_item (mongoc_set_t *set,
-+ mongoc_set_for_each_cb_t cb,
-+ void *ctx);
-+
-+/* id of first item in set for which "cb" returns true, or 0. */
-+uint32_t
-+mongoc_set_find_id (mongoc_set_t *set,
-+ mongoc_set_for_each_cb_t cb,
-+ void *ctx);
-+
-+BSON_END_DECLS
-+
-+#endif /* MONGOC_SET_PRIVATE_H */
-diff --git a/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-set.c b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-set.c
-new file mode 100644
-index 0000000..1c42d93
---- /dev/null
-+++ b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-set.c
-@@ -0,0 +1,217 @@
-+/*
-+ * 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.h>
-+
-+#include "mongoc-set-private.h"
-+
-+#undef MONGOC_LOG_DOMAIN
-+#define MONGOC_LOG_DOMAIN "set"
-+
-+mongoc_set_t *
-+mongoc_set_new (size_t nitems,
-+ mongoc_set_item_dtor dtor,
-+ void *dtor_ctx)
-+{
-+ mongoc_set_t *set = (mongoc_set_t *)bson_malloc (sizeof (*set));
-+
-+ set->items_allocated = nitems;
-+ set->items = (mongoc_set_item_t *)bson_malloc (sizeof (*set->items) * set->items_allocated);
-+ set->items_len = 0;
-+
-+ set->dtor = dtor;
-+ set->dtor_ctx = dtor_ctx;
-+
-+ return set;
-+}
-+
-+static int
-+mongoc_set_id_cmp (const void *a_,
-+ const void *b_)
-+{
-+ mongoc_set_item_t *a = (mongoc_set_item_t *)a_;
-+ mongoc_set_item_t *b = (mongoc_set_item_t *)b_;
-+
-+ if (a->id == b->id) {
-+ return 0;
-+ }
-+
-+ return a->id < b->id ? -1 : 1;
-+}
-+
-+void
-+mongoc_set_add (mongoc_set_t *set,
-+ uint32_t id,
-+ void *item)
-+{
-+ if (set->items_len >= set->items_allocated) {
-+ set->items_allocated *= 2;
-+ set->items = (mongoc_set_item_t *)bson_realloc (set->items,
-+ sizeof (*set->items) * set->items_allocated);
-+ }
-+
-+ set->items[set->items_len].id = id;
-+ set->items[set->items_len].item = item;
-+
-+ set->items_len++;
-+
-+ if (set->items_len > 1 && set->items[set->items_len - 2].id > id) {
-+ qsort (set->items, set->items_len, sizeof (*set->items),
-+ mongoc_set_id_cmp);
-+ }
-+}
-+
-+void
-+mongoc_set_rm (mongoc_set_t *set,
-+ uint32_t id)
-+{
-+ mongoc_set_item_t *ptr;
-+ mongoc_set_item_t key;
-+ int i;
-+
-+ key.id = id;
-+
-+ ptr = (mongoc_set_item_t *)bsearch (&key, set->items, set->items_len, sizeof (key),
-+ mongoc_set_id_cmp);
-+
-+ if (ptr) {
-+ set->dtor(ptr->item, set->dtor_ctx);
-+
-+ i = ptr - set->items;
-+
-+ if (i != set->items_len - 1) {
-+ memmove (set->items + i, set->items + i + 1,
-+ (set->items_len - (i + 1)) * sizeof (key));
-+ }
-+
-+ set->items_len--;
-+ }
-+}
-+
-+void *
-+mongoc_set_get (mongoc_set_t *set,
-+ uint32_t id)
-+{
-+ mongoc_set_item_t *ptr;
-+ mongoc_set_item_t key;
-+
-+ key.id = id;
-+
-+ ptr = (mongoc_set_item_t *)bsearch (&key, set->items, set->items_len, sizeof (key),
-+ mongoc_set_id_cmp);
-+
-+ return ptr ? ptr->item : NULL;
-+}
-+
-+void *
-+mongoc_set_get_item (mongoc_set_t *set,
-+ int idx)
-+{
-+ BSON_ASSERT (set);
-+ BSON_ASSERT (idx < set->items_len);
-+
-+ return set->items[idx].item;
-+}
-+
-+
-+void
-+mongoc_set_destroy (mongoc_set_t *set)
-+{
-+ int i;
-+
-+ for (i = 0; i < set->items_len; i++) {
-+ set->dtor(set->items[i].item, set->dtor_ctx);
-+ }
-+
-+ bson_free (set->items);
-+ bson_free (set);
-+}
-+
-+void
-+mongoc_set_for_each (mongoc_set_t *set,
-+ mongoc_set_for_each_cb_t cb,
-+ void *ctx)
-+{
-+ size_t i;
-+ mongoc_set_item_t *old_set;
-+ size_t items_len;
-+
-+ items_len = set->items_len;
-+
-+ old_set = (mongoc_set_item_t *)bson_malloc (sizeof (*old_set) * items_len);
-+ memcpy (old_set, set->items, sizeof (*old_set) * items_len);
-+
-+ for (i = 0; i < items_len; i++) {
-+ if (!cb (old_set[i].item, ctx)) {
-+ break;
-+ }
-+ }
-+
-+ bson_free (old_set);
-+}
-+
-+
-+static mongoc_set_item_t *
-+_mongoc_set_find (mongoc_set_t *set,
-+ mongoc_set_for_each_cb_t cb,
-+ void *ctx)
-+{
-+ size_t i;
-+ size_t items_len;
-+ mongoc_set_item_t *item;
-+
-+ items_len = set->items_len;
-+
-+ for (i = 0; i < items_len; i++) {
-+ item = &set->items[i];
-+ if (cb (item->item, ctx)) {
-+ return item;
-+ }
-+ }
-+
-+ return NULL;
-+}
-+
-+
-+void *
-+mongoc_set_find_item (mongoc_set_t *set,
-+ mongoc_set_for_each_cb_t cb,
-+ void *ctx)
-+{
-+ mongoc_set_item_t *item;
-+
-+ if ((item = _mongoc_set_find (set, cb, ctx))) {
-+ return item->item;
-+ }
-+
-+ return NULL;
-+}
-+
-+
-+uint32_t
-+mongoc_set_find_id (mongoc_set_t *set,
-+ mongoc_set_for_each_cb_t cb,
-+ void *ctx)
-+{
-+ mongoc_set_item_t *item;
-+
-+ if ((item = _mongoc_set_find (set, cb, ctx))) {
-+ return item->id;
-+ }
-+
-+ return 0;
-+}
-diff --git a/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-thread-private.h b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-thread-private.h
-new file mode 100644
-index 0000000..b71d139
---- /dev/null
-+++ b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-thread-private.h
-@@ -0,0 +1,126 @@
-+/*
-+ * 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.
-+ */
-+
-+#ifndef MONGOC_THREAD_PRIVATE_H
-+#define MONGOC_THREAD_PRIVATE_H
-+
-+#if !defined (MONGOC_I_AM_A_DRIVER) && !defined (MONGOC_COMPILATION)
-+#error "Only <mongoc.h> can be included directly."
-+#endif
-+
-+#include <bson.h>
-+
-+#include "mongoc-config.h"
-+
-+
-+#if !defined(_WIN32)
-+# include <pthread.h>
-+# define MONGOC_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
-+# define mongoc_cond_t pthread_cond_t
-+# define mongoc_cond_broadcast pthread_cond_broadcast
-+# define mongoc_cond_init(_n) pthread_cond_init((_n), NULL)
-+# define mongoc_cond_wait pthread_cond_wait
-+# define mongoc_cond_signal pthread_cond_signal
-+static BSON_INLINE int
-+mongoc_cond_timedwait (pthread_cond_t *cond,
-+ pthread_mutex_t *mutex,
-+ int64_t timeout_msec)
-+{
-+ struct timespec to;
-+ struct timeval tv;
-+ int64_t msec;
-+
-+ bson_gettimeofday (&tv);
-+
-+ msec = ((int64_t)tv.tv_sec * 1000) + (tv.tv_usec / 1000) + timeout_msec;
-+
-+ to.tv_sec = msec / 1000;
-+ to.tv_nsec = (msec % 1000) * 1000 * 1000;
-+
-+ return pthread_cond_timedwait (cond, mutex, &to);
-+}
-+# define mongoc_cond_destroy pthread_cond_destroy
-+# define mongoc_mutex_t pthread_mutex_t
-+# define mongoc_mutex_init(_n) pthread_mutex_init((_n), NULL)
-+# define mongoc_mutex_lock pthread_mutex_lock
-+# define mongoc_mutex_unlock pthread_mutex_unlock
-+# define mongoc_mutex_destroy pthread_mutex_destroy
-+# define mongoc_thread_t pthread_t
-+# define mongoc_thread_create(_t,_f,_d) pthread_create((_t), NULL, (_f), (_d))
-+# define mongoc_thread_join(_n) pthread_join((_n), NULL)
-+# define mongoc_once_t pthread_once_t
-+# define mongoc_once pthread_once
-+# define MONGOC_ONCE_FUN(n) void n(void)
-+# define MONGOC_ONCE_RETURN return
-+# ifdef _PTHREAD_ONCE_INIT_NEEDS_BRACES
-+# define MONGOC_ONCE_INIT {PTHREAD_ONCE_INIT}
-+# else
-+# define MONGOC_ONCE_INIT PTHREAD_ONCE_INIT
-+# endif
-+#else
-+# define mongoc_thread_t HANDLE
-+static BSON_INLINE int
-+mongoc_thread_create (mongoc_thread_t *thread,
-+ void *(*cb)(void *),
-+ void *arg)
-+{
-+ *thread = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE) cb, arg, 0, NULL);
-+ return 0;
-+}
-+# define mongoc_thread_join(_n) WaitForSingleObject((_n), INFINITE)
-+# define mongoc_mutex_t CRITICAL_SECTION
-+# define mongoc_mutex_init InitializeCriticalSection
-+# define mongoc_mutex_lock EnterCriticalSection
-+# define mongoc_mutex_unlock LeaveCriticalSection
-+# define mongoc_mutex_destroy DeleteCriticalSection
-+# define mongoc_cond_t CONDITION_VARIABLE
-+# define mongoc_cond_init InitializeConditionVariable
-+# define mongoc_cond_wait(_c, _m) mongoc_cond_timedwait((_c), (_m), INFINITE)
-+static BSON_INLINE int
-+mongoc_cond_timedwait (mongoc_cond_t *cond,
-+ mongoc_mutex_t *mutex,
-+ int64_t timeout_msec)
-+{
-+ int r;
-+
-+ if (SleepConditionVariableCS(cond, mutex, timeout_msec)) {
-+ return 0;
-+ } else {
-+ r = GetLastError();
-+
-+ if (r == WAIT_TIMEOUT || r == ERROR_TIMEOUT) {
-+ return WSAETIMEDOUT;
-+ } else {
-+ return EINVAL;
-+ }
-+ }
-+}
-+# define mongoc_cond_signal WakeConditionVariable
-+# define mongoc_cond_broadcast WakeAllConditionVariable
-+static BSON_INLINE int
-+mongoc_cond_destroy (mongoc_cond_t *_ignored)
-+{
-+ return 0;
-+}
-+# define mongoc_once_t INIT_ONCE
-+# define MONGOC_ONCE_INIT INIT_ONCE_STATIC_INIT
-+# define mongoc_once(o, c) InitOnceExecuteOnce(o, c, NULL, NULL)
-+# define MONGOC_ONCE_FUN(n) BOOL CALLBACK n(PINIT_ONCE _ignored_a, PVOID _ignored_b, PVOID *_ignored_c)
-+# define MONGOC_ONCE_RETURN return true
-+#endif
-+
-+
-+#endif /* MONGOC_THREAD_PRIVATE_H */
-diff --git a/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-topology-description-private.h b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-topology-description-private.h
-new file mode 100644
-index 0000000..e6c72fb
---- /dev/null
-+++ b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-topology-description-private.h
-@@ -0,0 +1,98 @@
-+/*
-+ * 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.
-+ */
-+
-+#ifndef MONGOC_TOPOLOGY_DESCRIPTION_PRIVATE_H
-+#define MONGOC_TOPOLOGY_DESCRIPTION_PRIVATE_H
-+
-+#include "mongoc-set-private.h"
-+#include "mongoc-server-description.h"
-+
-+#define MONGOC_SS_DEFAULT_TIMEOUT_MS 30000
-+#define MONGOC_SS_DEFAULT_LOCAL_THRESHOLD_MS 15
-+
-+typedef enum
-+ {
-+ MONGOC_TOPOLOGY_UNKNOWN,
-+ MONGOC_TOPOLOGY_SHARDED,
-+ MONGOC_TOPOLOGY_RS_NO_PRIMARY,
-+ MONGOC_TOPOLOGY_RS_WITH_PRIMARY,
-+ MONGOC_TOPOLOGY_SINGLE,
-+ MONGOC_TOPOLOGY_DESCRIPTION_TYPES
-+ } mongoc_topology_description_type_t;
-+
-+typedef struct _mongoc_topology_description_t
-+{
-+ mongoc_topology_description_type_t type;
-+ mongoc_set_t *servers;
-+ char *set_name;
-+ int64_t max_set_version;
-+ bson_oid_t max_election_id;
-+ bool compatible;
-+ char *compatibility_error;
-+ uint32_t max_server_id;
-+ bool stale;
-+} mongoc_topology_description_t;
-+
-+typedef enum
-+ {
-+ MONGOC_SS_READ,
-+ MONGOC_SS_WRITE
-+ } mongoc_ss_optype_t;
-+
-+void
-+mongoc_topology_description_init (mongoc_topology_description_t *description,
-+ mongoc_topology_description_type_t type);
-+
-+void
-+mongoc_topology_description_destroy (mongoc_topology_description_t *description);
-+
-+void
-+mongoc_topology_description_handle_ismaster (
-+ mongoc_topology_description_t *topology,
-+ mongoc_server_description_t *sd,
-+ const bson_t *reply,
-+ int64_t rtt_msec,
-+ bson_error_t *error);
-+
-+mongoc_server_description_t *
-+mongoc_topology_description_select (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);
-+
-+void
-+mongoc_topology_description_suitable_servers (
-+ mongoc_array_t *set, /* OUT */
-+ mongoc_ss_optype_t optype,
-+ mongoc_topology_description_t *topology,
-+ const mongoc_read_prefs_t *read_pref,
-+ size_t local_threshold_ms);
-+
-+void
-+mongoc_topology_description_invalidate_server (mongoc_topology_description_t *topology,
-+ uint32_t id);
-+
-+bool
-+mongoc_topology_description_add_server (mongoc_topology_description_t *topology,
-+ const char *server,
-+ uint32_t *id /* OUT */);
-+
-+#endif /* MONGOC_TOPOLOGY_DESCRIPTION_H */
-diff --git a/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-topology-description.c b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-topology-description.c
-new file mode 100644
-index 0000000..38e21db
---- /dev/null
-+++ b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-topology-description.c
-@@ -0,0 +1,1402 @@
-+/*
-+ * 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-private.h"
-+#include "mongoc-trace.h"
-+#include "mongoc-util-private.h"
-+
-+
-+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,
-+ mongoc_topology_description_type_t type)
-+{
-+ ENTRY;
-+
-+ BSON_ASSERT (description);
-+ BSON_ASSERT (type == MONGOC_TOPOLOGY_UNKNOWN ||
-+ type == MONGOC_TOPOLOGY_SINGLE ||
-+ type == MONGOC_TOPOLOGY_RS_NO_PRIMARY);
-+
-+ memset (description, 0, sizeof (*description));
-+
-+ description->type = type;
-+ description->servers = mongoc_set_new(8, _mongoc_topology_server_dtor, NULL);
-+ description->set_name = NULL;
-+ description->max_set_version = MONGOC_NO_SET_VERSION;
-+ description->compatible = true;
-+ description->compatibility_error = NULL;
-+ description->stale = true;
-+
-+ EXIT;
-+}
-+
-+/*
-+ *--------------------------------------------------------------------------
-+ *
-+ * mongoc_topology_description_destroy --
-+ *
-+ * Destroy allocated resources within @description
-+ *
-+ * Returns:
-+ * None.
-+ *
-+ * Side effects:
-+ * None.
-+ *
-+ *--------------------------------------------------------------------------
-+ */
-+void
-+mongoc_topology_description_destroy (mongoc_topology_description_t *description)
-+{
-+ ENTRY;
-+
-+ BSON_ASSERT(description);
-+
-+ mongoc_set_destroy(description->servers);
-+
-+ if (description->set_name) {
-+ bson_free (description->set_name);
-+ }
-+
-+ if (description->compatibility_error) {
-+ bson_free (description->compatibility_error);
-+ }
-+
-+ EXIT;
-+}
-+
-+/* find the primary, then stop iterating */
-+static bool
-+_mongoc_topology_description_has_primary_cb (void *item,
-+ void *ctx /* OUT */)
-+{
-+ mongoc_server_description_t *server = (mongoc_server_description_t *)item;
-+ mongoc_server_description_t **primary = (mongoc_server_description_t **)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 mongoc_server_description_t *
-+_mongoc_topology_description_has_primary (mongoc_topology_description_t *description)
-+{
-+ mongoc_server_description_t *primary = NULL;
-+
-+ mongoc_set_for_each(description->servers, _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,
-+ 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,
-+ 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,
-+ 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_POSSIBLE_PRIMARY:
-+ 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_POSSIBLE_PRIMARY:
-+ 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;
-+ }
-+ default:
-+ return false;
-+ }
-+}
-+
-+typedef struct _mongoc_suitable_data_t
-+{
-+ mongoc_read_mode_t read_mode;
-+ mongoc_topology_description_type_t topology_type;
-+ mongoc_server_description_t *primary; /* OUT */
-+ 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 (void *item,
-+ void *ctx)
-+{
-+ mongoc_server_description_t *server = (mongoc_server_description_t *)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)) {
-+
-+ if (server->type == MONGOC_SERVER_RS_PRIMARY) {
-+ data->primary = server;
-+
-+ 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;
-+ }
-+ return true;
-+}
-+
-+/* if any mongos are candidates, add them to the candidates array */
-+static bool
-+_mongoc_find_suitable_mongos_cb (void *item,
-+ void *ctx)
-+{
-+ mongoc_server_description_t *server = (mongoc_server_description_t *)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_suitable_servers --
-+ *
-+ * Return an array of suitable server descriptions for this
-+ * operation and read preference.
-+ *
-+ * NOTE: this method should only be called while holding the mutex on
-+ * the owning topology object.
-+ *
-+ * Returns:
-+ * Array of server descriptions, or NULL upon failure.
-+ *
-+ * Side effects:
-+ * None.
-+ *
-+ *-------------------------------------------------------------------------
-+ */
-+
-+void
-+mongoc_topology_description_suitable_servers (
-+ mongoc_array_t *set, /* OUT */
-+ mongoc_ss_optype_t optype,
-+ mongoc_topology_description_t *topology,
-+ const mongoc_read_prefs_t *read_pref,
-+ size_t local_threshold_ms)
-+{
-+ mongoc_suitable_data_t data;
-+ mongoc_server_description_t **candidates;
-+ mongoc_server_description_t *server;
-+ int64_t nearest = -1;
-+ int i;
-+ mongoc_read_mode_t read_mode = mongoc_read_prefs_get_mode(read_pref);
-+
-+ candidates = (mongoc_server_description_t **)bson_malloc0(sizeof(*candidates) * topology->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) {
-+ server = (mongoc_server_description_t *)mongoc_set_get_item (topology->servers, 0);
-+ if (_mongoc_topology_description_server_is_candidate (server->type, read_mode, topology->type)) {
-+ _mongoc_array_append_val (set, server);
-+ }
-+ 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(topology->servers, _mongoc_replica_set_read_suitable_cb, &data);
-+
-+ /* if we have a primary, it's a candidate, for some read modes we are done */
-+ if (read_mode == MONGOC_READ_PRIMARY || read_mode == MONGOC_READ_PRIMARY_PREFERRED) {
-+ if (data.primary) {
-+ _mongoc_array_append_val (set, data.primary);
-+ goto DONE;
-+ }
-+ }
-+
-+ if (! mongoc_server_description_filter_eligible (data.candidates, data.candidates_len, read_pref)) {
-+ if (read_mode == MONGOC_READ_NEAREST) {
-+ goto DONE;
-+ } else {
-+ data.has_secondary = false;
-+ }
-+ }
-+
-+ if (data.has_secondary &&
-+ (read_mode == MONGOC_READ_SECONDARY || read_mode == MONGOC_READ_SECONDARY_PREFERRED)) {
-+ /* secondary or secondary preferred and we have one. */
-+
-+ for (i = 0; i < data.candidates_len; i++) {
-+ if (candidates[i] && candidates[i]->type == MONGOC_SERVER_RS_PRIMARY) {
-+ candidates[i] = NULL;
-+ }
-+ }
-+ } else if (read_mode == MONGOC_READ_SECONDARY_PREFERRED && data.primary) {
-+ /* secondary preferred, but only the one primary is a candidate */
-+ _mongoc_array_append_val (set, data.primary);
-+ goto DONE;
-+ }
-+
-+ } 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(topology->servers, _mongoc_topology_description_has_primary_cb,
-+ &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 (topology->servers, _mongoc_find_suitable_mongos_cb, &data);
-+ }
-+
-+ /* 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)) {
-+ nearest = candidates[i]->round_trip_time;
-+ }
-+ }
-+
-+ for (i = 0; i < data.candidates_len; i++) {
-+ if (candidates[i] && (candidates[i]->round_trip_time <= nearest + local_threshold_ms)) {
-+ _mongoc_array_append_val (set, candidates[i]);
-+ }
-+ }
-+
-+DONE:
-+
-+ bson_free (candidates);
-+
-+ return;
-+}
-+
-+
-+/*
-+ *-------------------------------------------------------------------------
-+ *
-+ * 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.
-+ *
-+ * NOTE: this method should only be called while holding the mutex on
-+ * the owning topology object.
-+ *
-+ * Returns:
-+ * Selected server description, or NULL upon failure.
-+ *
-+ * Side effects:
-+ * None.
-+ *
-+ *-------------------------------------------------------------------------
-+ */
-+
-+mongoc_server_description_t *
-+mongoc_topology_description_select (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 *sd = NULL;
-+
-+ ENTRY;
-+
-+ if (!topology->compatible) {
-+ /* TODO, should we return an error object here,
-+ or just treat as a case where there are no suitable servers? */
-+ RETURN(NULL);
-+ }
-+
-+ if (topology->type == MONGOC_TOPOLOGY_SINGLE) {
-+ sd = (mongoc_server_description_t *)mongoc_set_get_item (topology->servers, 0);
-+
-+ if (sd->has_is_master) {
-+ RETURN(sd);
-+ } else {
-+ 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) {
-+ sd = _mongoc_array_index(&suitable_servers, mongoc_server_description_t*,
-+ rand() % suitable_servers.len);
-+ }
-+
-+ _mongoc_array_destroy (&suitable_servers);
-+
-+ 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. Caller should hold the mutex on the
-+ * owning topology object while calling this method and while using
-+ * the returned reference.
-+ *
-+ * 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)
-+{
-+ mongoc_server_description_t *sd;
-+
-+ BSON_ASSERT (description);
-+
-+ sd = (mongoc_server_description_t *)mongoc_set_get(description->servers, 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,
-+ mongoc_server_description_t *server)
-+{
-+ BSON_ASSERT (description);
-+ BSON_ASSERT (server);
-+
-+ mongoc_set_rm(description->servers, server->id);
-+}
-+
-+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 (void *item,
-+ void *ctx /* IN - OUT */)
-+{
-+ mongoc_server_description_t *server = (mongoc_server_description_t *)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 (description->servers, _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(description->servers, _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,
-+ 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 and other parameters are reset to defaults.
-+ *
-+ * NOTE: this method should only be called while holding the mutex on
-+ * the owning topology object.
-+ *
-+ *--------------------------------------------------------------------------
-+ */
-+void
-+mongoc_topology_description_invalidate_server (mongoc_topology_description_t *topology,
-+ uint32_t id)
-+{
-+ mongoc_server_description_t *sd;
-+ bson_error_t error;
-+
-+ sd = mongoc_topology_description_server_by_id (topology, id, NULL);
-+ mongoc_topology_description_handle_ismaster (topology, sd, NULL, 0, &error);
-+
-+ return;
-+}
-+
-+/*
-+ *--------------------------------------------------------------------------
-+ *
-+ * 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.
-+ *
-+ * NOTE: this method should only be called while holding the mutex on
-+ * the owning topology object.
-+ *
-+ * 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(topology->servers, server_id, description);
-+ }
-+
-+ if (id) {
-+ *id = server_id;
-+ }
-+
-+ return true;
-+}
-+
-+
-+static void
-+_mongoc_topology_description_add_new_servers (
-+ mongoc_topology_description_t *topology,
-+ 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_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;
-+ 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);
-+ }
-+ 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,
-+ mongoc_server_description_t *primary)
-+{
-+ mongoc_array_t to_remove;
-+ int i;
-+ mongoc_server_description_t *member;
-+ const char *address;
-+
-+ _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 < topology->servers->items_len; i++) {
-+ member = (mongoc_server_description_t *)mongoc_set_get_item (topology->servers, i);
-+ 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++) {
-+ 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 (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,
-+ mongoc_server_description_t *server)
-+{
-+ mongoc_primary_and_topology_t data;
-+
-+ 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_ismaster(). 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)) {
-+ /* stale primary */
-+ mongoc_topology_description_invalidate_server (topology, server->id);
-+ _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(topology->servers, _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,
-+ 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 (!_mongoc_topology_description_matches_me (server)) {
-+ _mongoc_topology_description_remove_server(topology, server);
-+ return;
-+ }
-+
-+ /* 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);
-+ }
-+}
-+
-+/*
-+ *--------------------------------------------------------------------------
-+ *
-+ * _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,
-+ 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,
-+ 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,
-+ 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,
-+ 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,
-+ mongoc_server_description_t *server)
-+{
-+ BSON_ASSERT (topology);
-+ BSON_ASSERT (server);
-+
-+ if (!_mongoc_topology_description_has_server(topology, server->connection_address, NULL)) return;
-+
-+ if (topology->servers->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,
-+ 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
-+ }
-+};
-+
-+/*
-+ *--------------------------------------------------------------------------
-+ *
-+ * mongoc_topology_description_handle_ismaster --
-+ *
-+ * Handle an ismaster. This is called by the background SDAM process,
-+ * and by client when invalidating servers.
-+ *
-+ * NOTE: this method should only be called while holding the mutex on
-+ * the owning topology object.
-+ *
-+ *--------------------------------------------------------------------------
-+ */
-+
-+void
-+mongoc_topology_description_handle_ismaster (
-+ mongoc_topology_description_t *topology,
-+ mongoc_server_description_t *sd,
-+ const bson_t *ismaster_response,
-+ int64_t rtt_msec,
-+ bson_error_t *error)
-+{
-+ BSON_ASSERT (topology);
-+ BSON_ASSERT (sd);
-+
-+ if (!_mongoc_topology_description_has_server (topology,
-+ sd->connection_address,
-+ NULL)) {
-+ MONGOC_DEBUG("Couldn't find %s in Topology Description", sd->connection_address);
-+ return;
-+ }
-+
-+ mongoc_server_description_handle_ismaster (sd, ismaster_response, rtt_msec,
-+ error);
-+
-+ if (gSDAMTransitionTable[sd->type][topology->type]) {
-+ TRACE("Transitioning to %d for %d", topology->type, sd->type);
-+ gSDAMTransitionTable[sd->type][topology->type] (topology, sd);
-+ } else {
-+ TRACE("No transition entry to %d for %d", topology->type, sd->type);
-+ }
-+}
-diff --git a/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-topology-private.h b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-topology-private.h
-new file mode 100644
-index 0000000..fc7f982
---- /dev/null
-+++ b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-topology-private.h
-@@ -0,0 +1,102 @@
-+/*
-+ * 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.
-+ */
-+
-+#ifndef MONGOC_TOPOLOGY_PRIVATE_H
-+#define MONGOC_TOPOLOGY_PRIVATE_H
-+
-+#include "mongoc-read-prefs-private.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"
-+
-+#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_SERVER_SELECTION_TIMEOUT_MS 30000
-+#define MONGOC_TOPOLOGY_HEARTBEAT_FREQUENCY_MS_MULTI_THREADED 10000
-+#define MONGOC_TOPOLOGY_HEARTBEAT_FREQUENCY_MS_SINGLE_THREADED 60000
-+
-+typedef enum {
-+ MONGOC_TOPOLOGY_BG_OFF,
-+ MONGOC_TOPOLOGY_BG_RUNNING,
-+ MONGOC_TOPOLOGY_BG_SHUTTING_DOWN,
-+} mongoc_topology_bg_state_t;
-+
-+typedef struct _mongoc_topology_t
-+{
-+ mongoc_topology_description_t description;
-+ mongoc_uri_t *uri;
-+ mongoc_topology_scanner_t *scanner;
-+ bool server_selection_try_once;
-+
-+ int64_t last_scan;
-+ int64_t connect_timeout_msec;
-+ int64_t server_selection_timeout_msec;
-+ int64_t heartbeat_msec;
-+
-+ mongoc_mutex_t mutex;
-+ mongoc_cond_t cond_client;
-+ mongoc_cond_t cond_server;
-+ mongoc_thread_t thread;
-+
-+ mongoc_topology_bg_state_t bg_thread_state;
-+ bool scan_requested;
-+ bool scanning;
-+ bool got_ismaster;
-+ bool shutdown_requested;
-+ bool single_threaded;
-+ bool stale;
-+} mongoc_topology_t;
-+
-+mongoc_topology_t *
-+mongoc_topology_new (const mongoc_uri_t *uri,
-+ bool single_threaded);
-+
-+void
-+mongoc_topology_destroy (mongoc_topology_t *topology);
-+
-+mongoc_server_description_t *
-+mongoc_topology_select (mongoc_topology_t *topology,
-+ mongoc_ss_optype_t optype,
-+ const mongoc_read_prefs_t *read_prefs,
-+ int64_t local_threshold_msec,
-+ bson_error_t *error);
-+
-+mongoc_server_description_t *
-+mongoc_topology_server_by_id (mongoc_topology_t *topology,
-+ uint32_t id,
-+ bson_error_t *error);
-+
-+bool mongoc_topology_get_server_type (mongoc_topology_t *topology,
-+ uint32_t id,
-+ mongoc_topology_description_type_t *topology_type,
-+ mongoc_server_description_type_t *server_type,
-+ bson_error_t *error);
-+
-+void
-+mongoc_topology_request_scan (mongoc_topology_t *topology);
-+
-+void
-+mongoc_topology_invalidate_server (mongoc_topology_t *topology,
-+ uint32_t id);
-+
-+int64_t
-+mongoc_topology_server_timestamp (mongoc_topology_t *topology,
-+ uint32_t id);
-+
-+#endif
-diff --git a/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-topology-scanner-private.h b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-topology-scanner-private.h
-new file mode 100644
-index 0000000..c8517ac
---- /dev/null
-+++ b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-topology-scanner-private.h
-@@ -0,0 +1,152 @@
-+/*
-+ * 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.
-+ */
-+
-+#ifndef MONGOC_TOPOLOGY_SCANNER_PRIVATE_H
-+#define MONGOC_TOPOLOGY_SCANNER_PRIVATE_H
-+
-+/* TODO: rename to TOPOLOGY scanner */
-+
-+#if !defined (MONGOC_I_AM_A_DRIVER) && !defined (MONGOC_COMPILATION)
-+#error "Only <mongoc.h> can be included directly."
-+#endif
-+
-+#include <bson.h>
-+#include "mongoc-async-private.h"
-+#include "mongoc-async-cmd-private.h"
-+#include "mongoc-host-list.h"
-+
-+BSON_BEGIN_DECLS
-+
-+typedef void (*mongoc_topology_scanner_cb_t)(uint32_t id,
-+ const bson_t *bson,
-+ int64_t rtt,
-+ void *data,
-+ bson_error_t *error);
-+
-+struct mongoc_topology_scanner;
-+
-+typedef struct mongoc_topology_scanner_node
-+{
-+ uint32_t id;
-+ mongoc_async_cmd_t *cmd;
-+ mongoc_stream_t *stream;
-+ int64_t timestamp;
-+ int64_t last_used;
-+ int64_t last_failed;
-+ bool has_auth;
-+ mongoc_host_list_t host;
-+ struct addrinfo *dns_results;
-+ struct addrinfo *current_dns_result;
-+ struct mongoc_topology_scanner *ts;
-+
-+ struct mongoc_topology_scanner_node *next;
-+ struct mongoc_topology_scanner_node *prev;
-+
-+ bool retired;
-+ bson_error_t last_error;
-+} mongoc_topology_scanner_node_t;
-+
-+typedef struct mongoc_topology_scanner
-+{
-+ mongoc_async_t *async;
-+ mongoc_topology_scanner_node_t *nodes;
-+ uint32_t seq;
-+ bson_t ismaster_cmd;
-+ mongoc_topology_scanner_cb_t cb;
-+ void *cb_data;
-+ bool in_progress;
-+ const mongoc_uri_t *uri;
-+ mongoc_async_cmd_setup_t setup;
-+ mongoc_stream_initiator_t initiator;
-+ void *initiator_context;
-+
-+#ifdef MONGOC_ENABLE_SSL
-+ mongoc_ssl_opt_t *ssl_opts;
-+#endif
-+} mongoc_topology_scanner_t;
-+
-+mongoc_topology_scanner_t *
-+mongoc_topology_scanner_new (const mongoc_uri_t *uri,
-+ mongoc_topology_scanner_cb_t cb,
-+ void *data);
-+
-+void
-+mongoc_topology_scanner_destroy (mongoc_topology_scanner_t *ts);
-+
-+mongoc_topology_scanner_node_t *
-+mongoc_topology_scanner_add (mongoc_topology_scanner_t *ts,
-+ const mongoc_host_list_t *host,
-+ uint32_t id);
-+
-+void
-+mongoc_topology_scanner_add_and_scan (mongoc_topology_scanner_t *ts,
-+ const mongoc_host_list_t *host,
-+ uint32_t id,
-+ int64_t timeout_msec);
-+
-+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);
-+
-+void
-+mongoc_topology_scanner_start (mongoc_topology_scanner_t *ts,
-+ int32_t timeout_msec,
-+ bool obey_cooldown);
-+
-+bool
-+mongoc_topology_scanner_work (mongoc_topology_scanner_t *ts,
-+ int32_t timeout_msec);
-+
-+void
-+mongoc_topology_scanner_sum_errors (mongoc_topology_scanner_t *ts,
-+ bson_error_t *error);
-+
-+void
-+mongoc_topology_scanner_reset (mongoc_topology_scanner_t *ts);
-+
-+bool
-+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);
-+
-+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);
-+
-+#ifdef MONGOC_ENABLE_SSL
-+void
-+mongoc_topology_scanner_set_ssl_opts (mongoc_topology_scanner_t *ts,
-+ mongoc_ssl_opt_t *opts);
-+#endif
-+
-+BSON_END_DECLS
-+
-+#endif /* MONGOC_TOPOLOGY_SCANNER_PRIVATE_H */
-diff --git a/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-topology.c b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-topology.c
-new file mode 100644
-index 0000000..be7eb9a
---- /dev/null
-+++ b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-topology.c
-@@ -0,0 +1,915 @@
-+/*
-+ * 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-error.h"
-+#include "mongoc-topology-private.h"
-+#include "mongoc-uri-private.h"
-+#include "mongoc-util-private.h"
-+
-+#include "utlist.h"
-+
-+static void
-+_mongoc_topology_background_thread_stop (mongoc_topology_t *topology);
-+
-+static void
-+_mongoc_topology_background_thread_start (mongoc_topology_t *topology);
-+
-+static void
-+_mongoc_topology_request_scan (mongoc_topology_t *topology);
-+
-+static bool
-+_mongoc_topology_reconcile_add_nodes (void *item,
-+ void *ctx)
-+{
-+ mongoc_server_description_t *sd = item;
-+ mongoc_topology_t *topology = (mongoc_topology_t *)ctx;
-+ mongoc_topology_scanner_t *scanner = topology->scanner;
-+
-+ /* quickly search by id, then check if a node for this host was retired in
-+ * this scan. */
-+ if (! mongoc_topology_scanner_get_node (scanner, sd->id) &&
-+ ! mongoc_topology_scanner_has_node_for_host (scanner, &sd->host)) {
-+ mongoc_topology_scanner_add_and_scan (scanner, &sd->host, sd->id,
-+ topology->connect_timeout_msec);
-+ }
-+
-+ return true;
-+}
-+
-+void
-+mongoc_topology_reconcile (mongoc_topology_t *topology) {
-+ mongoc_topology_scanner_node_t *ele, *tmp;
-+ mongoc_topology_description_t *description;
-+ mongoc_topology_scanner_t *scanner;
-+
-+ description = &topology->description;
-+ scanner = topology->scanner;
-+
-+ /* Add newly discovered nodes */
-+ mongoc_set_for_each(description->servers,
-+ _mongoc_topology_reconcile_add_nodes,
-+ topology);
-+
-+ /* Remove removed nodes */
-+ DL_FOREACH_SAFE (scanner->nodes, ele, tmp) {
-+ if (!mongoc_topology_description_server_by_id (description, ele->id, NULL)) {
-+ mongoc_topology_scanner_node_retire (ele);
-+ }
-+ }
-+}
-+/*
-+ *-------------------------------------------------------------------------
-+ *
-+ * _mongoc_topology_scanner_cb --
-+ *
-+ * Callback method to handle ismaster responses received by async
-+ * command objects.
-+ *
-+ * NOTE: This method locks the given topology's mutex.
-+ *
-+ *-------------------------------------------------------------------------
-+ */
-+
-+void
-+_mongoc_topology_scanner_cb (uint32_t id,
-+ const bson_t *ismaster_response,
-+ int64_t rtt_msec,
-+ void *data,
-+ bson_error_t *error)
-+{
-+ mongoc_topology_t *topology;
-+ mongoc_server_description_t *sd;
-+
-+ BSON_ASSERT (data);
-+
-+ topology = (mongoc_topology_t *)data;
-+
-+ if (rtt_msec >= 0) {
-+ /* If the scanner failed to create a socket for this server, that means
-+ * we're in scanner_start, which means we're under the mutex. So don't
-+ * take the mutex for rtt < 0 */
-+
-+ mongoc_mutex_lock (&topology->mutex);
-+ }
-+
-+ sd = mongoc_topology_description_server_by_id (&topology->description, id,
-+ NULL);
-+
-+ if (sd) {
-+ mongoc_topology_description_handle_ismaster (&topology->description, sd,
-+ ismaster_response, rtt_msec,
-+ error);
-+
-+ /* The processing of the ismaster results above may have added/removed
-+ * server descriptions. We need to reconcile that with our monitoring agents
-+ */
-+
-+ mongoc_topology_reconcile(topology);
-+
-+ /* TODO only wake up all clients if we found any topology changes */
-+ mongoc_cond_broadcast (&topology->cond_client);
-+ }
-+
-+ if (rtt_msec >= 0) {
-+ mongoc_mutex_unlock (&topology->mutex);
-+ }
-+}
-+
-+/*
-+ *-------------------------------------------------------------------------
-+ *
-+ * 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)
-+{
-+ mongoc_topology_t *topology;
-+ mongoc_topology_description_type_t init_type;
-+ uint32_t id;
-+ const mongoc_host_list_t *hl;
-+
-+ BSON_ASSERT (uri);
-+
-+ topology = (mongoc_topology_t *)bson_malloc0(sizeof *topology);
-+
-+ /*
-+ * Not ideal, but there's no great way to do this.
-+ * Base on the URI, we assume:
-+ * - 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
-+ */
-+ if (mongoc_uri_get_replica_set(uri)) {
-+ init_type = MONGOC_TOPOLOGY_RS_NO_PRIMARY;
-+ } else {
-+ hl = mongoc_uri_get_hosts(uri);
-+ if (hl->next) {
-+ init_type = MONGOC_TOPOLOGY_UNKNOWN;
-+ } else {
-+ init_type = MONGOC_TOPOLOGY_SINGLE;
-+ }
-+ }
-+
-+ mongoc_topology_description_init(&topology->description, init_type);
-+ topology->description.set_name = bson_strdup(mongoc_uri_get_replica_set(uri));
-+
-+ topology->uri = mongoc_uri_copy (uri);
-+ topology->scanner = mongoc_topology_scanner_new (topology->uri,
-+ _mongoc_topology_scanner_cb,
-+ topology);
-+ 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,
-+ "serverselectiontryonce",
-+ true);
-+ } else {
-+ topology->server_selection_try_once = false;
-+ }
-+
-+ topology->server_selection_timeout_msec = mongoc_uri_get_option_as_int32(
-+ topology->uri, "serverselectiontimeoutms",
-+ MONGOC_TOPOLOGY_SERVER_SELECTION_TIMEOUT_MS);
-+
-+ /* 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, "connecttimeoutms",
-+ MONGOC_DEFAULT_CONNECTTIMEOUTMS);
-+
-+ topology->heartbeat_msec = mongoc_uri_get_option_as_int32(
-+ topology->uri, "heartbeatfrequencyms",
-+ (single_threaded ? MONGOC_TOPOLOGY_HEARTBEAT_FREQUENCY_MS_SINGLE_THREADED :
-+ MONGOC_TOPOLOGY_HEARTBEAT_FREQUENCY_MS_MULTI_THREADED)
-+ );
-+
-+ mongoc_mutex_init (&topology->mutex);
-+ mongoc_cond_init (&topology->cond_client);
-+ mongoc_cond_init (&topology->cond_server);
-+
-+ for ( hl = mongoc_uri_get_hosts (uri); hl; hl = hl->next) {
-+ mongoc_topology_description_add_server (&topology->description,
-+ hl->host_and_port,
-+ &id);
-+ mongoc_topology_scanner_add (topology->scanner, hl, id);
-+ }
-+
-+ if (! topology->single_threaded) {
-+ _mongoc_topology_background_thread_start (topology);
-+ }
-+
-+ return topology;
-+}
-+
-+/*
-+ *-------------------------------------------------------------------------
-+ *
-+ * 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;
-+ }
-+
-+ _mongoc_topology_background_thread_stop (topology);
-+
-+ mongoc_uri_destroy (topology->uri);
-+ mongoc_topology_description_destroy(&topology->description);
-+ mongoc_topology_scanner_destroy (topology->scanner);
-+ mongoc_cond_destroy (&topology->cond_client);
-+ mongoc_cond_destroy (&topology->cond_server);
-+ mongoc_mutex_destroy (&topology->mutex);
-+
-+ bson_free(topology);
-+}
-+
-+/*
-+ *--------------------------------------------------------------------------
-+ *
-+ * _mongoc_topology_run_scanner --
-+ *
-+ * Not threadsafe, the expectation is that we're either single
-+ * threaded or only the background thread runs scans.
-+ *
-+ * Crank the underlying scanner until we've timed out or finished.
-+ *
-+ * Returns:
-+ * true if there is more work to do, false otherwise
-+ *
-+ *--------------------------------------------------------------------------
-+ */
-+static bool
-+_mongoc_topology_run_scanner (mongoc_topology_t *topology,
-+ int64_t work_msec)
-+{
-+ int64_t now;
-+ int64_t expire_at;
-+ bool keep_going = true;
-+
-+ now = bson_get_monotonic_time ();
-+ expire_at = now + (work_msec * 1000);
-+
-+ /* while there is more work to do and we haven't timed out */
-+ while (keep_going && now <= expire_at) {
-+ keep_going = mongoc_topology_scanner_work (topology->scanner, (expire_at - now) / 1000);
-+
-+ if (keep_going) {
-+ now = bson_get_monotonic_time ();
-+ }
-+ }
-+
-+ return keep_going;
-+}
-+
-+/*
-+ *--------------------------------------------------------------------------
-+ *
-+ * _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.
-+ *
-+ *--------------------------------------------------------------------------
-+ */
-+static void
-+_mongoc_topology_do_blocking_scan (mongoc_topology_t *topology, bson_error_t *error) {
-+ mongoc_topology_scanner_start (topology->scanner,
-+ topology->connect_timeout_msec,
-+ true);
-+
-+ while (_mongoc_topology_run_scanner (topology,
-+ topology->connect_timeout_msec)) {}
-+
-+ /* Aggregate all scanner errors, if any */
-+ mongoc_topology_scanner_sum_errors (topology->scanner, error);
-+ /* "retired" nodes can be checked again in the next scan */
-+ mongoc_topology_scanner_reset (topology->scanner);
-+ topology->last_scan = bson_get_monotonic_time ();
-+ topology->stale = false;
-+}
-+
-+/*
-+ *-------------------------------------------------------------------------
-+ *
-+ * 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.
-+ *
-+ * NOTE: this method locks and unlocks @topology's mutex.
-+ *
-+ * Parameters:
-+ * @topology: The topology.
-+ * @optype: Whether we are selecting for a read or write operation.
-+ * @read_prefs: Required, the read preferences for the command.
-+ * @local_threshold_ms: Maximum latency *beyond* the nearest server
-+ * among which to randomly select servers. See Server Selection
-+ * Spec.
-+ * @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.
-+ *
-+ *-------------------------------------------------------------------------
-+ */
-+mongoc_server_description_t *
-+mongoc_topology_select (mongoc_topology_t *topology,
-+ mongoc_ss_optype_t optype,
-+ const mongoc_read_prefs_t *read_prefs,
-+ int64_t local_threshold_ms,
-+ bson_error_t *error)
-+{
-+ int r;
-+ mongoc_server_description_t *selected_server = NULL;
-+ bool try_once;
-+ int64_t sleep_usec;
-+ bool tried_once;
-+ bson_error_t scanner_error = { 0 };
-+
-+ /* 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);
-+
-+ 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) {
-+ tried_once = false;
-+ next_update = topology->last_scan + topology->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
-+ + MONGOC_TOPOLOGY_MIN_HEARTBEAT_FREQUENCY_MS * 1000;
-+
-+ if (scan_ready > expire_at && !try_once) {
-+ /* selection timeout will expire before min heartbeat passes */
-+ bson_set_error(error,
-+ MONGOC_ERROR_SERVER_SELECTION,
-+ MONGOC_ERROR_SERVER_SELECTION_FAILURE,
-+ "No suitable servers found: "
-+ "`minheartbeatfrequencyms` not reached yet");
-+ goto FAIL;
-+ }
-+
-+ sleep_usec = scan_ready - loop_end;
-+ if (sleep_usec > 0) {
-+ _mongoc_usleep (sleep_usec);
-+ }
-+
-+ /* takes up to connectTimeoutMS. sets "last_scan", clears "stale" */
-+ _mongoc_topology_do_blocking_scan (topology, &scanner_error);
-+ tried_once = true;
-+ }
-+
-+ selected_server = mongoc_topology_description_select(&topology->description,
-+ optype,
-+ read_prefs,
-+ local_threshold_ms);
-+
-+ if (selected_server) {
-+ return mongoc_server_description_new_copy(selected_server);
-+ }
-+
-+ topology->stale = true;
-+
-+ if (try_once) {
-+ if (tried_once) {
-+ if (scanner_error.code) {
-+ bson_set_error(error,
-+ MONGOC_ERROR_SERVER_SELECTION,
-+ MONGOC_ERROR_SERVER_SELECTION_FAILURE,
-+ "No suitable servers found "
-+ "(`serverselectiontryonce` set): %s", scanner_error.message);
-+ } else {
-+ bson_set_error(error,
-+ MONGOC_ERROR_SERVER_SELECTION,
-+ MONGOC_ERROR_SERVER_SELECTION_FAILURE,
-+ "No suitable servers found "
-+ "(`serverselectiontryonce` set)");
-+ }
-+ goto FAIL;
-+ }
-+ } else {
-+ loop_end = bson_get_monotonic_time ();
-+
-+ if (loop_end > expire_at) {
-+ /* no time left in server_selection_timeout_msec */
-+ bson_set_error(error,
-+ MONGOC_ERROR_SERVER_SELECTION,
-+ MONGOC_ERROR_SERVER_SELECTION_FAILURE,
-+ "No suitable servers found: "
-+ "`serverselectiontimeoutms` timed out");
-+ goto FAIL;
-+ }
-+ }
-+ }
-+ }
-+
-+ /* With background thread */
-+ /* we break out when we've found a server or timed out */
-+ for (;;) {
-+ mongoc_mutex_lock (&topology->mutex);
-+ selected_server = mongoc_topology_description_select(&topology->description,
-+ optype,
-+ read_prefs,
-+ local_threshold_ms);
-+
-+ if (! selected_server) {
-+ _mongoc_topology_request_scan (topology);
-+
-+ r = mongoc_cond_timedwait (&topology->cond_client, &topology->mutex,
-+ (expire_at - loop_start) / 1000);
-+
-+ mongoc_mutex_unlock (&topology->mutex);
-+
-+#ifdef _WIN32
-+ if (r == WSAETIMEDOUT) {
-+#else
-+ if (r == ETIMEDOUT) {
-+#endif
-+ /* handle timeouts */
-+ bson_set_error(error,
-+ MONGOC_ERROR_SERVER_SELECTION,
-+ MONGOC_ERROR_SERVER_SELECTION_FAILURE,
-+ "Timed out trying to select a server");
-+ goto FAIL;
-+ } 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);
-+ goto FAIL;
-+ }
-+
-+ loop_start = bson_get_monotonic_time ();
-+
-+ if (loop_start > expire_at) {
-+ bson_set_error(error,
-+ MONGOC_ERROR_SERVER_SELECTION,
-+ MONGOC_ERROR_SERVER_SELECTION_FAILURE,
-+ "Timed out trying to select a server");
-+ goto FAIL;
-+ }
-+ } else {
-+ selected_server = mongoc_server_description_new_copy(selected_server);
-+ mongoc_mutex_unlock (&topology->mutex);
-+ return selected_server;
-+ }
-+ }
-+
-+FAIL:
-+ topology->stale = true;
-+
-+ return NULL;
-+}
-+
-+/*
-+ *-------------------------------------------------------------------------
-+ *
-+ * mongoc_topology_server_by_id --
-+ *
-+ * Get the server description for @id, if that server is present
-+ * in @description. Otherwise, return NULL and fill out the optional
-+ * @error.
-+ *
-+ * NOTE: this method returns a copy of the original server
-+ * description. Callers must own and clean up this copy.
-+ *
-+ * NOTE: this method locks and unlocks @topology's mutex.
-+ *
-+ * Returns:
-+ * A mongoc_server_description_t, or NULL.
-+ *
-+ * Side effects:
-+ * Fills out optional @error if server not found.
-+ *
-+ *-------------------------------------------------------------------------
-+ */
-+
-+mongoc_server_description_t *
-+mongoc_topology_server_by_id (mongoc_topology_t *topology,
-+ uint32_t id,
-+ bson_error_t *error)
-+{
-+ mongoc_server_description_t *sd;
-+
-+ mongoc_mutex_lock (&topology->mutex);
-+
-+ sd = mongoc_server_description_new_copy (
-+ mongoc_topology_description_server_by_id (&topology->description,
-+ id,
-+ error));
-+
-+ mongoc_mutex_unlock (&topology->mutex);
-+
-+ return sd;
-+}
-+
-+/*
-+ *-------------------------------------------------------------------------
-+ *
-+ * mongoc_topology_get_server_type --
-+ *
-+ * Get the topology type, and the server type for @id, if that server
-+ * is present in @description. Otherwise, return false and fill out
-+ * the optional @error.
-+ *
-+ * NOTE: this method locks and unlocks @topology's mutex.
-+ *
-+ * Returns:
-+ * True on success.
-+ *
-+ * Side effects:
-+ * Fills out optional @error if server not found.
-+ *
-+ *-------------------------------------------------------------------------
-+ */
-+
-+bool
-+mongoc_topology_get_server_type (
-+ mongoc_topology_t *topology,
-+ uint32_t id,
-+ mongoc_topology_description_type_t *topology_type /* OUT */,
-+ mongoc_server_description_type_t *server_type /* OUT */,
-+ bson_error_t *error)
-+{
-+ mongoc_server_description_t *sd;
-+ bool ret = false;
-+
-+ BSON_ASSERT (topology);
-+ BSON_ASSERT (topology_type);
-+ BSON_ASSERT (server_type);
-+
-+ mongoc_mutex_lock (&topology->mutex);
-+
-+ sd = mongoc_topology_description_server_by_id (&topology->description,
-+ id,
-+ error);
-+
-+ if (sd) {
-+ *topology_type = topology->description.type;
-+ *server_type = sd->type;
-+ ret = true;
-+ }
-+
-+ mongoc_mutex_unlock (&topology->mutex);
-+
-+ return ret;
-+}
-+
-+/*
-+ *--------------------------------------------------------------------------
-+ *
-+ * _mongoc_topology_request_scan --
-+ *
-+ * Non-locking variant
-+ *
-+ *--------------------------------------------------------------------------
-+ */
-+
-+static void
-+_mongoc_topology_request_scan (mongoc_topology_t *topology)
-+{
-+ topology->scan_requested = true;
-+
-+ mongoc_cond_signal (&topology->cond_server);
-+}
-+
-+/*
-+ *--------------------------------------------------------------------------
-+ *
-+ * mongoc_topology_request_scan --
-+ *
-+ * Used from within the driver to request an immediate topology check.
-+ *
-+ * NOTE: this method locks and unlocks @topology's mutex.
-+ *
-+ *--------------------------------------------------------------------------
-+ */
-+
-+void
-+mongoc_topology_request_scan (mongoc_topology_t *topology)
-+{
-+ mongoc_mutex_lock (&topology->mutex);
-+
-+ _mongoc_topology_request_scan (topology);
-+
-+ mongoc_mutex_unlock (&topology->mutex);
-+}
-+
-+/*
-+ *--------------------------------------------------------------------------
-+ *
-+ * mongoc_topology_invalidate_server --
-+ *
-+ * Invalidate the given server after receiving a network error in
-+ * another part of the client.
-+ *
-+ * NOTE: this method uses @topology's mutex.
-+ *
-+ *--------------------------------------------------------------------------
-+ */
-+void
-+mongoc_topology_invalidate_server (mongoc_topology_t *topology,
-+ uint32_t id)
-+{
-+ mongoc_mutex_lock (&topology->mutex);
-+ mongoc_topology_description_invalidate_server (&topology->description, id);
-+ mongoc_mutex_unlock (&topology->mutex);
-+}
-+
-+/*
-+ *--------------------------------------------------------------------------
-+ *
-+ * mongoc_topology_server_timestamp --
-+ *
-+ * Return the topology's scanner's timestamp for the given server,
-+ * or -1 if there is no scanner node for the given server.
-+ *
-+ * NOTE: this method uses @topology's mutex.
-+ *
-+ * Returns:
-+ * Timestamp, or -1
-+ *
-+ *--------------------------------------------------------------------------
-+ */
-+int64_t
-+mongoc_topology_server_timestamp (mongoc_topology_t *topology,
-+ uint32_t id)
-+{
-+ mongoc_topology_scanner_node_t *node;
-+ int64_t timestamp = -1;
-+
-+ mongoc_mutex_lock (&topology->mutex);
-+
-+ node = mongoc_topology_scanner_get_node (topology->scanner, id);
-+ if (node) {
-+ timestamp = node->timestamp;
-+ }
-+
-+ mongoc_mutex_unlock (&topology->mutex);
-+
-+ return timestamp;
-+}
-+
-+/*
-+ *--------------------------------------------------------------------------
-+ *
-+ * _mongoc_topology_run_background --
-+ *
-+ * The background topology monitoring thread runs in this loop.
-+ *
-+ * NOTE: this method uses @topology's mutex.
-+ *
-+ *--------------------------------------------------------------------------
-+ */
-+static
-+void * _mongoc_topology_run_background (void *data)
-+{
-+ mongoc_topology_t *topology;
-+ int64_t now;
-+ int64_t last_scan;
-+ int64_t timeout;
-+ int64_t force_timeout;
-+ int r;
-+
-+ BSON_ASSERT (data);
-+
-+ last_scan = 0;
-+ topology = (mongoc_topology_t *)data;
-+ /* we exit this loop when shutdown_requested, or on error */
-+ for (;;) {
-+ /* unlocked after starting a scan or after breaking out of the loop */
-+ mongoc_mutex_lock (&topology->mutex);
-+
-+ /* we exit this loop on error, or when we should scan immediately */
-+ for (;;) {
-+ if (topology->shutdown_requested) goto DONE;
-+
-+ now = bson_get_monotonic_time ();
-+
-+ if (last_scan == 0) {
-+ /* set up the "last scan" as exactly long enough to force an
-+ * immediate scan on the first pass */
-+ last_scan = now - (topology->heartbeat_msec * 1000);
-+ }
-+
-+ timeout = topology->heartbeat_msec - ((now - last_scan) / 1000);
-+
-+ /* if someone's specifically asked for a scan, use a shorter interval */
-+ if (topology->scan_requested) {
-+ force_timeout = MONGOC_TOPOLOGY_MIN_HEARTBEAT_FREQUENCY_MS - ((now - last_scan) / 1000);
-+
-+ timeout = BSON_MIN (timeout, force_timeout);
-+ }
-+
-+ /* if we can start scanning, do so immediately */
-+ if (timeout <= 0) {
-+ mongoc_topology_scanner_start (topology->scanner,
-+ topology->connect_timeout_msec,
-+ false);
-+ break;
-+ } else {
-+ /* otherwise wait until someone:
-+ * o requests a scan
-+ * o we time out
-+ * o requests a shutdown
-+ */
-+ r = mongoc_cond_timedwait (&topology->cond_server, &topology->mutex, timeout);
-+
-+#ifdef _WIN32
-+ if (! (r == 0 || r == WSAETIMEDOUT)) {
-+#else
-+ if (! (r == 0 || r == ETIMEDOUT)) {
-+#endif
-+ /* handle errors */
-+ goto DONE;
-+ }
-+
-+ /* if we timed out, or were woken up, check if it's time to scan
-+ * again, or bail out */
-+ }
-+ }
-+
-+ topology->scan_requested = false;
-+ topology->scanning = true;
-+
-+ /* scanning locks and unlocks the mutex itself until the scan is done */
-+ mongoc_mutex_unlock (&topology->mutex);
-+
-+ while (_mongoc_topology_run_scanner (topology,
-+ topology->connect_timeout_msec)) {}
-+
-+ mongoc_mutex_lock (&topology->mutex);
-+
-+ /* "retired" nodes can be checked again in the next scan */
-+ mongoc_topology_scanner_reset (topology->scanner);
-+
-+ topology->last_scan = bson_get_monotonic_time ();
-+ topology->scanning = false;
-+ mongoc_mutex_unlock (&topology->mutex);
-+
-+ last_scan = bson_get_monotonic_time();
-+ }
-+
-+DONE:
-+ mongoc_mutex_unlock (&topology->mutex);
-+
-+ return NULL;
-+}
-+
-+/*
-+ *--------------------------------------------------------------------------
-+ *
-+ * mongoc_topology_background_thread_start --
-+ *
-+ * Start the topology background thread running. This should only be
-+ * called once per pool. If clients are created separately (not
-+ * through a pool) the SDAM logic will not be run in a background
-+ * thread.
-+ *
-+ * NOTE: this method uses @topology's mutex.
-+ *
-+ *--------------------------------------------------------------------------
-+ */
-+
-+static void
-+_mongoc_topology_background_thread_start (mongoc_topology_t *topology)
-+{
-+ bool launch_thread = true;
-+
-+ if (topology->single_threaded) {
-+ return;
-+ }
-+
-+ mongoc_mutex_lock (&topology->mutex);
-+ if (topology->bg_thread_state != MONGOC_TOPOLOGY_BG_OFF) launch_thread = false;
-+ topology->bg_thread_state = MONGOC_TOPOLOGY_BG_RUNNING;
-+ mongoc_mutex_unlock (&topology->mutex);
-+
-+ if (launch_thread) {
-+ mongoc_thread_create (&topology->thread, _mongoc_topology_run_background,
-+ topology);
-+ }
-+}
-+
-+/*
-+ *--------------------------------------------------------------------------
-+ *
-+ * mongoc_topology_background_thread_stop --
-+ *
-+ * Stop the topology background thread. Called by the owning pool at
-+ * its destruction.
-+ *
-+ * NOTE: this method uses @topology's mutex.
-+ *
-+ *--------------------------------------------------------------------------
-+ */
-+
-+static void
-+_mongoc_topology_background_thread_stop (mongoc_topology_t *topology)
-+{
-+ bool join_thread = false;
-+
-+ if (topology->single_threaded) {
-+ return;
-+ }
-+
-+ mongoc_mutex_lock (&topology->mutex);
-+ if (topology->bg_thread_state == MONGOC_TOPOLOGY_BG_RUNNING) {
-+ /* if the background thread is running, request a shutdown and signal the
-+ * thread */
-+ topology->shutdown_requested = true;
-+ mongoc_cond_signal (&topology->cond_server);
-+ topology->bg_thread_state = MONGOC_TOPOLOGY_BG_SHUTTING_DOWN;
-+ join_thread = true;
-+ } else if (topology->bg_thread_state == MONGOC_TOPOLOGY_BG_SHUTTING_DOWN) {
-+ /* if we're mid shutdown, wait until it shuts down */
-+ while (topology->bg_thread_state != MONGOC_TOPOLOGY_BG_OFF) {
-+ mongoc_cond_wait (&topology->cond_client, &topology->mutex);
-+ }
-+ } else {
-+ /* nothing to do if it's already off */
-+ }
-+
-+ mongoc_mutex_unlock (&topology->mutex);
-+
-+ if (join_thread) {
-+ /* if we're joining the thread, wait for it to come back and broadcast
-+ * all listeners */
-+ mongoc_thread_join (topology->thread);
-+ mongoc_cond_broadcast (&topology->cond_client);
-+ }
-+}
-diff --git a/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-uri-private.h b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-uri-private.h
-new file mode 100644
-index 0000000..df33181
---- /dev/null
-+++ b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-uri-private.h
-@@ -0,0 +1,87 @@
-+/*
-+ * 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.
-+ */
-+
-+#ifndef MONGOC_URI_PRIVATE_H
-+#define MONGOC_URI_PRIVATE_H
-+
-+#if !defined (MONGOC_I_AM_A_DRIVER) && !defined (MONGOC_COMPILATION)
-+#error "Only <mongoc.h> can be included directly."
-+#endif
-+
-+#include "mongoc-uri.h"
-+
-+
-+BSON_BEGIN_DECLS
-+
-+
-+void
-+mongoc_uri_lowercase_hostname ( const char *src,
-+ char *buf /* OUT */,
-+ int len);
-+void
-+mongoc_uri_append_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_set_username ( mongoc_uri_t *uri,
-+ const char *username);
-+bool
-+mongoc_uri_set_password ( mongoc_uri_t *uri,
-+ const char *password);
-+bool
-+mongoc_uri_set_database ( mongoc_uri_t *uri,
-+ const char *database);
-+bool
-+mongoc_uri_set_auth_source ( mongoc_uri_t *uri,
-+ const char *value);
-+bool
-+mongoc_uri_option_is_int32 (const char *key);
-+bool
-+mongoc_uri_option_is_bool (const char *key);
-+bool
-+mongoc_uri_option_is_utf8 (const char *key);
-+int32_t
-+mongoc_uri_get_option_as_int32 (const mongoc_uri_t *uri,
-+ const char *option,
-+ int32_t fallback);
-+bool
-+mongoc_uri_get_option_as_bool (const mongoc_uri_t *uri,
-+ const char *option,
-+ bool fallback);
-+const char*
-+mongoc_uri_get_option_as_utf8 (const mongoc_uri_t *uri,
-+ const char *option,
-+ const char *fallback);
-+bool
-+mongoc_uri_set_option_as_int32 ( mongoc_uri_t *uri,
-+ const char *option,
-+ int32_t value);
-+bool
-+mongoc_uri_set_option_as_bool ( mongoc_uri_t *uri,
-+ const char *option,
-+ bool value);
-+bool
-+mongoc_uri_set_option_as_utf8 ( mongoc_uri_t *uri,
-+ const char *option,
-+ const char *value);
-+
-+BSON_END_DECLS
-+
-+
-+#endif /* MONGOC_URI_PRIVATE_H */
-diff --git a/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-uri.c b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-uri.c
-new file mode 100644
-index 0000000..c58ae5d
---- /dev/null
-+++ b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-uri.c
-@@ -0,0 +1,1559 @@
-+/*
-+ * 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-host-list.h"
-+#include "mongoc-host-list-private.h"
-+#include "mongoc-log.h"
-+#include "mongoc-socket.h"
-+#include "mongoc-uri-private.h"
-+#include "mongoc-read-concern-private.h"
-+#include "mongoc-write-concern-private.h"
-+
-+
-+struct _mongoc_uri_t
-+{
-+ char *str;
-+ mongoc_host_list_t *hosts;
-+ char *username;
-+ char *password;
-+ char *database;
-+ bson_t options;
-+ bson_t credentials;
-+ mongoc_read_prefs_t *read_prefs;
-+ mongoc_read_concern_t *read_concern;
-+ mongoc_write_concern_t *write_concern;
-+};
-+
-+static void
-+mongoc_uri_do_unescape (char **str)
-+{
-+ char *tmp;
-+
-+ if ((tmp = *str)) {
-+ *str = mongoc_uri_unescape(tmp);
-+ bson_free(tmp);
-+ }
-+}
-+
-+void
-+mongoc_uri_lowercase_hostname (const char *src,
-+ char *buf /* OUT */,
-+ int len)
-+{
-+ bson_unichar_t c;
-+ const char *iter;
-+ char *buf_iter;
-+
-+ /* TODO: this code only accepts ascii, and assumes that lowercased
-+ chars are the same width as originals */
-+ for (iter = src, buf_iter = buf;
-+ iter && *iter && (c = bson_utf8_get_char(iter)) && buf_iter - buf < len;
-+ iter = bson_utf8_next_char(iter), buf_iter++) {
-+ assert(c < 128);
-+ *buf_iter = tolower(c);
-+ }
-+}
-+
-+void
-+mongoc_uri_append_host (mongoc_uri_t *uri,
-+ const char *host,
-+ uint16_t port)
-+{
-+ mongoc_host_list_t *iter;
-+ mongoc_host_list_t *link_;
-+
-+ link_ = (mongoc_host_list_t *)bson_malloc0(sizeof *link_);
-+ mongoc_uri_lowercase_hostname(host, link_->host, sizeof link_->host);
-+ if (strchr (host, ':')) {
-+ bson_snprintf (link_->host_and_port, sizeof link_->host_and_port,
-+ "[%s]:%hu", host, port);
-+ link_->family = AF_INET6;
-+ } else {
-+ bson_snprintf (link_->host_and_port, sizeof link_->host_and_port,
-+ "%s:%hu", host, port);
-+ link_->family = strstr (host, ".sock") ? AF_UNIX : AF_INET;
-+ }
-+ link_->host_and_port[sizeof link_->host_and_port - 1] = '\0';
-+ link_->port = port;
-+
-+ if ((iter = uri->hosts)) {
-+ for (; iter && iter->next; iter = iter->next) {}
-+ iter->next = link_;
-+ } else {
-+ uri->hosts = link_;
-+ }
-+}
-+
-+/*
-+ *--------------------------------------------------------------------------
-+ *
-+ * 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;
-+}
-+
-+
-+static bool
-+mongoc_uri_parse_scheme (const char *str,
-+ const char **end)
-+{
-+ if (!!strncmp(str, "mongodb://", 10)) {
-+ return false;
-+ }
-+
-+ *end = str + 10;
-+
-+ return true;
-+}
-+
-+
-+static bool
-+mongoc_uri_parse_userpass (mongoc_uri_t *uri,
-+ const char *str,
-+ const char **end)
-+{
-+ bool ret = false;
-+ const char *end_userpass;
-+ const char *end_user;
-+ char *s;
-+
-+ if ((s = scan_to_unichar(str, '@', "", &end_userpass))) {
-+ if ((uri->username = scan_to_unichar(s, ':', "", &end_user))) {
-+ uri->password = bson_strdup(end_user + 1);
-+ } else {
-+ uri->username = bson_strndup(str, end_userpass - str);
-+ uri->password = NULL;
-+ }
-+ mongoc_uri_do_unescape(&uri->username);
-+ mongoc_uri_do_unescape(&uri->password);
-+ *end = end_userpass + 1;
-+ bson_free(s);
-+ ret = true;
-+ } else {
-+ ret = true;
-+ }
-+
-+ return ret;
-+}
-+
-+static bool
-+mongoc_uri_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;
-+}
-+
-+
-+static bool
-+mongoc_uri_parse_host6 (mongoc_uri_t *uri,
-+ const char *str)
-+{
-+ uint16_t port = MONGOC_DEFAULT_PORT;
-+ const char *portstr;
-+ const char *end_host;
-+ char *hostname;
-+
-+ if ((portstr = strrchr (str, ':')) && !strstr (portstr, "]")) {
-+ if (!mongoc_uri_parse_port(&port, portstr + 1)) {
-+ return false;
-+ }
-+ }
-+
-+ hostname = scan_to_unichar (str + 1, ']', "", &end_host);
-+
-+ mongoc_uri_do_unescape (&hostname);
-+ if (!hostname) {
-+ return false;
-+ }
-+
-+ mongoc_uri_append_host (uri, hostname, port);
-+ bson_free (hostname);
-+
-+ return true;
-+}
-+
-+
-+bool
-+mongoc_uri_parse_host (mongoc_uri_t *uri,
-+ const char *str)
-+{
-+ uint16_t port;
-+ const char *end_host;
-+ char *hostname;
-+
-+ if (*str == '[' && strchr (str, ']')) {
-+ return mongoc_uri_parse_host6 (uri, str);
-+ }
-+
-+ if ((hostname = scan_to_unichar(str, ':', "?/,", &end_host))) {
-+ end_host++;
-+ if (!mongoc_uri_parse_port(&port, end_host)) {
-+ bson_free (hostname);
-+ return false;
-+ }
-+ } else {
-+ hostname = bson_strdup(str);
-+ port = MONGOC_DEFAULT_PORT;
-+ }
-+
-+ mongoc_uri_do_unescape(&hostname);
-+ if (!hostname) {
-+ /* invalid */
-+ bson_free (hostname);
-+ return false;
-+ }
-+
-+ mongoc_uri_append_host(uri, hostname, port);
-+ bson_free(hostname);
-+
-+ return true;
-+}
-+
-+
-+bool
-+_mongoc_host_list_from_string (mongoc_host_list_t *host_list,
-+ const char *host_and_port)
-+{
-+ bool rval = false;
-+ char *uri_str = NULL;
-+ mongoc_uri_t *uri = NULL;
-+ const mongoc_host_list_t *uri_hl;
-+
-+ BSON_ASSERT (host_list);
-+ BSON_ASSERT (host_and_port);
-+
-+ uri_str = bson_strdup_printf("mongodb://%s/", host_and_port);
-+ if (! uri_str) goto CLEANUP;
-+
-+ uri = mongoc_uri_new(uri_str);
-+ if (! uri) goto CLEANUP;
-+
-+ uri_hl = mongoc_uri_get_hosts(uri);
-+ if (uri_hl->next) goto CLEANUP;
-+
-+ memcpy(host_list, uri_hl, sizeof(*uri_hl));
-+
-+ rval = true;
-+
-+CLEANUP:
-+
-+ bson_free(uri_str);
-+ if (uri) mongoc_uri_destroy(uri);
-+
-+ return rval;
-+}
-+
-+
-+static bool
-+mongoc_uri_parse_hosts (mongoc_uri_t *uri,
-+ const char *str,
-+ const char **end)
-+{
-+ bool ret = false;
-+ const char *end_hostport;
-+ const char *sock;
-+ const char *tmp;
-+ char *s;
-+
-+ /*
-+ * 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
-+ * ",".
-+ *
-+ * When you reach a "/" or "?" that is not part of a file-system path, we
-+ * have completed our parsing of hosts.
-+ */
-+
-+again:
-+ if (((*str == '/') && (sock = strstr(str, ".sock"))) &&
-+ (!(tmp = strstr(str, ",")) || (tmp > sock)) &&
-+ (!(tmp = strstr(str, "?")) || (tmp > sock))) {
-+ s = bson_strndup(str, sock + 5 - str);
-+ if (!mongoc_uri_parse_host(uri, s)) {
-+ bson_free(s);
-+ return false;
-+ }
-+ bson_free(s);
-+ str = sock + 5;
-+ ret = true;
-+ if (*str == ',') {
-+ str++;
-+ goto again;
-+ }
-+ } else if ((s = scan_to_unichar(str, ',', "/", &end_hostport))) {
-+ if (!mongoc_uri_parse_host(uri, s)) {
-+ bson_free(s);
-+ return false;
-+ }
-+ bson_free(s);
-+ str = end_hostport + 1;
-+ ret = true;
-+ goto again;
-+ } else if ((s = scan_to_unichar(str, '/', "", &end_hostport)) ||
-+ (s = scan_to_unichar(str, '?', "", &end_hostport))) {
-+ if (!mongoc_uri_parse_host(uri, s)) {
-+ bson_free(s);
-+ return false;
-+ }
-+ bson_free(s);
-+ *end = end_hostport;
-+ return true;
-+ } else if (*str) {
-+ if (!mongoc_uri_parse_host(uri, str)) {
-+ return false;
-+ }
-+ *end = str + strlen(str);
-+ return true;
-+ }
-+
-+ return ret;
-+}
-+
-+
-+static bool
-+mongoc_uri_parse_database (mongoc_uri_t *uri,
-+ const char *str,
-+ const char **end)
-+{
-+ const char *end_database;
-+
-+ if ((uri->database = scan_to_unichar(str, '?', "", &end_database))) {
-+ *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;
-+ }
-+
-+ 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 */
-+ bson_append_document(&uri->credentials, "mechanismProperties",
-+ -1, (const bson_t *)&properties);
-+ return true;
-+}
-+
-+static void
-+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_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);
-+ }
-+ }
-+
-+ mongoc_read_prefs_add_tag(uri->read_prefs, &b);
-+ bson_destroy(&b);
-+}
-+
-+
-+/*
-+ *--------------------------------------------------------------------------
-+ *
-+ * 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_option_is_int32 (const char *key)
-+{
-+ return !strcasecmp(key, "connecttimeoutms") ||
-+ !strcasecmp(key, "heartbeatfrequencyms") ||
-+ !strcasecmp(key, "serverselectiontimeoutms") ||
-+ !strcasecmp(key, "socketcheckintervalms") ||
-+ !strcasecmp(key, "sockettimeoutms") ||
-+ !strcasecmp(key, "maxpoolsize") ||
-+ !strcasecmp(key, "minpoolsize") ||
-+ !strcasecmp(key, "maxidletimems") ||
-+ !strcasecmp(key, "waitqueuemultiple") ||
-+ !strcasecmp(key, "waitqueuetimeoutms") ||
-+ !strcasecmp(key, "wtimeoutms");
-+}
-+
-+bool
-+mongoc_uri_option_is_bool (const char *key)
-+{
-+ return !strcasecmp(key, "canonicalizeHostname") ||
-+ !strcasecmp(key, "journal") ||
-+ !strcasecmp(key, "safe") ||
-+ !strcasecmp(key, "serverSelectionTryOnce") ||
-+ !strcasecmp(key, "slaveok") ||
-+ !strcasecmp(key, "ssl");
-+}
-+
-+bool
-+mongoc_uri_option_is_utf8 (const char *key)
-+{
-+ if (mongoc_uri_option_is_bool(key) || mongoc_uri_option_is_int32(key)) {
-+ return false;
-+ }
-+
-+ if (!strcasecmp(key, "readpreferencetags") ||
-+ !strcasecmp(key, "authmechanismproperties")) {
-+ return false;
-+ }
-+
-+ if (!strcasecmp(key, "username") || !strcasecmp(key, "password")
-+ || !strcasecmp(key, "authsource") || !strcasecmp(key, "database")) {
-+ return false;
-+ }
-+
-+ return true;
-+}
-+
-+static bool
-+mongoc_uri_parse_option (mongoc_uri_t *uri,
-+ const char *str)
-+{
-+ int32_t v_int;
-+ const char *end_key;
-+ char *key = NULL;
-+ char *value = NULL;
-+ bool ret = false;
-+
-+ if (!(key = scan_to_unichar(str, '=', "", &end_key))) {
-+ goto CLEANUP;
-+ }
-+
-+ value = bson_strdup(end_key + 1);
-+ mongoc_uri_do_unescape(&value);
-+ if (!value) {
-+ /* do_unescape detected invalid UTF-8 and freed value */
-+ goto CLEANUP;
-+ }
-+
-+ if (mongoc_uri_option_is_int32(key)) {
-+ v_int = (int) strtol (value, NULL, 10);
-+ BSON_APPEND_INT32 (&uri->options, key, v_int);
-+ } else if (!strcasecmp(key, "w")) {
-+ if (*value == '-' || isdigit(*value)) {
-+ v_int = (int) strtol (value, NULL, 10);
-+ BSON_APPEND_INT32 (&uri->options, "w", v_int);
-+ } else if (0 == strcasecmp (value, "majority")) {
-+ BSON_APPEND_UTF8 (&uri->options, "w", "majority");
-+ } else if (*value) {
-+ BSON_APPEND_UTF8 (&uri->options, "w", value);
-+ }
-+ } else if (mongoc_uri_option_is_bool(key)) {
-+ bson_append_bool (&uri->options, key, -1,
-+ (0 == strcasecmp (value, "true")) ||
-+ (0 == strcasecmp (value, "t")) ||
-+ (0 == strcmp (value, "1")));
-+ } else if (!strcasecmp(key, "readpreferencetags")) {
-+ mongoc_uri_parse_tags(uri, value);
-+ } else if (!strcasecmp(key, "authmechanism") ||
-+ !strcasecmp(key, "authsource")) {
-+ bson_append_utf8(&uri->credentials, key, -1, value, -1);
-+ } else if (!strcasecmp(key, "readconcernlevel")) {
-+ mongoc_read_concern_set_level (uri->read_concern, value);
-+ } else if (!strcasecmp(key, "authmechanismproperties")) {
-+ if (!mongoc_uri_parse_auth_mechanism_properties(uri, value)) {
-+ bson_free(key);
-+ bson_free(value);
-+ return false;
-+ }
-+ } else {
-+ bson_append_utf8(&uri->options, key, -1, value, -1);
-+ }
-+
-+ ret = true;
-+
-+CLEANUP:
-+ bson_free(key);
-+ bson_free(value);
-+
-+ return ret;
-+}
-+
-+
-+static bool
-+mongoc_uri_parse_options (mongoc_uri_t *uri,
-+ const char *str)
-+{
-+ const char *end_option;
-+ char *option;
-+
-+again:
-+ if ((option = scan_to_unichar(str, '&', "", &end_option))) {
-+ if (!mongoc_uri_parse_option(uri, option)) {
-+ bson_free(option);
-+ return false;
-+ }
-+ bson_free(option);
-+ str = end_option + 1;
-+ goto again;
-+ } else if (*str) {
-+ if (!mongoc_uri_parse_option(uri, str)) {
-+ return false;
-+ }
-+ }
-+
-+ return true;
-+}
-+
-+
-+static bool
-+mongoc_uri_finalize_auth (mongoc_uri_t *uri) {
-+ bson_iter_t iter;
-+ const char *source = NULL;
-+ const char *mechanism = mongoc_uri_get_auth_mechanism(uri);
-+
-+ if (bson_iter_init_find_case(&iter, &uri->credentials, "authSource")) {
-+ source = bson_iter_utf8(&iter, NULL);
-+ }
-+
-+ /* authSource with GSSAPI or X509 should always be external */
-+ if (mechanism) {
-+ if (!strcasecmp(mechanism, "GSSAPI") ||
-+ !strcasecmp(mechanism, "MONGODB-X509")) {
-+ if (source) {
-+ if (strcasecmp(source, "$external")) {
-+ return false;
-+ }
-+ } else {
-+ bson_append_utf8(&uri->credentials, "authsource", -1, "$external", -1);
-+ }
-+ }
-+ }
-+ return true;
-+}
-+
-+static bool
-+mongoc_uri_parse (mongoc_uri_t *uri,
-+ const char *str)
-+{
-+ if (!mongoc_uri_parse_scheme(str, &str)) {
-+ return false;
-+ }
-+
-+ if (!*str || !mongoc_uri_parse_userpass(uri, str, &str)) {
-+ return false;
-+ }
-+
-+ if (!*str || !mongoc_uri_parse_hosts(uri, str, &str)) {
-+ return false;
-+ }
-+
-+ switch (*str) {
-+ case '/':
-+ str++;
-+ if (*str && !mongoc_uri_parse_database(uri, str, &str)) {
-+ return false;
-+ }
-+ if (!*str) {
-+ break;
-+ }
-+ /* Fall through */
-+ case '?':
-+ str++;
-+ if (*str && !mongoc_uri_parse_options(uri, str)) {
-+ return false;
-+ }
-+ break;
-+ default:
-+ break;
-+ }
-+
-+ return mongoc_uri_finalize_auth(uri);
-+}
-+
-+
-+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, "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, "authMechanism") &&
-+ BSON_ITER_HOLDS_UTF8 (&iter)) {
-+ return bson_iter_utf8 (&iter, NULL);
-+ }
-+
-+ return NULL;
-+}
-+
-+
-+bool
-+mongoc_uri_get_mechanism_properties (const mongoc_uri_t *uri, bson_t *properties)
-+{
-+ bson_iter_t iter;
-+
-+ if (!uri) {
-+ return false;
-+ }
-+
-+ if (bson_iter_init_find_case (&iter, &uri->credentials, "mechanismProperties") &&
-+ BSON_ITER_HOLDS_DOCUMENT (&iter)) {
-+ uint32_t len = 0;
-+ const uint8_t *data = NULL;
-+
-+ bson_iter_document (&iter, &len, &data);
-+ bson_init_static (properties, data, len);
-+
-+ return true;
-+ }
-+
-+ return false;
-+}
-+
-+
-+static void
-+_mongoc_uri_assign_read_prefs_mode (mongoc_uri_t *uri) /* IN */
-+{
-+ const char *str;
-+ bson_iter_t iter;
-+
-+ BSON_ASSERT(uri);
-+
-+ if (mongoc_uri_get_option_as_bool (uri, "slaveok", false)) {
-+ mongoc_read_prefs_set_mode(uri->read_prefs, MONGOC_READ_SECONDARY_PREFERRED);
-+ }
-+
-+ if (bson_iter_init_find_case(&iter, &uri->options, "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_WARNING("Unsupported readPreference value [readPreference=%s].", str);
-+ }
-+ }
-+
-+ /* Warn on conflict, since read preference will be validated later */
-+ if (mongoc_read_prefs_get_mode(uri->read_prefs) == MONGOC_READ_PRIMARY &&
-+ !bson_empty(mongoc_read_prefs_get_tags(uri->read_prefs))) {
-+ MONGOC_WARNING("Primary read preference mode conflicts with tags.");
-+ }
-+}
-+
-+
-+static void
-+_mongoc_uri_build_write_concern (mongoc_uri_t *uri) /* IN */
-+{
-+ mongoc_write_concern_t *write_concern;
-+ const char *str;
-+ bson_iter_t iter;
-+ int32_t wtimeoutms;
-+ int value;
-+
-+ BSON_ASSERT (uri);
-+
-+ write_concern = mongoc_write_concern_new ();
-+
-+ if (bson_iter_init_find_case (&iter, &uri->options, "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_int32(uri, "wtimeoutms", 0);
-+
-+ if (bson_iter_init_find_case (&iter, &uri->options, "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, "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:
-+ /* Warn on conflict, since write concern will be validated later */
-+ if (mongoc_write_concern_get_journal(write_concern)) {
-+ MONGOC_WARNING("Journal conflicts with w value [w=%d].", value);
-+ }
-+ mongoc_write_concern_set_w(write_concern, value);
-+ break;
-+ default:
-+ if (value > 0) {
-+ mongoc_write_concern_set_w (write_concern, value);
-+ if (value > 1) {
-+ mongoc_write_concern_set_wtimeout (write_concern, wtimeoutms);
-+ }
-+ break;
-+ }
-+ MONGOC_WARNING ("Unsupported w value [w=%d].", value);
-+ break;
-+ }
-+ } else if (BSON_ITER_HOLDS_UTF8 (&iter)) {
-+ str = bson_iter_utf8 (&iter, NULL);
-+
-+ if (0 == strcasecmp ("majority", str)) {
-+ mongoc_write_concern_set_wmajority (write_concern, wtimeoutms);
-+ } else {
-+ mongoc_write_concern_set_wtag (write_concern, str);
-+ mongoc_write_concern_set_wtimeout (write_concern, wtimeoutms);
-+ }
-+ } else {
-+ BSON_ASSERT (false);
-+ }
-+ }
-+
-+ uri->write_concern = write_concern;
-+}
-+
-+
-+mongoc_uri_t *
-+mongoc_uri_new (const char *uri_string)
-+{
-+ mongoc_uri_t *uri;
-+
-+ uri = (mongoc_uri_t *)bson_malloc0(sizeof *uri);
-+ bson_init(&uri->options);
-+ bson_init(&uri->credentials);
-+
-+ /* Initialize read_prefs since tag 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)) {
-+ mongoc_uri_destroy(uri);
-+ return NULL;
-+ }
-+
-+ uri->str = bson_strdup(uri_string);
-+
-+ _mongoc_uri_assign_read_prefs_mode(uri);
-+
-+ if (!mongoc_read_prefs_is_valid(uri->read_prefs)) {
-+ mongoc_uri_destroy(uri);
-+ return NULL;
-+ }
-+
-+ _mongoc_uri_build_write_concern (uri);
-+
-+ if (!_mongoc_write_concern_is_valid(uri->write_concern)) {
-+ mongoc_uri_destroy(uri);
-+ return NULL;
-+ }
-+
-+ 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;
-+
-+ BSON_ASSERT (uri);
-+
-+ if (bson_iter_init_find_case(&iter, &uri->credentials, "authSource")) {
-+ return bson_iter_utf8(&iter, NULL);
-+ }
-+
-+ 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, "authSource", value);
-+
-+ return true;
-+}
-+
-+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->options);
-+ bson_destroy(&uri->credentials);
-+ 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_ASSERT (uri);
-+
-+ copy = (mongoc_uri_t *)bson_malloc0(sizeof (*copy));
-+
-+ copy->str = bson_strdup (uri->str);
-+ 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);
-+
-+ for (iter = uri->hosts; iter; iter = iter->next) {
-+ mongoc_uri_append_host (copy, iter->host, iter->port);
-+ }
-+
-+ bson_copy_to (&uri->options, &copy->options);
-+ bson_copy_to (&uri->credentials, &copy->credentials);
-+
-+ 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);
-+}
-+
-+
-+/*
-+ *--------------------------------------------------------------------------
-+ *
-+ * mongoc_uri_unescape --
-+ *
-+ * Escapes an UTF-8 encoded string containing URI escaped segments
-+ * such as %20.
-+ *
-+ * It is a programming error to call this function with a string
-+ * that is not UTF-8 encoded!
-+ *
-+ * Returns:
-+ * A newly allocated string that should be freed with bson_free().
-+ *
-+ * Side effects:
-+ * None.
-+ *
-+ *--------------------------------------------------------------------------
-+ */
-+
-+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;
-+
-+ 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
-+ !isprint(hex)) {
-+ bson_string_free(str, true);
-+ return NULL;
-+ }
-+ bson_string_append_c(str, hex);
-+ ptr += 2;
-+ break;
-+ default:
-+ bson_string_append_unichar(str, c);
-+ break;
-+ }
-+ }
-+
-+ 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;
-+}
-+
-+
-+const mongoc_read_concern_t *
-+mongoc_uri_get_read_concern (const mongoc_uri_t *uri) /* IN */
-+{
-+ BSON_ASSERT (uri);
-+
-+ return uri->read_concern;
-+}
-+
-+
-+const mongoc_write_concern_t *
-+mongoc_uri_get_write_concern (const mongoc_uri_t *uri) /* IN */
-+{
-+ BSON_ASSERT (uri);
-+
-+ return uri->write_concern;
-+}
-+
-+
-+bool
-+mongoc_uri_get_ssl (const mongoc_uri_t *uri) /* IN */
-+{
-+ bson_iter_t iter;
-+
-+ BSON_ASSERT (uri);
-+
-+ return (bson_iter_init_find_case (&iter, &uri->options, "ssl") &&
-+ BSON_ITER_HOLDS_BOOL (&iter) &&
-+ bson_iter_bool (&iter));
-+}
-+
-+/*
-+ *--------------------------------------------------------------------------
-+ *
-+ * 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,
-+ int32_t fallback)
-+{
-+ const bson_t *options;
-+ bson_iter_t iter;
-+ int32_t retval = fallback;
-+
-+ if ((options = mongoc_uri_get_options (uri)) &&
-+ bson_iter_init_find_case (&iter, options, option) &&
-+ BSON_ITER_HOLDS_INT32 (&iter)) {
-+
-+ if (!(retval = bson_iter_int32(&iter))) {
-+ retval = fallback;
-+ }
-+ }
-+
-+ return 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,
-+ int32_t value)
-+{
-+ const bson_t *options;
-+ bson_iter_t iter;
-+
-+ BSON_ASSERT (option);
-+
-+ if (!mongoc_uri_option_is_int32 (option)) {
-+ 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 {
-+ return false;
-+ }
-+ }
-+
-+ bson_append_int32(&uri->options, option, -1, value);
-+ 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,
-+ bool fallback)
-+{
-+ const bson_t *options;
-+ bson_iter_t iter;
-+
-+ 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,
-+ bool value)
-+{
-+ const bson_t *options;
-+ bson_iter_t iter;
-+
-+ 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;
-+ }
-+ }
-+ bson_append_bool(&uri->options, option, -1, value);
-+ 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,
-+ const char *fallback)
-+{
-+ const bson_t *options;
-+ bson_iter_t iter;
-+
-+ 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,
-+ const char *value)
-+{
-+ size_t len;
-+
-+ BSON_ASSERT (option);
-+
-+ len = strlen(value);
-+
-+ if (!bson_utf8_validate (value, len, false)) {
-+ return false;
-+ }
-+
-+ if (!mongoc_uri_option_is_utf8 (option)) {
-+ return false;
-+ }
-+
-+ mongoc_uri_bson_append_or_replace_key (&uri->options, option, value);
-+
-+ return true;
-+}
-+
-diff --git a/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-util-private.h b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-util-private.h
-new file mode 100644
-index 0000000..8e7f5a3
---- /dev/null
-+++ b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-util-private.h
-@@ -0,0 +1,56 @@
-+/*
-+ * 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.
-+ */
-+
-+#ifndef MONGOC_UTIL_PRIVATE_H
-+#define MONGOC_UTIL_PRIVATE_H
-+
-+#if !defined (MONGOC_I_AM_A_DRIVER) && !defined (MONGOC_COMPILATION)
-+#error "Only <mongoc.h> can be included directly."
-+#endif
-+
-+#include <bson.h>
-+
-+/* string comparison functions for Windows */
-+#ifdef _WIN32
-+# define strcasecmp _stricmp
-+# define strncasecmp _strnicmp
-+#endif
-+
-+/* Suppress CWE-252 ("Unchecked return value") warnings for things we can't deal with */
-+#if defined(__GNUC__) && __GNUC__ >= 4
-+# define _ignore_value(x) (({ __typeof__ (x) __x = (x); (void) __x; }))
-+#else
-+# define _ignore_value(x) ((void) (x))
-+#endif
-+
-+
-+BSON_BEGIN_DECLS
-+
-+
-+char *_mongoc_hex_md5 (const char *input);
-+
-+void _mongoc_usleep (int64_t usec);
-+
-+const char *_mongoc_get_command_name (const bson_t *command);
-+
-+void _mongoc_get_db_name (const char *ns,
-+ char *db /* OUT */);
-+
-+void _mongoc_bson_destroy_if_set (bson_t *bson);
-+BSON_END_DECLS
-+
-+
-+#endif /* MONGOC_UTIL_PRIVATE_H */
-diff --git a/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-write-command-private.h b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-write-command-private.h
-new file mode 100644
-index 0000000..c9525a8
---- /dev/null
-+++ b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-write-command-private.h
-@@ -0,0 +1,147 @@
-+/*
-+ * 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.
-+ */
-+
-+#ifndef MONGOC_WRITE_COMMAND_PRIVATE_H
-+#define MONGOC_WRITE_COMMAND_PRIVATE_H
-+
-+#if !defined (MONGOC_I_AM_A_DRIVER) && !defined (MONGOC_COMPILATION)
-+#error "Only <mongoc.h> can be included directly."
-+#endif
-+
-+#include <bson.h>
-+
-+#include "mongoc-client.h"
-+#include "mongoc-error.h"
-+#include "mongoc-write-concern.h"
-+#include "mongoc-server-stream-private.h"
-+
-+
-+BSON_BEGIN_DECLS
-+
-+
-+#define MONGOC_WRITE_COMMAND_DELETE 0
-+#define MONGOC_WRITE_COMMAND_INSERT 1
-+#define MONGOC_WRITE_COMMAND_UPDATE 2
-+
-+
-+typedef enum
-+{
-+ MONGOC_BYPASS_DOCUMENT_VALIDATION_FALSE = 0,
-+ MONGOC_BYPASS_DOCUMENT_VALIDATION_TRUE = 1 << 0,
-+ MONGOC_BYPASS_DOCUMENT_VALIDATION_DEFAULT = 1 << 1,
-+} mongoc_write_bypass_document_validation_t;
-+
-+struct _mongoc_bulk_write_flags_t
-+{
-+ bool ordered;
-+ mongoc_write_bypass_document_validation_t bypass_document_validation;
-+};
-+
-+
-+typedef struct
-+{
-+ int type;
-+ uint32_t hint;
-+ bson_t *documents;
-+ uint32_t n_documents;
-+ mongoc_bulk_write_flags_t flags;
-+ union {
-+ struct {
-+ bool multi;
-+ } delete_;
-+ struct {
-+ bool allow_bulk_op_insert;
-+ } insert;
-+ } u;
-+} mongoc_write_command_t;
-+
-+
-+typedef struct
-+{
-+ /* true after a legacy update prevents us from calculating nModified */
-+ bool omit_nModified;
-+ uint32_t nInserted;
-+ uint32_t nMatched;
-+ uint32_t nModified;
-+ uint32_t nRemoved;
-+ uint32_t nUpserted;
-+ /* like [{"index": int, "_id": value}, ...] */
-+ bson_t writeErrors;
-+ /* like [{"index": int, "code": int, "errmsg": str}, ...] */
-+ bson_t upserted;
-+ /* like [{"code": 64, "errmsg": "duplicate"}, ...] */
-+ uint32_t n_writeConcernErrors;
-+ bson_t writeConcernErrors;
-+ bool failed;
-+ bson_error_t error;
-+ uint32_t upsert_append_count;
-+} mongoc_write_result_t;
-+
-+
-+void _mongoc_write_command_destroy (mongoc_write_command_t *command);
-+void _mongoc_write_command_init_insert (mongoc_write_command_t *command,
-+ const bson_t *document,
-+ mongoc_bulk_write_flags_t flags,
-+ bool allow_bulk_op_insert);
-+void _mongoc_write_command_init_delete (mongoc_write_command_t *command,
-+ const bson_t *selectors,
-+ bool multi,
-+ mongoc_bulk_write_flags_t flags);
-+void _mongoc_write_command_init_update (mongoc_write_command_t *command,
-+ const bson_t *selector,
-+ const bson_t *update,
-+ bool upsert,
-+ bool multi,
-+ mongoc_bulk_write_flags_t flags);
-+void _mongoc_write_command_insert_append (mongoc_write_command_t *command,
-+ const bson_t *document);
-+void _mongoc_write_command_update_append (mongoc_write_command_t *command,
-+ const bson_t *selector,
-+ const bson_t *update,
-+ bool upsert,
-+ bool multi);
-+
-+void _mongoc_write_command_delete_append (mongoc_write_command_t *command,
-+ const bson_t *selector);
-+
-+void _mongoc_write_command_execute (mongoc_write_command_t *command,
-+ mongoc_client_t *client,
-+ mongoc_server_stream_t *server_stream,
-+ const char *database,
-+ const char *collection,
-+ const mongoc_write_concern_t *write_concern,
-+ uint32_t offset,
-+ mongoc_write_result_t *result);
-+void _mongoc_write_result_init (mongoc_write_result_t *result);
-+void _mongoc_write_result_merge (mongoc_write_result_t *result,
-+ mongoc_write_command_t *command,
-+ const bson_t *reply,
-+ uint32_t offset);
-+void _mongoc_write_result_merge_legacy (mongoc_write_result_t *result,
-+ mongoc_write_command_t *command,
-+ const bson_t *reply,
-+ mongoc_error_code_t default_code,
-+ uint32_t offset);
-+bool _mongoc_write_result_complete (mongoc_write_result_t *result,
-+ bson_t *reply,
-+ bson_error_t *error);
-+void _mongoc_write_result_destroy (mongoc_write_result_t *result);
-+
-+
-+BSON_END_DECLS
-+
-+
-+#endif /* MONGOC_WRITE_COMMAND_PRIVATE_H */
-diff --git a/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-write-command.c b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-write-command.c
-new file mode 100644
-index 0000000..a062c88
---- /dev/null
-+++ b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-write-command.c
-@@ -0,0 +1,1527 @@
-+/*
-+ * 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.h>
-+
-+#include "mongoc-client-private.h"
-+#include "mongoc-error.h"
-+#include "mongoc-trace.h"
-+#include "mongoc-write-command-private.h"
-+#include "mongoc-write-concern-private.h"
-+#include "mongoc-util-private.h"
-+
-+
-+/*
-+ * TODO:
-+ *
-+ * - Remove error parameter to ops, favor result->error.
-+ */
-+
-+#define WRITE_CONCERN_DOC(wc) \
-+ (wc && _mongoc_write_concern_needs_gle ((wc))) ? \
-+ (_mongoc_write_concern_get_bson((mongoc_write_concern_t*)(wc))) : \
-+ (&gEmptyWriteConcern)
-+
-+typedef void (*mongoc_write_op_t) (mongoc_write_command_t *command,
-+ mongoc_client_t *client,
-+ mongoc_server_stream_t *server_stream,
-+ const char *database,
-+ const char *collection,
-+ const mongoc_write_concern_t *write_concern,
-+ uint32_t offset,
-+ mongoc_write_result_t *result,
-+ bson_error_t *error);
-+
-+
-+static bson_t gEmptyWriteConcern = BSON_INITIALIZER;
-+
-+/* indexed by MONGOC_WRITE_COMMAND_DELETE, INSERT, UPDATE */
-+static const char *gCommandNames[] = { "delete", "insert", "update"};
-+static const char *gCommandFields[] = { "deletes", "documents", "updates"};
-+static const uint32_t gCommandFieldLens[] = { 7, 9, 7 };
-+
-+static int32_t
-+_mongoc_write_result_merge_arrays (uint32_t offset,
-+ mongoc_write_result_t *result,
-+ bson_t *dest,
-+ bson_iter_t *iter);
-+
-+void
-+_mongoc_write_command_insert_append (mongoc_write_command_t *command,
-+ const bson_t *document)
-+{
-+ const char *key;
-+ bson_iter_t iter;
-+ bson_oid_t oid;
-+ bson_t tmp;
-+ char keydata [16];
-+
-+ ENTRY;
-+
-+ BSON_ASSERT (command);
-+ BSON_ASSERT (command->type == MONGOC_WRITE_COMMAND_INSERT);
-+ BSON_ASSERT (document);
-+ BSON_ASSERT (document->len >= 5);
-+
-+ key = NULL;
-+ bson_uint32_to_string (command->n_documents,
-+ &key, keydata, sizeof keydata);
-+
-+ BSON_ASSERT (key);
-+
-+ /*
-+ * If the document does not contain an "_id" field, we need to generate
-+ * a new oid for "_id".
-+ */
-+ if (!bson_iter_init_find (&iter, document, "_id")) {
-+ bson_init (&tmp);
-+ bson_oid_init (&oid, NULL);
-+ BSON_APPEND_OID (&tmp, "_id", &oid);
-+ bson_concat (&tmp, document);
-+ BSON_APPEND_DOCUMENT (command->documents, key, &tmp);
-+ bson_destroy (&tmp);
-+ } else {
-+ BSON_APPEND_DOCUMENT (command->documents, key, document);
-+ }
-+
-+ command->n_documents++;
-+
-+ EXIT;
-+}
-+
-+void
-+_mongoc_write_command_update_append (mongoc_write_command_t *command,
-+ const bson_t *selector,
-+ const bson_t *update,
-+ bool upsert,
-+ bool multi)
-+{
-+ const char *key;
-+ char keydata [16];
-+ bson_t doc;
-+
-+ ENTRY;
-+
-+ BSON_ASSERT (command);
-+ BSON_ASSERT (command->type == MONGOC_WRITE_COMMAND_UPDATE);
-+ BSON_ASSERT (selector && update);
-+
-+ bson_init (&doc);
-+ BSON_APPEND_DOCUMENT (&doc, "q", selector);
-+ BSON_APPEND_DOCUMENT (&doc, "u", update);
-+ BSON_APPEND_BOOL (&doc, "upsert", upsert);
-+ BSON_APPEND_BOOL (&doc, "multi", multi);
-+
-+ key = NULL;
-+ bson_uint32_to_string (command->n_documents, &key, keydata, sizeof keydata);
-+ BSON_ASSERT (key);
-+ BSON_APPEND_DOCUMENT (command->documents, key, &doc);
-+ command->n_documents++;
-+
-+ bson_destroy (&doc);
-+
-+ EXIT;
-+}
-+
-+void
-+_mongoc_write_command_delete_append (mongoc_write_command_t *command,
-+ const bson_t *selector)
-+{
-+ const char *key;
-+ char keydata [16];
-+ bson_t doc;
-+
-+ ENTRY;
-+
-+ BSON_ASSERT (command);
-+ BSON_ASSERT (command->type == MONGOC_WRITE_COMMAND_DELETE);
-+ BSON_ASSERT (selector);
-+
-+ BSON_ASSERT (selector->len >= 5);
-+
-+ bson_init (&doc);
-+ BSON_APPEND_DOCUMENT (&doc, "q", selector);
-+ BSON_APPEND_INT32 (&doc, "limit", command->u.delete_.multi ? 0 : 1);
-+
-+ key = NULL;
-+ bson_uint32_to_string (command->n_documents, &key, keydata, sizeof keydata);
-+ BSON_ASSERT (key);
-+ BSON_APPEND_DOCUMENT (command->documents, key, &doc);
-+ command->n_documents++;
-+
-+ bson_destroy (&doc);
-+
-+ EXIT;
-+}
-+
-+void
-+_mongoc_write_command_init_insert (mongoc_write_command_t *command, /* IN */
-+ const bson_t *document, /* IN */
-+ mongoc_bulk_write_flags_t flags, /* IN */
-+ bool allow_bulk_op_insert) /* IN */
-+{
-+ ENTRY;
-+
-+ BSON_ASSERT (command);
-+
-+ command->type = MONGOC_WRITE_COMMAND_INSERT;
-+ command->documents = bson_new ();
-+ command->n_documents = 0;
-+ command->flags = flags;
-+ command->u.insert.allow_bulk_op_insert = (uint8_t)allow_bulk_op_insert;
-+ command->hint = 0;
-+
-+ /* must handle NULL document from mongoc_collection_insert_bulk */
-+ if (document) {
-+ _mongoc_write_command_insert_append (command, document);
-+ }
-+
-+ EXIT;
-+}
-+
-+
-+void
-+_mongoc_write_command_init_delete (mongoc_write_command_t *command, /* IN */
-+ const bson_t *selector, /* IN */
-+ bool multi, /* IN */
-+ mongoc_bulk_write_flags_t flags) /* IN */
-+{
-+ ENTRY;
-+
-+ BSON_ASSERT (command);
-+ BSON_ASSERT (selector);
-+
-+ command->type = MONGOC_WRITE_COMMAND_DELETE;
-+ command->documents = bson_new ();
-+ command->n_documents = 0;
-+ command->u.delete_.multi = (uint8_t)multi;
-+ command->flags = flags;
-+ command->hint = 0;
-+
-+ _mongoc_write_command_delete_append (command, selector);
-+
-+ EXIT;
-+}
-+
-+
-+void
-+_mongoc_write_command_init_update (mongoc_write_command_t *command, /* IN */
-+ const bson_t *selector, /* IN */
-+ const bson_t *update, /* IN */
-+ bool upsert, /* IN */
-+ bool multi, /* IN */
-+ mongoc_bulk_write_flags_t flags) /* IN */
-+{
-+ ENTRY;
-+
-+ BSON_ASSERT (command);
-+ BSON_ASSERT (selector);
-+ BSON_ASSERT (update);
-+
-+ command->type = MONGOC_WRITE_COMMAND_UPDATE;
-+ command->documents = bson_new ();
-+ command->n_documents = 0;
-+ command->flags = flags;
-+ command->hint = 0;
-+
-+ _mongoc_write_command_update_append (command, selector, update, upsert, multi);
-+
-+ EXIT;
-+}
-+
-+
-+static void
-+_mongoc_write_command_delete_legacy (mongoc_write_command_t *command,
-+ mongoc_client_t *client,
-+ mongoc_server_stream_t *server_stream,
-+ const char *database,
-+ const char *collection,
-+ const mongoc_write_concern_t *write_concern,
-+ uint32_t offset,
-+ mongoc_write_result_t *result,
-+ bson_error_t *error)
-+{
-+ const uint8_t *data;
-+ mongoc_rpc_t rpc;
-+ bson_iter_t iter;
-+ bson_iter_t q_iter;
-+ uint32_t len;
-+ bson_t *gle = NULL;
-+ char ns [MONGOC_NAMESPACE_MAX + 1];
-+ bool r;
-+
-+ ENTRY;
-+
-+ BSON_ASSERT (command);
-+ BSON_ASSERT (client);
-+ BSON_ASSERT (database);
-+ BSON_ASSERT (server_stream);
-+ BSON_ASSERT (collection);
-+
-+ r = bson_iter_init (&iter, command->documents);
-+
-+ if (!r) {
-+ BSON_ASSERT (false);
-+ EXIT;
-+ }
-+
-+ if (!command->n_documents || !bson_iter_next (&iter)) {
-+ bson_set_error (error,
-+ MONGOC_ERROR_COLLECTION,
-+ MONGOC_ERROR_COLLECTION_DELETE_FAILED,
-+ "Cannot do an empty delete.");
-+ result->failed = true;
-+ EXIT;
-+ }
-+
-+ bson_snprintf (ns, sizeof ns, "%s.%s", database, collection);
-+
-+ do {
-+ /* the document is like { "q": { <selector> }, limit: <0 or 1> } */
-+ r = (bson_iter_recurse (&iter, &q_iter) &&
-+ bson_iter_find (&q_iter, "q") &&
-+ BSON_ITER_HOLDS_DOCUMENT (&q_iter));
-+
-+ if (!r) {
-+ BSON_ASSERT (false);
-+ EXIT;
-+ }
-+
-+ bson_iter_document (&q_iter, &len, &data);
-+ BSON_ASSERT (data);
-+ BSON_ASSERT (len >= 5);
-+
-+ rpc.delete_.msg_len = 0;
-+ rpc.delete_.request_id = 0;
-+ rpc.delete_.response_to = 0;
-+ rpc.delete_.opcode = MONGOC_OPCODE_DELETE;
-+ rpc.delete_.zero = 0;
-+ rpc.delete_.collection = ns;
-+ rpc.delete_.flags = command->u.delete_.multi ? MONGOC_DELETE_NONE
-+ : MONGOC_DELETE_SINGLE_REMOVE;
-+ rpc.delete_.selector = data;
-+
-+ if (!mongoc_cluster_sendv_to_server (&client->cluster,
-+ &rpc, 1, server_stream,
-+ write_concern, error)) {
-+ result->failed = true;
-+ EXIT;
-+ }
-+
-+ if (_mongoc_write_concern_needs_gle (write_concern)) {
-+ if (!_mongoc_client_recv_gle (client, server_stream, &gle, error)) {
-+ result->failed = true;
-+ EXIT;
-+ }
-+
-+ _mongoc_write_result_merge_legacy (
-+ result, command, gle,
-+ MONGOC_ERROR_COLLECTION_DELETE_FAILED, offset);
-+
-+ offset++;
-+ bson_destroy (gle);
-+ }
-+ } while (bson_iter_next (&iter));
-+
-+ EXIT;
-+}
-+
-+
-+/*
-+ *-------------------------------------------------------------------------
-+ *
-+ * too_large_error --
-+ *
-+ * Fill a bson_error_t and optional bson_t with error info after
-+ * receiving a document for bulk insert, update, or remove that is
-+ * larger than max_bson_size.
-+ *
-+ * "err_doc" should be NULL or an empty initialized bson_t.
-+ *
-+ * Returns:
-+ * None.
-+ *
-+ * Side effects:
-+ * "error" and optionally "err_doc" are filled out.
-+ *
-+ *-------------------------------------------------------------------------
-+ */
-+
-+static void
-+too_large_error (bson_error_t *error,
-+ int32_t idx,
-+ int32_t len,
-+ int32_t max_bson_size,
-+ bson_t *err_doc)
-+{
-+ /* MongoDB 2.6 uses code 2 for "too large". TODO: see CDRIVER-644 */
-+ const int code = 2;
-+
-+ bson_set_error (error, MONGOC_ERROR_BSON, code,
-+ "Document %u is too large for the cluster. "
-+ "Document is %u bytes, max is %d.",
-+ idx, len, max_bson_size);
-+
-+ if (err_doc) {
-+ BSON_APPEND_INT32 (err_doc, "index", idx);
-+ BSON_APPEND_UTF8 (err_doc, "err", error->message);
-+ BSON_APPEND_INT32 (err_doc, "code", code);
-+ }
-+}
-+
-+
-+static void
-+_mongoc_write_command_insert_legacy (mongoc_write_command_t *command,
-+ mongoc_client_t *client,
-+ mongoc_server_stream_t *server_stream,
-+ const char *database,
-+ const char *collection,
-+ const mongoc_write_concern_t *write_concern,
-+ uint32_t offset,
-+ mongoc_write_result_t *result,
-+ bson_error_t *error)
-+{
-+ uint32_t current_offset;
-+ mongoc_iovec_t *iov;
-+ const uint8_t *data;
-+ mongoc_rpc_t rpc;
-+ bson_iter_t iter;
-+ uint32_t len;
-+ bson_t *gle = NULL;
-+ uint32_t size = 0;
-+ bool has_more;
-+ char ns [MONGOC_NAMESPACE_MAX + 1];
-+ bool r;
-+ uint32_t n_docs_in_batch;
-+ uint32_t idx = 0;
-+ int32_t max_msg_size;
-+ int32_t max_bson_obj_size;
-+ bool singly;
-+
-+ ENTRY;
-+
-+ BSON_ASSERT (command);
-+ BSON_ASSERT (client);
-+ BSON_ASSERT (database);
-+ BSON_ASSERT (server_stream);
-+ BSON_ASSERT (collection);
-+ BSON_ASSERT (command->type == MONGOC_WRITE_COMMAND_INSERT);
-+
-+ current_offset = offset;
-+
-+ max_bson_obj_size = mongoc_server_stream_max_bson_obj_size (server_stream);
-+ max_msg_size = mongoc_server_stream_max_msg_size (server_stream);
-+
-+ singly = !command->u.insert.allow_bulk_op_insert;
-+
-+ r = bson_iter_init (&iter, command->documents);
-+
-+ if (!r) {
-+ BSON_ASSERT (false);
-+ EXIT;
-+ }
-+
-+ if (!command->n_documents || !bson_iter_next (&iter)) {
-+ bson_set_error (error,
-+ MONGOC_ERROR_COLLECTION,
-+ MONGOC_ERROR_COLLECTION_INSERT_FAILED,
-+ "Cannot do an empty insert.");
-+ result->failed = true;
-+ EXIT;
-+ }
-+
-+ bson_snprintf (ns, sizeof ns, "%s.%s", database, collection);
-+
-+ iov = (mongoc_iovec_t *)bson_malloc ((sizeof *iov) * command->n_documents);
-+
-+again:
-+ has_more = false;
-+ n_docs_in_batch = 0;
-+ size = (uint32_t)(sizeof (mongoc_rpc_header_t) +
-+ 4 +
-+ strlen (database) +
-+ 1 +
-+ strlen (collection) +
-+ 1);
-+
-+ do {
-+ BSON_ASSERT (BSON_ITER_HOLDS_DOCUMENT (&iter));
-+ BSON_ASSERT (n_docs_in_batch <= idx);
-+ BSON_ASSERT (idx < command->n_documents);
-+
-+ bson_iter_document (&iter, &len, &data);
-+
-+ BSON_ASSERT (data);
-+ BSON_ASSERT (len >= 5);
-+
-+ if (len > max_bson_obj_size) {
-+ /* document is too large */
-+ bson_t write_err_doc = BSON_INITIALIZER;
-+
-+ too_large_error (error, idx, len,
-+ max_bson_obj_size, &write_err_doc);
-+
-+ _mongoc_write_result_merge_legacy (
-+ result, command, &write_err_doc,
-+ MONGOC_ERROR_COLLECTION_INSERT_FAILED, offset + idx);
-+
-+ bson_destroy (&write_err_doc);
-+
-+ if (command->flags.ordered) {
-+ /* send the batch so far (if any) and return the error */
-+ break;
-+ }
-+ } else if ((n_docs_in_batch == 1 && singly) || size > (max_msg_size - len)) {
-+ /* batch is full, send it and then start the next batch */
-+ has_more = true;
-+ break;
-+ } else {
-+ /* add document to batch and continue building the batch */
-+ iov[n_docs_in_batch].iov_base = (void *) data;
-+ iov[n_docs_in_batch].iov_len = len;
-+ size += len;
-+ n_docs_in_batch++;
-+ }
-+
-+ idx++;
-+ } while (bson_iter_next (&iter));
-+
-+ if (n_docs_in_batch) {
-+ rpc.insert.msg_len = 0;
-+ rpc.insert.request_id = 0;
-+ rpc.insert.response_to = 0;
-+ rpc.insert.opcode = MONGOC_OPCODE_INSERT;
-+ rpc.insert.flags = (
-+ (command->flags.ordered) ? MONGOC_INSERT_NONE
-+ : MONGOC_INSERT_CONTINUE_ON_ERROR);
-+ rpc.insert.collection = ns;
-+ rpc.insert.documents = iov;
-+ rpc.insert.n_documents = n_docs_in_batch;
-+
-+ if (!mongoc_cluster_sendv_to_server (&client->cluster,
-+ &rpc, 1, server_stream,
-+ write_concern, error)) {
-+ result->failed = true;
-+ GOTO (cleanup);
-+ }
-+
-+ if (_mongoc_write_concern_needs_gle (write_concern)) {
-+ bool err = false;
-+ bson_iter_t citer;
-+
-+ if (!_mongoc_client_recv_gle (client, server_stream, &gle, error)) {
-+ result->failed = true;
-+ GOTO (cleanup);
-+ }
-+
-+ err = (bson_iter_init_find (&citer, gle, "err")
-+ && bson_iter_as_bool (&citer));
-+
-+ /*
-+ * Overwrite the "n" field since it will be zero. Otherwise, our
-+ * merge_legacy code will not know how many we tried in this batch.
-+ */
-+ if (!err &&
-+ bson_iter_init_find (&citer, gle, "n") &&
-+ BSON_ITER_HOLDS_INT32 (&citer) &&
-+ !bson_iter_int32 (&citer)) {
-+ bson_iter_overwrite_int32 (&citer, n_docs_in_batch);
-+ }
-+ }
-+ }
-+
-+cleanup:
-+
-+ if (gle) {
-+ _mongoc_write_result_merge_legacy (
-+ result, command, gle, MONGOC_ERROR_COLLECTION_INSERT_FAILED,
-+ current_offset);
-+
-+ current_offset = offset + idx;
-+ bson_destroy (gle);
-+ gle = NULL;
-+ }
-+
-+ if (has_more) {
-+ GOTO (again);
-+ }
-+
-+ bson_free (iov);
-+
-+ EXIT;
-+}
-+
-+
-+void
-+_empty_error (mongoc_write_command_t *command,
-+ bson_error_t *error)
-+{
-+ static const uint32_t codes[] = {
-+ MONGOC_ERROR_COLLECTION_DELETE_FAILED,
-+ MONGOC_ERROR_COLLECTION_INSERT_FAILED,
-+ MONGOC_ERROR_COLLECTION_UPDATE_FAILED
-+ };
-+
-+ bson_set_error (error,
-+ MONGOC_ERROR_COLLECTION,
-+ codes[command->type],
-+ "Cannot do an empty %s",
-+ gCommandNames[command->type]);
-+}
-+
-+
-+bool
-+_mongoc_write_command_will_overflow (uint32_t len_so_far,
-+ uint32_t document_len,
-+ uint32_t n_documents_written,
-+ int32_t max_bson_size,
-+ int32_t max_write_batch_size)
-+{
-+ /* max BSON object size + 16k bytes.
-+ * server guarantees there is enough room: SERVER-10643
-+ */
-+ int32_t max_cmd_size = max_bson_size + 16384;
-+
-+ BSON_ASSERT (max_bson_size);
-+
-+ if (len_so_far + document_len > max_cmd_size) {
-+ return true;
-+ } else if (max_write_batch_size > 0 &&
-+ n_documents_written >= max_write_batch_size) {
-+ return true;
-+ }
-+
-+ return false;
-+}
-+
-+
-+static void
-+_mongoc_write_command_update_legacy (mongoc_write_command_t *command,
-+ mongoc_client_t *client,
-+ mongoc_server_stream_t *server_stream,
-+ const char *database,
-+ const char *collection,
-+ const mongoc_write_concern_t *write_concern,
-+ uint32_t offset,
-+ mongoc_write_result_t *result,
-+ bson_error_t *error)
-+{
-+ mongoc_rpc_t rpc;
-+ bson_iter_t iter, subiter, subsubiter;
-+ bson_t doc;
-+ bool has_update, has_selector, is_upsert;
-+ bson_t update, selector;
-+ bson_t *gle = NULL;
-+ const uint8_t *data = NULL;
-+ uint32_t len = 0;
-+ size_t err_offset;
-+ bool val = false;
-+ char ns [MONGOC_NAMESPACE_MAX + 1];
-+ int32_t affected = 0;
-+ int vflags = (BSON_VALIDATE_UTF8 | BSON_VALIDATE_UTF8_ALLOW_NULL
-+ | BSON_VALIDATE_DOLLAR_KEYS | BSON_VALIDATE_DOT_KEYS);
-+
-+ ENTRY;
-+
-+ BSON_ASSERT (command);
-+ BSON_ASSERT (client);
-+ BSON_ASSERT (database);
-+ BSON_ASSERT (server_stream);
-+ BSON_ASSERT (collection);
-+
-+ bson_iter_init (&iter, command->documents);
-+ while (bson_iter_next (&iter)) {
-+ if (bson_iter_recurse (&iter, &subiter) &&
-+ bson_iter_find (&subiter, "u") &&
-+ BSON_ITER_HOLDS_DOCUMENT (&subiter)) {
-+ bson_iter_document (&subiter, &len, &data);
-+ bson_init_static (&doc, data, len);
-+
-+ if (bson_iter_init (&subsubiter, &doc) &&
-+ bson_iter_next (&subsubiter) &&
-+ (bson_iter_key (&subsubiter) [0] != '$') &&
-+ !bson_validate (&doc, (bson_validate_flags_t)vflags, &err_offset)) {
-+ result->failed = true;
-+ bson_set_error (error,
-+ MONGOC_ERROR_BSON,
-+ MONGOC_ERROR_BSON_INVALID,
-+ "update document is corrupt or contains "
-+ "invalid keys including $ or .");
-+ EXIT;
-+ }
-+ } else {
-+ result->failed = true;
-+ bson_set_error (error,
-+ MONGOC_ERROR_BSON,
-+ MONGOC_ERROR_BSON_INVALID,
-+ "updates is malformed.");
-+ EXIT;
-+ }
-+ }
-+
-+ bson_snprintf (ns, sizeof ns, "%s.%s", database, collection);
-+
-+ bson_iter_init (&iter, command->documents);
-+ while (bson_iter_next (&iter)) {
-+ rpc.update.msg_len = 0;
-+ rpc.update.request_id = 0;
-+ rpc.update.response_to = 0;
-+ rpc.update.opcode = MONGOC_OPCODE_UPDATE;
-+ rpc.update.zero = 0;
-+ rpc.update.collection = ns;
-+ rpc.update.flags = MONGOC_UPDATE_NONE;
-+
-+ has_update = false;
-+ has_selector = false;
-+ is_upsert = false;
-+
-+ bson_iter_recurse (&iter, &subiter);
-+ while (bson_iter_next (&subiter)) {
-+ if (strcmp (bson_iter_key (&subiter), "u") == 0) {
-+ bson_iter_document (&subiter, &len, &data);
-+ rpc.update.update = data;
-+ bson_init_static (&update, data, len);
-+ has_update = true;
-+ } else if (strcmp (bson_iter_key (&subiter), "q") == 0) {
-+ bson_iter_document (&subiter, &len, &data);
-+ rpc.update.selector = data;
-+ bson_init_static (&selector, data, len);
-+ has_selector = true;
-+ } else if (strcmp (bson_iter_key (&subiter), "multi") == 0) {
-+ val = bson_iter_bool (&subiter);
-+ if (val) {
-+ rpc.update.flags = (mongoc_update_flags_t)(
-+ rpc.update.flags | MONGOC_UPDATE_MULTI_UPDATE);
-+ }
-+ } else if (strcmp (bson_iter_key (&subiter), "upsert") == 0) {
-+ val = bson_iter_bool (&subiter);
-+ if (val) {
-+ rpc.update.flags = (mongoc_update_flags_t)(
-+ rpc.update.flags | MONGOC_UPDATE_UPSERT);
-+ }
-+ is_upsert = true;
-+ }
-+ }
-+
-+ if (!mongoc_cluster_sendv_to_server (&client->cluster,
-+ &rpc, 1, server_stream,
-+ write_concern, error)) {
-+ result->failed = true;
-+ EXIT;
-+ }
-+
-+ if (_mongoc_write_concern_needs_gle (write_concern)) {
-+ if (!_mongoc_client_recv_gle (client, server_stream, &gle, error)) {
-+ result->failed = true;
-+ EXIT;
-+ }
-+
-+ if (bson_iter_init_find (&subiter, gle, "n") &&
-+ BSON_ITER_HOLDS_INT32 (&subiter)) {
-+ affected = bson_iter_int32 (&subiter);
-+ }
-+
-+ /*
-+ * CDRIVER-372:
-+ *
-+ * Versions of MongoDB before 2.6 don't return the _id for an
-+ * upsert if _id is not an ObjectId.
-+ */
-+ if (is_upsert &&
-+ affected &&
-+ !bson_iter_init_find (&subiter, gle, "upserted") &&
-+ bson_iter_init_find (&subiter, gle, "updatedExisting") &&
-+ BSON_ITER_HOLDS_BOOL (&subiter) &&
-+ !bson_iter_bool (&subiter)) {
-+ if (has_update && bson_iter_init_find (&subiter, &update, "_id")) {
-+ _ignore_value (bson_append_iter (gle, "upserted", 8, &subiter));
-+ } else if (has_selector &&
-+ bson_iter_init_find (&subiter, &selector, "_id")) {
-+ _ignore_value (bson_append_iter (gle, "upserted", 8, &subiter));
-+ }
-+ }
-+
-+ _mongoc_write_result_merge_legacy (
-+ result, command, gle,
-+ MONGOC_ERROR_COLLECTION_UPDATE_FAILED, offset);
-+
-+ offset++;
-+ bson_destroy (gle);
-+ }
-+ }
-+
-+ EXIT;
-+}
-+
-+
-+static mongoc_write_op_t gLegacyWriteOps[3] = {
-+ _mongoc_write_command_delete_legacy,
-+ _mongoc_write_command_insert_legacy,
-+ _mongoc_write_command_update_legacy };
-+
-+
-+static void
-+_mongoc_write_command(mongoc_write_command_t *command,
-+ mongoc_client_t *client,
-+ mongoc_server_stream_t *server_stream,
-+ const char *database,
-+ const char *collection,
-+ const mongoc_write_concern_t *write_concern,
-+ uint32_t offset,
-+ mongoc_write_result_t *result,
-+ bson_error_t *error)
-+{
-+ const uint8_t *data;
-+ bson_iter_t iter;
-+ const char *key;
-+ uint32_t len = 0;
-+ bson_t tmp;
-+ bson_t ar;
-+ bson_t cmd;
-+ bson_t reply;
-+ char str [16];
-+ bool has_more;
-+ bool ret = false;
-+ uint32_t i;
-+ int32_t max_bson_obj_size;
-+ int32_t max_write_batch_size;
-+ int32_t min_wire_version;
-+ uint32_t overhead;
-+ uint32_t key_len;
-+
-+ ENTRY;
-+
-+ BSON_ASSERT (command);
-+ BSON_ASSERT (client);
-+ BSON_ASSERT (database);
-+ BSON_ASSERT (server_stream);
-+ BSON_ASSERT (collection);
-+
-+ max_bson_obj_size = mongoc_server_stream_max_bson_obj_size (server_stream);
-+ max_write_batch_size = mongoc_server_stream_max_write_batch_size (server_stream);
-+
-+ /*
-+ * If we have an unacknowledged write and the server supports the legacy
-+ * opcodes, then submit the legacy opcode so we don't need to wait for
-+ * a response from the server.
-+ */
-+
-+ min_wire_version = server_stream->sd->min_wire_version;
-+ if ((min_wire_version == 0) &&
-+ !_mongoc_write_concern_needs_gle (write_concern)) {
-+ if (command->flags.bypass_document_validation != MONGOC_BYPASS_DOCUMENT_VALIDATION_DEFAULT) {
-+ bson_set_error (error,
-+ MONGOC_ERROR_COMMAND,
-+ MONGOC_ERROR_COMMAND_INVALID_ARG,
-+ "Cannot set bypassDocumentValidation for unacknowledged writes");
-+ EXIT;
-+ }
-+ gLegacyWriteOps[command->type] (command, client, server_stream, database,
-+ collection, write_concern, offset,
-+ result, error);
-+ EXIT;
-+ }
-+
-+ if (!command->n_documents ||
-+ !bson_iter_init (&iter, command->documents) ||
-+ !bson_iter_next (&iter)) {
-+ _empty_error (command, error);
-+ result->failed = true;
-+ EXIT;
-+ }
-+
-+again:
-+ bson_init (&cmd);
-+ has_more = false;
-+ i = 0;
-+
-+ BSON_APPEND_UTF8 (&cmd, gCommandNames[command->type], collection);
-+ BSON_APPEND_DOCUMENT (&cmd, "writeConcern",
-+ WRITE_CONCERN_DOC (write_concern));
-+ BSON_APPEND_BOOL (&cmd, "ordered", command->flags.ordered);
-+ if (command->flags.bypass_document_validation != MONGOC_BYPASS_DOCUMENT_VALIDATION_DEFAULT) {
-+ BSON_APPEND_BOOL (&cmd, "bypassDocumentValidation",
-+ !!command->flags.bypass_document_validation);
-+ }
-+
-+ /* 1 byte to specify array type, 1 byte for field name's null terminator */
-+ overhead = cmd.len + 2 + gCommandFieldLens[command->type];
-+
-+ if (!_mongoc_write_command_will_overflow (overhead,
-+ command->documents->len,
-+ command->n_documents,
-+ max_bson_obj_size,
-+ max_write_batch_size)) {
-+ /* copy the whole documents buffer as e.g. "updates": [...] */
-+ bson_append_array (&cmd,
-+ gCommandFields[command->type],
-+ gCommandFieldLens[command->type],
-+ command->documents);
-+ i = command->n_documents;
-+ } else {
-+ bson_append_array_begin (&cmd,
-+ gCommandFields[command->type],
-+ gCommandFieldLens[command->type],
-+ &ar);
-+
-+ do {
-+ if (!BSON_ITER_HOLDS_DOCUMENT (&iter)) {
-+ BSON_ASSERT (false);
-+ }
-+
-+ bson_iter_document (&iter, &len, &data);
-+ key_len = (uint32_t) bson_uint32_to_string (i, &key, str, sizeof str);
-+
-+ if (_mongoc_write_command_will_overflow (overhead,
-+ key_len + len + 2 + ar.len,
-+ i,
-+ max_bson_obj_size,
-+ max_write_batch_size)) {
-+ has_more = true;
-+ break;
-+ }
-+
-+ if (!bson_init_static (&tmp, data, len)) {
-+ BSON_ASSERT (false);
-+ }
-+
-+ BSON_APPEND_DOCUMENT (&ar, key, &tmp);
-+
-+ bson_destroy (&tmp);
-+
-+ i++;
-+ } while (bson_iter_next (&iter));
-+
-+ bson_append_array_end (&cmd, &ar);
-+ }
-+
-+ if (!i) {
-+ too_large_error (error, i, len, max_bson_obj_size, NULL);
-+ result->failed = true;
-+ ret = false;
-+ } else {
-+ ret = mongoc_cluster_run_command (&client->cluster, server_stream->stream,
-+ server_stream->sd->id, MONGOC_QUERY_NONE,
-+ database, &cmd, &reply, error);
-+
-+ if (!ret) {
-+ result->failed = true;
-+ }
-+
-+ _mongoc_write_result_merge (result, command, &reply, offset);
-+ offset += i;
-+ bson_destroy (&reply);
-+ }
-+
-+ bson_destroy (&cmd);
-+
-+ if (has_more && (ret || !command->flags.ordered)) {
-+ GOTO (again);
-+ }
-+
-+ EXIT;
-+}
-+
-+
-+void
-+_mongoc_write_command_execute (mongoc_write_command_t *command, /* IN */
-+ mongoc_client_t *client, /* IN */
-+ mongoc_server_stream_t *server_stream, /* IN */
-+ const char *database, /* IN */
-+ const char *collection, /* IN */
-+ const mongoc_write_concern_t *write_concern, /* IN */
-+ uint32_t offset, /* IN */
-+ mongoc_write_result_t *result) /* OUT */
-+{
-+ ENTRY;
-+
-+ BSON_ASSERT (command);
-+ BSON_ASSERT (client);
-+ BSON_ASSERT (server_stream);
-+ BSON_ASSERT (database);
-+ BSON_ASSERT (collection);
-+ BSON_ASSERT (result);
-+
-+ if (!write_concern) {
-+ write_concern = client->write_concern;
-+ }
-+
-+ if (!_mongoc_write_concern_is_valid(write_concern)) {
-+ bson_set_error (&result->error,
-+ MONGOC_ERROR_COMMAND,
-+ MONGOC_ERROR_COMMAND_INVALID_ARG,
-+ "The write concern is invalid.");
-+ result->failed = true;
-+ EXIT;
-+ }
-+
-+ if (!command->hint) {
-+ command->hint = server_stream->sd->id;
-+ } else {
-+ BSON_ASSERT (command->hint == server_stream->sd->id);
-+ }
-+
-+ if (server_stream->sd->max_wire_version >= WIRE_VERSION_WRITE_CMD) {
-+ _mongoc_write_command (command, client, server_stream, database,
-+ collection, write_concern, offset,
-+ result, &result->error);
-+ } else {
-+ gLegacyWriteOps[command->type] (command, client, server_stream, database,
-+ collection, write_concern, offset,
-+ result, &result->error);
-+ }
-+
-+ EXIT;
-+}
-+
-+
-+void
-+_mongoc_write_command_destroy (mongoc_write_command_t *command)
-+{
-+ ENTRY;
-+
-+ if (command) {
-+ bson_destroy (command->documents);
-+ }
-+
-+ EXIT;
-+}
-+
-+
-+void
-+_mongoc_write_result_init (mongoc_write_result_t *result) /* IN */
-+{
-+ ENTRY;
-+
-+ BSON_ASSERT (result);
-+
-+ memset (result, 0, sizeof *result);
-+
-+ bson_init (&result->upserted);
-+ bson_init (&result->writeConcernErrors);
-+ bson_init (&result->writeErrors);
-+
-+ EXIT;
-+}
-+
-+
-+void
-+_mongoc_write_result_destroy (mongoc_write_result_t *result)
-+{
-+ ENTRY;
-+
-+ BSON_ASSERT (result);
-+
-+ bson_destroy (&result->upserted);
-+ bson_destroy (&result->writeConcernErrors);
-+ bson_destroy (&result->writeErrors);
-+
-+ EXIT;
-+}
-+
-+
-+static void
-+_mongoc_write_result_append_upsert (mongoc_write_result_t *result,
-+ int32_t idx,
-+ const bson_value_t *value)
-+{
-+ bson_t child;
-+ const char *keyptr = NULL;
-+ char key[12];
-+ int len;
-+
-+ BSON_ASSERT (result);
-+ BSON_ASSERT (value);
-+
-+ len = (int)bson_uint32_to_string (result->upsert_append_count, &keyptr, key,
-+ sizeof key);
-+
-+ bson_append_document_begin (&result->upserted, keyptr, len, &child);
-+ BSON_APPEND_INT32 (&child, "index", idx);
-+ BSON_APPEND_VALUE (&child, "_id", value);
-+ bson_append_document_end (&result->upserted, &child);
-+
-+ result->upsert_append_count++;
-+}
-+
-+
-+static void
-+_append_write_concern_err_legacy (mongoc_write_result_t *result,
-+ const char *err,
-+ int32_t code)
-+{
-+ char str[16];
-+ const char *key;
-+ size_t keylen;
-+ bson_t write_concern_error;
-+
-+ /* don't set result->failed; record the write concern err and continue */
-+ keylen = bson_uint32_to_string (result->n_writeConcernErrors, &key,
-+ str, sizeof str);
-+
-+ BSON_ASSERT (keylen < INT_MAX);
-+
-+ bson_append_document_begin (&result->writeConcernErrors, key, (int) keylen,
-+ &write_concern_error);
-+
-+ bson_append_int32 (&write_concern_error, "code", 4, code);
-+ bson_append_utf8 (&write_concern_error, "errmsg", 6, err, -1);
-+ bson_append_document_end (&result->writeConcernErrors, &write_concern_error);
-+ result->n_writeConcernErrors++;
-+}
-+
-+
-+static void
-+_append_write_err_legacy (mongoc_write_result_t *result,
-+ const char *err,
-+ int32_t code,
-+ uint32_t offset)
-+{
-+ bson_t holder, write_errors, child;
-+ bson_iter_t iter;
-+
-+ BSON_ASSERT (code > 0);
-+
-+ bson_set_error (&result->error, MONGOC_ERROR_COLLECTION, (uint32_t) code,
-+ "%s", err);
-+
-+ /* stop processing, if result->ordered */
-+ result->failed = true;
-+
-+ bson_init (&holder);
-+ bson_append_array_begin (&holder, "0", 1, &write_errors);
-+ bson_append_document_begin (&write_errors, "0", 1, &child);
-+
-+ /* set error's "index" to 0; fixed up in _mongoc_write_result_merge_arrays */
-+ bson_append_int32 (&child, "index", 5, 0);
-+ bson_append_int32 (&child, "code", 4, code);
-+ bson_append_utf8 (&child, "errmsg", 6, err, -1);
-+ bson_append_document_end (&write_errors, &child);
-+ bson_append_array_end (&holder, &write_errors);
-+ bson_iter_init (&iter, &holder);
-+ bson_iter_next (&iter);
-+
-+ _mongoc_write_result_merge_arrays (offset, result,
-+ &result->writeErrors, &iter);
-+
-+ bson_destroy (&holder);
-+}
-+
-+
-+void
-+_mongoc_write_result_merge_legacy (mongoc_write_result_t *result, /* IN */
-+ mongoc_write_command_t *command, /* IN */
-+ const bson_t *reply, /* IN */
-+ mongoc_error_code_t default_code,
-+ uint32_t offset)
-+{
-+ const bson_value_t *value;
-+ bson_iter_t iter;
-+ bson_iter_t ar;
-+ bson_iter_t citer;
-+ const char *err = NULL;
-+ int32_t code = 0;
-+ int32_t n = 0;
-+ int32_t upsert_idx = 0;
-+
-+ ENTRY;
-+
-+ BSON_ASSERT (result);
-+ BSON_ASSERT (reply);
-+
-+ if (bson_iter_init_find (&iter, reply, "n") &&
-+ BSON_ITER_HOLDS_INT32 (&iter)) {
-+ n = bson_iter_int32 (&iter);
-+ }
-+
-+ if (bson_iter_init_find (&iter, reply, "err") &&
-+ BSON_ITER_HOLDS_UTF8 (&iter)) {
-+ err = bson_iter_utf8 (&iter, NULL);
-+ }
-+
-+ if (bson_iter_init_find (&iter, reply, "code") &&
-+ BSON_ITER_HOLDS_INT32 (&iter)) {
-+ code = bson_iter_int32 (&iter);
-+ }
-+
-+ if (code || err) {
-+ if (!err) {
-+ err = "unknown error";
-+ }
-+
-+ if (bson_iter_init_find (&iter, reply, "wtimeout") &&
-+ bson_iter_as_bool (&iter)) {
-+
-+ if (!code) {
-+ code = (int32_t) MONGOC_ERROR_WRITE_CONCERN_ERROR;
-+ }
-+
-+ _append_write_concern_err_legacy (result, err, code);
-+ } else {
-+ if (!code) {
-+ code = (int32_t) default_code;
-+ }
-+
-+ _append_write_err_legacy (result, err, code, offset);
-+ }
-+ }
-+
-+ switch (command->type) {
-+ case MONGOC_WRITE_COMMAND_INSERT:
-+ if (n) {
-+ result->nInserted += n;
-+ }
-+ break;
-+ case MONGOC_WRITE_COMMAND_DELETE:
-+ result->nRemoved += n;
-+ break;
-+ case MONGOC_WRITE_COMMAND_UPDATE:
-+ if (bson_iter_init_find (&iter, reply, "upserted") &&
-+ !BSON_ITER_HOLDS_ARRAY (&iter)) {
-+ result->nUpserted += n;
-+ value = bson_iter_value (&iter);
-+ _mongoc_write_result_append_upsert (result, offset, value);
-+ } else if (bson_iter_init_find (&iter, reply, "upserted") &&
-+ BSON_ITER_HOLDS_ARRAY (&iter)) {
-+ result->nUpserted += n;
-+ if (bson_iter_recurse (&iter, &ar)) {
-+ while (bson_iter_next (&ar)) {
-+ if (BSON_ITER_HOLDS_DOCUMENT (&ar) &&
-+ bson_iter_recurse (&ar, &citer) &&
-+ bson_iter_find (&citer, "_id")) {
-+ value = bson_iter_value (&citer);
-+ _mongoc_write_result_append_upsert (result,
-+ offset + upsert_idx,
-+ value);
-+ upsert_idx++;
-+ }
-+ }
-+ }
-+ } else if ((n == 1) &&
-+ bson_iter_init_find (&iter, reply, "updatedExisting") &&
-+ BSON_ITER_HOLDS_BOOL (&iter) &&
-+ !bson_iter_bool (&iter)) {
-+ result->nUpserted += n;
-+ } else {
-+ result->nMatched += n;
-+ }
-+ break;
-+ default:
-+ break;
-+ }
-+
-+ result->omit_nModified = true;
-+
-+ EXIT;
-+}
-+
-+
-+static int32_t
-+_mongoc_write_result_merge_arrays (uint32_t offset,
-+ mongoc_write_result_t *result, /* IN */
-+ bson_t *dest, /* IN */
-+ bson_iter_t *iter) /* IN */
-+{
-+ const bson_value_t *value;
-+ bson_iter_t ar;
-+ bson_iter_t citer;
-+ int32_t idx;
-+ int32_t count = 0;
-+ int32_t aridx;
-+ bson_t child;
-+ const char *keyptr = NULL;
-+ char key[12];
-+ int len;
-+
-+ ENTRY;
-+
-+ BSON_ASSERT (result);
-+ BSON_ASSERT (dest);
-+ BSON_ASSERT (iter);
-+ BSON_ASSERT (BSON_ITER_HOLDS_ARRAY (iter));
-+
-+ aridx = bson_count_keys (dest);
-+
-+ if (bson_iter_recurse (iter, &ar)) {
-+ while (bson_iter_next (&ar)) {
-+ if (BSON_ITER_HOLDS_DOCUMENT (&ar) &&
-+ bson_iter_recurse (&ar, &citer)) {
-+ len = (int)bson_uint32_to_string (aridx++, &keyptr, key,
-+ sizeof key);
-+ bson_append_document_begin (dest, keyptr, len, &child);
-+ while (bson_iter_next (&citer)) {
-+ if (BSON_ITER_IS_KEY (&citer, "index")) {
-+ idx = bson_iter_int32 (&citer) + offset;
-+ BSON_APPEND_INT32 (&child, "index", idx);
-+ } else {
-+ value = bson_iter_value (&citer);
-+ BSON_APPEND_VALUE (&child, bson_iter_key (&citer), value);
-+ }
-+ }
-+ bson_append_document_end (dest, &child);
-+ count++;
-+ }
-+ }
-+ }
-+
-+ RETURN (count);
-+}
-+
-+
-+void
-+_mongoc_write_result_merge (mongoc_write_result_t *result, /* IN */
-+ mongoc_write_command_t *command, /* IN */
-+ const bson_t *reply, /* IN */
-+ uint32_t offset)
-+{
-+ int32_t server_index = 0;
-+ const bson_value_t *value;
-+ bson_iter_t iter;
-+ bson_iter_t citer;
-+ bson_iter_t ar;
-+ int32_t n_upserted = 0;
-+ int32_t affected = 0;
-+
-+ ENTRY;
-+
-+ BSON_ASSERT (result);
-+ BSON_ASSERT (reply);
-+
-+ if (bson_iter_init_find (&iter, reply, "n") &&
-+ BSON_ITER_HOLDS_INT32 (&iter)) {
-+ affected = bson_iter_int32 (&iter);
-+ }
-+
-+ if (bson_iter_init_find (&iter, reply, "writeErrors") &&
-+ BSON_ITER_HOLDS_ARRAY (&iter) &&
-+ bson_iter_recurse (&iter, &citer) &&
-+ bson_iter_next (&citer)) {
-+ result->failed = true;
-+ }
-+
-+ switch (command->type) {
-+ case MONGOC_WRITE_COMMAND_INSERT:
-+ result->nInserted += affected;
-+ break;
-+ case MONGOC_WRITE_COMMAND_DELETE:
-+ result->nRemoved += affected;
-+ break;
-+ case MONGOC_WRITE_COMMAND_UPDATE:
-+
-+ /* server returns each upserted _id with its index into this batch
-+ * look for "upserted": [{"index": 4, "_id": ObjectId()}, ...] */
-+ if (bson_iter_init_find (&iter, reply, "upserted")) {
-+ if (BSON_ITER_HOLDS_ARRAY (&iter) &&
-+ (bson_iter_recurse (&iter, &ar))) {
-+
-+ while (bson_iter_next (&ar)) {
-+ if (BSON_ITER_HOLDS_DOCUMENT (&ar) &&
-+ bson_iter_recurse (&ar, &citer) &&
-+ bson_iter_find (&citer, "index") &&
-+ BSON_ITER_HOLDS_INT32 (&citer)) {
-+ server_index = bson_iter_int32 (&citer);
-+
-+ if (bson_iter_recurse (&ar, &citer) &&
-+ bson_iter_find (&citer, "_id")) {
-+ value = bson_iter_value (&citer);
-+ _mongoc_write_result_append_upsert (result,
-+ offset + server_index,
-+ value);
-+ n_upserted++;
-+ }
-+ }
-+ }
-+ }
-+ result->nUpserted += n_upserted;
-+ /*
-+ * XXX: The following addition to nMatched needs some checking.
-+ * I'm highly skeptical of it.
-+ */
-+ result->nMatched += BSON_MAX (0, (affected - n_upserted));
-+ } else {
-+ result->nMatched += affected;
-+ }
-+ /*
-+ * SERVER-13001 - in a mixed sharded cluster a call to update could
-+ * return nModified (>= 2.6) or not (<= 2.4). If any call does not
-+ * return nModified we can't report a valid final count so omit the
-+ * field completely.
-+ */
-+ if (bson_iter_init_find (&iter, reply, "nModified") &&
-+ BSON_ITER_HOLDS_INT32 (&iter)) {
-+ result->nModified += bson_iter_int32 (&iter);
-+ } else {
-+ /*
-+ * nModified could be BSON_TYPE_NULL, which should also be omitted.
-+ */
-+ result->omit_nModified = true;
-+ }
-+ break;
-+ default:
-+ BSON_ASSERT (false);
-+ break;
-+ }
-+
-+ if (bson_iter_init_find (&iter, reply, "writeErrors") &&
-+ BSON_ITER_HOLDS_ARRAY (&iter)) {
-+ _mongoc_write_result_merge_arrays (offset, result, &result->writeErrors,
-+ &iter);
-+ }
-+
-+ if (bson_iter_init_find (&iter, reply, "writeConcernError") &&
-+ BSON_ITER_HOLDS_DOCUMENT (&iter)) {
-+
-+ uint32_t len;
-+ const uint8_t *data;
-+ bson_t write_concern_error;
-+ char str[16];
-+ const char *key;
-+
-+ /* writeConcernError is a subdocument in the server response
-+ * append it to the result->writeConcernErrors array */
-+ bson_iter_document (&iter, &len, &data);
-+ bson_init_static (&write_concern_error, data, len);
-+
-+ bson_uint32_to_string (result->n_writeConcernErrors, &key,
-+ str, sizeof str);
-+
-+ bson_append_document (&result->writeConcernErrors,
-+ key, -1, &write_concern_error);
-+
-+ result->n_writeConcernErrors++;
-+ }
-+
-+ EXIT;
-+}
-+
-+
-+/*
-+ * If error is not set, set code from first document in array like
-+ * [{"code": 64, "errmsg": "duplicate"}, ...]. Format the error message
-+ * from all errors in array.
-+*/
-+static void
-+_set_error_from_response (bson_t *bson_array,
-+ mongoc_error_domain_t domain,
-+ const char *error_type,
-+ bson_error_t *error /* OUT */)
-+{
-+ bson_iter_t array_iter;
-+ bson_iter_t doc_iter;
-+ bson_string_t *compound_err;
-+ const char *errmsg = NULL;
-+ int32_t code = 0;
-+ uint32_t n_keys, i;
-+
-+ compound_err = bson_string_new (NULL);
-+ n_keys = bson_count_keys (bson_array);
-+ if (n_keys > 1) {
-+ bson_string_append_printf (compound_err,
-+ "Multiple %s errors: ",
-+ error_type);
-+ }
-+
-+ if (!bson_empty0 (bson_array) && bson_iter_init (&array_iter, bson_array)) {
-+
-+ /* get first code and all error messages */
-+ i = 0;
-+
-+ while (bson_iter_next (&array_iter)) {
-+ if (BSON_ITER_HOLDS_DOCUMENT (&array_iter) &&
-+ bson_iter_recurse (&array_iter, &doc_iter)) {
-+
-+ /* parse doc, which is like {"code": 64, "errmsg": "duplicate"} */
-+ while (bson_iter_next (&doc_iter)) {
-+
-+ /* use the first error code we find */
-+ if (BSON_ITER_IS_KEY (&doc_iter, "code") && code == 0) {
-+ code = bson_iter_int32 (&doc_iter);
-+ } else if (BSON_ITER_IS_KEY (&doc_iter, "errmsg")) {
-+ errmsg = bson_iter_utf8 (&doc_iter, NULL);
-+
-+ /* build message like 'Multiple write errors: "foo", "bar"' */
-+ if (n_keys > 1) {
-+ bson_string_append_printf (compound_err, "\"%s\"", errmsg);
-+ if (i < n_keys - 1) {
-+ bson_string_append (compound_err, ", ");
-+ }
-+ } else {
-+ /* single error message */
-+ bson_string_append (compound_err, errmsg);
-+ }
-+ }
-+ }
-+
-+ i++;
-+ }
-+ }
-+
-+ if (code && compound_err->len) {
-+ bson_set_error (error, domain, (uint32_t) code,
-+ "%s", compound_err->str);
-+ }
-+ }
-+
-+ bson_string_free (compound_err, true);
-+}
-+
-+
-+bool
-+_mongoc_write_result_complete (mongoc_write_result_t *result,
-+ bson_t *bson,
-+ bson_error_t *error)
-+{
-+ ENTRY;
-+
-+ BSON_ASSERT (result);
-+
-+ if (bson) {
-+ BSON_APPEND_INT32 (bson, "nInserted", result->nInserted);
-+ BSON_APPEND_INT32 (bson, "nMatched", result->nMatched);
-+ if (!result->omit_nModified) {
-+ BSON_APPEND_INT32 (bson, "nModified", result->nModified);
-+ }
-+ BSON_APPEND_INT32 (bson, "nRemoved", result->nRemoved);
-+ BSON_APPEND_INT32 (bson, "nUpserted", result->nUpserted);
-+ if (!bson_empty0 (&result->upserted)) {
-+ BSON_APPEND_ARRAY (bson, "upserted", &result->upserted);
-+ }
-+ BSON_APPEND_ARRAY (bson, "writeErrors", &result->writeErrors);
-+ if (result->n_writeConcernErrors) {
-+ BSON_APPEND_ARRAY (bson, "writeConcernErrors",
-+ &result->writeConcernErrors);
-+ }
-+ }
-+
-+ /* set bson_error_t from first write error or write concern error */
-+ _set_error_from_response (&result->writeErrors,
-+ MONGOC_ERROR_COMMAND,
-+ "write",
-+ &result->error);
-+
-+ if (!result->error.code) {
-+ _set_error_from_response (&result->writeConcernErrors,
-+ MONGOC_ERROR_WRITE_CONCERN,
-+ "write concern",
-+ &result->error);
-+ }
-+
-+ if (error) {
-+ memcpy (error, &result->error, sizeof *error);
-+ }
-+
-+ RETURN (!result->failed && result->error.code == 0);
-+}
-diff --git a/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-write-concern-private.h b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-write-concern-private.h
-new file mode 100644
-index 0000000..991afa9
---- /dev/null
-+++ b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-write-concern-private.h
-@@ -0,0 +1,55 @@
-+/*
-+ * 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.
-+ */
-+
-+#ifndef MONGOC_WRITE_CONCERN_PRIVATE_H
-+#define MONGOC_WRITE_CONCERN_PRIVATE_H
-+
-+#if !defined (MONGOC_I_AM_A_DRIVER) && !defined (MONGOC_COMPILATION)
-+#error "Only <mongoc.h> can be included directly."
-+#endif
-+
-+#include <bson.h>
-+
-+
-+BSON_BEGIN_DECLS
-+
-+
-+#define MONGOC_WRITE_CONCERN_FSYNC_DEFAULT -1
-+#define MONGOC_WRITE_CONCERN_JOURNAL_DEFAULT -1
-+
-+
-+struct _mongoc_write_concern_t
-+{
-+ int8_t fsync_;
-+ int8_t journal;
-+ int32_t w;
-+ int32_t wtimeout;
-+ char *wtag;
-+ bool frozen;
-+ bson_t compiled;
-+ bson_t compiled_gle;
-+};
-+
-+
-+const bson_t *_mongoc_write_concern_get_gle (mongoc_write_concern_t *write_concern);
-+const bson_t *_mongoc_write_concern_get_bson (mongoc_write_concern_t *write_concern);
-+bool _mongoc_write_concern_needs_gle (const mongoc_write_concern_t *write_concern);
-+bool _mongoc_write_concern_is_valid (const mongoc_write_concern_t *write_concern);
-+
-+BSON_END_DECLS
-+
-+
-+#endif /* MONGOC_WRITE_CONCERN_PRIVATE_H */
-diff --git a/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-write-concern.c b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-write-concern.c
-new file mode 100644
-index 0000000..634288d
---- /dev/null
-+++ b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-write-concern.c
-@@ -0,0 +1,436 @@
-+/*
-+ * 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-log.h"
-+#include "mongoc-write-concern.h"
-+#include "mongoc-write-concern-private.h"
-+
-+
-+static BSON_INLINE bool
-+_mongoc_write_concern_warn_frozen (mongoc_write_concern_t *write_concern)
-+{
-+ if (write_concern->frozen) {
-+ MONGOC_WARNING("Cannot modify a frozen write-concern.");
-+ }
-+
-+ return write_concern->frozen;
-+}
-+
-+static void
-+_mongoc_write_concern_freeze (mongoc_write_concern_t *write_concern);
-+
-+
-+/**
-+ * mongoc_write_concern_new:
-+ *
-+ * Create a new mongoc_write_concern_t.
-+ *
-+ * Returns: A newly allocated mongoc_write_concern_t. This should be freed
-+ * with mongoc_write_concern_destroy().
-+ */
-+mongoc_write_concern_t *
-+mongoc_write_concern_new (void)
-+{
-+ mongoc_write_concern_t *write_concern;
-+
-+ write_concern = (mongoc_write_concern_t *)bson_malloc0(sizeof *write_concern);
-+ write_concern->w = MONGOC_WRITE_CONCERN_W_DEFAULT;
-+ write_concern->fsync_ = MONGOC_WRITE_CONCERN_FSYNC_DEFAULT;
-+ write_concern->journal = MONGOC_WRITE_CONCERN_JOURNAL_DEFAULT;
-+
-+ return write_concern;
-+}
-+
-+
-+mongoc_write_concern_t *
-+mongoc_write_concern_copy (const mongoc_write_concern_t *write_concern)
-+{
-+ mongoc_write_concern_t *ret = NULL;
-+
-+ if (write_concern) {
-+ ret = mongoc_write_concern_new();
-+ ret->fsync_ = write_concern->fsync_;
-+ ret->journal = write_concern->journal;
-+ ret->w = write_concern->w;
-+ ret->wtimeout = write_concern->wtimeout;
-+ ret->frozen = false;
-+ ret->wtag = bson_strdup (write_concern->wtag);
-+ }
-+
-+ return ret;
-+}
-+
-+
-+/**
-+ * mongoc_write_concern_destroy:
-+ * @write_concern: A mongoc_write_concern_t.
-+ *
-+ * Releases a mongoc_write_concern_t and all associated memory.
-+ */
-+void
-+mongoc_write_concern_destroy (mongoc_write_concern_t *write_concern)
-+{
-+ if (write_concern) {
-+ if (write_concern->compiled.len) {
-+ bson_destroy (&write_concern->compiled);
-+ bson_destroy (&write_concern->compiled_gle);
-+ }
-+
-+ bson_free (write_concern->wtag);
-+ bson_free (write_concern);
-+ }
-+}
-+
-+
-+bool
-+mongoc_write_concern_get_fsync (const mongoc_write_concern_t *write_concern)
-+{
-+ BSON_ASSERT (write_concern);
-+ return (write_concern->fsync_ == true);
-+}
-+
-+
-+/**
-+ * mongoc_write_concern_set_fsync:
-+ * @write_concern: A mongoc_write_concern_t.
-+ * @fsync_: If the write concern requires fsync() by the server.
-+ *
-+ * Set if fsync() should be called on the server before acknowledging a
-+ * write request.
-+ */
-+void
-+mongoc_write_concern_set_fsync (mongoc_write_concern_t *write_concern,
-+ bool fsync_)
-+{
-+ BSON_ASSERT (write_concern);
-+
-+ if (!_mongoc_write_concern_warn_frozen(write_concern)) {
-+ write_concern->fsync_ = !!fsync_;
-+ }
-+}
-+
-+
-+bool
-+mongoc_write_concern_get_journal (const mongoc_write_concern_t *write_concern)
-+{
-+ BSON_ASSERT (write_concern);
-+ return (write_concern->journal == true);
-+}
-+
-+
-+/**
-+ * mongoc_write_concern_set_journal:
-+ * @write_concern: A mongoc_write_concern_t.
-+ * @journal: If the write should be journaled.
-+ *
-+ * Set if the write request should be journaled before acknowledging the
-+ * write request.
-+ */
-+void
-+mongoc_write_concern_set_journal (mongoc_write_concern_t *write_concern,
-+ bool journal)
-+{
-+ BSON_ASSERT (write_concern);
-+
-+ if (!_mongoc_write_concern_warn_frozen(write_concern)) {
-+ write_concern->journal = !!journal;
-+ }
-+}
-+
-+
-+int32_t
-+mongoc_write_concern_get_w (const mongoc_write_concern_t *write_concern)
-+{
-+ BSON_ASSERT (write_concern);
-+ return write_concern->w;
-+}
-+
-+
-+/**
-+ * mongoc_write_concern_set_w:
-+ * @w: The number of nodes for write or MONGOC_WRITE_CONCERN_W_MAJORITY
-+ * for "majority".
-+ *
-+ * Sets the number of nodes that must acknowledge the write request before
-+ * acknowledging the write request to the client.
-+ *
-+ * You may specifiy @w as MONGOC_WRITE_CONCERN_W_MAJORITY to request that
-+ * a "majority" of nodes acknowledge the request.
-+ */
-+void
-+mongoc_write_concern_set_w (mongoc_write_concern_t *write_concern,
-+ int32_t w)
-+{
-+ BSON_ASSERT (write_concern);
-+ BSON_ASSERT (w >= -3);
-+
-+ if (!_mongoc_write_concern_warn_frozen(write_concern)) {
-+ write_concern->w = w;
-+ }
-+}
-+
-+
-+int32_t
-+mongoc_write_concern_get_wtimeout (const mongoc_write_concern_t *write_concern)
-+{
-+ BSON_ASSERT (write_concern);
-+ return write_concern->wtimeout;
-+}
-+
-+
-+/**
-+ * mongoc_write_concern_set_wtimeout:
-+ * @write_concern: A mongoc_write_concern_t.
-+ * @wtimeout_msec: Number of milliseconds before timeout.
-+ *
-+ * Sets the number of milliseconds to wait before considering a write
-+ * request as failed. A value of 0 indicates no write timeout.
-+ *
-+ * The @wtimeout_msec parameter must be positive or zero. Negative values will
-+ * be ignored.
-+ */
-+void
-+mongoc_write_concern_set_wtimeout (mongoc_write_concern_t *write_concern,
-+ int32_t wtimeout_msec)
-+{
-+ BSON_ASSERT (write_concern);
-+
-+ if (wtimeout_msec < 0) {
-+ return;
-+ }
-+
-+ if (!_mongoc_write_concern_warn_frozen(write_concern)) {
-+ write_concern->wtimeout = wtimeout_msec;
-+ }
-+}
-+
-+
-+bool
-+mongoc_write_concern_get_wmajority (const mongoc_write_concern_t *write_concern)
-+{
-+ BSON_ASSERT (write_concern);
-+ return (write_concern->w == MONGOC_WRITE_CONCERN_W_MAJORITY);
-+}
-+
-+
-+/**
-+ * mongoc_write_concern_set_wmajority:
-+ * @write_concern: A mongoc_write_concern_t.
-+ * @wtimeout_msec: Number of milliseconds before timeout.
-+ *
-+ * Sets the "w" of a write concern to "majority". It is suggested that
-+ * you provide a reasonable @wtimeout_msec to wait before considering the
-+ * write request failed. A @wtimeout_msec value of 0 indicates no write timeout.
-+ *
-+ * The @wtimeout_msec parameter must be positive or zero. Negative values will
-+ * be ignored.
-+ */
-+void
-+mongoc_write_concern_set_wmajority (mongoc_write_concern_t *write_concern,
-+ int32_t wtimeout_msec)
-+{
-+ BSON_ASSERT (write_concern);
-+
-+ if (!_mongoc_write_concern_warn_frozen(write_concern)) {
-+ write_concern->w = MONGOC_WRITE_CONCERN_W_MAJORITY;
-+
-+ if (wtimeout_msec >= 0) {
-+ write_concern->wtimeout = wtimeout_msec;
-+ }
-+ }
-+}
-+
-+
-+const char *
-+mongoc_write_concern_get_wtag (const mongoc_write_concern_t *write_concern)
-+{
-+ BSON_ASSERT (write_concern);
-+
-+ if (write_concern->w == MONGOC_WRITE_CONCERN_W_TAG) {
-+ return write_concern->wtag;
-+ }
-+
-+ return NULL;
-+}
-+
-+
-+void
-+mongoc_write_concern_set_wtag (mongoc_write_concern_t *write_concern,
-+ const char *wtag)
-+{
-+ BSON_ASSERT (write_concern);
-+
-+ if (!_mongoc_write_concern_warn_frozen (write_concern)) {
-+ bson_free (write_concern->wtag);
-+ write_concern->wtag = bson_strdup (wtag);
-+ write_concern->w = MONGOC_WRITE_CONCERN_W_TAG;
-+ }
-+}
-+
-+/**
-+ * mongoc_write_concern_get_bson:
-+ * @write_concern: A mongoc_write_concern_t.
-+ *
-+ * This is an internal function.
-+ *
-+ * Freeze the write concern if necessary and retrieve the encoded bson_t
-+ * representing the write concern.
-+ *
-+ * You may not modify the write concern further after calling this function.
-+ *
-+ * Returns: A bson_t that should not be modified or freed as it is owned by
-+ * the mongoc_write_concern_t instance.
-+ */
-+const bson_t *
-+_mongoc_write_concern_get_bson (mongoc_write_concern_t *write_concern) {
-+ if (!write_concern->frozen) {
-+ _mongoc_write_concern_freeze(write_concern);
-+ }
-+
-+ return &write_concern->compiled;
-+}
-+
-+/**
-+ * mongoc_write_concern_get_gle:
-+ * @write_concern: A mongoc_write_concern_t.
-+ *
-+ * This is an internal function.
-+ *
-+ * Freeze the write concern if necessary and retrieve the encoded bson_t
-+ * representing the write concern as a get last error command.
-+ *
-+ * You may not modify the write concern further after calling this function.
-+ *
-+ * Returns: A bson_t that should not be modified or freed as it is owned by
-+ * the mongoc_write_concern_t instance.
-+ */
-+const bson_t *
-+_mongoc_write_concern_get_gle (mongoc_write_concern_t *write_concern) {
-+ if (!write_concern->frozen) {
-+ _mongoc_write_concern_freeze(write_concern);
-+ }
-+
-+ return &write_concern->compiled_gle;
-+}
-+
-+/**
-+ * mongoc_write_concern_freeze:
-+ * @write_concern: A mongoc_write_concern_t.
-+ *
-+ * This is an internal function.
-+ *
-+ * Freeze the write concern if necessary and encode it into a bson_ts which
-+ * represent the raw bson form and the get last error command form.
-+ *
-+ * You may not modify the write concern further after calling this function.
-+ */
-+static void
-+_mongoc_write_concern_freeze (mongoc_write_concern_t *write_concern)
-+{
-+ bson_t *compiled;
-+ bson_t *compiled_gle;
-+
-+ BSON_ASSERT (write_concern);
-+
-+ compiled = &write_concern->compiled;
-+ compiled_gle = &write_concern->compiled_gle;
-+
-+ write_concern->frozen = true;
-+
-+ bson_init (compiled);
-+ bson_init (compiled_gle);
-+
-+ if (write_concern->w == MONGOC_WRITE_CONCERN_W_TAG) {
-+ BSON_ASSERT (write_concern->wtag);
-+ BSON_APPEND_UTF8 (compiled, "w", write_concern->wtag);
-+ } else if (write_concern->w == MONGOC_WRITE_CONCERN_W_MAJORITY) {
-+ BSON_APPEND_UTF8 (compiled, "w", "majority");
-+ } else if (write_concern->w == MONGOC_WRITE_CONCERN_W_DEFAULT) {
-+ /* Do Nothing */
-+ } else if (write_concern->w > 0) {
-+ BSON_APPEND_INT32 (compiled, "w", write_concern->w);
-+ }
-+
-+ if (write_concern->fsync_ != MONGOC_WRITE_CONCERN_FSYNC_DEFAULT) {
-+ bson_append_bool(compiled, "fsync", 5, !!write_concern->fsync_);
-+ }
-+
-+ if (write_concern->journal != MONGOC_WRITE_CONCERN_JOURNAL_DEFAULT) {
-+ bson_append_bool(compiled, "j", 1, !!write_concern->journal);
-+ }
-+
-+ if (write_concern->wtimeout) {
-+ bson_append_int32(compiled, "wtimeout", 8, write_concern->wtimeout);
-+ }
-+
-+ BSON_APPEND_INT32 (compiled_gle, "getlasterror", 1);
-+ bson_concat (compiled_gle, compiled);
-+}
-+
-+
-+/**
-+ * mongoc_write_concern_needs_gle:
-+ * @concern: (in): A mongoc_write_concern_t.
-+ *
-+ * Checks to see if @write_concern requests that a getlasterror command is to
-+ * be delivered to the MongoDB server.
-+ *
-+ * Returns: true if a getlasterror command should be sent.
-+ */
-+bool
-+_mongoc_write_concern_needs_gle (const mongoc_write_concern_t *write_concern)
-+{
-+ if (write_concern) {
-+ return (((write_concern->w != MONGOC_WRITE_CONCERN_W_UNACKNOWLEDGED) &&
-+ (write_concern->w != MONGOC_WRITE_CONCERN_W_ERRORS_IGNORED)) ||
-+ mongoc_write_concern_get_fsync(write_concern) ||
-+ mongoc_write_concern_get_journal(write_concern));
-+ }
-+ return false;
-+}
-+
-+
-+/**
-+ * _mongoc_write_concern_is_valid:
-+ * @write_concern: (in): A mongoc_write_concern_t.
-+ *
-+ * Checks to see if @write_concern is valid and does not contain conflicting
-+ * options.
-+ *
-+ * Returns: true if the write concern is valid; otherwise false.
-+ */
-+bool
-+_mongoc_write_concern_is_valid (const mongoc_write_concern_t *write_concern)
-+{
-+ if (!write_concern) {
-+ return false;
-+ }
-+
-+ /* Journal or fsync should require acknowledgement. */
-+ if ((mongoc_write_concern_get_fsync (write_concern) ||
-+ mongoc_write_concern_get_journal (write_concern)) &&
-+ (write_concern->w == MONGOC_WRITE_CONCERN_W_UNACKNOWLEDGED ||
-+ write_concern->w == MONGOC_WRITE_CONCERN_W_ERRORS_IGNORED)) {
-+ return false;
-+ }
-+
-+ if (write_concern->wtimeout < 0) {
-+ return false;
-+ }
-+
-+ return true;
-+}
diff --git a/debian/patches/0002-Add-mongoc-cursor.c-to-priv-library.patch b/debian/patches/0002-Add-mongoc-cursor.c-to-priv-library.patch
deleted file mode 100644
index 0e083b29..00000000
--- a/debian/patches/0002-Add-mongoc-cursor.c-to-priv-library.patch
+++ /dev/null
@@ -1,1341 +0,0 @@
-From: =?utf-8?q?Ond=C5=99ej_Sur=C3=BD?= <ondrej@sury.org>
-Date: Mon, 14 Mar 2016 22:47:25 +0100
-Subject: Add mongoc-cursor.c to -priv library
-
----
- mongodb-1.1.4/config.m4 | 1 +
- .../src/libmongoc-priv/src/mongoc/mongoc-cursor.c | 1313 ++++++++++++++++++++
- 2 files changed, 1314 insertions(+)
- create mode 100644 mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-cursor.c
-
-diff --git a/mongodb-1.1.4/config.m4 b/mongodb-1.1.4/config.m4
-index 32cd4ae..faae487 100644
---- a/mongodb-1.1.4/config.m4
-+++ b/mongodb-1.1.4/config.m4
-@@ -288,6 +288,7 @@ MONGOC_SOURCES_SASL=mongoc-sasl.c
-
-
- MONGOC_PRIV_SOURCES="\
-+ mongoc-cursor.c \
- mongoc-cursor-cursorid.c \
- mongoc-log.c \
- mongoc-server-description.c \
-diff --git a/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-cursor.c b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-cursor.c
-new file mode 100644
-index 0000000..1b88acd
---- /dev/null
-+++ b/mongodb-1.1.4/src/libmongoc-priv/src/mongoc/mongoc-cursor.c
-@@ -0,0 +1,1313 @@
-+/*
-+ * 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-counters-private.h"
-+#include "mongoc-error.h"
-+#include "mongoc-log.h"
-+#include "mongoc-trace.h"
-+#include "mongoc-cursor-cursorid-private.h"
-+#include "mongoc-read-concern-private.h"
-+#include "mongoc-util-private.h"
-+
-+
-+#undef MONGOC_LOG_DOMAIN
-+#define MONGOC_LOG_DOMAIN "cursor"
-+
-+
-+#define CURSOR_FAILED(cursor_) ((cursor_)->error.domain != 0)
-+
-+static const bson_t *
-+_mongoc_cursor_op_query (mongoc_cursor_t *cursor,
-+ mongoc_server_stream_t *server_stream);
-+
-+static const bson_t *
-+_mongoc_cursor_find_command (mongoc_cursor_t *cursor);
-+
-+
-+static int32_t
-+_mongoc_n_return (mongoc_cursor_t * cursor)
-+{
-+ if (cursor->is_command) {
-+ /* commands always have n_return of 1 */
-+ return 1;
-+ } else if (cursor->limit < 0) {
-+ return cursor->limit;
-+ } else if (cursor->limit) {
-+ int32_t remaining = cursor->limit - cursor->count;
-+ BSON_ASSERT (remaining > 0);
-+
-+ if (cursor->batch_size) {
-+ return BSON_MIN ((int32_t) cursor->batch_size, remaining);
-+ } else {
-+ /* batch_size 0 means accept the default */
-+ return remaining;
-+ }
-+ } else {
-+ return cursor->batch_size;
-+ }
-+}
-+
-+mongoc_cursor_t *
-+_mongoc_cursor_new (mongoc_client_t *client,
-+ const char *db_and_collection,
-+ mongoc_query_flags_t qflags,
-+ uint32_t skip,
-+ int32_t limit,
-+ uint32_t batch_size,
-+ bool is_command,
-+ const bson_t *query,
-+ const bson_t *fields,
-+ const mongoc_read_prefs_t *read_prefs,
-+ const mongoc_read_concern_t *read_concern)
-+{
-+ mongoc_cursor_t *cursor;
-+ bson_iter_t iter;
-+ int flags = qflags;
-+ const char *dot;
-+
-+ ENTRY;
-+
-+ BSON_ASSERT (client);
-+ BSON_ASSERT (db_and_collection);
-+
-+ if (!read_concern) {
-+ read_concern = client->read_concern;
-+ }
-+ if (!read_prefs) {
-+ read_prefs = client->read_prefs;
-+ }
-+
-+ cursor = (mongoc_cursor_t *)bson_malloc0 (sizeof *cursor);
-+
-+ /*
-+ * Cursors execute their query lazily. This sadly means that we must copy
-+ * some extra data around between the bson_t structures. This should be
-+ * small in most cases, so it reduces to a pure memcpy. The benefit to this
-+ * design is simplified error handling by API consumers.
-+ */
-+
-+ cursor->client = client;
-+ bson_strncpy (cursor->ns, db_and_collection, sizeof cursor->ns);
-+
-+ cursor->nslen = (uint32_t)bson_strnlen (cursor->ns, sizeof cursor->ns);
-+ dot = strstr (db_and_collection, ".");
-+
-+ if (dot) {
-+ cursor->dblen = (uint32_t)(dot - db_and_collection);
-+ } else {
-+ /* a database name with no collection name */
-+ cursor->dblen = cursor->nslen;
-+ }
-+
-+ cursor->flags = (mongoc_query_flags_t)flags;
-+ cursor->skip = skip;
-+ cursor->limit = limit;
-+ cursor->batch_size = batch_size;
-+ cursor->is_command = is_command;
-+ cursor->has_fields = !!fields;
-+
-+#define MARK_FAILED(c) \
-+ do { \
-+ bson_init (&(c)->query); \
-+ bson_init (&(c)->fields); \
-+ (c)->done = true; \
-+ (c)->end_of_event = true; \
-+ (c)->sent = true; \
-+ } while (0)
-+
-+ /* we can't have exhaust queries with limits */
-+ if ((flags & MONGOC_QUERY_EXHAUST) && limit) {
-+ bson_set_error (&cursor->error,
-+ MONGOC_ERROR_CURSOR,
-+ MONGOC_ERROR_CURSOR_INVALID_CURSOR,
-+ "Cannot specify MONGOC_QUERY_EXHAUST and set a limit.");
-+ MARK_FAILED (cursor);
-+ GOTO (finish);
-+ }
-+
-+ /* we can't have exhaust queries with sharded clusters */
-+ if ((flags & MONGOC_QUERY_EXHAUST) &&
-+ (client->topology->description.type == MONGOC_TOPOLOGY_SHARDED)) {
-+ bson_set_error (&cursor->error,
-+ MONGOC_ERROR_CURSOR,
-+ MONGOC_ERROR_CURSOR_INVALID_CURSOR,
-+ "Cannot specify MONGOC_QUERY_EXHAUST with sharded cluster.");
-+ MARK_FAILED (cursor);
-+ GOTO (finish);
-+ }
-+
-+ /*
-+ * Check types of various optional parameters.
-+ */
-+ if (query && !is_command) {
-+ if (bson_iter_init_find (&iter, query, "$explain") &&
-+ !(BSON_ITER_HOLDS_BOOL (&iter) || BSON_ITER_HOLDS_INT32 (&iter))) {
-+ bson_set_error (&cursor->error,
-+ MONGOC_ERROR_CURSOR,
-+ MONGOC_ERROR_CURSOR_INVALID_CURSOR,
-+ "$explain must be a boolean.");
-+ MARK_FAILED (cursor);
-+ GOTO (finish);
-+ }
-+
-+ if (bson_iter_init_find (&iter, query, "$snapshot") &&
-+ !BSON_ITER_HOLDS_BOOL (&iter) &&
-+ !BSON_ITER_HOLDS_INT32 (&iter)) {
-+ bson_set_error (&cursor->error,
-+ MONGOC_ERROR_CURSOR,
-+ MONGOC_ERROR_CURSOR_INVALID_CURSOR,
-+ "$snapshot must be a boolean.");
-+ MARK_FAILED (cursor);
-+ GOTO (finish);
-+ }
-+ }
-+
-+ /*
-+ * Check if we have a mixed top-level query and dollar keys such
-+ * as $orderby. This is not allowed (you must use {$query:{}}.
-+ */
-+ if (query && bson_iter_init (&iter, query)) {
-+ bool found_dollar = false;
-+ bool found_non_dollar = false;
-+
-+ while (bson_iter_next (&iter)) {
-+ if (bson_iter_key (&iter)[0] == '$') {
-+ found_dollar = true;
-+ } else {
-+ found_non_dollar = true;
-+ }
-+ }
-+
-+ if (found_dollar && found_non_dollar) {
-+ bson_set_error (&cursor->error,
-+ MONGOC_ERROR_CURSOR,
-+ MONGOC_ERROR_CURSOR_INVALID_CURSOR,
-+ "Cannot mix top-level query with dollar keys such "
-+ "as $orderby. Use {$query: {},...} instead.");
-+ MARK_FAILED (cursor);
-+ GOTO (finish);
-+ }
-+ }
-+
-+ /* don't use MARK_FAILED after this, you'll leak cursor->query */
-+ if (query) {
-+ bson_copy_to(query, &cursor->query);
-+ } else {
-+ bson_init(&cursor->query);
-+ }
-+
-+ if (fields) {
-+ bson_copy_to(fields, &cursor->fields);
-+ } else {
-+ bson_init(&cursor->fields);
-+ }
-+
-+ if (read_prefs) {
-+ cursor->read_prefs = mongoc_read_prefs_copy (read_prefs);
-+ }
-+
-+ if (read_concern) {
-+ cursor->read_concern = mongoc_read_concern_copy (read_concern);
-+ }
-+
-+ _mongoc_buffer_init(&cursor->buffer, NULL, 0, NULL, NULL);
-+
-+finish:
-+ mongoc_counter_cursors_active_inc();
-+
-+ RETURN (cursor);
-+}
-+
-+
-+void
-+mongoc_cursor_destroy (mongoc_cursor_t *cursor)
-+{
-+ ENTRY;
-+
-+ BSON_ASSERT(cursor);
-+
-+ if (cursor->iface.destroy) {
-+ cursor->iface.destroy(cursor);
-+ } else {
-+ _mongoc_cursor_destroy(cursor);
-+ }
-+
-+ EXIT;
-+}
-+
-+void
-+_mongoc_cursor_destroy (mongoc_cursor_t *cursor)
-+{
-+ char db[MONGOC_NAMESPACE_MAX];
-+ ENTRY;
-+
-+ BSON_ASSERT (cursor);
-+
-+ if (cursor->in_exhaust) {
-+ cursor->client->in_exhaust = false;
-+ if (!cursor->done) {
-+ /* The only way to stop an exhaust cursor is to kill the connection */
-+ mongoc_cluster_disconnect_node (&cursor->client->cluster,
-+ cursor->hint);
-+ }
-+ } else if (cursor->rpc.reply.cursor_id) {
-+ bson_strncpy (db, cursor->ns, cursor->dblen + 1);
-+
-+ _mongoc_client_kill_cursor(cursor->client,
-+ cursor->hint,
-+ cursor->rpc.reply.cursor_id,
-+ db,
-+ cursor->ns + cursor->dblen + 1);
-+ }
-+
-+ if (cursor->reader) {
-+ bson_reader_destroy(cursor->reader);
-+ cursor->reader = NULL;
-+ }
-+
-+ bson_destroy(&cursor->query);
-+ bson_destroy(&cursor->fields);
-+ _mongoc_buffer_destroy(&cursor->buffer);
-+ mongoc_read_prefs_destroy(cursor->read_prefs);
-+ mongoc_read_concern_destroy(cursor->read_concern);
-+
-+ 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;
-+
-+ ENTRY;
-+
-+ if (cursor->hint) {
-+ server_stream = mongoc_cluster_stream_for_server (&cursor->client->cluster,
-+ cursor->hint,
-+ true /* reconnect_ok */,
-+ &cursor->error);
-+ } else {
-+ server_stream = mongoc_cluster_stream_for_reads (&cursor->client->cluster,
-+ cursor->read_prefs,
-+ &cursor->error);
-+
-+ if (server_stream) {
-+ cursor->hint = server_stream->sd->id;
-+ }
-+ }
-+
-+ RETURN (server_stream);
-+}
-+
-+
-+bool
-+_use_find_command (const mongoc_cursor_t *cursor,
-+ const mongoc_server_stream_t *server_stream)
-+{
-+ /* Find, getMore And killCursors Commands Spec: "the find command cannot be
-+ * used to execute other commands" and "the find command does not support the
-+ * exhaust flag."
-+ */
-+ return server_stream->sd->max_wire_version >= WIRE_VERSION_FIND_CMD &&
-+ !cursor->is_command &&
-+ !(cursor->flags & MONGOC_QUERY_EXHAUST);
-+}
-+
-+
-+static const bson_t *
-+_mongoc_cursor_initial_query (mongoc_cursor_t *cursor)
-+{
-+ mongoc_server_stream_t *server_stream;
-+ const bson_t *b = NULL;
-+
-+ ENTRY;
-+
-+ BSON_ASSERT (cursor);
-+
-+ server_stream = _mongoc_cursor_fetch_stream (cursor);
-+
-+ if (!server_stream) {
-+ GOTO (done);
-+ }
-+
-+ if (_use_find_command (cursor, server_stream)) {
-+ b = _mongoc_cursor_find_command (cursor);
-+ } else {
-+ /* When the user explicitly provides a readConcern -- but the server
-+ * doesn't support readConcern, we must error:
-+ * https://github.com/mongodb/specifications/blob/master/source/read-write-concern/read-write-concern.rst#errors-1
-+ */
-+ if (cursor->read_concern->level != NULL
-+ && server_stream->sd->max_wire_version < WIRE_VERSION_READ_CONCERN) {
-+ bson_set_error (&cursor->error,
-+ MONGOC_ERROR_COMMAND,
-+ MONGOC_ERROR_PROTOCOL_BAD_WIRE_VERSION,
-+ "The selected server does not support readConcern");
-+ } else {
-+ b = _mongoc_cursor_op_query (cursor, server_stream);
-+ }
-+ }
-+
-+done:
-+ /* no-op if server_stream is NULL */
-+ mongoc_server_stream_cleanup (server_stream);
-+
-+ if (!b) {
-+ cursor->done = true;
-+ }
-+
-+ RETURN (b);
-+}
-+
-+
-+static const bson_t *
-+_mongoc_cursor_op_query (mongoc_cursor_t *cursor,
-+ mongoc_server_stream_t *server_stream)
-+{
-+ mongoc_apply_read_prefs_result_t result = READ_PREFS_RESULT_INIT;
-+ mongoc_rpc_t rpc;
-+ uint32_t request_id;
-+ const bson_t *bson = NULL;
-+
-+ ENTRY;
-+
-+ cursor->sent = true;
-+
-+ rpc.query.msg_len = 0;
-+ rpc.query.request_id = 0;
-+ rpc.query.response_to = 0;
-+ rpc.query.opcode = MONGOC_OPCODE_QUERY;
-+ rpc.query.flags = cursor->flags;
-+ rpc.query.collection = cursor->ns;
-+ rpc.query.skip = cursor->skip;
-+ if ((cursor->flags & MONGOC_QUERY_TAILABLE_CURSOR)) {
-+ rpc.query.n_return = 0;
-+ } else {
-+ rpc.query.n_return = _mongoc_n_return(cursor);
-+ }
-+
-+ if (cursor->has_fields) {
-+ rpc.query.fields = bson_get_data (&cursor->fields);
-+ } else {
-+ rpc.query.fields = NULL;
-+ }
-+
-+ apply_read_preferences (cursor->read_prefs, server_stream,
-+ &cursor->query, cursor->flags, &result);
-+
-+ rpc.query.query = bson_get_data (result.query_with_read_prefs);
-+ rpc.query.flags = result.flags;
-+
-+ if (!mongoc_cluster_sendv_to_server (&cursor->client->cluster,
-+ &rpc, 1, server_stream,
-+ NULL, &cursor->error)) {
-+ GOTO (failure);
-+ }
-+
-+ request_id = BSON_UINT32_FROM_LE (rpc.header.request_id);
-+
-+ _mongoc_buffer_clear(&cursor->buffer, false);
-+
-+ if (!_mongoc_client_recv(cursor->client,
-+ &cursor->rpc,
-+ &cursor->buffer,
-+ server_stream,
-+ &cursor->error)) {
-+ GOTO (failure);
-+ }
-+
-+ if (cursor->rpc.header.opcode != MONGOC_OPCODE_REPLY) {
-+ bson_set_error (&cursor->error,
-+ MONGOC_ERROR_PROTOCOL,
-+ MONGOC_ERROR_PROTOCOL_INVALID_REPLY,
-+ "Invalid opcode. Expected %d, got %d.",
-+ MONGOC_OPCODE_REPLY, cursor->rpc.header.opcode);
-+ GOTO (failure);
-+ }
-+
-+ if (cursor->rpc.header.response_to != request_id) {
-+ bson_set_error (&cursor->error,
-+ MONGOC_ERROR_PROTOCOL,
-+ MONGOC_ERROR_PROTOCOL_INVALID_REPLY,
-+ "Invalid response_to for query. Expected %d, got %d.",
-+ request_id, cursor->rpc.header.response_to);
-+ GOTO (failure);
-+ }
-+
-+ if (cursor->is_command) {
-+ if (_mongoc_rpc_parse_command_error (&cursor->rpc,
-+ &cursor->error)) {
-+ GOTO (failure);
-+ }
-+ } else {
-+ if (_mongoc_rpc_parse_query_error (&cursor->rpc,
-+ &cursor->error)) {
-+ GOTO (failure);
-+ }
-+ }
-+
-+ if (cursor->reader) {
-+ bson_reader_destroy (cursor->reader);
-+ }
-+
-+ cursor->reader = bson_reader_new_from_data(
-+ cursor->rpc.reply.documents,
-+ (size_t) cursor->rpc.reply.documents_len);
-+
-+ if ((cursor->flags & MONGOC_QUERY_EXHAUST)) {
-+ cursor->in_exhaust = true;
-+ cursor->client->in_exhaust = true;
-+ }
-+
-+ cursor->done = false;
-+ cursor->end_of_event = false;
-+ cursor->sent = true;
-+
-+ _mongoc_read_from_buffer (cursor, &bson);
-+
-+ apply_read_prefs_result_cleanup (&result);
-+
-+ RETURN (bson);
-+
-+failure:
-+ cursor->done = true;
-+
-+ apply_read_prefs_result_cleanup (&result);
-+
-+ RETURN (false);
-+}
-+
-+
-+bool
-+_mongoc_cursor_run_command (mongoc_cursor_t *cursor,
-+ const bson_t *command)
-+{
-+ mongoc_cluster_t *cluster;
-+ mongoc_server_stream_t *server_stream;
-+ char cmd_ns[MONGOC_NAMESPACE_MAX];
-+ mongoc_apply_read_prefs_result_t read_prefs_result = READ_PREFS_RESULT_INIT;
-+ bool ret = false;
-+ bson_t bson;
-+ mongoc_rpc_t rpc;
-+
-+ ENTRY;
-+
-+ cluster = &cursor->client->cluster;
-+
-+ server_stream = _mongoc_cursor_fetch_stream (cursor);
-+
-+ if (!server_stream) {
-+ GOTO (done);
-+ }
-+
-+ _mongoc_buffer_clear (&cursor->buffer, false);
-+
-+ bson_snprintf (cmd_ns, sizeof cmd_ns, "%.*s.$cmd", cursor->dblen,
-+ cursor->ns);
-+
-+ apply_read_preferences (cursor->read_prefs, server_stream,
-+ command, cursor->flags, &read_prefs_result);
-+
-+ _mongoc_rpc_prep_command (&rpc,
-+ cmd_ns,
-+ read_prefs_result.query_with_read_prefs,
-+ read_prefs_result.flags);
-+
-+ if (!mongoc_cluster_run_command_rpc (cluster, server_stream->stream,
-+ server_stream->sd->id,
-+ _mongoc_get_command_name (&cursor->query),
-+ &rpc, &cursor->rpc, &cursor->buffer,
-+ &cursor->error)) {
-+ GOTO (done);
-+ }
-+
-+ /* static-init "bson" to point into buffer */
-+ if (!_mongoc_rpc_reply_get_first (&cursor->rpc.reply, &bson)) {
-+ bson_set_error (&cursor->error,
-+ MONGOC_ERROR_BSON,
-+ MONGOC_ERROR_BSON_INVALID,
-+ "Failed to decode reply BSON document.");
-+ GOTO (done);
-+ }
-+
-+ if (_mongoc_rpc_parse_command_error (&cursor->rpc, &cursor->error)) {
-+ GOTO (done);
-+ }
-+
-+ if (cursor->reader) {
-+ bson_reader_destroy (cursor->reader);
-+ }
-+
-+ cursor->reader = bson_reader_new_from_data (
-+ cursor->rpc.reply.documents,
-+ (size_t)cursor->rpc.reply.documents_len);
-+
-+ ret = true;
-+
-+done:
-+ apply_read_prefs_result_cleanup (&read_prefs_result);
-+ mongoc_server_stream_cleanup (server_stream);
-+
-+ return ret;
-+}
-+
-+
-+static bool
-+_invalid_field (const char *query_field,
-+ mongoc_cursor_t *cursor)
-+{
-+ if (query_field[0] == '\0') {
-+ bson_set_error (&cursor->error,
-+ MONGOC_ERROR_CURSOR,
-+ MONGOC_ERROR_CURSOR_INVALID_CURSOR,
-+ "empty string is not a valid query operator");
-+ return true;
-+ }
-+
-+ return false;
-+}
-+
-+
-+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 ("query", query_field)) {
-+ *cmd_field = "filter";
-+ *len = 6;
-+ } else if (!strcmp ("orderby", query_field)) {
-+ *cmd_field = "sort";
-+ *len = 4;
-+ } else if (!strcmp ("showDiskLoc", query_field)) { /* <= MongoDb 3.0 */
-+ *cmd_field = "showRecordId";
-+ *len = 12;
-+ } else if (!strcmp("hint", query_field)) {
-+ *cmd_field = "hint";
-+ *len = 4;
-+ } else if (!strcmp("comment", query_field)) {
-+ *cmd_field = "comment";
-+ *len = 7;
-+ } else if (!strcmp("maxScan", query_field)) {
-+ *cmd_field = "maxScan";
-+ *len = 7;
-+ } else if (!strcmp("maxTimeMS", query_field)) {
-+ *cmd_field = "maxTimeMS";
-+ *len = 9;
-+ } else if (!strcmp("max", query_field)) {
-+ *cmd_field = "max";
-+ *len = 3;
-+ } else if (!strcmp("min", query_field)) {
-+ *cmd_field = "min";
-+ *len = 3;
-+ } else if (!strcmp("returnKey", query_field)) {
-+ *cmd_field = "returnKey";
-+ *len = 9;
-+ } else if (!strcmp("snapshot", query_field)) {
-+ *cmd_field = "snapshot";
-+ *len = 8;
-+ } else {
-+ /* not a special command field, must be a query operator like $or */
-+ return false;
-+ }
-+
-+ return true;
-+}
-+
-+
-+static void
-+_mongoc_cursor_prepare_find_command_flags (mongoc_cursor_t *cursor,
-+ bson_t *command)
-+{
-+ mongoc_query_flags_t flags = cursor->flags;
-+
-+ if (flags & MONGOC_QUERY_TAILABLE_CURSOR) {
-+ bson_append_bool (command, "tailable", 8, true);
-+ }
-+
-+ if (flags & MONGOC_QUERY_OPLOG_REPLAY) {
-+ bson_append_bool (command, "oplogReplay", 11, true);
-+ }
-+
-+ if (flags & MONGOC_QUERY_NO_CURSOR_TIMEOUT) {
-+ bson_append_bool (command, "noCursorTimeout", 15, true);
-+ }
-+
-+ if (flags & MONGOC_QUERY_AWAIT_DATA) {
-+ bson_append_bool (command, "awaitData", 9, true);
-+ }
-+
-+ if (flags & MONGOC_QUERY_PARTIAL) {
-+ bson_append_bool (command, "allowPartialResults", 19, true);
-+ }
-+}
-+
-+
-+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);
-+}
-+
-+
-+static bool
-+_mongoc_cursor_prepare_find_command (mongoc_cursor_t *cursor,
-+ bson_t *command)
-+{
-+ const char *collection;
-+ int collection_len;
-+ bson_iter_t iter;
-+ const char *command_field;
-+ int len;
-+ const bson_value_t *value;
-+
-+ _mongoc_cursor_collection (cursor, &collection, &collection_len);
-+ bson_append_utf8 (command, "find", 4, collection, collection_len);
-+
-+ if (bson_empty0 (&cursor->query)) {
-+ /* Find, getMore And killCursors Commands Spec: filter "MUST be included
-+ * in the command".
-+ */
-+ bson_t empty = BSON_INITIALIZER;
-+ bson_append_document (command, "filter", 6, &empty);
-+ } else if (bson_has_field (&cursor->query, "$query")) {
-+ bson_iter_init (&iter, &cursor->query);
-+ while (bson_iter_next (&iter)) {
-+ if (_invalid_field (bson_iter_key (&iter), cursor)) {
-+ return false;
-+ }
-+
-+ value = bson_iter_value (&iter);
-+ if (_translate_query_opt (bson_iter_key (&iter),
-+ &command_field,
-+ &len)) {
-+ bson_append_value (command, command_field, len, value);
-+ } else {
-+ bson_append_value (command, bson_iter_key (&iter), -1, value);
-+ }
-+ }
-+ } else if (bson_has_field (&cursor->query, "filter")) {
-+ bson_concat (command, &cursor->query);
-+ } else {
-+ /* cursor->query has no "$query", use it as the filter */
-+ bson_append_document (command, "filter", 6, &cursor->query);
-+ }
-+
-+ if (!bson_empty0 (&cursor->fields)) {
-+ bson_append_document (command, "projection", 10, &cursor->fields);
-+ }
-+
-+ if (cursor->skip) {
-+ bson_append_int64 (command, "skip", 4, cursor->skip);
-+ }
-+
-+ if (cursor->limit) {
-+ if (cursor->limit < 0) {
-+ bson_append_bool (command, "singleBatch", 11, true);
-+ }
-+
-+ bson_append_int64 (command, "limit", 5, labs(cursor->limit));
-+ }
-+
-+ if (cursor->batch_size) {
-+ bson_append_int32 (command, "batchSize", 9, cursor->batch_size);
-+ }
-+
-+ if (cursor->read_concern->level != NULL) {
-+ const bson_t *read_concern_bson;
-+
-+ read_concern_bson = _mongoc_read_concern_get_bson (cursor->read_concern);
-+ BSON_APPEND_DOCUMENT (command, "readConcern", read_concern_bson);
-+ }
-+
-+ _mongoc_cursor_prepare_find_command_flags (cursor, command);
-+
-+ return true;
-+}
-+
-+
-+static const bson_t *
-+_mongoc_cursor_find_command (mongoc_cursor_t *cursor)
-+{
-+ bson_t command = BSON_INITIALIZER;
-+ const bson_t *bson = NULL;
-+
-+ ENTRY;
-+
-+ if (!_mongoc_cursor_prepare_find_command (cursor, &command)) {
-+ RETURN (NULL);
-+ }
-+
-+ _mongoc_cursor_cursorid_init (cursor, &command);
-+ bson_destroy (&command);
-+
-+ BSON_ASSERT (cursor->iface.next);
-+ _mongoc_cursor_cursorid_next (cursor, &bson);
-+
-+ RETURN (bson);
-+}
-+
-+
-+static const bson_t *
-+_mongoc_cursor_get_more (mongoc_cursor_t *cursor)
-+{
-+ mongoc_server_stream_t *server_stream;
-+ const bson_t *b = NULL;
-+
-+ ENTRY;
-+
-+ BSON_ASSERT (cursor);
-+
-+ server_stream = _mongoc_cursor_fetch_stream (cursor);
-+ if (!server_stream) {
-+ GOTO (failure);
-+ }
-+
-+ if (!cursor->in_exhaust && !cursor->rpc.reply.cursor_id) {
-+ bson_set_error (&cursor->error,
-+ MONGOC_ERROR_CURSOR,
-+ MONGOC_ERROR_CURSOR_INVALID_CURSOR,
-+ "No valid cursor was provided.");
-+ GOTO (failure);
-+ }
-+
-+ if (!_mongoc_cursor_op_getmore (cursor, server_stream)) {
-+ GOTO (failure);
-+ }
-+
-+ mongoc_server_stream_cleanup (server_stream);
-+
-+ if (cursor->reader) {
-+ _mongoc_read_from_buffer (cursor, &b);
-+ }
-+
-+ RETURN (b);
-+
-+failure:
-+ cursor->done = true;
-+
-+ mongoc_server_stream_cleanup (server_stream);
-+
-+ RETURN (NULL);
-+}
-+
-+
-+bool
-+_mongoc_cursor_op_getmore (mongoc_cursor_t *cursor,
-+ mongoc_server_stream_t *server_stream)
-+{
-+ mongoc_rpc_t rpc;
-+ uint32_t request_id;
-+ bool ret = false;
-+
-+ ENTRY;
-+
-+ if (cursor->in_exhaust) {
-+ request_id = (uint32_t) cursor->rpc.header.request_id;
-+ } else {
-+ rpc.get_more.cursor_id = cursor->rpc.reply.cursor_id;
-+ rpc.get_more.msg_len = 0;
-+ rpc.get_more.request_id = 0;
-+ rpc.get_more.response_to = 0;
-+ rpc.get_more.opcode = MONGOC_OPCODE_GET_MORE;
-+ rpc.get_more.zero = 0;
-+ rpc.get_more.collection = cursor->ns;
-+ if ((cursor->flags & MONGOC_QUERY_TAILABLE_CURSOR)) {
-+ rpc.get_more.n_return = 0;
-+ } else {
-+ rpc.get_more.n_return = _mongoc_n_return(cursor);
-+ }
-+
-+ if (!mongoc_cluster_sendv_to_server (&cursor->client->cluster,
-+ &rpc, 1, server_stream,
-+ NULL, &cursor->error)) {
-+ GOTO (done);
-+ }
-+
-+ request_id = BSON_UINT32_FROM_LE (rpc.header.request_id);
-+ }
-+
-+ _mongoc_buffer_clear (&cursor->buffer, false);
-+
-+ if (!_mongoc_client_recv (cursor->client,
-+ &cursor->rpc,
-+ &cursor->buffer,
-+ server_stream,
-+ &cursor->error)) {
-+ GOTO (done);
-+ }
-+
-+ if (cursor->rpc.header.opcode != MONGOC_OPCODE_REPLY) {
-+ bson_set_error (&cursor->error,
-+ MONGOC_ERROR_PROTOCOL,
-+ MONGOC_ERROR_PROTOCOL_INVALID_REPLY,
-+ "Invalid opcode. Expected %d, got %d.",
-+ MONGOC_OPCODE_REPLY, cursor->rpc.header.opcode);
-+ GOTO (done);
-+ }
-+
-+ if (cursor->rpc.header.response_to != request_id) {
-+ bson_set_error (&cursor->error,
-+ MONGOC_ERROR_PROTOCOL,
-+ MONGOC_ERROR_PROTOCOL_INVALID_REPLY,
-+ "Invalid response_to for getmore. Expected %d, got %d.",
-+ request_id, cursor->rpc.header.response_to);
-+ GOTO (done);
-+ }
-+
-+ if (_mongoc_rpc_parse_query_error (&cursor->rpc,
-+ &cursor->error)) {
-+ GOTO (done);
-+ }
-+
-+ if (cursor->reader) {
-+ bson_reader_destroy (cursor->reader);
-+ }
-+
-+ cursor->reader = bson_reader_new_from_data (
-+ cursor->rpc.reply.documents,
-+ (size_t)cursor->rpc.reply.documents_len);
-+
-+ ret = true;
-+
-+done:
-+ RETURN (ret);
-+}
-+
-+
-+bool
-+mongoc_cursor_error (mongoc_cursor_t *cursor,
-+ bson_error_t *error)
-+{
-+ bool ret;
-+
-+ ENTRY;
-+
-+ BSON_ASSERT(cursor);
-+
-+ if (cursor->iface.error) {
-+ ret = cursor->iface.error(cursor, error);
-+ } else {
-+ ret = _mongoc_cursor_error(cursor, error);
-+ }
-+
-+ RETURN(ret);
-+}
-+
-+
-+bool
-+_mongoc_cursor_error (mongoc_cursor_t *cursor,
-+ bson_error_t *error)
-+{
-+ ENTRY;
-+
-+ BSON_ASSERT (cursor);
-+
-+ if (BSON_UNLIKELY(CURSOR_FAILED (cursor))) {
-+ bson_set_error(error,
-+ cursor->error.domain,
-+ cursor->error.code,
-+ "%s",
-+ cursor->error.message);
-+ RETURN(true);
-+ }
-+
-+ RETURN(false);
-+}
-+
-+
-+bool
-+mongoc_cursor_next (mongoc_cursor_t *cursor,
-+ const bson_t **bson)
-+{
-+ bool ret;
-+
-+ ENTRY;
-+
-+ BSON_ASSERT(cursor);
-+ BSON_ASSERT(bson);
-+
-+ TRACE ("cursor_id(%"PRId64")", cursor->rpc.reply.cursor_id);
-+
-+ if (bson) {
-+ *bson = NULL;
-+ }
-+
-+ if (CURSOR_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);
-+ }
-+
-+ if (cursor->iface.next) {
-+ ret = cursor->iface.next(cursor, bson);
-+ } else {
-+ ret = _mongoc_cursor_next(cursor, bson);
-+ }
-+
-+ cursor->current = *bson;
-+
-+ cursor->count++;
-+
-+ RETURN(ret);
-+}
-+
-+
-+bool
-+_mongoc_read_from_buffer (mongoc_cursor_t *cursor,
-+ const bson_t **bson)
-+{
-+ bool eof = false;
-+
-+ BSON_ASSERT (cursor->reader);
-+
-+ *bson = bson_reader_read (cursor->reader, &eof);
-+ cursor->end_of_event = eof ? 1 : 0;
-+
-+ return *bson ? true : false;
-+}
-+
-+
-+bool
-+_mongoc_cursor_next (mongoc_cursor_t *cursor,
-+ const bson_t **bson)
-+{
-+ const bson_t *b = NULL;
-+
-+ ENTRY;
-+
-+ BSON_ASSERT (cursor);
-+
-+ if (bson) {
-+ *bson = NULL;
-+ }
-+
-+ if (cursor->done || CURSOR_FAILED (cursor)) {
-+ bson_set_error (&cursor->error,
-+ MONGOC_ERROR_CURSOR,
-+ MONGOC_ERROR_CURSOR_INVALID_CURSOR,
-+ "Cannot advance a completed or failed cursor.");
-+ RETURN (false);
-+ }
-+
-+ /*
-+ * If we reached our limit, make sure we mark this as done and do not try to
-+ * make further progress.
-+ */
-+ if (cursor->limit && cursor->count >= labs(cursor->limit)) {
-+ cursor->done = true;
-+ RETURN (false);
-+ }
-+
-+ /*
-+ * Try to read the next document from the reader if it exists, we might
-+ * get NULL back and EOF, in which case we need to submit a getmore.
-+ */
-+ if (cursor->reader) {
-+ _mongoc_read_from_buffer (cursor, &b);
-+ if (b) {
-+ GOTO (complete);
-+ }
-+ }
-+
-+ /*
-+ * Check to see if we need to send a GET_MORE for more results.
-+ */
-+ if (!cursor->sent) {
-+ b = _mongoc_cursor_initial_query (cursor);
-+ } else if (BSON_UNLIKELY (cursor->end_of_event) && cursor->rpc.reply.cursor_id) {
-+ b = _mongoc_cursor_get_more (cursor);
-+ }
-+
-+complete:
-+ cursor->done = (cursor->end_of_event &&
-+ ((cursor->in_exhaust && !cursor->rpc.reply.cursor_id) ||
-+ (!b && !(cursor->flags & MONGOC_QUERY_TAILABLE_CURSOR))));
-+
-+ if (bson) {
-+ *bson = b;
-+ }
-+
-+ RETURN (!!b);
-+}
-+
-+
-+bool
-+mongoc_cursor_more (mongoc_cursor_t *cursor)
-+{
-+ bool ret;
-+
-+ ENTRY;
-+
-+ BSON_ASSERT(cursor);
-+
-+ if (cursor->iface.more) {
-+ ret = cursor->iface.more(cursor);
-+ } else {
-+ ret = _mongoc_cursor_more(cursor);
-+ }
-+
-+ RETURN(ret);
-+}
-+
-+
-+bool
-+_mongoc_cursor_more (mongoc_cursor_t *cursor)
-+{
-+ BSON_ASSERT (cursor);
-+
-+ if (CURSOR_FAILED (cursor)) {
-+ return false;
-+ }
-+
-+ return (!cursor->sent ||
-+ cursor->rpc.reply.cursor_id ||
-+ !cursor->end_of_event);
-+}
-+
-+
-+void
-+mongoc_cursor_get_host (mongoc_cursor_t *cursor,
-+ mongoc_host_list_t *host)
-+{
-+ BSON_ASSERT(cursor);
-+ BSON_ASSERT(host);
-+
-+ if (cursor->iface.get_host) {
-+ cursor->iface.get_host(cursor, host);
-+ } else {
-+ _mongoc_cursor_get_host(cursor, host);
-+ }
-+
-+ EXIT;
-+}
-+
-+void
-+_mongoc_cursor_get_host (mongoc_cursor_t *cursor,
-+ mongoc_host_list_t *host)
-+{
-+ mongoc_server_description_t *description;
-+
-+ BSON_ASSERT (cursor);
-+ BSON_ASSERT (host);
-+
-+ memset(host, 0, sizeof *host);
-+
-+ if (!cursor->hint) {
-+ MONGOC_WARNING("%s(): Must send query before fetching peer.",
-+ BSON_FUNC);
-+ return;
-+ }
-+
-+ description = mongoc_topology_server_by_id(cursor->client->topology,
-+ cursor->hint,
-+ &cursor->error);
-+ if (!description) {
-+ return;
-+ }
-+
-+ *host = description->host;
-+
-+ mongoc_server_description_destroy (description);
-+
-+ return;
-+}
-+
-+mongoc_cursor_t *
-+mongoc_cursor_clone (const mongoc_cursor_t *cursor)
-+{
-+ mongoc_cursor_t *ret;
-+
-+ BSON_ASSERT(cursor);
-+
-+ if (cursor->iface.clone) {
-+ ret = cursor->iface.clone(cursor);
-+ } else {
-+ ret = _mongoc_cursor_clone(cursor);
-+ }
-+
-+ RETURN(ret);
-+}
-+
-+
-+mongoc_cursor_t *
-+_mongoc_cursor_clone (const mongoc_cursor_t *cursor)
-+{
-+ mongoc_cursor_t *_clone;
-+
-+ ENTRY;
-+
-+ BSON_ASSERT (cursor);
-+
-+ _clone = (mongoc_cursor_t *)bson_malloc0 (sizeof *_clone);
-+
-+ _clone->client = cursor->client;
-+ _clone->is_command = cursor->is_command;
-+ _clone->flags = cursor->flags;
-+ _clone->skip = cursor->skip;
-+ _clone->batch_size = cursor->batch_size;
-+ _clone->limit = cursor->limit;
-+ _clone->nslen = cursor->nslen;
-+ _clone->dblen = cursor->dblen;
-+ _clone->has_fields = cursor->has_fields;
-+
-+ 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);
-+ }
-+
-+
-+ bson_copy_to (&cursor->query, &_clone->query);
-+ bson_copy_to (&cursor->fields, &_clone->fields);
-+
-+ bson_strncpy (_clone->ns, cursor->ns, sizeof _clone->ns);
-+
-+ _mongoc_buffer_init (&_clone->buffer, NULL, 0, NULL, NULL);
-+
-+ mongoc_counter_cursors_active_inc ();
-+
-+ RETURN (_clone);
-+}
-+
-+
-+/*
-+ *--------------------------------------------------------------------------
-+ *
-+ * mongoc_cursor_is_alive --
-+ *
-+ * Checks to see if a cursor is alive.
-+ *
-+ * This is primarily useful with tailable cursors.
-+ *
-+ * Returns:
-+ * true if the cursor is alive.
-+ *
-+ * Side effects:
-+ * None.
-+ *
-+ *--------------------------------------------------------------------------
-+ */
-+
-+bool
-+mongoc_cursor_is_alive (const mongoc_cursor_t *cursor) /* IN */
-+{
-+ BSON_ASSERT (cursor);
-+
-+ return (!cursor->sent ||
-+ (!CURSOR_FAILED (cursor) &&
-+ !cursor->done &&
-+ (cursor->rpc.header.opcode == MONGOC_OPCODE_REPLY) &&
-+ cursor->rpc.reply.cursor_id));
-+}
-+
-+
-+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);
-+ cursor->batch_size = batch_size;
-+}
-+
-+uint32_t
-+mongoc_cursor_get_batch_size (const mongoc_cursor_t *cursor)
-+{
-+ BSON_ASSERT (cursor);
-+
-+ return cursor->batch_size;
-+}
-+
-+uint32_t
-+mongoc_cursor_get_hint (const mongoc_cursor_t *cursor)
-+{
-+ BSON_ASSERT (cursor);
-+
-+ return cursor->hint;
-+}
-+
-+int64_t
-+mongoc_cursor_get_id (const mongoc_cursor_t *cursor)
-+{
-+ BSON_ASSERT(cursor);
-+
-+ return cursor->rpc.reply.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->sent) {
-+ cursor->max_await_time_ms = max_await_time_ms;
-+ }
-+}
-+
-+uint32_t
-+mongoc_cursor_get_max_await_time_ms (const mongoc_cursor_t *cursor)
-+{
-+ BSON_ASSERT (cursor);
-+
-+ return cursor->max_await_time_ms;
-+}
diff --git a/debian/patches/series b/debian/patches/series
deleted file mode 100644
index 4944cd0e..00000000
--- a/debian/patches/series
+++ /dev/null
@@ -1,2 +0,0 @@
-0001-Try-linking-with-public-libmongoc-1.0-library-and-sl.patch
-0002-Add-mongoc-cursor.c-to-priv-library.patch
diff --git a/debian/rules b/debian/rules
index 0e49cc8e..7e2c9622 100755
--- a/debian/rules
+++ b/debian/rules
@@ -1,40 +1,40 @@
#!/usr/bin/make -f
SHELL=/bin/sh -e
PECL_NAME := $(shell dpkg-parsechangelog -SSource | sed -e s/php-//)
SOURCE_DIR := $(shell ls -1d $(PECL_NAME)-*)
INSTALL_ROOT := $(CURDIR)/debian/php-$(PECL_NAME)
PHP_VERSIONS := $(shell /usr/sbin/phpquery -V)
%:
dh $@ --with php --sourcedirectory=$(SOURCE_DIR)
override_dh_auto_configure:
for v in $(PHP_VERSIONS); do \
cp -a $(CURDIR)/$(SOURCE_DIR) $(CURDIR)/build-$$v; \
cd $(CURDIR)/build-$$v; \
phpize$$v; \
done
cd $(SOURCE_DIR) && phpize
for v in $(PHP_VERSIONS); do \
- dh_auto_configure --builddirectory=$(CURDIR)/build-$$v --sourcedirectory=$(SOURCE_DIR) -- --enable-$(PECL_NAME) --with-php-config=/usr/bin/php-config$$v --with-libbson --with-libmongoc; \
+ dh_auto_configure --builddirectory=$(CURDIR)/build-$$v --sourcedirectory=$(SOURCE_DIR) -- --enable-$(PECL_NAME) --with-php-config=/usr/bin/php-config$$v --with-libbson; \
done
override_dh_auto_build:
for v in $(PHP_VERSIONS); do \
dh_auto_build --builddirectory=$(CURDIR)/build-$$v --sourcedirectory=$(SOURCE_DIR); \
done
override_dh_auto_install:
for v in $(PHP_VERSIONS); do \
dh_auto_install --builddirectory=$(CURDIR)/build-$$v --sourcedirectory=$(SOURCE_DIR) -- INSTALL_ROOT=$(INSTALL_ROOT); \
done
override_dh_auto_clean:
for v in $(PHP_VERSIONS); do \
dh_auto_clean --builddirectory=$(CURDIR)/build-$$v --sourcedirectory=$(SOURCE_DIR); \
rm -rf $(CURDIR)/build-$$v; \
done
cd $(SOURCE_DIR) && phpize --clean

File Metadata

Mime Type
text/x-diff
Expires
Tue, Jun 16, 12:12 AM (2 w, 2 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
70297
Default Alt Text
(363 KB)

Event Timeline