コード例 #1
0
ファイル: audioscrobbler.c プロジェクト: Speaky10k/scmpc
/**
 * Submit new songs from the queue
 */
static gboolean as_submit(void)
{
	gchar *querystring;
	gint ret;
	gushort num_songs;

	if (queue_get_length() < 1)
		return FALSE;

	num_songs = build_querystring(&querystring);
	if (num_songs <= 0) {
		g_free(querystring);
		return FALSE;
	}

	g_debug("querystring = %s", querystring);

	curl_easy_setopt(as_conn.handle, CURLOPT_WRITEDATA, buffer);
	curl_easy_setopt(as_conn.handle, CURLOPT_POSTFIELDS, querystring);
	curl_easy_setopt(as_conn.handle, CURLOPT_URL, API_URL);

	ret = curl_easy_perform(as_conn.handle);
	g_free(querystring);
	if (ret != 0) {
		g_message("Failed to connect to Audioscrobbler: %s",
			curl_easy_strerror(ret));
		return FALSE;
	}

	if (strstr(buffer, "<lfm status=\"ok\">")) {
		g_message("%d song%s submitted.", num_songs,
				(num_songs > 1 ? "s" : ""));
		queue_clear_n(num_songs);
	} else if (strstr(buffer, "<lfm status=\"failed\">")) {
		as_parse_error(buffer);
	} else {
		g_message("Could not parse Audioscrobbler submit"
				" response.");
		g_debug("Response was: %s", buffer);
	}

	g_free(buffer);
	buffer = NULL;

	return TRUE;
}
コード例 #2
0
/*%
 * This function is the real core of the driver.   Zone, record
 * and client strings are passed in (or NULL is passed if the
 * string is not available).  The type of query we want to run
 * is indicated by the query flag, and the dbdata object is passed
 * passed in to.  dbdata really holds either:
 *		1) a list of database instances (in multithreaded mode) OR
 *		2) a single database instance (in single threaded mode)
 * The function will construct the query and obtain an available
 * database instance (DBI).  It will then run the query and hopefully
 * obtain a result set.  Postgres is nice, in that once the result
 * set is returned, we can make the db connection available for another
 * thread to use, while this thread continues on.  So, the DBI is made
 * available ASAP by unlocking the instance_lock after we have cleaned
 * it up properly.
 */
static isc_result_t
postgres_get_resultset(const char *zone, const char *record,
		       const char *client, unsigned int query,
		       void *dbdata, PGresult **rs)
{
	isc_result_t result;
	dbinstance_t *dbi = NULL;
	char *querystring = NULL;
	unsigned int i = 0;
	unsigned int j = 0;

	/* temporarily get a unique thread # */
	unsigned int dlz_thread_num = 1+(int) (1000.0*rand()/(RAND_MAX+1.0));

	REQUIRE(*rs == NULL);

#if 0
	/* temporary logging message */
	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
		      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
		      "%d Getting DBI", dlz_thread_num);
#endif

	/* get db instance / connection */
#ifdef ISC_PLATFORM_USETHREADS

	/* find an available DBI from the list */
	dbi = postgres_find_avail_conn((db_list_t *) dbdata);

#else /* ISC_PLATFORM_USETHREADS */

	/*
	 * only 1 DBI - no need to lock instance lock either
	 * only 1 thread in the whole process, no possible contention.
	 */
	dbi =  (dbinstance_t *) dbdata;

#endif /* ISC_PLATFORM_USETHREADS */

#if 0
	/* temporary logging message */
	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
		      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
		      "%d Got DBI - checking query", dlz_thread_num);
#endif

	/* if DBI is null, can't do anything else */
	if (dbi == NULL) {
		result = ISC_R_FAILURE;
		goto cleanup;
	}

	/* what type of query are we going to run? */
	switch(query) {
	case ALLNODES:
		/*
		 * if the query was not passed in from the config file
		 * then we can't run it.  return not_implemented, so
		 * it's like the code for that operation was never
		 * built into the driver.... AHHH flexibility!!!
		 */
		if (dbi->allnodes_q == NULL) {
			result = ISC_R_NOTIMPLEMENTED;
			goto cleanup;
		}
		break;
	case ALLOWXFR:
		/* same as comments as ALLNODES */
		if (dbi->allowxfr_q == NULL) {
			result = ISC_R_NOTIMPLEMENTED;
			goto cleanup;
		}
		break;
	case AUTHORITY:
		/* same as comments as ALLNODES */
		if (dbi->authority_q == NULL) {
			result = ISC_R_NOTIMPLEMENTED;
			goto cleanup;
		}
		break;
	case FINDZONE:
		/* this is required.  It's the whole point of DLZ! */
		if (dbi->findzone_q == NULL) {
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
				      "No query specified for findzone.  "
				      "Findzone requires a query");
			result = ISC_R_FAILURE;
			goto cleanup;
		}
		break;
	case LOOKUP:
		/* this is required.  It's also a major point of DLZ! */
		if (dbi->lookup_q == NULL) {
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
				      "No query specified for lookup.  "
				      "Lookup requires a query");
			result = ISC_R_FAILURE;
			goto cleanup;
		}
		break;
	default:
		/*
		 * this should never happen.  If it does, the code is
		 * screwed up!
		 */
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "Incorrect query flag passed to "
				 "postgres_get_resultset");
		result = ISC_R_UNEXPECTED;
		goto cleanup;
	}

