/** * 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; }
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 */ }