コード例 #1
0
ファイル: Server.cpp プロジェクト: Jekshmek/mongo-hhvm-driver
Array HHVM_METHOD(MongoDBDriverServer, getInfo)
{
	MongoDBDriverServerData* data = Native::data<MongoDBDriverServerData>(this_);
	mongoc_server_description_t *sd;

	if ((sd = mongoc_client_get_server_description(data->m_client, data->m_server_id))) {
		const bson_t       *is_master = mongoc_server_description_ismaster(sd);

		Variant v;

		hippo_bson_conversion_options_t options = HIPPO_TYPEMAP_DEBUG_INITIALIZER;

		/* Yeah, this is not pretty. But, C++ doesn't have finally, and I don't
		 * want to bson_copy the is_master thing just because of that */
		try {
			BsonToVariantConverter convertor(bson_get_data(is_master), is_master->len, options);
			convertor.convert(&v);
		} catch (...) {
			mongoc_server_description_destroy(sd);
			throw;
		}

		return v.toArray();
	}

	throw MongoDriver::Utils::CreateAndConstruct(MongoDriver::s_MongoDriverExceptionRuntimeException_className, "Failed to get server description", HPHP::Variant((uint64_t) 0));
}
コード例 #2
0
static void
test_rtt_calculation_cb (bson_t *test)
{
   mongoc_server_description_t *description;
   bson_iter_t iter;

   BSON_ASSERT (test);

   description = (mongoc_server_description_t *)bson_malloc0(sizeof *description);
   mongoc_server_description_init(description, "localhost:27017", 1);

   /* parse RTT into server description */
   assert(bson_iter_init_find(&iter, test, "avg_rtt_ms"));
   description->round_trip_time_msec = bson_iter_int64(&iter);

   /* update server description with new rtt */
   assert(bson_iter_init_find(&iter, test, "new_rtt_ms"));
   mongoc_server_description_update_rtt(description, bson_iter_int64(&iter));

   /* ensure new RTT was calculated correctly */
   assert(bson_iter_init_find(&iter, test, "new_avg_rtt"));
   assert(description->round_trip_time_msec == bson_iter_int64(&iter));

   mongoc_server_description_destroy(description);
}
コード例 #3
0
ファイル: test-replica-set.c プロジェクト: 3rf/mongo-c-driver
static ha_node_t *
get_replica (mongoc_client_t *client, uint32_t id)
{
   mongoc_server_description_t *description;
   ha_node_t *iter;

   description = mongoc_topology_server_by_id(client->topology, id, NULL);
   BSON_ASSERT(description);

   for (iter = replica_set->nodes; iter; iter = iter->next) {
      if (iter->port == description->host.port) {
         mongoc_server_description_destroy(description);
         return iter;
      }
   }

   mongoc_server_description_destroy(description);
   BSON_ASSERT(false);
   return NULL;
}
コード例 #4
0
ファイル: Server.cpp プロジェクト: Jekshmek/mongo-hhvm-driver
String HHVM_METHOD(MongoDBDriverServer, getHost)
{
	MongoDBDriverServerData* data = Native::data<MongoDBDriverServerData>(this_);
	mongoc_server_description_t *sd;

	if ((sd = mongoc_client_get_server_description(data->m_client, data->m_server_id))) {
		String host(mongoc_server_description_host(sd)->host);
		mongoc_server_description_destroy(sd);

		return host;
	}

	throw MongoDriver::Utils::CreateAndConstruct(MongoDriver::s_MongoDriverExceptionRuntimeException_className, "Failed to get server description", HPHP::Variant((uint64_t) 0));
}
コード例 #5
0
ファイル: Server.cpp プロジェクト: Jekshmek/mongo-hhvm-driver
bool HHVM_METHOD(MongoDBDriverServer, isArbiter)
{
	MongoDBDriverServerData* data = Native::data<MongoDBDriverServerData>(this_);
	mongoc_server_description_t *sd;

	if ((sd = mongoc_client_get_server_description(data->m_client, data->m_server_id))) {
		bool isType;

		isType = (strcmp(mongoc_server_description_type(sd), hippo_server_description_type_map[HIPPO_SERVER_RS_ARBITER].name) == 0);

		mongoc_server_description_destroy(sd);

		return isType;
	}

	throw MongoDriver::Utils::CreateAndConstruct(MongoDriver::s_MongoDriverExceptionRuntimeException_className, "Failed to get server description", HPHP::Variant((uint64_t) 0));
}
コード例 #6
0
ファイル: Server.cpp プロジェクト: Jekshmek/mongo-hhvm-driver
int64_t HHVM_METHOD(MongoDBDriverServer, getLatency)
{
	MongoDBDriverServerData* data = Native::data<MongoDBDriverServerData>(this_);
	mongoc_server_description_t *sd;

	if ((sd = mongoc_client_get_server_description(data->m_client, data->m_server_id))) {
		int64_t round_trip;

		round_trip = mongoc_server_description_round_trip_time(sd);

		mongoc_server_description_destroy(sd);

		return round_trip;
	}

	throw MongoDriver::Utils::CreateAndConstruct(MongoDriver::s_MongoDriverExceptionRuntimeException_className, "Failed to get server description", HPHP::Variant((uint64_t) 0));
}
コード例 #7
0
ファイル: Server.cpp プロジェクト: Jekshmek/mongo-hhvm-driver
Array HHVM_METHOD(MongoDBDriverServer, __debugInfo)
{
	MongoDBDriverServerData* data = Native::data<MongoDBDriverServerData>(this_);
	mongoc_server_description_t *sd;
	bson_error_t error;

	Array retval = Array::Create();

	if ((sd = mongoc_topology_description_server_by_id(&data->m_client->topology->description, data->m_server_id, &error))) {
		mongodb_driver_add_server_debug(sd, &retval);

		mongoc_server_description_destroy(sd);
		return retval;
	}

	throw MongoDriver::Utils::CreateAndConstruct(MongoDriver::s_MongoDriverExceptionRuntimeException_className, "Failed to get server description", HPHP::Variant((uint64_t) 0));
}
コード例 #8
0
Object HHVM_METHOD(MongoDBDriverManager, selectServer, const Object &readPreference)
{
	MongoDBDriverManagerData* data = Native::data<MongoDBDriverManagerData>(this_);
	MongoDBDriverReadPreferenceData *rp_data = Native::data<MongoDBDriverReadPreferenceData>(readPreference.get());
	bson_error_t error;
	mongoc_server_description_t *selected_server = NULL;
	Object tmp;

	selected_server = mongoc_client_select_server(data->m_client, false, rp_data->m_read_preference, &error);
	if (selected_server) {
		tmp = hippo_mongo_driver_server_create_from_id(data->m_client, selected_server->id);
		mongoc_server_description_destroy(selected_server);
		return tmp;
	} else {
		throw MongoDriver::Utils::throwExceptionFromBsonError(&error);
	}
}
コード例 #9
0
ファイル: Server.cpp プロジェクト: Jekshmek/mongo-hhvm-driver
bool HHVM_METHOD(MongoDBDriverServer, isPassive)
{
	MongoDBDriverServerData* data = Native::data<MongoDBDriverServerData>(this_);
	mongoc_server_description_t *sd;

	if ((sd = mongoc_client_get_server_description(data->m_client, data->m_server_id))) {
		bson_iter_t iter;

		const bson_t *is_master = mongoc_server_description_ismaster(sd);
		bool retval = !!(bson_iter_init_find_case(&iter, is_master, "passive") && bson_iter_as_bool(&iter));

		mongoc_server_description_destroy(sd);

		return retval;
	}

	throw MongoDriver::Utils::CreateAndConstruct(MongoDriver::s_MongoDriverExceptionRuntimeException_className, "Failed to get server description", HPHP::Variant((uint64_t) 0));
}
コード例 #10
0
static void
_mongoc_topology_server_dtor (void *server_,
                              void *ctx_)
{
   mongoc_server_description_destroy ((mongoc_server_description_t *)server_);
}
コード例 #11
0
ファイル: test-replica-set.c プロジェクト: 3rf/mongo-c-driver
static void
test1 (void)
{
   mongoc_server_description_t *description;
   mongoc_collection_t *collection;
   mongoc_read_prefs_t *read_prefs;
   mongoc_cursor_t *cursor;
   mongoc_client_t *client;
   mongoc_client_pool_t *pool = NULL;
   const bson_t *doc;
   bson_error_t error;
   bool r;
   ha_node_t *replica;
   bson_t q;
   int i;

   bson_init(&q);

   if (use_pool) {
      pool = ha_replica_set_create_client_pool(replica_set);
      client = mongoc_client_pool_pop (pool);
   } else {
      client = ha_replica_set_create_client(replica_set);
   }

   collection = mongoc_client_get_collection(client, "test1", "test1");

   MONGOC_DEBUG("Inserting test documents.");
   insert_test_docs(collection);
   MONGOC_INFO("Test documents inserted.");

   read_prefs = mongoc_read_prefs_new(MONGOC_READ_SECONDARY);

   MONGOC_DEBUG("Sending query to a SECONDARY.");
   cursor = mongoc_collection_find(collection,
                                   MONGOC_QUERY_NONE,
                                   0,
                                   0,
                                   100,
                                   &q,
                                   NULL,
                                   read_prefs);

   BSON_ASSERT(cursor);
   BSON_ASSERT(!cursor->server_id);

   /*
    * Send OP_QUERY to server and get first document back.
    */
   MONGOC_INFO("Sending OP_QUERY.");
   r = mongoc_cursor_next(cursor, &doc);
   BSON_ASSERT(r);
   BSON_ASSERT(cursor->server_id);
   BSON_ASSERT(cursor->sent);
   BSON_ASSERT(!cursor->done);
   BSON_ASSERT(cursor->rpc.reply.n_returned == 100);
   BSON_ASSERT(!cursor->end_of_event);

   /*
    * Make sure we queried a secondary.
    */
   description = mongoc_topology_server_by_id(client->topology,
                                              cursor->server_id,
                                              &error);
   ASSERT_OR_PRINT (description, error);
   BSON_ASSERT (description->type != MONGOC_SERVER_RS_PRIMARY);
   mongoc_server_description_destroy(description);

   /*
    * Exhaust the items in our first OP_REPLY.
    */
   MONGOC_DEBUG("Exhausting OP_REPLY.");
   for (i = 0; i < 98; i++) {
      r = mongoc_cursor_next(cursor, &doc);
      BSON_ASSERT(r);
      BSON_ASSERT(cursor->server_id);
      BSON_ASSERT(!cursor->done);
      BSON_ASSERT(!cursor->end_of_event);
   }

   /*
    * Finish off the last item in this OP_REPLY.
    */
   MONGOC_INFO("Fetcing last doc from OP_REPLY.");
   r = mongoc_cursor_next(cursor, &doc);
   BSON_ASSERT(r);
   BSON_ASSERT(cursor->server_id);
   BSON_ASSERT(cursor->sent);
   BSON_ASSERT(!cursor->done);
   BSON_ASSERT(!cursor->end_of_event);

   /*
    * Determine which node we queried by using the server_id to
    * get the cluster information.
    */

   BSON_ASSERT(cursor->server_id);
   replica = get_replica(client, cursor->server_id);

   /*
    * Kill the node we are communicating with.
    */
   MONGOC_INFO("Killing replicaSet node to synthesize failure.");
   ha_node_kill(replica);

   /*
    * Try to fetch the next result set, expect failure.
    */
   MONGOC_DEBUG("Checking for expected failure.");
   r = mongoc_cursor_next(cursor, &doc);
   BSON_ASSERT(!r);

   r = mongoc_cursor_error(cursor, &error);
   BSON_ASSERT(r);
   MONGOC_WARNING("%s", error.message);

   mongoc_cursor_destroy(cursor);
   mongoc_read_prefs_destroy(read_prefs);
   mongoc_collection_destroy(collection);

   if (use_pool) {
      mongoc_client_pool_push (pool, client);
      mongoc_client_pool_destroy (pool);
   } else {
      mongoc_client_destroy(client);
   }
   bson_destroy(&q);

   ha_node_restart(replica);
}
コード例 #12
0
bool
_mongoc_client_command_simple_with_hint (mongoc_client_t           *client,
                                         const char                *db_name,
                                         const bson_t              *command,
                                         const mongoc_read_prefs_t *read_prefs,
                                         bool                       is_write_command,
                                         bson_t                    *reply,
                                         uint32_t                   hint,
                                         bson_error_t              *error)
{
   mongoc_cluster_t *cluster;
   mongoc_stream_t *stream;
   mongoc_server_description_t *sd;
   mongoc_ss_optype_t optype;
   bool reply_initialized = false;
   bool ret = false;

   BSON_ASSERT (client);
   BSON_ASSERT (db_name);
   BSON_ASSERT (command);

   cluster = &client->cluster;

   if (!hint) {
      optype = is_write_command ? MONGOC_SS_WRITE : MONGOC_SS_READ;
      sd = mongoc_cluster_select_by_optype (cluster,
                                            optype,
                                            read_prefs,
                                            error);

      if (!sd) {
         GOTO (done);
      }

      hint = sd->id;
      mongoc_server_description_destroy (sd);
   }

   stream = mongoc_cluster_fetch_stream (cluster,
                                         hint,
                                         true /* reconnect_ok */,
                                         error);

   if (!stream) {
      GOTO (done);
   }

   ret = mongoc_cluster_run_command_with_read_preference (cluster,
                                                          stream,
                                                          db_name,
                                                          command,
                                                          hint,
                                                          read_prefs,
                                                          is_write_command,
                                                          reply,
                                                          error);

   reply_initialized = true;

done:
   if (!reply_initialized && reply) {
      bson_init (reply);
   }

   return ret;
}
コード例 #13
0
/*---------------------------------------------------------------------------
 *
 * _make_cursor --
 *
 *       Construct and send the aggregate command and create the resulting
 *       cursor. On error, stream->cursor remains NULL, otherwise it is
 *       created and must be destroyed.
 *
 * Return:
 *       False on error and sets stream->err.
 *
 *--------------------------------------------------------------------------
 */