#if 0
	/* temporary logging message */
	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
		      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
		      "%d checked query", dlz_thread_num);
#endif

	/*
	 * was a zone string passed?  If so, make it safe for use in
	 * queries.
	 */
	if (zone != NULL) {
		dbi->zone = postgres_escape_string(zone);
		if (dbi->zone == NULL) {
			result = ISC_R_NOMEMORY;
			goto cleanup;
		}
	} else {	/* no string passed, set the string pointer to NULL */
		dbi->zone = NULL;
	}

#if 0
	/* temporary logging message */
	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
		      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
		      "%d did zone", dlz_thread_num);
#endif

	/*
	 * was a record string passed?  If so, make it safe for use in
	 * queries.
	 */
	if (record != NULL) {
		dbi->record = postgres_escape_string(record);
		if (dbi->record == NULL) {
			result = ISC_R_NOMEMORY;
			goto cleanup;
		}
	} else {	/* no string passed, set the string pointer to NULL */
		dbi->record = NULL;
	}


#if 0
	/* temporary logging message */
	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
		      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
		      "%d did record", dlz_thread_num);
#endif

	/*
	 * was a client string passed?  If so, make it safe for use in
	 * queries.
	 */
	if (client != NULL) {
		dbi->client = postgres_escape_string(client);
		if (dbi->client == NULL) {
			result = ISC_R_NOMEMORY;
			goto cleanup;
		}
	} else {	/* no string passed, set the string pointer to NULL */
		dbi->client = NULL;
	}

#if 0
	/* temporary logging message */
	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
	DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
		      "%d did client", dlz_thread_num);
#endif

	/*
	 * what type of query are we going to run?
	 * this time we build the actual query to run.
	 */
	switch(query) {
	case ALLNODES:
		querystring = build_querystring(ns_g_mctx, dbi->allnodes_q);
		break;
	case ALLOWXFR:
		querystring = build_querystring(ns_g_mctx, dbi->allowxfr_q);
		break;
	case AUTHORITY:
		querystring = build_querystring(ns_g_mctx, dbi->authority_q);
		break;
	case FINDZONE:
		querystring = build_querystring(ns_g_mctx, dbi->findzone_q);
		break;
	case LOOKUP:
		querystring = build_querystring(ns_g_mctx, dbi->lookup_q);
		break;
	default:
		/*
		 * this should never happen.  If it does, the code is
		 * screwed up!
		 */
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "Incorrect query flag passed to "
				 "postgres_get_resultset");
		result = ISC_R_UNEXPECTED;
		goto cleanup;
	}

#if 0
	/* temporary logging message */
	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
		      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
		      "%d built query", dlz_thread_num);
#endif

	/* if the querystring is null, Bummer, outta RAM.  UPGRADE TIME!!!   */
	if (querystring  == NULL) {
		result = ISC_R_NOMEMORY;
		goto cleanup;
	}

#if 0
	/* temporary logging message */
	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
		      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
		      "%d query is '%s'", dlz_thread_num, querystring);
#endif

	/*
	 * output the full query string during debug so we can see
	 * what lame error the query has.
	 */
	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
		      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1),
		      "\nQuery String: %s\n", querystring);

	/* attempt query up to 3 times. */
	for (j=0; j < 3; j++) {
#if 0
		/* temporary logging message */
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
			      "%d executing query for %d time",
			      dlz_thread_num, j);
#endif
		/* try to get result set */
		*rs = PQexec((PGconn *)dbi->dbconn, querystring );
		result = ISC_R_SUCCESS;
		/*
		 * if result set is null, reset DB connection, max 3
		 * attempts.
		 */
		for (i=0; *rs == NULL && i < 3; i++) {
#if 0
			/* temporary logging message */
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
				      "%d resetting connection",
				      dlz_thread_num);
#endif
			result = ISC_R_FAILURE;
			PQreset((PGconn *) dbi->dbconn);
			/* connection ok, break inner loop */
			if (PQstatus((PGconn *) dbi->dbconn) == CONNECTION_OK)
				break;
		}
		/* result set ok, break outter loop */
		if (PQresultStatus(*rs) == PGRES_TUPLES_OK) {
#if 0
			/* temporary logging message */
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
				      "%d rs ok", dlz_thread_num);
#endif
			break;
		} else {
			/* we got a result set object, but it's not right. */
#if 0
			/* temporary logging message */
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
				      "%d clearing rs", dlz_thread_num);
#endif
			PQclear(*rs);	/* get rid of it */
			/* in case this was the last attempt */
			result = ISC_R_FAILURE;
		}
	}

 cleanup:
	/* it's always good to cleanup after yourself */

#if 0
	/* temporary logging message */
	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
		      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
		      "%d cleaning up", dlz_thread_num);
