Example #1
0
DBClientBase *mongo_connection_pool_get(mongo_connection_pool_t *conn_pool)
{
  DBClientBase *conn = NULL;
  void *data = NULL;

  switch_assert(conn_pool != NULL);

  switch_mutex_lock(conn_pool->mutex);

  if (switch_queue_trypop(conn_pool->connections, &data) == SWITCH_STATUS_SUCCESS) {
    conn = (DBClientBase *) data;
  } else if (mongo_connection_create(&conn, conn_pool->conn_str) == SWITCH_STATUS_SUCCESS) {
    if (++conn_pool->size > conn_pool->max_connections) {
      switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Connection pool is empty. You may want to increase 'max-connections'\n");
    }
  }

  switch_mutex_unlock(conn_pool->mutex);

#ifdef MONGO_POOL_DEBUG
  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "POOL get: size %d conn: %p\n", (int) switch_queue_size(conn_pool->connections), conn);
#endif

  return conn;
}
switch_status_t mongo_connection_pool_create(mongo_connection_pool_t **conn_pool, switch_size_t min_connections, switch_size_t max_connections,
					     const char *conn_str)
{
  switch_memory_pool_t *pool = NULL;
  switch_status_t status = SWITCH_STATUS_SUCCESS;
  mongo_connection_pool_t *cpool = NULL;
  DBClientBase *conn = NULL;

  if ((status = switch_core_new_memory_pool(&pool)) != SWITCH_STATUS_SUCCESS) {
    return status;
  }

  if (!(cpool = (mongo_connection_pool_t *)switch_core_alloc(pool, sizeof(mongo_connection_pool_t)))) {
    switch_goto_status(SWITCH_STATUS_MEMERR, done);
  }

  if ((status = switch_mutex_init(&cpool->mutex, SWITCH_MUTEX_NESTED, pool)) != SWITCH_STATUS_SUCCESS) {
    goto done;
  } 

  if ((status = switch_queue_create(&cpool->connections, max_connections, pool)) != SWITCH_STATUS_SUCCESS) {
    goto done;
  }

  cpool->min_connections = min_connections;
  cpool->max_connections = max_connections;
  cpool->conn_str = switch_core_strdup(pool, conn_str);
  
  cpool->pool = pool;

  for (cpool->size = 0; cpool->size < min_connections; cpool->size++) {

    if (mongo_connection_create(&conn, conn_str) == SWITCH_STATUS_SUCCESS) {
      mongo_connection_pool_put(cpool, conn);
    } else {
      break;
    }
  }

 done:

  if (status == SWITCH_STATUS_SUCCESS) {
    *conn_pool = cpool;
  } else {
    switch_core_destroy_memory_pool(&pool);
  }


  return status;
}
Example #3
0
/* Helpers */
static mongo_connection *mongo_get_connection_single(mongo_con_manager *manager, mongo_server_def *server, mongo_server_options *options, int connection_flags, char **error_message)
{
	char *hash;
	mongo_connection *con = NULL;
	mongo_connection_blacklist *blacklist = NULL;

	hash = mongo_server_create_hash(server);

	/* See if a connection is in our blacklist to short-circut trying to
	 * connect to a node that is known to be down. This is done so we don't
	 * waste precious time in connecting to unreachable nodes */
	blacklist = mongo_manager_blacklist_find_by_hash(manager, hash);
	if (blacklist) {
		struct timeval start;
		/* It is blacklisted, but it may have been a long time again and
		 * chances are we should give it another try */
		if (mongo_connection_ping_check(manager, blacklist->last_ping, &start)) {
			/* The connection is blacklisted, but we've reached our ping
			 * interval so lets remove the blacklisting and pretend we didn't
			 * know about it */
			mongo_manager_blacklist_deregister(manager, blacklist, hash);
		} else {
			/* Otherwise short-circut the connection attempt, and say we failed
			 * right away */
			free(hash);
			*error_message = strdup("Previous connection attempts failed, server blacklisted");
			return NULL;
		}
	}

	con = mongo_manager_connection_find_by_hash(manager, hash);

	/* If we aren't about to (re-)connect then all we care about if it was a
	 * known connection or not */
	if (connection_flags & MONGO_CON_FLAG_DONT_CONNECT) {
		free(hash);
		return con;
	}

	/* If we found a valid connection check if we need to ping it */
	if (con) {
		/* Do the ping, if needed */
		if (!mongo_connection_ping(manager,  con, options, error_message)) {
			/* If the ping failed, deregister the connection */
			mongo_manager_connection_deregister(manager, con);
			/* Set the return value to NULL, as the connection is broken and
			 * has been removed */
			con = NULL;
		}

		free(hash);
		return con;
	}

	/* Since we didn't find an existing connection, lets make one! */
	con = mongo_connection_create(manager, hash, server, options, error_message);
	if (con) {
		/* When we make a connection, we need to figure out the server version it is */
		if (!mongo_connection_get_server_version(manager, con, options, error_message)) {
			mongo_manager_log(manager, MLOG_CON, MLOG_WARN, "server_version: error while getting the server version %s:%d: %s", server->host, server->port, *error_message);
			mongo_connection_destroy(manager, con, MONGO_CLOSE_BROKEN);
			free(hash);
			return NULL;
		}

		/* Do authentication if requested */
		/* Note: Arbiters don't contain any data, including auth stuff, so you cannot authenticate on an arbiter */
		if (con->connection_type != MONGO_NODE_ARBITER) {
			if (!manager->authenticate(manager, con, options, server, error_message)) {
				mongo_connection_destroy(manager, con, MONGO_CLOSE_BROKEN);
				free(hash);
				return NULL;
			}
		}

		/* Do the first-time ping to record the latency of the connection */
		if (mongo_connection_ping(manager, con, options, error_message)) {
			/* Register the connection on successful pinging */
			mongo_manager_connection_register(manager, con);
		} else {
			/* Or kill it and reset the return value if the ping somehow failed */
			mongo_connection_destroy(manager, con, MONGO_CLOSE_BROKEN);
			con = NULL;
		}
	}

	free(hash);
	return con;
}
Example #4
0
static mongo_connection *mongo_get_connection_single(mongo_con_manager *manager, mongo_server_def *server, mongo_server_options *options, int connection_flags, char **error_message)
{
	char *hash;
	mongo_connection *con = NULL;
	mongo_connection_blacklist *blacklist = NULL;

	hash = mongo_server_create_hash(server);

	/* See if a connection is in our blacklist to short-circut trying to connect
	 * to a node that is known to be down. This is done so we don't waste
	 * precious time in connecting to unreachable nodes */
	blacklist = mongo_manager_blacklist_find_by_hash(manager, hash);
	if (blacklist) {
		struct timeval start;
		/* It is blacklisted, but it may have been a long time again and chances are
		 * we should give it another try */
		if (mongo_connection_ping_check(manager, blacklist->last_ping, &start)) {
			/* The connection is blacklisted, but we've reached our ping interval
			 * so lets remove the blacklisting and pretend we didn't know about it
			 */
			mongo_manager_blacklist_deregister(manager, blacklist, hash);
			con = NULL;
		} else {
			/* Otherwise short-circut the connection attempt, and say we failed right away */
			free(hash);
			return NULL;
		}
	}

	con = mongo_manager_connection_find_by_hash(manager, hash);

	/* If we aren't about to (re-)connect then all we care about if it was a known connection or not */
	if (connection_flags & MONGO_CON_FLAG_DONT_CONNECT) {
		free(hash);
		return con;
	}

	/* If we found a valid connection check if we need to ping it */
	if (con) {
		/* Do the ping, if needed */
		if (!mongo_connection_ping(manager,  con, options, error_message)) {
			/* If the ping failed, deregister the connection */
			mongo_manager_connection_deregister(manager, con);
			/* Set the return value to NULL, as the connection is broken and has been removed */
			con = NULL;
		}

		free(hash);
		return con;
	}

	/* Since we didn't find an existing connection, lets make one! */
	con = mongo_connection_create(manager, hash, server, options, error_message);
	if (con) {
		/* Do authentication if requested */
		if (server->db && server->username && server->password) {
			mongo_manager_log(manager, MLOG_CON, MLOG_INFO, "get_connection_single: authenticating %s", hash);
			if (!authenticate_connection(manager, con, options, server->authdb ? server->authdb : server->db, server->username, server->password, error_message)) {
				mongo_connection_destroy(manager, con, MONGO_CLOSE_BROKEN);
				free(hash);
				return NULL;
			}
		}
		/* Do the first-time ping to record the latency of the connection */
		if (mongo_connection_ping(manager, con, options, error_message)) {
			/* Register the connection on successful pinging */
			mongo_manager_connection_register(manager, con);
		} else {
			/* Or kill it and reset the return value if the ping somehow failed */
			mongo_connection_destroy(manager, con, MONGO_CLOSE_BROKEN);
			con = NULL;
		}
	}

	free(hash);
	return con;
}