fault/fm-common/sources/fmDb.cpp

200 lines
5.1 KiB
C++

//
// Copyright (c) 2016 Wind River Systems, Inc.
//
// SPDX-License-Identifier: Apache-2.0
//
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include "fmLog.h"
#include "fmAPI.h"
#include "fmTime.h"
#include "fmAlarmUtils.h"
#include "fmDbUtils.h"
#include "fmDb.h"
#include "fmDbConstants.h"
#include "fmThread.h"
CFmDBSession::CFmDBSession() {
m_conn.uri = NULL;
m_conn.pgconn = NULL;
m_conn.status = DB_DISCONNECTED;
}
CFmDBSession::~CFmDBSession() {
if (m_conn.pgconn != NULL){
PQfinish(m_conn.pgconn);
}
}
bool CFmDBSession::connect(const char *uri){
const char *val = NULL;
PGconn *pgconn = NULL;
size_t retries = 30, count = 0, my_sleep = 2; //2 seconds
while (count < retries){
/* Make a connection to the database */
pgconn = PQconnectdb(uri);
/* Check to see that the backend connection was successfully made */
if ((pgconn == NULL) || (PQstatus(pgconn) != CONNECTION_OK)){
FM_INFO_LOG("failed to connected to DB: (%s), retry (%d of %d) ",
uri, count+1, retries);
if (pgconn != NULL) {
FM_INFO_LOG("Postgress error message: (%s).", PQerrorMessage(pgconn));
PQfinish(pgconn);
}
sleep(my_sleep);
count++;
}else {
break;
}
}
if (count == retries) return false;
m_conn.status = DB_CONNECTED;
m_conn.pgconn = pgconn;
m_conn.uri = uri;
val = get_parameter_status("standard_conforming_strings");
//FM_INFO_LOG("connect: server standard_conforming_strings parameter: %s",
// val ? val : "unavailable");
m_conn.equote = (val && (0 == strcmp("off", val)));
//FM_INFO_LOG("connect: server requires E'' quotes: %s", m_conn.equote ? "YES" : "NO");
m_conn.server_version = PQserverVersion(m_conn.pgconn);
m_conn.protocol = PQprotocolVersion(m_conn.pgconn);
m_conn.encoding = get_parameter_status("client_encoding");
return true;
}
bool CFmDBSession::check_conn(){
if (PQstatus(m_conn.pgconn) != CONNECTION_OK) {
FM_ERROR_LOG("DB connection NOT OK\n");
disconnect();
return connect(m_conn.uri);
}
return true;
}
void CFmDBSession::disconnect(){
if (m_conn.pgconn != NULL){
PQfinish(m_conn.pgconn);
}
if (m_conn.status == DB_CONNECTED){
m_conn.status = DB_DISCONNECTED;
}
}
const char * CFmDBSession::get_parameter_status(const char *param){
return PQparameterStatus(m_conn.pgconn, param);
}
bool CFmDBSession::query(const char *db_cmd,fm_db_result_t & result) {
PGresult *res;
int nfields, ntuples, i, j;
if (check_conn() == false){
FM_ERROR_LOG("Failed to reconnect: %s", PQerrorMessage(m_conn.pgconn));
return false;
}
res = PQexec(m_conn.pgconn, db_cmd);
if (PQresultStatus(res) != PGRES_TUPLES_OK){
FM_ERROR_LOG("Status:(%s)\n", PQresStatus(PQresultStatus(res)));
FM_ERROR_LOG("Failed to execute (%s) (%s)", db_cmd, PQresultErrorMessage(res));
PQclear(res);
return false;
}
nfields = PQnfields(res);
ntuples = PQntuples(res);
FM_DEBUG_LOG("Execute cmd:(%s) OK, entries found: (%u)\n", db_cmd, ntuples);
for (i = 0; i < ntuples; ++i){
fm_db_single_result_t single_result;
for (j =0; j < nfields; ++j){
char * key = PQfname(res, j);
char * value = PQgetvalue(res, i, j);
single_result[key] = value;
}
result.push_back(single_result);
}
PQclear(res);
return true;
}
bool CFmDBSession::cmd(const char *db_cmd){
PGresult *res;
bool rc = true;
if (check_conn() == false){
FM_ERROR_LOG("Failed to reconnect: %s", PQerrorMessage(m_conn.pgconn));
return false;
}
res = PQexec(m_conn.pgconn, db_cmd);
if (PQresultStatus(res) != PGRES_COMMAND_OK) {
FM_ERROR_LOG("Status:(%s)\n", PQresStatus(PQresultStatus(res)));
FM_ERROR_LOG("Failed to execute (%s) (%s)", db_cmd, PQresultErrorMessage(res));
rc = false;
}
if (rc){
int row = atoi(PQcmdTuples(res));
FM_DEBUG_LOG("SQL command returned successful: %d rows affected.\n", row);
if (row < 1) rc = false;
}
PQclear(res);
return rc;
}
bool CFmDBSession::params_cmd(fm_db_util_sql_params & sql_params){
PGresult *res, *last_res;
bool rc = true;
if (check_conn() == false){
FM_ERROR_LOG("Failed to reconnect: %s", PQerrorMessage(m_conn.pgconn));
return false;
}
res = PQexecParams(m_conn.pgconn, sql_params.db_cmd.c_str(), sql_params.n_params,
NULL,(const char* const*)&(sql_params.param_values[0]),
(const int*)&(sql_params.param_lengths[0]), (const int*)&(sql_params.param_format[0]), 1);
if (PQresultStatus(res) != PGRES_COMMAND_OK) {
FM_ERROR_LOG("Status:(%s)\n", PQresStatus(PQresultStatus(res)));
FM_ERROR_LOG("Failed to execute (%s) (%s)", sql_params.db_cmd.c_str(),
PQresultErrorMessage(res));
rc = false;
}
if (rc){
while ((last_res=PQgetResult(m_conn.pgconn)) != NULL){
if (PQstatus(m_conn.pgconn) == CONNECTION_BAD){
FM_INFO_LOG("POSTGRES DB connection is bad.");
PQclear(last_res);
break;
}
FM_INFO_LOG("Waiting for POSTGRES command to finish: (%d)", PQresultStatus(last_res));
PQclear(last_res);
fmThreadSleep(10);
}
int row = atoi(PQcmdTuples(res));
FM_DEBUG_LOG("SQL command returned successful: %d rows affected.", row);
if (row < 1) {
rc = false;
FM_ERROR_LOG("SQL command returned successful, but no row affected.");
}
}
PQclear(res);
return rc;
}