#endif

	/* if we couldn't even allocate DBI, just return NULL */
	if (dbi == NULL)
		return ISC_R_FAILURE;

	/* free dbi->zone string */
	if (dbi->zone != NULL)
		isc_mem_free(ns_g_mctx, dbi->zone);

	/* free dbi->record string */
	if (dbi->record != NULL)
		isc_mem_free(ns_g_mctx, dbi->record);

	/* free dbi->client string */
	if (dbi->client != NULL)
		isc_mem_free(ns_g_mctx, dbi->client);

#ifdef ISC_PLATFORM_USETHREADS

#if 0
	/* temporary logging message */
	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
		      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
		      "%d unlocking mutex", dlz_thread_num);
#endif

	/* release the lock so another thread can use this dbi */
	isc_mutex_unlock(&dbi->instance_lock);

#endif /* ISC_PLATFORM_USETHREADS */

	/* release query string */
	if (querystring  != NULL)
		isc_mem_free(ns_g_mctx, querystring );

#if 0
	/* temporary logging message */
	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
		      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
		      "%d returning", dlz_thread_num);
#endif

	/* return result */
	return result;
}
コード例 #3
0
static isc_result_t
mysql_get_resultset(const char *zone, const char *record,
		    const char *client, unsigned int query,
		    void *dbdata, MYSQL_RES **rs)
{
	isc_result_t result;
	dbinstance_t *dbi = NULL;
	char *querystring = NULL;
	unsigned int i = 0;
	unsigned int j = 0;
	int qres = 0;

	if (query != COUNTZONE)
		REQUIRE(*rs == NULL);
	else
		REQUIRE(rs == NULL);

	/* get db instance / connection */
	dbi =  (dbinstance_t *) dbdata;

	/* if DBI is null, can't do anything else */
	if (dbi == NULL) {
		result = ISC_R_FAILURE;
		goto cleanup;
	}

	/* what type of query are we going to run? */
	switch(query) {
	case ALLNODES:
		/*
		 * if the query was not passed in from the config file
		 * then we can't run it.  return not_implemented, so
		 * it's like the code for that operation was never
		 * built into the driver.... AHHH flexibility!!!
		 */
		if (dbi->allnodes_q == NULL) {
			result = ISC_R_NOTIMPLEMENTED;
			goto cleanup;
		}
		break;
	case ALLOWXFR:
		/* same as comments as ALLNODES */
		if (dbi->allowxfr_q == NULL) {
			result = ISC_R_NOTIMPLEMENTED;
			goto cleanup;
		}
		break;
	case AUTHORITY:
		/* same as comments as ALLNODES */
		if (dbi->authority_q == NULL) {
			result = ISC_R_NOTIMPLEMENTED;
			goto cleanup;
		}
		break;
	case FINDZONE:
		/* this is required.  It's the whole point of DLZ! */
		if (dbi->findzone_q == NULL) {
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
				      "No query specified for findzone.  "
				      "Findzone requires a query");
			result = ISC_R_FAILURE;
			goto cleanup;
		}
		break;
	case COUNTZONE:
		/* same as comments as ALLNODES */
		if (dbi->countzone_q == NULL) {
			result = ISC_R_NOTIMPLEMENTED;
			goto cleanup;
		}
		break;
	case LOOKUP:
		/* this is required.  It's also a major point of DLZ! */
		if (dbi->lookup_q == NULL) {
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
				      "No query specified for lookup.  "
				      "Lookup requires a query");
			result = ISC_R_FAILURE;
			goto cleanup;
		}
		break;
	default:
		/*
		 * this should never happen.  If it does, the code is
		 * screwed up!
		 */
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "Incorrect query flag passed to "
				 "mysql_get_resultset");
		result = ISC_R_UNEXPECTED;
		goto cleanup;
	}


	/*
	 * was a zone string passed?  If so, make it safe for use in
	 * queries.
	 */
	if (zone != NULL) {
		dbi->zone = mysqldrv_escape_string((MYSQL *) dbi->dbconn,
						   zone);
		if (dbi->zone == NULL) {
			result = ISC_R_NOMEMORY;
			goto cleanup;
		}
	} else {	/* no string passed, set the string pointer to NULL */
		dbi->zone = NULL;
	}

	/*
	 * was a record string passed?  If so, make it safe for use in
	 * queries.
	 */
	if (record != NULL) {
		dbi->record = mysqldrv_escape_string((MYSQL *) dbi->dbconn,
						     record);
		if (dbi->record == NULL) {
			result = ISC_R_NOMEMORY;
			goto cleanup;
		}
	} else {	/* no string passed, set the string pointer to NULL */
		dbi->record = NULL;
	}

	/*
	 * was a client string passed?  If so, make it safe for use in
	 * queries.
	 */
	if (client != NULL) {
		dbi->client = mysqldrv_escape_string((MYSQL *) dbi->dbconn,
						     client);
		if (dbi->client == NULL) {
			result = ISC_R_NOMEMORY;
			goto cleanup;
		}
	} else {	/* no string passed, set the string pointer to NULL */
		dbi->client = NULL;
	}

	/*
	 * what type of query are we going to run?  this time we build
	 * the actual query to run.
	 */
	switch(query) {
	case ALLNODES:
		querystring = build_querystring(ns_g_mctx, dbi->allnodes_q);
		break;
	case ALLOWXFR:
		querystring = build_querystring(ns_g_mctx, dbi->allowxfr_q);
		break;
	case AUTHORITY:
		querystring = build_querystring(ns_g_mctx, dbi->authority_q);
		break;
	case FINDZONE:
		querystring = build_querystring(ns_g_mctx, dbi->findzone_q);
		break;
	case COUNTZONE:
		querystring = build_querystring(ns_g_mctx, dbi->countzone_q);
		break;
	case LOOKUP:
		querystring = build_querystring(ns_g_mctx, dbi->lookup_q);
		break;
	default:
		/*
		 * this should never happen.  If it does, the code is
		 * screwed up!
		 */
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "Incorrect query flag passed to "
				 "mysql_get_resultset");
		result = ISC_R_UNEXPECTED;
		goto cleanup;
	}

	/* if the querystring is null, Bummer, outta RAM.  UPGRADE TIME!!!   */
	if (querystring == NULL) {
		result = ISC_R_NOMEMORY;
		goto cleanup;
	}

	/*
	 * output the full query string during debug so we can see
	 * what lame error the query has.
	 */
	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
		      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1),
		      "\nQuery String: %s\n", querystring);

	/* attempt query up to 3 times. */
	for (i=0; i < 3; i++) {
		qres = mysql_query((MYSQL *) dbi->dbconn, querystring);
		if (qres == 0)
			break;
		for (j=0; mysql_ping((MYSQL *) dbi->dbconn) != 0 && j < 4; j++)
			;
	}

	if (qres == 0) {
		result = ISC_R_SUCCESS;
		if (query != COUNTZONE) {
			*rs = mysql_store_result((MYSQL *) dbi->dbconn);
			if (*rs == NULL)
				result = ISC_R_FAILURE;
		}
	} else {
		result = ISC_R_FAILURE;
	}


 cleanup:
	/* it's always good to cleanup after yourself */

	/* if we couldn't even get DBI, just return NULL */
	if (dbi == NULL)
		return ISC_R_FAILURE;

	/* free dbi->zone string */
	if (dbi->zone != NULL)
		isc_mem_free(ns_g_mctx, dbi->zone);

	/* free dbi->record string */
	if (dbi->record != NULL)
		isc_mem_free(ns_g_mctx, dbi->record);

	/* free dbi->client string */
	if (dbi->client != NULL)
		isc_mem_free(ns_g_mctx, dbi->client);

	/* release query string */
	if (querystring  != NULL)
		isc_mem_free(ns_g_mctx, querystring);

	/* return result */
	return result;
}
コード例 #4
0
/*%
 * This function is the real core of the module.   Zone, record
 * and client strings are passed in (or NULL is passed if the
 * string is not available).  The type of query we want to run
 * is indicated by the query flag, and the dbdata object is passed
 * passed in to.  dbdata really holds a single database instance.
 * The function will construct and run the query, hopefully getting
 * a result set.
 */