static bool
_make_cursor (mongoc_change_stream_t *stream)
{
   mongoc_client_session_t *cs = NULL;
   bson_t command_opts;
   bson_t command; /* { aggregate: "coll", pipeline: [], ... } */
   bson_t reply;
   bson_t getmore_opts = BSON_INITIALIZER;
   bson_iter_t iter;
   mongoc_server_description_t *sd;
   uint32_t server_id;
   int32_t max_wire_version = -1;

   BSON_ASSERT (stream);
   BSON_ASSERT (!stream->cursor);
   _make_command (stream, &command);
   bson_copy_to (&(stream->opts.extra), &command_opts);
   sd = mongoc_client_select_server (
      stream->client, false /* for_writes */, stream->read_prefs, &stream->err);
   if (!sd) {
      goto cleanup;
   }
   server_id = mongoc_server_description_id (sd);
   bson_append_int32 (&command_opts, "serverId", 8, server_id);
   bson_append_int32 (&getmore_opts, "serverId", 8, server_id);
   max_wire_version = sd->max_wire_version;
   mongoc_server_description_destroy (sd);

   if (bson_iter_init_find (&iter, &command_opts, "sessionId")) {
      if (!_mongoc_client_session_from_iter (
             stream->client, &iter, &cs, &stream->err)) {
         goto cleanup;
      }
   } else if (stream->implicit_session) {
      /* If an implicit session was created before, and this cursor is now
       * being recreated after resuming, then use the same session as before. */
      cs = stream->implicit_session;
      if (!mongoc_client_session_append (cs, &command_opts, &stream->err)) {
         goto cleanup;
      }
   } else {
      /* Create an implicit session. This session lsid must be the same for the
       * agg command and the subsequent getMores. Thus, this implicit session is
       * passed as if it were an explicit session to
       * collection_read_command_with_opts and cursor_new_from_reply, but it is
       * still implicit and its lifetime is owned by this change_stream_t. */
      mongoc_session_opt_t *session_opts;
      session_opts = mongoc_session_opts_new ();
      mongoc_session_opts_set_causal_consistency (session_opts, false);
      /* returns NULL if sessions aren't supported. ignore errors. */
      cs = mongoc_client_start_session (stream->client, session_opts, NULL);
      stream->implicit_session = cs;
      mongoc_session_opts_destroy (session_opts);
      if (cs &&
          !mongoc_client_session_append (cs, &command_opts, &stream->err)) {
         goto cleanup;
      }
   }

   if (cs && !mongoc_client_session_append (cs, &getmore_opts, &stream->err)) {
      goto cleanup;
   }

   if (stream->read_concern && !bson_has_field (&command_opts, "readConcern")) {
      mongoc_read_concern_append (stream->read_concern, &command_opts);
   }

   /* even though serverId has already been set, still pass the read prefs.
    * they are necessary for OP_MSG if sending to a secondary. */
   if (!mongoc_client_read_command_with_opts (stream->client,
                                              stream->db,
                                              &command,
                                              stream->read_prefs,
                                              &command_opts,
                                              &reply,
                                              &stream->err)) {
      bson_destroy (&stream->err_doc);
      bson_copy_to (&reply, &stream->err_doc);
      bson_destroy (&reply);
      goto cleanup;
   }

   bson_append_bool (
      &getmore_opts, MONGOC_CURSOR_TAILABLE, MONGOC_CURSOR_TAILABLE_LEN, true);
   bson_append_bool (&getmore_opts,
                     MONGOC_CURSOR_AWAIT_DATA,
                     MONGOC_CURSOR_AWAIT_DATA_LEN,
                     true);

   /* maxTimeMS is only appended to getMores if these are set in cursor opts. */
   if (stream->max_await_time_ms > 0) {
      bson_append_int64 (&getmore_opts,
                         MONGOC_CURSOR_MAX_AWAIT_TIME_MS,
                         MONGOC_CURSOR_MAX_AWAIT_TIME_MS_LEN,
                         stream->max_await_time_ms);
   }

   if (stream->batch_size > 0) {
      bson_append_int32 (&getmore_opts,
                         MONGOC_CURSOR_BATCH_SIZE,
                         MONGOC_CURSOR_BATCH_SIZE_LEN,
                         stream->batch_size);
   }

   /* Change streams spec: "If neither startAtOperationTime nor resumeAfter are
    * specified, and the max wire version is >= 7, and the initial aggregate
    * command does not return a resumeToken (indicating no results), the
    * ChangeStream MUST save the operationTime from the initial aggregate
    * command when it returns." */
   if (bson_empty (&stream->resume_token) &&
       _mongoc_timestamp_empty (&stream->operation_time) &&
       max_wire_version >= 7 &&
       bson_iter_init_find (&iter, &reply, "operationTime")) {
      _mongoc_timestamp_set_from_bson (&stream->operation_time, &iter);
   }
   /* steals reply. */
   stream->cursor = mongoc_cursor_new_from_command_reply_with_opts (
      stream->client, &reply, &getmore_opts);

cleanup:
   bson_destroy (&command);
   bson_destroy (&command_opts);
   bson_destroy (&getmore_opts);
   return stream->err.code == 0;
}
コード例 #14
0
/* Construct and send the aggregate command and create the resulting cursor.
 * Returns false on error, and sets stream->err. On error, stream->cursor
 * remains NULL, otherwise it is created and must be destroyed. */
