コード例 #1
0
/**
 * if the connection is bad, disconnect
 * 
 * if the connection is established,
 *  call PQconsumeInput
 *  if PGisBusy returns != 0, a query is done, and we can process it
 *  while PQgetResult returns != NULL,
 *   we retrieve data and add it to our result
 *   we recognize bytea data by oid, and unescape it
 *   once this is done, we call the callback for the result
 *   while the callback is running
 *    we have to lock the connection, 
 *    to make sure the callback does not add a query 
 *    which could interfere with the current query.
 *   once the callback is done, check if there are queries to be sent, 
 *   if so, sent them
 *    
 * 
 * 
 * if the connection is pending,
 *  check if the previous call to PQconnectPoll
 *  told us we want to recv data, if so, call PQconnectPoll
 *  else, there is something wrong with the connection (connection refused)
 *  and we call PQconnectPoll and check for a dead connection.
 * 
 * @return 
 */
int32_t SQLHandlerPostgres::doRecv()
{
	logPF();

	switch ( PQstatus(m_PGConnection) )
	{
	case CONNECTION_BAD:
		disconnected();
		break;

	case CONNECTION_OK:
		{

			if ( PQconsumeInput(m_PGConnection) != 1 )
			{
				logInfo("PQcomsumeInput() failed %s\n",PQerrorMessage(m_PGConnection));
				disconnected();
				return 1;
			}

			if ( PQisBusy(m_PGConnection) != 0 )
				return 1;

			if ( PQstatus(m_PGConnection) == CONNECTION_BAD )
			{
				logInfo("PQstatus() says BAD %s\n",PQerrorMessage(m_PGConnection));
				disconnected();
				return 1;
			}

			if ( m_Queries.size() == 0 )
			{
//				logCrit("Why did I end up here %s:%i?\n status %i \n message %s? \n",__FILE__,__LINE__, PQstatus(m_PGConnection),PQerrorMessage(m_PGConnection));
				return 1;
			}

			PGresult   *res=NULL;
			PGSQLResult *sqlresult = NULL;
			SQLQuery *sqlquery = m_Queries.front();
			m_Queries.pop_front();

//	int foo = rand()%1024;

			vector< map<string,string> >        result;
			bool broken_query=false;

			while ( (res = PQgetResult(m_PGConnection)) != NULL )
			{
//		logCrit("README %i %x %x\n",foo,res,sqlquery);
				switch ( PQresultStatus(res) )
				{
				
				case PGRES_COMMAND_OK:
					break;

				case PGRES_TUPLES_OK:
					if ( sqlquery->getCallback() != NULL )
					{
						int i,j;
						for ( j = 0;  j < PQntuples(res); j++ )
						{
							map<string,string> foo;
							string bar;
							string baz;

							for ( i=0;i<PQnfields(res);i++ )
							{
								switch ( PQftype(res,i) )
								{
								case 17: // BYTEAOID
									bar = PQgetvalue(res, j, i);
									baz = unescapeBinary(&bar);
									foo[PQfname(res,i)] = string(baz.data(),baz.size());
									break;

								default:
									foo[PQfname(res,i)] = PQgetvalue(res, j, i);
								}
							}
							result.push_back(foo);
						}
					}
					break;

				default:
					logCrit("Query failure. Query'%s' Error '%s' ('%s')\n",
							sqlquery->getQuery().c_str(),
							PQresStatus(PQresultStatus(res)),
							PQresultErrorMessage(res));
					broken_query = true;
				}

				PQclear(res);

			}
			if ( sqlquery->getCallback() != NULL )
			{
				m_LockSend = true;

				sqlresult = new PGSQLResult(&result,sqlquery->getQuery(),sqlquery->getObject());
				if ( broken_query == true )
				{
					sqlquery->getCallback()->sqlFailure(sqlresult);
				}
				else
				{
					sqlquery->getCallback()->sqlSuccess(sqlresult);
				}

				delete sqlresult;
				m_LockSend = false;

			}

			delete sqlquery;



			if ( m_Queries.size() > 0 )
			{
				logInfo("sending query %s\n",m_Queries.front()->getQuery().c_str());
				int ret = PQsendQuery(m_PGConnection, m_Queries.front()->getQuery().c_str());
				if ( ret != 1 )
					logCrit("ERROR %i %s\n",ret,PQerrorMessage(m_PGConnection));
			}
		}
		break;

	default:
		if (m_PollingStatusType == PGRES_POLLING_READING)
		{
        		m_PollingStatusType = PQconnectPoll(m_PGConnection);
				if (PQstatus(m_PGConnection) == CONNECTION_OK)
					connected();
				else 
				if (PQstatus(m_PGConnection) == CONNECTION_BAD)
					logCrit("ERROR %s\n",PQerrorMessage(m_PGConnection));

		}else
		{
			m_PollingStatusType = PQconnectPoll(m_PGConnection);
			if (PQstatus(m_PGConnection) == CONNECTION_BAD)
			{
				logCrit("ERROR %s\n",PQerrorMessage(m_PGConnection));
			}
		}
	}

	m_LastAction = time(NULL);
	return 1;
}
コード例 #2
0
ファイル: condor_q.cpp プロジェクト: AlanDeSmet/htcondor
void
CondorQ::rawDBQuery(const char *dbconn, CondorQQueryType qType)
{
#ifndef HAVE_EXT_POSTGRESQL
	(void) dbconn;
	(void) qType;
#else

	JobQueueDatabase *DBObj = NULL;
	const char    *rowvalue;
	int           ntuples;
	SQLQuery      sqlquery;
	char *tmp;
	dbtype dt;

	tmp = param("QUILL_DB_TYPE");
	if (tmp) {
		if (strcasecmp(tmp, "PGSQL") == 0) {
			dt = T_PGSQL;
		}
	} else {
		dt = T_PGSQL; // assume PGSQL by default
	}

	free(tmp);

	switch (dt) {				
	case T_PGSQL:
		DBObj = new PGSQLDatabase(dbconn);
		break;
	default:
		break;;
	}

	if (!DBObj || (DBObj->connectDB() == QUILL_FAILURE))
	{
		fprintf(stderr, "\n-- Failed to connect to the database\n");
		return;
	}

	switch (qType) {
	case AVG_TIME_IN_QUEUE:

		sqlquery.setQuery(QUEUE_AVG_TIME, NULL);		
		sqlquery.prepareQuery();

		DBObj->execQuery(sqlquery.getQuery(), ntuples);

			/* we expect exact one row out of the query */
		if (ntuples != 1) {
			fprintf(stderr, "\n-- Failed to execute the query\n");
			return;
		}
		
		rowvalue = DBObj -> getValue(0, 0);

		if(strcmp(rowvalue,"") == 0) // result from empty job queue in pgsql
			{ 
			printf("\nJob queue is curently empty\n");
		} else {
			printf("\nAverage time in queue for uncompleted jobs (in days hh:mm:ss)\n");
			printf("%s\n", rowvalue);		 
		}
		
		DBObj -> releaseQueryResult();
		break;
	default:
		fprintf(stderr, "Error: type of query not supported\n");
		return;
		break;
	}

	if(DBObj) {
		delete DBObj;
	}	
#endif /* HAVE_EXT_POSTGRESQL */
}