static isc_result_t
mysql_get_resultset(const char *zone, const char *record,
		    const char *client, unsigned int query,
		    void *dbdata, MYSQL_RES **rs)
{
	isc_result_t result;
	dbinstance_t *dbi = NULL;
	mysql_instance_t *db = (mysql_instance_t *)dbdata;
	char *querystring = NULL;
	unsigned int i = 0;
	unsigned int j = 0;
	int qres = 0;

#if PTHREADS
	/* find an available DBI from the list */
	dbi = mysql_find_avail_conn(db);
#else /* PTHREADS */
	/*
	 * only 1 DBI - no need to lock instance lock either
	 * only 1 thread in the whole process, no possible contention.
	 */
	dbi = (dbinstance_t *)(db->db);
#endif /* PTHREADS */

	if (dbi == NULL) {
		result = ISC_R_FAILURE;
		goto cleanup;
	}

	/* what type of query are we going to run? */
	switch(query) {
	case ALLNODES:
		if (dbi->allnodes_q == NULL) {
			result = ISC_R_NOTIMPLEMENTED;
			goto cleanup;
		}
		break;
	case ALLOWXFR:
		if (dbi->allowxfr_q == NULL) {
			result = ISC_R_NOTIMPLEMENTED;
			goto cleanup;
		}
		break;
	case AUTHORITY:
		if (dbi->authority_q == NULL) {
			result = ISC_R_NOTIMPLEMENTED;
			goto cleanup;
		}
		break;
	case FINDZONE:
		if (dbi->findzone_q == NULL) {
			db->log(ISC_LOG_DEBUG(2),
				"No query specified for findzone.  "
				"Findzone requires a query");
			result = ISC_R_FAILURE;
			goto cleanup;
		}
		break;
	case COUNTZONE:
		if (dbi->countzone_q == NULL) {
			result = ISC_R_NOTIMPLEMENTED;
			goto cleanup;
		}
		break;
	case LOOKUP:
		if (dbi->lookup_q == NULL) {
			db->log(ISC_LOG_DEBUG(2),
				"No query specified for lookup.  "
				"Lookup requires a query");
			result = ISC_R_FAILURE;
			goto cleanup;
		}
		break;
	default:
		db->log(ISC_LOG_ERROR,
			"Incorrect query flag passed to "
			"mysql_get_resultset");
		result = ISC_R_UNEXPECTED;
		goto cleanup;
	}


	if (zone != NULL) {
		if (dbi->zone != NULL)
			free(dbi->zone);

		dbi->zone = mysqldrv_escape_string((MYSQL *) dbi->dbconn,
						   zone);
		if (dbi->zone == NULL) {
			result = ISC_R_NOMEMORY;
			goto cleanup;
		}
	} else
		dbi->zone = NULL;

	if (record != NULL) {
		if (dbi->record != NULL)
			free(dbi->record);

		dbi->record = mysqldrv_escape_string((MYSQL *) dbi->dbconn,
						     record);
		if (dbi->record == NULL) {
			result = ISC_R_NOMEMORY;
			goto cleanup;
		}
	} else
		dbi->record = NULL;

	if (client != NULL) {
		if (dbi->client != NULL)
			free(dbi->client);

		dbi->client = mysqldrv_escape_string((MYSQL *) dbi->dbconn,
						     client);
		if (dbi->client == NULL) {
			result = ISC_R_NOMEMORY;
			goto cleanup;
		}
	} else
		dbi->client = NULL;

	/*
	 * what type of query are we going to run?  this time we build
	 * the actual query to run.
	 */
	switch(query) {
	case ALLNODES:
		querystring = build_querystring(dbi->allnodes_q);
		break;
	case ALLOWXFR:
		querystring = build_querystring(dbi->allowxfr_q);
		break;
	case AUTHORITY:
		querystring = build_querystring(dbi->authority_q);
		break;
	case FINDZONE:
		querystring = build_querystring(dbi->findzone_q);
		break;
	case COUNTZONE:
		querystring = build_querystring(dbi->countzone_q);
		break;
	case LOOKUP:
		querystring = build_querystring(dbi->lookup_q);
		break;
	default:
		db->log(ISC_LOG_ERROR,
			"Incorrect query flag passed to "
			"mysql_get_resultset");
		result = ISC_R_UNEXPECTED; goto cleanup;
	}

	if (querystring == NULL) {
		result = ISC_R_NOMEMORY;
		goto cleanup;
	}

	/* output the full query string when debugging */
	db->log(ISC_LOG_DEBUG(1), "\nQuery String: %s\n", querystring);

	/* attempt query up to 3 times. */
	for (i = 0; i < 3; i++) {
		qres = mysql_query((MYSQL *) dbi->dbconn, querystring);
		if (qres == 0)
			break;
		for (j = 0; j < 4; j++)
		     if (mysql_ping((MYSQL *) dbi->dbconn) == 0)
			     break;
	}

	if (qres == 0) {
		result = ISC_R_SUCCESS;
		if (query != COUNTZONE) {
			*rs = mysql_store_result((MYSQL *) dbi->dbconn);
			if (*rs == NULL)
				result = ISC_R_FAILURE;
		}
	} else
		result = ISC_R_FAILURE;

 cleanup:
	if (dbi == NULL)
		return (ISC_R_FAILURE);

	if (dbi->zone != NULL) {
		free(dbi->zone);
		dbi->zone = NULL;
	}
	if (dbi->record != NULL) {
		free(dbi->record);
		dbi->record = NULL;
	}
	if (dbi->client != NULL) {
		free(dbi->client);
		dbi->client = NULL;
	}

	/* release the lock so another thread can use this dbi */
	(void) dlz_mutex_unlock(&dbi->lock);

	if (querystring != NULL)
		free(querystring);

	return (result);
}
コード例 #5
0
static isc_result_t
odbc_get_resultset(const char *zone, const char *record,
		   const char *client, unsigned int query,
		   void *dbdata, dbinstance_t **r_dbi)
{

	isc_result_t result;
	dbinstance_t *dbi = NULL;
	char *querystring = NULL;
	unsigned int j = 0;
	SQLRETURN sqlRes;

	REQUIRE(*r_dbi == NULL);

	/* get db instance / connection */
#ifdef ISC_PLATFORM_USETHREADS

	/* find an available DBI from the list */
	dbi = odbc_find_avail_conn(((odbc_instance_t *) dbdata)->db);

#else /* ISC_PLATFORM_USETHREADS */

	/*
	 * only 1 DBI - no need to lock instance lock either
	 * only 1 thread in the whole process, no possible contention.
	 */
	dbi =  (dbinstance_t *) ((odbc_instance_t *) dbdata)->db;

#endif /* ISC_PLATFORM_USETHREADS */

	/* if DBI is null, can't do anything else */
	if (dbi == NULL) {
		result = ISC_R_FAILURE;
		goto cleanup;
	}

	/* what type of query are we going to run? */
	switch(query) {
	case ALLNODES:
		/*
		 * if the query was not passed in from the config file
		 * then we can't run it.  return not_implemented, so
		 * it's like the code for that operation was never
		 * built into the driver.... AHHH flexibility!!!
		 */
		if (dbi->allnodes_q == NULL) {
			result = ISC_R_NOTIMPLEMENTED;
			goto cleanup;
		}
		break;
	case ALLOWXFR:
		/* same as comments as ALLNODES */
		if (dbi->allowxfr_q == NULL) {
			result = ISC_R_NOTIMPLEMENTED;
			goto cleanup;
		}
		break;
	case AUTHORITY:
		/* same as comments as ALLNODES */
		if (dbi->authority_q == NULL) {
			result = ISC_R_NOTIMPLEMENTED;
			goto cleanup;
		}
		break;
	case FINDZONE:
		/* this is required.  It's the whole point of DLZ! */
		if (dbi->findzone_q == NULL) {
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
				      "No query specified for findzone.  "
				      "Findzone requires a query");
			result = ISC_R_FAILURE;
			goto cleanup;
		}
		break;
	case LOOKUP:
		/* this is required.  It's also a major point of DLZ! */
		if (dbi->lookup_q == NULL) {
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
				      "No query specified for lookup.  "
				      "Lookup requires a query");
			result = ISC_R_FAILURE;
			goto cleanup;
		}
		break;
	default:
		/*
		 * this should never happen.  If it does, the code is
		 * screwed up!
		 */
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "Incorrect query flag passed to "
				 "odbc_get_resultset");
		result = ISC_R_UNEXPECTED;
		goto cleanup;
	}


	/*
	 * was a zone string passed?  If so, make it safe for use in
	 * queries.
	 */
	if (zone != NULL) {
		dbi->zone = odbc_escape_string(zone);
		if (dbi->zone == NULL) {
			result = ISC_R_NOMEMORY;
			goto cleanup;
		}
	} else {	/* no string passed, set the string pointer to NULL */
		dbi->zone = NULL;
	}

	/*
	 * was a record string passed?  If so, make it safe for use in
	 * queries.
	 */
	if (record != NULL) {
		dbi->record = odbc_escape_string(record);
		if (dbi->record == NULL) {
			result = ISC_R_NOMEMORY;
			goto cleanup;
		}
	} else {	/* no string passed, set the string pointer to NULL */
		dbi->record = NULL;
	}

	/*
	 * was a client string passed?  If so, make it safe for use in
	 * queries.
	 */
	if (client != NULL) {
		dbi->client = odbc_escape_string(client);
		if (dbi->client == NULL) {
			result = ISC_R_NOMEMORY;
			goto cleanup;
		}
	} else {	/* no string passed, set the string pointer to NULL */
		dbi->client = NULL;
	}

	/*
	 * what type of query are we going to run?
	 * this time we build the actual query to run.
	 */
	switch(query) {
	case ALLNODES:
		querystring = build_querystring(ns_g_mctx, dbi->allnodes_q);
		break;
	case ALLOWXFR:
		querystring = build_querystring(ns_g_mctx, dbi->allowxfr_q);
		break;
	case AUTHORITY:
		querystring = build_querystring(ns_g_mctx, dbi->authority_q);
		break;
	case FINDZONE:
		querystring = build_querystring(ns_g_mctx, dbi->findzone_q);
		break;
	case LOOKUP:
		querystring = build_querystring(ns_g_mctx, dbi->lookup_q);
		break;
	default:
		/*
		 * this should never happen.  If it does, the code is
		 * screwed up!
		 */
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "Incorrect query flag passed to "
				 "odbc_get_resultset");
		result = ISC_R_UNEXPECTED;
		goto cleanup;
	}

	/* if the querystring is null, Bummer, outta RAM.  UPGRADE TIME!!!   */
	if (querystring  == NULL) {
		result = ISC_R_NOMEMORY;
		goto cleanup;
	}

	/* output the full query string during debug so we can see */
	/* what lame error the query has. */
	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
		      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1),
		      "\nQuery String: %s\n", querystring);

	/* attempt query up to 3 times. */
	for (j=0; j < 3; j++) {
		/* try to get result set */
		sqlRes = SQLExecDirect(((odbc_db_t *) dbi->dbconn)->stmnt,
				       (SQLCHAR *) querystring,
				       (SQLINTEGER) strlen(querystring));

		/* if error, reset DB connection */
		if (!sqlOK(sqlRes)) {
			/* close cursor */
			SQLCloseCursor(((odbc_db_t *) dbi->dbconn)->stmnt);
			/* attempt to reconnect */
			result = odbc_connect((odbc_instance_t *) dbdata,
					      (odbc_db_t **) &(dbi->dbconn));
			/* check if we reconnected */
			if (result != ISC_R_SUCCESS)
				break;
			/* incase this is the last time through the loop */
			result = ISC_R_FAILURE;
		} else {
			result = ISC_R_SUCCESS;
			/* return dbi */
			*r_dbi = dbi;
			/* result set ok, break loop */
			break;
		}
	}	/* end for loop */

 cleanup:	/* it's always good to cleanup after yourself */

		/* if we couldn't even allocate DBI, just return NULL */
	if (dbi == NULL)
		return ISC_R_FAILURE;

	/* free dbi->zone string */
	if (dbi->zone != NULL)
		isc_mem_free(ns_g_mctx, dbi->zone);

	/* free dbi->record string */
	if (dbi->record != NULL)
		isc_mem_free(ns_g_mctx, dbi->record);

	/* free dbi->client string */
	if (dbi->client != NULL)
		isc_mem_free(ns_g_mctx, dbi->client);