static bool
_make_cursor (mongoc_change_stream_t *stream)
{
   mongoc_client_session_t *cs = NULL;
   bson_t command_opts;
   bson_t command; /* { aggregate: "coll", pipeline: [], ... } */
   bson_t reply;
   bson_iter_t iter;
   mongoc_server_description_t *sd;
   uint32_t server_id;

   BSON_ASSERT (stream);
   BSON_ASSERT (!stream->cursor);
   _make_command (stream, &command);
   bson_copy_to (&stream->opts, &command_opts);
   sd = mongoc_client_select_server (stream->coll->client,
                                     false /* for_writes */,
                                     stream->coll->read_prefs,
                                     &stream->err);
   if (!sd) {
      goto cleanup;
   }
   server_id = mongoc_server_description_id (sd);
   bson_append_int32 (&command_opts, "serverId", 8, server_id);
   mongoc_server_description_destroy (sd);

   if (bson_iter_init_find (&iter, &command_opts, "sessionId")) {
      if (!_mongoc_client_session_from_iter (
             stream->coll->client, &iter, &cs, &stream->err)) {
         goto cleanup;
      }
   } else if (stream->implicit_session) {
      /* If an implicit session was created before, and this cursor is now
       * being recreated after resuming, then use the same session as before. */
      cs = stream->implicit_session;
      if (!mongoc_client_session_append (cs, &command_opts, &stream->err)) {
         goto cleanup;
      }
   } else {
      /* Create an implicit session. This session lsid must be the same for the
       * agg command and the subsequent getMores. Thus, this implicit session is
       * passed as if it were an explicit session to
       * collection_read_command_with_opts and cursor_new_from_reply, but it is
       * still implicit and its lifetime is owned by this change_stream_t. */
      mongoc_session_opt_t *session_opts;
      session_opts = mongoc_session_opts_new ();
      mongoc_session_opts_set_causal_consistency (session_opts, false);
      /* returns NULL if sessions aren't supported. ignore errors. */
      cs =
         mongoc_client_start_session (stream->coll->client, session_opts, NULL);
      stream->implicit_session = cs;
      mongoc_session_opts_destroy (session_opts);
      if (cs &&
          !mongoc_client_session_append (cs, &command_opts, &stream->err)) {
         goto cleanup;
      }
   }

   /* use inherited read preference and read concern of the collection */
   if (!mongoc_collection_read_command_with_opts (
          stream->coll, &command, NULL, &command_opts, &reply, &stream->err)) {
      bson_destroy (&stream->err_doc);
      bson_copy_to (&reply, &stream->err_doc);
      bson_destroy (&reply);
      goto cleanup;
   }

   stream->cursor = mongoc_cursor_new_from_command_reply (
      stream->coll->client, &reply, server_id); /* steals reply */

   if (cs) {
      stream->cursor->client_session = cs;
      stream->cursor->explicit_session = true;
   }

   /* maxTimeMS is only appended to getMores if these are set in cursor opts */
   bson_append_bool (&stream->cursor->opts,
                     MONGOC_CURSOR_TAILABLE,
                     MONGOC_CURSOR_TAILABLE_LEN,
                     true);
   bson_append_bool (&stream->cursor->opts,
                     MONGOC_CURSOR_AWAIT_DATA,
                     MONGOC_CURSOR_AWAIT_DATA_LEN,
                     true);

   if (stream->max_await_time_ms > 0) {
      BSON_ASSERT (
         _mongoc_cursor_set_opt_int64 (stream->cursor,
                                       MONGOC_CURSOR_MAX_AWAIT_TIME_MS,
                                       stream->max_await_time_ms));
   }

   if (stream->batch_size > 0) {
      mongoc_cursor_set_batch_size (stream->cursor,
                                    (uint32_t) stream->batch_size);
   }

cleanup:
   bson_destroy (&command);
   bson_destroy (&command_opts);
   return stream->err.code == 0;
}