#ifdef ISC_PLATFORM_USETHREADS

	/* if we are done using this dbi, release the lock */
	if (result != ISC_R_SUCCESS)
		isc_mutex_unlock(&dbi->instance_lock);

#endif /* ISC_PLATFORM_USETHREADS */

	/* release query string */
	if (querystring  != NULL)
		isc_mem_free(ns_g_mctx, querystring );

	/* return result */
	return result;

}
コード例 #6
0
ファイル: dlz_ldap_dynamic.c プロジェクト: enukane/netbsd-src
/*%
 * This function is the real core of the driver.   Zone, record
 * and client strings are passed in (or NULL is passed if the
 * string is not available).  The type of query we want to run
 * is indicated by the query flag, and the dbdata object is passed
 * passed in to.  dbdata really holds either:
 *		1) a list of database instances (in multithreaded mode) OR
 *		2) a single database instance (in single threaded mode)
 * The function will construct the query and obtain an available
 * database instance (DBI).  It will then run the query and hopefully
 * obtain a result set.
 */
static isc_result_t
ldap_get_results(const char *zone, const char *record,
		 const char *client, unsigned int query,
		 void *dbdata, void *ptr)
{
	isc_result_t result;
	ldap_instance_t *db = (ldap_instance_t *)dbdata;
	dbinstance_t *dbi = NULL;
	char *querystring = NULL;
	LDAPURLDesc *ldap_url = NULL;
	int ldap_result = 0;
	LDAPMessage *ldap_msg = NULL;
	int i;
	int entries;

	/* get db instance / connection */
#if PTHREADS
	/* find an available DBI from the list */
	dbi = ldap_find_avail_conn(db);
#else /* PTHREADS */
	/*
	 * only 1 DBI - no need to lock instance lock either
	 * only 1 thread in the whole process, no possible contention.
	 */
	dbi = (dbinstance_t *)(db->db);
#endif /* PTHREADS */

	/* if DBI is null, can't do anything else */
	if (dbi == NULL)
		return (ISC_R_FAILURE);

	/* set fields */
	if (zone != NULL) {
		dbi->zone = strdup(zone);
		if (dbi->zone == NULL) {
			result = ISC_R_NOMEMORY;
			goto cleanup;
		}
	} else
		dbi->zone = NULL;

	if (record != NULL) {
		dbi->record = strdup(record);
		if (dbi->record == NULL) {
			result = ISC_R_NOMEMORY;
			goto cleanup;
		}
	} else
		dbi->record = NULL;

	if (client != NULL) {
		dbi->client = strdup(client);
		if (dbi->client == NULL) {
			result = ISC_R_NOMEMORY;
			goto cleanup;
		}
	} else
		dbi->client = NULL;


	/* what type of query are we going to run? */
	switch (query) {
	case ALLNODES:
		/*
		 * if the query was not passed in from the config file
		 * then we can't run it.  return not_implemented, so
		 * it's like the code for that operation was never
		 * built into the driver.... AHHH flexibility!!!
		 */
		if (dbi->allnodes_q == NULL) {
			result = ISC_R_NOTIMPLEMENTED;
			goto cleanup;
		} else
			querystring = build_querystring(dbi->allnodes_q);
		break;
	case ALLOWXFR:
		/* same as comments as ALLNODES */
		if (dbi->allowxfr_q == NULL) {
			result = ISC_R_NOTIMPLEMENTED;
			goto cleanup;
		} else
			querystring = build_querystring(dbi->allowxfr_q);
		break;
	case AUTHORITY:
		/* same as comments as ALLNODES */
		if (dbi->authority_q == NULL) {
			result = ISC_R_NOTIMPLEMENTED;
			goto cleanup;
		} else
			querystring = build_querystring(dbi->authority_q);
		break;
	case FINDZONE:
		/* this is required.  It's the whole point of DLZ! */
		if (dbi->findzone_q == NULL) {
			db->log(ISC_LOG_DEBUG(2),
				"No query specified for findzone. "
				"Findzone requires a query");
			result = ISC_R_FAILURE;
			goto cleanup;
		} else
			querystring = build_querystring(dbi->findzone_q);
		break;
	case LOOKUP:
		/* this is required.  It's also a major point of DLZ! */
		if (dbi->lookup_q == NULL) {
			db->log(ISC_LOG_DEBUG(2),
				"No query specified for lookup. "
				"Lookup requires a query");
			result = ISC_R_FAILURE;
			goto cleanup;
		} else
			querystring = build_querystring(dbi->lookup_q);
		break;
	default:
		/*
		 * this should never happen.  If it does, the code is
		 * screwed up!
		 */
		db->log(ISC_LOG_ERROR,
			"Incorrect query flag passed to ldap_get_results");
		result = ISC_R_UNEXPECTED;
		goto cleanup;
	}

	/* if the querystring is null, Bummer, outta RAM.  UPGRADE TIME!!!   */
	if (querystring  == NULL) {
		result = ISC_R_NOMEMORY;
		goto cleanup;
	}

	/*
	 * output the full query string during debug so we can see
	 * what lame error the query has.
	 */
	db->log(ISC_LOG_DEBUG(1), "Query String: %s", querystring);

	/* break URL down into it's component parts, if error cleanup */
	ldap_result = ldap_url_parse(querystring, &ldap_url);
	if (ldap_result != LDAP_SUCCESS || ldap_url == NULL) {
		result = ISC_R_FAILURE;
		goto cleanup;
	}

	for (i = 0; i < 3; i++) {
		/*
		 * dbi->dbconn may be null if trying to reconnect on a
		 * previous query failed.
		 */
		if (dbi->dbconn == NULL) {
			db->log(ISC_LOG_INFO,
				"LDAP driver attempting to re-connect");

			result = ldap_connect((ldap_instance_t *) dbdata, dbi);
			if (result != ISC_R_SUCCESS) {
				result = ISC_R_FAILURE;
				continue;
			}
		}

		/* perform ldap search syncronously */
		ldap_result = ldap_search_s((LDAP *) dbi->dbconn,
					    ldap_url->lud_dn,
					    ldap_url->lud_scope,
					    ldap_url->lud_filter,
					    ldap_url->lud_attrs, 0, &ldap_msg);

		/*
		 * check return code.  No such object is ok, just
		 * didn't find what we wanted
		 */
		switch (ldap_result) {
		case LDAP_NO_SUCH_OBJECT:
    			db->log(ISC_LOG_DEBUG(1),
				"No object found matching query requirements");
			result = ISC_R_NOTFOUND;
			goto cleanup;
			break;
		case LDAP_SUCCESS:	/* on success do nothing */
			result = ISC_R_SUCCESS;
			i = 3;
			break;
		case LDAP_SERVER_DOWN:
			db->log(ISC_LOG_INFO,
				"LDAP driver attempting to re-connect");
			result = ldap_connect((ldap_instance_t *) dbdata, dbi);
			if (result != ISC_R_SUCCESS)
				result = ISC_R_FAILURE;
			break;
		default:
			/*
			 * other errors not ok.  Log error message and
			 * get out
			 */
    			db->log(ISC_LOG_ERROR, "LDAP error: %s",
				ldap_err2string(ldap_result));
			result = ISC_R_FAILURE;
			goto cleanup;
			break;
		}
	}

	if (result != ISC_R_SUCCESS)
		goto cleanup;

	switch (query) {
	case ALLNODES:
		result = ldap_process_results(db, (LDAP *) dbi->dbconn,
					      ldap_msg, ldap_url->lud_attrs,
					      ptr, ISC_TRUE);
		break;
	case AUTHORITY:
	case LOOKUP:
		result = ldap_process_results(db, (LDAP *) dbi->dbconn,
					      ldap_msg, ldap_url->lud_attrs,
					      ptr, ISC_FALSE);
		break;
	case ALLOWXFR:
		entries = ldap_count_entries((LDAP *) dbi->dbconn, ldap_msg);
		if (entries == 0)
			result = ISC_R_NOPERM;
		else if (entries > 0)
			result = ISC_R_SUCCESS;
		else
			result = ISC_R_FAILURE;
		break;
	case FINDZONE:
		entries = ldap_count_entries((LDAP *) dbi->dbconn, ldap_msg);
		if (entries == 0)
			result = ISC_R_NOTFOUND;
		else if (entries > 0)
			result = ISC_R_SUCCESS;
		else
			result = ISC_R_FAILURE;
		break;
	default:
		/*
		 * this should never happen.  If it does, the code is
		 * screwed up!
		 */
		db->log(ISC_LOG_ERROR,
			"Incorrect query flag passed to ldap_get_results");
		result = ISC_R_UNEXPECTED;
	}

 cleanup:
	/* it's always good to cleanup after yourself */

	/* if we retrieved results, free them */
	if (ldap_msg != NULL)
		ldap_msgfree(ldap_msg);

	if (ldap_url != NULL)
		ldap_free_urldesc(ldap_url);

	/* cleanup */
	if (dbi->zone != NULL)
		free(dbi->zone);
	if (dbi->record != NULL)
		free(dbi->record);
	if (dbi->client != NULL)
		free(dbi->client);
	dbi->zone = dbi->record = dbi->client = NULL;

	/* release the lock so another thread can use this dbi */
	(void) dlz_mutex_unlock(&dbi->lock);

	/* release query string */
	if (querystring != NULL)
		free(querystring);

	/* return result */
	return (result);
}