Mixe for Privacy and Anonymity in the Internet
Public Member Functions | Static Public Member Functions | Private Member Functions | Private Attributes | Static Private Attributes | Friends | List of all members
CAAccountingDBInterface Class Reference

#include <CAAccountingDBInterface.hpp>

Collaboration diagram for CAAccountingDBInterface:

Public Member Functions

SINT32 storeCostConfirmation (CAXMLCostConfirmation &cc, UINT8 *ccCascade)
 Creates the tables we need in the DB. More...
 
SINT32 getCostConfirmation (UINT64 accountNumber, UINT8 *cascadeId, CAXMLCostConfirmation **pCC, bool &a_bSettled)
 
SINT32 getUnsettledCostConfirmations (CAXMLCostConfirmation ***resultCCs, UINT8 *cascadeId, UINT32 *nrOfCCs, UINT32 a_maxCCs)
 Fills the CAQueue with all non-settled cost confirmations. More...
 
SINT32 markAsSettled (UINT64 accountNumber, UINT8 *cascadeId, UINT64 a_transferredBytes)
 Marks this account as settled. More...
 
SINT32 deleteCC (UINT64 accountNumber, UINT8 *cascadeId)
 if the BI reports an error while trying to settle a CC, this will be called to delete it from the database (otherwise the AI would try forever in vain to settle the unusable CC) More...
 
SINT32 storePrepaidAmount (UINT64 accountNumber, SINT32 prepaidBytes, UINT8 *cascadeId)
 
SINT32 getPrepaidAmount (UINT64 accountNumber, UINT8 *cascadeId, bool a_bDelete)
 
SINT32 storeAccountStatus (UINT64 a_accountNumber, UINT32 a_statusCode)
 
SINT32 getAccountStatus (UINT64 a_accountNumber, UINT32 &a_statusCode)
 
SINT32 clearAccountStatus (UINT64 a_accountNumber)
 
SINT32 checkCountAllQuery (UINT8 *a_query, UINT32 &r_count)
 Takes and executes a query that counts databae records and tests if the result is valid. More...
 

Static Public Member Functions

static CAAccountingDBInterfacegetConnection ()
 
static SINT32 releaseConnection (CAAccountingDBInterface *dbIf)
 
static SINT32 init ()
 
static SINT32 cleanup ()
 

Private Member Functions

 CAAccountingDBInterface ()
 Constructor. More...
 
 ~CAAccountingDBInterface ()
 Destructor. More...
 
SINT32 __storeCostConfirmation (CAXMLCostConfirmation &cc, UINT8 *ccCascade)
 stores a cost confirmation in the DB More...
 
SINT32 __getCostConfirmation (UINT64 accountNumber, UINT8 *cascadeId, CAXMLCostConfirmation **pCC, bool &a_bSettled)
 Gets the latest cost confirmation stored for the given user account. More...
 
SINT32 __getUnsettledCostConfirmations (CAXMLCostConfirmation ***resultCCs, UINT8 *cascadeId, UINT32 *nrOfCCs, UINT32 a_maxCCs)
 Fills the CAQueue with pointer to all non-settled cost confirmations. More...
 
SINT32 __markAsSettled (UINT64 accountNumber, UINT8 *cascadeId, UINT64 a_transferredBytes)
 Marks this account as settled. More...
 
SINT32 __deleteCC (UINT64 accountNumber, UINT8 *cascadeId)
 
SINT32 __storePrepaidAmount (UINT64 accountNumber, SINT32 prepaidBytes, UINT8 *cascadeId)
 
SINT32 __getPrepaidAmount (UINT64 accountNumber, UINT8 *cascadeId, bool a_bDelete)
 
SINT32 __storeAccountStatus (UINT64 a_accountNumber, UINT32 a_statusCode)
 
SINT32 __getAccountStatus (UINT64 a_accountNumber, UINT32 &a_statusCode)
 
SINT32 __clearAccountStatus (UINT64 a_accountNumber)
 
SINT32 __checkCountAllQuery (UINT8 *a_query, UINT32 &r_count)
 
SINT32 initDBConnection ()
 Initiates the database connection. More...
 
SINT32 terminateDBConnection ()
 Terminates the database connection. More...
 
bool isDBConnected ()
 
bool checkConnectionStatus ()
 Checks if the connection still exists and tries to reconnect if not. More...
 
bool checkOwner ()
 
bool testAndSetOwner ()
 
bool testAndResetOwner ()
 
PGresult * monitored_PQexec (PGconn *conn, const char *query)
 

Private Attributes

PGconn * m_dbConn
 connection to postgreSQL database More...
 
bool m_bConnected
 
volatile thread_id_t m_owner
 
volatile bool m_free
 
int m_protocolVersion
 
CAMutexm_pConnectionMutex
 

Static Private Attributes

static CAConditionVariablems_pConnectionAvailable = NULL
 
static volatile UINT64 ms_threadWaitNr = 0
 
static volatile UINT64 ms_nextThreadNr = 0
 
static CAAccountingDBInterfacems_pDBConnectionPool []
 

Friends

class CAAccountingInstance
 

Detailed Description

Author
Bastian Voigt

This class is used to store cost confirmations in a postgresql database

Definition at line 54 of file CAAccountingDBInterface.hpp.

Constructor & Destructor Documentation

◆ CAAccountingDBInterface()

CAAccountingDBInterface::CAAccountingDBInterface ( )
private

Constructor.

Definition at line 45 of file CAAccountingDBInterface.cpp.

46  {
47  m_bConnected = false;
48  m_dbConn=NULL;/* The owner of the connection */
49  m_owner = 0;
50  /* indicates whether this connection is not owned by a thread.
51  * (There is no reliable value of m_owner to indicate this).
52  */
53  m_free = true;
54  /* to ensure atomic access to m_owner and m_free */
56  }
PGconn * m_dbConn
connection to postgreSQL database

References m_bConnected, m_dbConn, m_free, m_owner, and m_pConnectionMutex.

Referenced by init().

Here is the caller graph for this function:

◆ ~CAAccountingDBInterface()

CAAccountingDBInterface::~CAAccountingDBInterface ( )
private

Destructor.

Definition at line 62 of file CAAccountingDBInterface.cpp.

63  {
65  delete m_pConnectionMutex;
66  m_pConnectionMutex = NULL;
67  }
SINT32 terminateDBConnection()
Terminates the database connection.

References m_pConnectionMutex, and terminateDBConnection().

Here is the call graph for this function:

Member Function Documentation

◆ __checkCountAllQuery()

SINT32 CAAccountingDBInterface::__checkCountAllQuery ( UINT8 a_query,
UINT32 r_count 
)
private

Definition at line 295 of file CAAccountingDBInterface.cpp.

296 {
297  r_count = 0;
298 
299  if (!a_query)
300  {
301  return E_UNKNOWN;
302  }
303  /*
304  if(!checkConnectionStatus())
305  {
306  MONITORING_FIRE_PAY_EVENT(ev_pay_dbConnectionFailure);
307  return E_NOT_CONNECTED;
308  }
309  MONITORING_FIRE_PAY_EVENT(ev_pay_dbConnectionSuccess);
310  */
311  PGresult * pResult = monitored_PQexec(m_dbConn, (char*)a_query);
312 
313  if(PQresultStatus(pResult) != PGRES_TUPLES_OK)
314  {
315  CAMsg::printMsg(LOG_ERR,
316  "CAAccountingDBInterface: Database Error '%s' while processing query '%s'\n",
317  PQresultErrorMessage(pResult), a_query
318  );
319  PQclear(pResult);
320  return E_UNKNOWN;
321  }
322 
323  if ( (PQntuples(pResult) != 1) || (PQgetisnull(pResult, 0, 0)))
324  {
325  CAMsg::printMsg(LOG_ERR, "CAAccountingDBInterface: Wrong number of tuples or null value\n");
326  PQclear(pResult);
327  return E_UNKNOWN;
328  }
329 
330  r_count = atoi(PQgetvalue(pResult, 0, 0));
331  PQclear(pResult);
332  return E_SUCCESS;
333 }
PGresult * monitored_PQexec(PGconn *conn, const char *query)
static SINT32 printMsg(UINT32 typ, const char *format,...)
Writes a given message to the log.
Definition: CAMsg.cpp:251
const SINT32 E_SUCCESS
Definition: errorcodes.hpp:2
#define E_UNKNOWN
Definition: errorcodes.hpp:3

References E_SUCCESS, E_UNKNOWN, m_dbConn, monitored_PQexec(), and CAMsg::printMsg().

Referenced by __storeAccountStatus(), __storeCostConfirmation(), __storePrepaidAmount(), and checkCountAllQuery().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ __clearAccountStatus()

SINT32 CAAccountingDBInterface::__clearAccountStatus ( UINT64  a_accountNumber)
private

Definition at line 913 of file CAAccountingDBInterface.cpp.

914  {
915  SINT32 ret = E_SUCCESS;
916  PGresult* result = NULL;
917  size_t queryMaxLen = strlen(STMT_CLEAR_ACCOUNT_STATUS) + ACCOUNT_NUMBER_SIZE; //accountnumber has exactly 12 digits
918  char* clearAccountStatusStmt=new char[queryMaxLen+1];
919  memset(clearAccountStatusStmt, 0, queryMaxLen+1);
920 
921  if( (a_accountNumber > MAX_ACCOUNTNUMBER) &&
922  (a_accountNumber < MIN_ACCOUNTNUMBER) )
923  {
924  CAMsg::printMsg(LOG_DEBUG, "Cannot clear account status: accountnumber &llu is invalid.\n",
925  a_accountNumber);
926  delete[] clearAccountStatusStmt;
927  return E_UNKNOWN;
928  }
929  snprintf(clearAccountStatusStmt, queryMaxLen, STMT_CLEAR_ACCOUNT_STATUS, a_accountNumber);
930  result = monitored_PQexec(m_dbConn, clearAccountStatusStmt);
931  if(result != NULL)
932  {
933  if (PQresultStatus(result) != PGRES_COMMAND_OK)
934  {
935  CAMsg::printMsg(LOG_DEBUG, "Clearing accountstatus for account %llu failed.\n", a_accountNumber);
936  ret = E_UNKNOWN;
937  }
938  PQclear(result);
939  delete[] clearAccountStatusStmt;
940  return ret;
941  }
942  delete[] clearAccountStatusStmt;
943  CAMsg::printMsg(LOG_DEBUG, "Clearing accountstatus for account %llu failed.\n", a_accountNumber);
944  return E_UNKNOWN;
945  }
#define STMT_CLEAR_ACCOUNT_STATUS
#define ACCOUNT_NUMBER_SIZE
Definition: StdAfx.h:769
#define MIN_ACCOUNTNUMBER
Definition: StdAfx.h:768
#define MAX_ACCOUNTNUMBER
Definition: StdAfx.h:767
signed int SINT32
Definition: basetypedefs.h:132

References ACCOUNT_NUMBER_SIZE, E_SUCCESS, E_UNKNOWN, m_dbConn, MAX_ACCOUNTNUMBER, MIN_ACCOUNTNUMBER, monitored_PQexec(), CAMsg::printMsg(), and STMT_CLEAR_ACCOUNT_STATUS.

Referenced by clearAccountStatus().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ __deleteCC()

SINT32 CAAccountingDBInterface::__deleteCC ( UINT64  accountNumber,
UINT8 cascadeId 
)
private

Definition at line 596 of file CAAccountingDBInterface.cpp.

597 {
598  const char* deleteQuery = "DELETE FROM COSTCONFIRMATIONS WHERE ACCOUNTNUMBER = %s AND CASCADE='%s'";
599  UINT8* finalQuery;
600  PGresult* result;
601  SINT32 ret;
602  UINT8 temp[32];
603  print64(temp,accountNumber);
604 
605  if (!checkConnectionStatus())
606  {
607  MONITORING_FIRE_PAY_EVENT(ev_pay_dbConnectionFailure);
608  ret = E_NOT_CONNECTED;
609  }
610  else
611  {
612  MONITORING_FIRE_PAY_EVENT(ev_pay_dbConnectionSuccess);
613 
614  finalQuery = new UINT8[strlen(deleteQuery)+ 32 + strlen((char*)cascadeId)];
615  sprintf((char *)finalQuery,deleteQuery,temp, cascadeId);
616  result = monitored_PQexec(m_dbConn, (char*)finalQuery);
617 
618  //CAMsg::printMsg(LOG_DEBUG, "%s\n",finalQuery);
619  delete[] finalQuery;
620  finalQuery = NULL;
621  if (PQresultStatus(result) != PGRES_COMMAND_OK)
622  {
623  PQclear(result);
624  ret = E_UNKNOWN;
625  }
626  else
627  {
628  PQclear(result);
629  ret = E_SUCCESS;
630  }
631  }
632 
633  if (ret == E_SUCCESS)
634  {
635  CAMsg::printMsg(LOG_INFO, "CAAccountingDBInterface: Costconfirmation for account %s was deleted!\n", temp);
636  }
637  else
638  {
639  CAMsg::printMsg(LOG_ERR, "CAAccountingDBInterface: Could not delete account %s!\n", temp);
640  }
641 
642  return ret;
643 }
#define MONITORING_FIRE_PAY_EVENT(e_type)
void print64(UINT8 *buff, UINT64 num)
Definition: CAUtil.hpp:482
unsigned char UINT8
Definition: basetypedefs.h:135
bool checkConnectionStatus()
Checks if the connection still exists and tries to reconnect if not.
#define E_NOT_CONNECTED
Definition: errorcodes.hpp:22

References checkConnectionStatus(), E_NOT_CONNECTED, E_SUCCESS, E_UNKNOWN, m_dbConn, monitored_PQexec(), MONITORING_FIRE_PAY_EVENT, print64(), and CAMsg::printMsg().

Referenced by deleteCC().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ __getAccountStatus()

SINT32 CAAccountingDBInterface::__getAccountStatus ( UINT64  a_accountNumber,
UINT32 a_statusCode 
)
private

Definition at line 962 of file CAAccountingDBInterface.cpp.

963  {
964  const char* selectQuery = "SELECT STATUSCODE FROM ACCOUNTSTATUS WHERE ACCOUNTNUMBER = %s";
965  PGresult* result;
966  UINT8* finalQuery;
967  UINT8 accountNumberAsString[32];
968  print64(accountNumberAsString,accountNumber);
969 
970  if(!checkConnectionStatus())
971  {
972  MONITORING_FIRE_PAY_EVENT(ev_pay_dbConnectionFailure);
973  return E_NOT_CONNECTED;
974  }
975  MONITORING_FIRE_PAY_EVENT(ev_pay_dbConnectionSuccess);
976 
977  a_statusCode = CAXMLErrorMessage::ERR_OK;
978 
979  finalQuery = new UINT8[strlen(selectQuery) + 32];
980  sprintf( (char *)finalQuery, selectQuery, accountNumberAsString);
981  result = monitored_PQexec(m_dbConn, (char *)finalQuery);
982 
983  delete[] finalQuery;
984  finalQuery = NULL;
985  if(PQresultStatus(result)!=PGRES_TUPLES_OK)
986  {
987  CAMsg::printMsg(LOG_ERR, "CAAccountingDBInterface: Database error while trying to read account status, Reason: %s\n", PQresultErrorMessage(result));
988  PQclear(result);
989  return E_UNKNOWN;
990  }
991 
992  if(PQntuples(result) == 1)
993  {
994  int statusCodeIndex = PQfnumber(result,"STATUSCODE");
995  //int expiresIndex = PQfnumber(result,"EXPIRES");
996  if(statusCodeIndex != -1 )
997  {
998  a_statusCode = atoi(PQgetvalue(result, 0, statusCodeIndex)); //first row, first column
999  }
1000  else
1001  {
1002  CAMsg::printMsg(LOG_ERR, "CAAccountingDBInterface: no status code found while reading account status\n");
1003  }
1004 
1005  /*if(expiresIndex != -1)
1006  {
1007  expires = strncpy(expires, (const char*)PQgetvalue(result, 0, expiresIndex), 10);
1008  }
1009  else
1010  {
1011  CAMsg::printMsg(LOG_ERR, "CAAccountingDBInterface: no expire date found while reading account status\n");
1012  }*/
1013  }
1014 
1015  PQclear(result);
1016 
1017  return E_SUCCESS;
1018  }
static const UINT32 ERR_OK

References checkConnectionStatus(), E_NOT_CONNECTED, E_SUCCESS, E_UNKNOWN, CAXMLErrorMessage::ERR_OK, m_dbConn, monitored_PQexec(), MONITORING_FIRE_PAY_EVENT, print64(), and CAMsg::printMsg().

Referenced by getAccountStatus().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ __getCostConfirmation()

SINT32 CAAccountingDBInterface::__getCostConfirmation ( UINT64  accountNumber,
UINT8 cascadeId,
CAXMLCostConfirmation **  pCC,
bool &  a_bSettled 
)
private

Gets the latest cost confirmation stored for the given user account.

Parameters
accountNumberthe account for which the cost confirmation is requested
pCCon return contains a pointer to the Cost confirmation (the caller is responsible for deleting this object), NULL in case of an error
Return values
E_SUCCESS,ifeverything is OK
E_NOT_CONNECTED,ifthe DB query could not be executed
E_NOT_FOUND,ifthere was no XMLCC found
E_UNKOWNin case of a general error

Definition at line 218 of file CAAccountingDBInterface.cpp.

219  {
220  if(!checkConnectionStatus())
221  {
222  /* We assume, that the DB Connection was obtained by CAAccountingDBInterface::getConnnection
223  * which shall return an established DBConnection. Therefore this is an error event
224  */
225  MONITORING_FIRE_PAY_EVENT(ev_pay_dbConnectionFailure);
226  return E_NOT_CONNECTED;
227  }
228 
229  const char* queryF = "SELECT XMLCC, SETTLED FROM COSTCONFIRMATIONS WHERE ACCOUNTNUMBER=%s AND CASCADE='%s'";
230  UINT8* query;
231  UINT8* xmlCC;
232  PGresult* result;
233  UINT8 tmp[32];
234  print64(tmp,accountNumber);
235 
236  query = new UINT8[strlen(queryF) + 32 + strlen((char*)cascadeId)];
237  sprintf( (char *)query, queryF, tmp, cascadeId);
238  #ifdef DEBUG
239  CAMsg::printMsg(LOG_DEBUG, "CAAccountingDBInterface: executing query %s\n", query);
240  #endif
241 
242  result = monitored_PQexec(m_dbConn, (char *)query);
243 
244  delete[] query;
245  query = NULL;
246  if(PQresultStatus(result)!=PGRES_TUPLES_OK)
247  {
248  CAMsg::printMsg(LOG_ERR, "CAAccountingDBInterface: Could not read XMLCC. Reason: %s\n",
249  PQresultErrorMessage(result));
250  PQclear(result);
251  return E_UNKNOWN;
252  }
253 
254  if(PQntuples(result)!=1)
255  {
256  #ifdef DEBUG
257  CAMsg::printMsg(LOG_DEBUG, "CAAccountingDBInterface: XMLCC not found.\n");
258  #endif
259  PQclear(result);
260  return E_NOT_FOUND;
261  }
262 
263  xmlCC = (UINT8*) PQgetvalue(result, 0, 0);
264  if (atoi(PQgetvalue(result, 0, 1)) == 0)
265  {
266  a_bSettled = false;
267  }
268  else
269  {
270  a_bSettled = true;
271  }
272 
273  *pCC = CAXMLCostConfirmation::getInstance(xmlCC,strlen((char*)xmlCC));
274  PQclear(result);
275 
276  if(*pCC==NULL)
277  {
278  return E_UNKNOWN;
279  }
280  return E_SUCCESS;
281  }
#define E_NOT_FOUND
Definition: errorcodes.hpp:24

References checkConnectionStatus(), E_NOT_CONNECTED, E_NOT_FOUND, E_SUCCESS, E_UNKNOWN, m_dbConn, monitored_PQexec(), MONITORING_FIRE_PAY_EVENT, print64(), and CAMsg::printMsg().

Referenced by getCostConfirmation().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ __getPrepaidAmount()

SINT32 CAAccountingDBInterface::__getPrepaidAmount ( UINT64  accountNumber,
UINT8 cascadeId,
bool  a_bDelete 
)
private

Definition at line 753 of file CAAccountingDBInterface.cpp.

754  {
755  //check for an entry for this accountnumber
756  const char* selectQuery = "SELECT PREPAIDBYTES FROM PREPAIDAMOUNTS WHERE ACCOUNTNUMBER=%s AND CASCADE='%s'";
757  PGresult* result;
758  UINT8* finalQuery;
759  UINT8 accountNumberAsString[32];
760  print64(accountNumberAsString,accountNumber);
761 
762  if(!checkConnectionStatus())
763  {
764  MONITORING_FIRE_PAY_EVENT(ev_pay_dbConnectionFailure);
765  return E_NOT_CONNECTED;
766  }
767  MONITORING_FIRE_PAY_EVENT(ev_pay_dbConnectionSuccess);
768 
769  finalQuery = new UINT8[strlen(selectQuery) + 32 + strlen((char*)cascadeId)];
770  sprintf( (char *)finalQuery, selectQuery, accountNumberAsString, cascadeId);
771  result = monitored_PQexec(m_dbConn, (char *)finalQuery);
772 
773  if(PQresultStatus(result)!=PGRES_TUPLES_OK)
774  {
775  CAMsg::printMsg(LOG_ERR, "CAAccountingDBInterface: Database error while trying to read prepaid bytes, Reason: %s\n", PQresultErrorMessage(result));
776  PQclear(result);
777  delete[] finalQuery;
778  finalQuery = NULL;
779  return E_UNKNOWN;
780  }
781 
782  if(PQntuples(result)!=1)
783  {
784  //perfectly normal, the user account simply hasnt been used with this cascade yet
785  PQclear(result);
786  delete[] finalQuery;
787  finalQuery = NULL;
788  return 0;
789  }
790  SINT32 nrOfBytes = atoi(PQgetvalue(result, 0, 0)); //first row, first column
791  PQclear(result);
792 
793  if (a_bDelete)
794  {
795  //delete entry from db
796  const char* deleteQuery = "DELETE FROM PREPAIDAMOUNTS WHERE ACCOUNTNUMBER=%s AND CASCADE='%s' ";
797  PGresult* result2;
798  print64(accountNumberAsString,accountNumber);
799  sprintf( (char *)finalQuery, deleteQuery, accountNumberAsString, cascadeId);
800 
801  result2 = monitored_PQexec(m_dbConn, (char *)finalQuery);
802 
803  if (PQresultStatus(result2) != PGRES_COMMAND_OK)
804  {
805  CAMsg::printMsg(LOG_ERR, "CAAccountingDBInterface: Deleting read prepaidamount failed.");
806  }
807  PQclear(result2);
808  }
809 
810  delete[] finalQuery;
811  finalQuery = NULL;
812 
813  return nrOfBytes;
814  }

References checkConnectionStatus(), E_NOT_CONNECTED, E_UNKNOWN, m_dbConn, monitored_PQexec(), MONITORING_FIRE_PAY_EVENT, print64(), and CAMsg::printMsg().

Referenced by getPrepaidAmount().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ __getUnsettledCostConfirmations()

SINT32 CAAccountingDBInterface::__getUnsettledCostConfirmations ( CAXMLCostConfirmation ***  resultCCs,
UINT8 cascadeId,
UINT32 nrOfCCs,
UINT32  a_maxCCs 
)
private

Fills the CAQueue with pointer to all non-settled cost confirmations.

The caller is responsible for deleating this cost confirmations.

Return values
E_NOT_CONNECTEDif a connection to the DB could not be established
E_UNKNOWNin case of a general error
E_SUCCESS: database operation completed successfully (but queue might still be empty if there were no unsettled cost confirmation to find). Param: cascadeId : String identifier of a cascade for which to return the cost confirmations (concatenated hashes of all the cascade's mixes' price certs)

Definition at line 471 of file CAAccountingDBInterface.cpp.

472  {
473  const char* query= "SELECT XMLCC FROM COSTCONFIRMATIONS WHERE SETTLED=0 AND CASCADE = '%s' LIMIT %u";
474  UINT8* finalQuery;
475  PGresult* result;
476  SINT32 numTuples, i;
477  UINT8* pTmpStr;
478  CAXMLCostConfirmation* pCC;
479 
480  if(!checkConnectionStatus())
481  {
482  MONITORING_FIRE_PAY_EVENT(ev_pay_dbConnectionFailure);
483  return E_NOT_CONNECTED;
484  }
485  MONITORING_FIRE_PAY_EVENT(ev_pay_dbConnectionSuccess);
486 
487  finalQuery = new UINT8[strlen(query)+strlen((char*)cascadeId)];
488  sprintf( (char*)finalQuery, query, cascadeId, a_maxCCs);
489 
490 #ifdef DEBUG
491  CAMsg::printMsg(LOG_DEBUG, "Getting Cost confirmations for cascade: ");
492  CAMsg::printMsg(LOG_DEBUG, (const char*) finalQuery);
493 #endif
494 
495  result = monitored_PQexec(m_dbConn, (char *)finalQuery);
496 
497  delete[] finalQuery;
498  finalQuery = NULL;
499  if(PQresultStatus(result) != PGRES_TUPLES_OK)
500  {
501  PQclear(result);
502  return E_UNKNOWN;
503  }
504  numTuples = PQntuples(result);
505  *nrOfCCs = numTuples;
506 
507  if(numTuples > 0)
508  {
509 
510  *resultCCs = new CAXMLCostConfirmation *[numTuples];
511  i = 0;
512  while(i < *nrOfCCs)
513  {
514  pTmpStr = (UINT8*) PQgetvalue(result, i, 0);
515  if( (pTmpStr!=NULL)&&
516  ( (pCC = CAXMLCostConfirmation::getInstance(pTmpStr,strlen((char*)pTmpStr)) )!=NULL))
517  {
518  (*resultCCs)[i] = pCC;
519  i++;
520  }
521  else
522  {
523  //ok, in this case we reserved a bit too much memory, but it is very unlikely and if it would happen
524  //there is no need to worry about it.
525  (*nrOfCCs)--;
526  }
527  }
528  }
529  PQclear(result);
530 
531  //CAMsg::printMsg(LOG_DEBUG, "Stop get unsettled CC\n");
532  return E_SUCCESS;
533  }

References checkConnectionStatus(), E_NOT_CONNECTED, E_SUCCESS, E_UNKNOWN, m_dbConn, monitored_PQexec(), MONITORING_FIRE_PAY_EVENT, and CAMsg::printMsg().

Referenced by getUnsettledCostConfirmations().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ __markAsSettled()

SINT32 CAAccountingDBInterface::__markAsSettled ( UINT64  accountNumber,
UINT8 cascadeId,
UINT64  a_transferredBytes 
)
private

Marks this account as settled.

Todo:
what to do if there was a new CC stored while we were busy settling the old one?
Return values
E_NOT_CONNECTEDif a connection to the DB could not be established
E_UNKNOWNin case of a general error

Definition at line 552 of file CAAccountingDBInterface.cpp.

553  {
554  const char* queryF = "UPDATE COSTCONFIRMATIONS SET SETTLED=1 WHERE ACCOUNTNUMBER=%s AND BYTES=%s AND CASCADE='%s'";
555  UINT8 * query;
556  PGresult * result;
557 
558  if(!checkConnectionStatus())
559  {
560  MONITORING_FIRE_PAY_EVENT(ev_pay_dbConnectionFailure);
561  return E_NOT_CONNECTED;
562  }
563  MONITORING_FIRE_PAY_EVENT(ev_pay_dbConnectionSuccess);
564 
565  UINT8 tmp[32], tmp2[32];
566  print64(tmp,accountNumber);
567  print64(tmp2,a_transferredBytes);
568  query = new UINT8[strlen(queryF) + 32 + 32 + strlen((char*)cascadeId)];
569  sprintf((char *)query, queryF, tmp, tmp2, cascadeId);
570  result = monitored_PQexec(m_dbConn, (char *)query);
571 
572  delete[] query;
573  query = NULL;
574  if(PQresultStatus(result) != PGRES_COMMAND_OK)
575  {
576  PQclear(result);
577  return E_UNKNOWN;
578  }
579  PQclear(result);
580 
581  return E_SUCCESS;
582  }

References checkConnectionStatus(), E_NOT_CONNECTED, E_SUCCESS, E_UNKNOWN, m_dbConn, monitored_PQexec(), MONITORING_FIRE_PAY_EVENT, and print64().

Referenced by markAsSettled().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ __storeAccountStatus()

SINT32 CAAccountingDBInterface::__storeAccountStatus ( UINT64  a_accountNumber,
UINT32  a_statusCode 
)
private

Definition at line 830 of file CAAccountingDBInterface.cpp.

831 {
832  const char* previousStatusQuery = "SELECT COUNT(*) FROM ACCOUNTSTATUS WHERE ACCOUNTNUMBER='%s' ";
833  //reverse order of columns, so insertQuery and updateQuery can be used with the same sprintf parameters
834  const char* insertQuery = "INSERT INTO ACCOUNTSTATUS(STATUSCODE,ACCOUNTNUMBER) VALUES ('%u', '%s')";
835  const char* updateQuery = "UPDATE ACCOUNTSTATUS SET STATUSCODE=%u WHERE ACCOUNTNUMBER=%s";
836  const char* query;
837 
838  PGresult* result;
839  UINT8* finalQuery;
840  UINT8 tmp[32];
841  UINT32 len;
842  UINT32 count;
843  print64(tmp,accountNumber);
844 
845  if(!checkConnectionStatus())
846  {
847  MONITORING_FIRE_PAY_EVENT(ev_pay_dbConnectionFailure);
848  return E_NOT_CONNECTED;
849  }
850  MONITORING_FIRE_PAY_EVENT(ev_pay_dbConnectionSuccess);
851 
852  len = max(strlen(previousStatusQuery), strlen(insertQuery));
853  len = max(len, strlen(updateQuery));
854  finalQuery = new UINT8[len + 32 + 32 + 32];
855  sprintf( (char *)finalQuery, previousStatusQuery, tmp);
856 
857  if (__checkCountAllQuery(finalQuery, count) != E_SUCCESS)
858  {
859  delete[] finalQuery;
860  finalQuery = NULL;
861  return E_UNKNOWN;
862  }
863 
864  // put query together (either insert or update)
865  if(count == 0)
866  {
867  query = insertQuery;
868  }
869  else
870  {
871  query = updateQuery;
872  }
873  sprintf((char*)finalQuery, query, statuscode, tmp);
874  result = monitored_PQexec(m_dbConn, (char *)finalQuery);
875 
876  if (PQresultStatus(result) != PGRES_COMMAND_OK) // || PQntuples(result) != 1)
877  {
878  CAMsg::printMsg(LOG_ERR, "CAAccountungDBInterface: Saving the account status failed!\n");
879  //if (PQresultStatus(result) != PGRES_COMMAND_OK)
880  {
881  CAMsg::printMsg(LOG_ERR,
882  "Database Error '%s' while processing query '%s'\n",
883  PQresultErrorMessage(result), finalQuery
884  );
885  }
886  delete[] finalQuery;
887  finalQuery = NULL;
888  if (result)
889  {
890  PQclear(result);
891  }
892  return E_UNKNOWN;
893  }
894  delete[] finalQuery;
895  finalQuery = NULL;
896  PQclear(result);
897  CAMsg::printMsg(LOG_DEBUG, "Stored status code %u for account nr. %s \n",statuscode, tmp);
898  return E_SUCCESS;
899 }
#define max(a, b)
Definition: StdAfx.h:654
unsigned int UINT32
Definition: basetypedefs.h:131
SINT32 __checkCountAllQuery(UINT8 *a_query, UINT32 &r_count)
UINT16 len
Definition: typedefs.hpp:0

References __checkCountAllQuery(), checkConnectionStatus(), E_NOT_CONNECTED, E_SUCCESS, E_UNKNOWN, len, m_dbConn, max, monitored_PQexec(), MONITORING_FIRE_PAY_EVENT, print64(), and CAMsg::printMsg().

Referenced by storeAccountStatus().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ __storeCostConfirmation()

SINT32 CAAccountingDBInterface::__storeCostConfirmation ( CAXMLCostConfirmation &  cc,
UINT8 ccCascade 
)
private

stores a cost confirmation in the DB

Todo:
optimize - maybe do check and insert/update in one step??

Definition at line 352 of file CAAccountingDBInterface.cpp.

353  {
354  #ifndef HAVE_NATIVE_UINT64
355  #warning Native UINT64 type not available - CostConfirmation Database might be non-functional
356  #endif
357  const char* previousCCQuery = "SELECT COUNT(*) FROM COSTCONFIRMATIONS WHERE ACCOUNTNUMBER='%s' AND CASCADE='%s'";
358  const char* query2F = "INSERT INTO COSTCONFIRMATIONS(BYTES, XMLCC, SETTLED, ACCOUNTNUMBER, CASCADE) VALUES ('%s', '%s', '%d', '%s', '%s')";
359  const char* query3F = "UPDATE COSTCONFIRMATIONS SET BYTES='%s', XMLCC='%s', SETTLED='%d' WHERE ACCOUNTNUMBER='%s' AND CASCADE='%s'";
360  const char* tempQuery;
361 
362  UINT8 * query;
363  UINT8 * pStrCC;
364  UINT32 size;
365  UINT32 len;
366  UINT32 count;
367  PGresult * pResult;
368  UINT8 strAccountNumber[32];
369  UINT8 tmp[32];
370 
371  if(!checkConnectionStatus())
372  {
373  MONITORING_FIRE_PAY_EVENT(ev_pay_dbConnectionFailure);
374  return E_NOT_CONNECTED;
375  }
376  MONITORING_FIRE_PAY_EVENT(ev_pay_dbConnectionSuccess);
377 
378  pStrCC = new UINT8[8192];
379  size=8192;
380  if(cc.toXMLString(pStrCC, &size)!=E_SUCCESS)
381  {
382  CAMsg::printMsg(LOG_DEBUG, "CAAccountingInstanceDBInterface: Could not transform CC to XML string!\n");
383  delete[] pStrCC;
384  pStrCC = NULL;
385  return E_UNKNOWN;
386  }
387 
388 #ifdef DEBUG
389  CAMsg::printMsg(LOG_DEBUG, "cc to store in db:%s\n",pStrCC);
390 #endif
391 
392  // Test: is there already an entry with this accountno. for the same cascade?
393  len = max(strlen(previousCCQuery), strlen(query2F));
394  len = max(len, strlen(query3F));
395  query = new UINT8[len + 32 + 32 + 1 + size + strlen((char*)ccCascade)];
396  print64(strAccountNumber,cc.getAccountNumber());
397  sprintf( (char*)query, previousCCQuery, strAccountNumber, ccCascade);
398 
399  // to receive result in binary format...
400  if (__checkCountAllQuery(query, count) != E_SUCCESS)
401  {
402  delete[] pStrCC;
403  pStrCC = NULL;
404  delete[] query;
405  query = NULL;
406  return E_UNKNOWN;
407  }
408 
409  // put query together (either insert or update)
410  print64(tmp,cc.getTransferredBytes());
411  if(count == 0)
412  {
413  tempQuery = query2F; // do insert
414  }
415  else
416  {
417  tempQuery = query3F; // do update
418  }
419  sprintf((char*)query, tempQuery, tmp, pStrCC, 0, strAccountNumber, ccCascade);
420 
421  // issue query..
422  pResult = monitored_PQexec(m_dbConn, (char*)query);
423 
424  delete[] pStrCC;
425  pStrCC = NULL;
426  if(PQresultStatus(pResult) != PGRES_COMMAND_OK) // || PQntuples(pResult) != 1)
427  {
428  CAMsg::printMsg(LOG_ERR, "Could not store CC!\n");
429  //if (PQresultStatus(pResult) != PGRES_COMMAND_OK)
430  {
431  CAMsg::printMsg(LOG_ERR,
432  "Database message '%s' while processing query '%s'\n",
433  PQresultErrorMessage(pResult), query
434  );
435  }
436  delete[] query;
437  query = NULL;
438  PQclear(pResult);
439  return E_UNKNOWN;
440  }
441  delete[] query;
442  query = NULL;
443  PQclear(pResult);
444 
445  #ifdef DEBUG
446  CAMsg::printMsg(LOG_DEBUG, "CAAccountingInstanceDBInterface: Finished storing CC in DB.\n");
447  #endif
448  return E_SUCCESS;
449  }

References __checkCountAllQuery(), checkConnectionStatus(), E_NOT_CONNECTED, E_SUCCESS, E_UNKNOWN, len, m_dbConn, max, monitored_PQexec(), MONITORING_FIRE_PAY_EVENT, print64(), and CAMsg::printMsg().

Referenced by storeCostConfirmation().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ __storePrepaidAmount()

SINT32 CAAccountingDBInterface::__storePrepaidAmount ( UINT64  accountNumber,
SINT32  prepaidBytes,
UINT8 cascadeId 
)
private

Definition at line 659 of file CAAccountingDBInterface.cpp.

660 {
661  const char* selectQuery = "SELECT COUNT(*) FROM PREPAIDAMOUNTS WHERE ACCOUNTNUMBER=%s AND CASCADE='%s'";
662  const char* insertQuery = "INSERT INTO PREPAIDAMOUNTS(PREPAIDBYTES, ACCOUNTNUMBER, CASCADE) VALUES (%d, %s, '%s')";
663  const char* updateQuery = "UPDATE PREPAIDAMOUNTS SET PREPAIDBYTES=%d WHERE ACCOUNTNUMBER=%s AND CASCADE='%s'";
664  //const char* deleteQuery = "DELETE FROM PREPAIDAMOUNTS WHERE ACCOUNTNUMBER = %s AND CASCADE='%s'";
665  const char* query;
666 
667  PGresult* result;
668  UINT8* finalQuery;
669  UINT8 tmp[32];
670  UINT32 len;
671  UINT32 count;
672  print64(tmp,accountNumber);
673 
674  if(!checkConnectionStatus())
675  {
676  MONITORING_FIRE_PAY_EVENT(ev_pay_dbConnectionFailure);
677  return E_NOT_CONNECTED;
678  }
679 
680  MONITORING_FIRE_PAY_EVENT(ev_pay_dbConnectionSuccess);
681 
682  len = max(strlen(selectQuery), strlen(insertQuery));
683  len = max(len, strlen(updateQuery));
684  finalQuery = new UINT8[len + 32 + 32 + strlen((char*)cascadeId)];
685  sprintf( (char *)finalQuery, selectQuery, tmp, cascadeId);
686 
687  if (__checkCountAllQuery(finalQuery, count) != E_SUCCESS)
688  {
689  delete[] finalQuery;
690  finalQuery = NULL;
691  /*if(!checkConnectionStatus())
692  {
693  MONITORING_FIRE_PAY_EVENT(ev_pay_dbConnectionFailure);
694  return E_NOT_CONNECTED;
695  }*/
696  return E_UNKNOWN;
697  }
698 
699  // put query together (either insert or update)
700  if(count == 0)
701  {
702  query = insertQuery;
703  }
704  else
705  {
706  query = updateQuery;
707  }
708  sprintf((char*)finalQuery, query, prepaidBytes, tmp, cascadeId);
709  result = monitored_PQexec(m_dbConn, (char *)finalQuery);
710 
711  if (PQresultStatus(result) != PGRES_COMMAND_OK) // || PQntuples(result) != 1)
712  {
713  CAMsg::printMsg(LOG_ERR, "CAAccountungDBInterface: Saving to prepaidamounts failed!\n");
714  //if (PQresultStatus(result) != PGRES_COMMAND_OK)
715  {
716  CAMsg::printMsg(LOG_ERR,
717  "Database message '%s' while processing query '%s'\n",
718  PQresultErrorMessage(result), finalQuery
719  );
720  }
721  delete[] finalQuery;
722  finalQuery = NULL;
723  if (result)
724  {
725  PQclear(result);
726  }
727  return E_UNKNOWN;
728  }
729  delete[] finalQuery;
730  finalQuery = NULL;
731  PQclear(result);
732  CAMsg::printMsg(LOG_DEBUG, "CAAccountingDBInterface: Stored %d prepaid bytes for account nr. %s \n",prepaidBytes, tmp);
733  return E_SUCCESS;
734 }

References __checkCountAllQuery(), checkConnectionStatus(), E_NOT_CONNECTED, E_SUCCESS, E_UNKNOWN, len, m_dbConn, max, monitored_PQexec(), MONITORING_FIRE_PAY_EVENT, print64(), and CAMsg::printMsg().

Referenced by storePrepaidAmount().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ checkConnectionStatus()

bool CAAccountingDBInterface::checkConnectionStatus ( )
private

Checks if the connection still exists and tries to reconnect if not.

Returns
if the database connection is active after the call or not

Definition at line 134 of file CAAccountingDBInterface.cpp.

135 {
136  if (!m_bConnected)
137  {
138  return false;
139  }
140 
141  if (PQstatus(m_dbConn) != CONNECTION_OK)
142  {
143  CAMsg::printMsg(LOG_ERR, "CAAccountingDBInterface: Connection to database lost! Reason: %s\n",
144  PQerrorMessage(m_dbConn));
145  PQreset(m_dbConn);
146 
147  if (PQstatus(m_dbConn) != CONNECTION_OK)
148  {
149  CAMsg::printMsg(LOG_ERR, "CAAccountingDBInterface: Could not reset database connection! Reason: %s\n",
150  PQerrorMessage(m_dbConn));
152  }
153  else
154  {
155  CAMsg::printMsg(LOG_INFO, "CAAccountingDBInterface: Database connection has been reset successfully!");
156  }
157  }
158  return m_bConnected;
159 }

References m_bConnected, m_dbConn, CAMsg::printMsg(), and terminateDBConnection().

Referenced by __deleteCC(), __getAccountStatus(), __getCostConfirmation(), __getPrepaidAmount(), __getUnsettledCostConfirmations(), __markAsSettled(), __storeAccountStatus(), __storeCostConfirmation(), __storePrepaidAmount(), getConnection(), and monitored_PQexec().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ checkCountAllQuery()

SINT32 CAAccountingDBInterface::checkCountAllQuery ( UINT8 a_query,
UINT32 r_count 
)

Takes and executes a query that counts databae records and tests if the result is valid.

Parameters
a_querya query that should return the count of database rows
r_countnumber of database rows; only valid if E_SUCCESS is returned

Definition at line 283 of file CAAccountingDBInterface.cpp.

284 {
285  if(checkOwner())
286  {
287  return __checkCountAllQuery(a_query, r_count);
288  }
289  else
290  {
291  return E_UNKNOWN;
292  }
293 }

References __checkCountAllQuery(), checkOwner(), and E_UNKNOWN.

Here is the call graph for this function:

◆ checkOwner()

bool CAAccountingDBInterface::checkOwner ( )
private

Definition at line 182 of file CAAccountingDBInterface.cpp.

183 {
184  bool isFree = false;
185  thread_id_t owner = 0;
187  owner = m_owner;
188  isFree = m_free;
190 
191  return ( (owner==CAThread::getSelfID()) && !isFree);
192 }
unsigned long long thread_id_t
Type of an ID for a thread which can be used to identify the current and other threads.
Definition: CAThread.hpp:70
SINT32 unlock()
Definition: CAMutex.hpp:52
SINT32 lock()
Definition: CAMutex.hpp:41
static thread_id_t getSelfID()
Definition: CAThread.hpp:201

References CAThread::getSelfID(), CAMutex::lock(), m_free, m_owner, m_pConnectionMutex, and CAMutex::unlock().

Referenced by checkCountAllQuery(), clearAccountStatus(), deleteCC(), getAccountStatus(), getCostConfirmation(), getPrepaidAmount(), getUnsettledCostConfirmations(), markAsSettled(), storeAccountStatus(), storeCostConfirmation(), and storePrepaidAmount().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ cleanup()

SINT32 CAAccountingDBInterface::cleanup ( )
static

Definition at line 1212 of file CAAccountingDBInterface.cpp.

1213 {
1214  UINT32 i;
1215  SINT32 dbConnStatus, ret = E_SUCCESS;
1216  if(ms_pDBConnectionPool != NULL)
1217  {
1218  for(i=0; i < MAX_DB_CONNECTIONS; i++)
1219  {
1220  if(ms_pDBConnectionPool[i] == NULL)
1221  {
1222  //CAMsg::printMsg(LOG_ERR, "CAAccountingDBInterface: DBConnection: Already cleaned up.\n");
1223  }
1224  else
1225  {
1226  dbConnStatus = ms_pDBConnectionPool[i]->terminateDBConnection();
1227  delete ms_pDBConnectionPool[i];
1228  ms_pDBConnectionPool[i] = NULL;
1229  }
1230  if(dbConnStatus != E_SUCCESS)
1231  {
1232  CAMsg::printMsg(LOG_ERR, "CAAccountingDBInterface: DBConnection cleanup: "
1233  "an error occured while closing DBConnection.\n");
1234  ret = dbConnStatus;
1235  }
1236  }
1237  }
1238  if(ms_pConnectionAvailable != NULL)
1239  {
1240  delete ms_pConnectionAvailable;
1241  ms_pConnectionAvailable = NULL;
1242  }
1243  return ret;
1244 }
#define MAX_DB_CONNECTIONS
static CAAccountingDBInterface * ms_pDBConnectionPool[]
static CAConditionVariable * ms_pConnectionAvailable

References E_SUCCESS, MAX_DB_CONNECTIONS, ms_pConnectionAvailable, ms_pDBConnectionPool, CAMsg::printMsg(), and terminateDBConnection().

Referenced by CAFirstMix::clean(), and CACmdLnOptions::setAccountingDatabase().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ clearAccountStatus()

SINT32 CAAccountingDBInterface::clearAccountStatus ( UINT64  a_accountNumber)

Definition at line 901 of file CAAccountingDBInterface.cpp.

902  {
903  if(checkOwner())
904  {
905  return __clearAccountStatus(a_accountNumber);
906  }
907  else
908  {
909  return E_UNKNOWN;
910  }
911  }
SINT32 __clearAccountStatus(UINT64 a_accountNumber)

References __clearAccountStatus(), checkOwner(), and E_UNKNOWN.

Referenced by CAAccountingInstance::__commitSettlementToDatabase(), and CAAccountingInstance::settlementTransaction().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ deleteCC()

SINT32 CAAccountingDBInterface::deleteCC ( UINT64  accountNumber,
UINT8 cascadeId 
)

if the BI reports an error while trying to settle a CC, this will be called to delete it from the database (otherwise the AI would try forever in vain to settle the unusable CC)

Definition at line 584 of file CAAccountingDBInterface.cpp.

585 {
586  if(checkOwner())
587  {
588  return __deleteCC(accountNumber, cascadeId);
589  }
590  else
591  {
592  return E_UNKNOWN;
593  }
594 }
SINT32 __deleteCC(UINT64 accountNumber, UINT8 *cascadeId)

References __deleteCC(), checkOwner(), and E_UNKNOWN.

Referenced by CAAccountingInstance::__handleSettleResult(), and CAAccountingInstance::settlementTransaction().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ getAccountStatus()

SINT32 CAAccountingDBInterface::getAccountStatus ( UINT64  a_accountNumber,
UINT32 a_statusCode 
)

Definition at line 947 of file CAAccountingDBInterface.cpp.

948  {
949  if(checkOwner())
950  {
951  return __getAccountStatus(a_accountNumber, a_statusCode);
952  }
953  else
954  {
955  return E_UNKNOWN;
956  }
957  }
SINT32 __getAccountStatus(UINT64 a_accountNumber, UINT32 &a_statusCode)

References __getAccountStatus(), checkOwner(), and E_UNKNOWN.

Referenced by CAAccountingInstance::__handleSettleResult(), CAAccountingInstance::finishLoginProcess(), CAAccountingInstance::handleChallengeResponse_internal(), and CAAccountingInstance::settlementTransaction().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ getConnection()

CAAccountingDBInterface * CAAccountingDBInterface::getConnection ( )
static

Definition at line 1020 of file CAAccountingDBInterface.cpp.

1021 {
1022  UINT32 i;
1023  UINT64 myWaitNr;
1024  CAAccountingDBInterface *returnedConnection = NULL;
1025 
1026  if(ms_pDBConnectionPool == NULL)
1027  {
1028  CAMsg::printMsg(LOG_ERR, "CAAccountingDBInterface: No DBConnection available. This should NEVER happen!\n");
1029  return NULL;
1030  }
1031  if(ms_pConnectionAvailable == NULL)
1032  {
1033  CAMsg::printMsg(LOG_ERR, "CAAccountingDBInterface: DBConnections not initialized. This should NEVER happen!\n");
1034  return NULL;
1035  }
1037  for(i=0; 1; i++)
1038  {
1039  if(ms_pDBConnectionPool[(i%MAX_DB_CONNECTIONS)] != NULL)
1040  {
1042  {
1043  returnedConnection = ms_pDBConnectionPool[(i%MAX_DB_CONNECTIONS)];
1044  break;
1045  }
1046  }
1047  if((i % MAX_DB_CONNECTIONS) == (MAX_DB_CONNECTIONS - 1) )
1048  {
1049  //wait until connection is free
1050  ms_threadWaitNr++;
1051  myWaitNr = ms_threadWaitNr;
1052 #ifdef DEBUG
1053  CAMsg::printMsg(LOG_DEBUG, "CAAccountingDBInterface: Thread %x waits for connection with waitNr %Lu and %Lu Threads waiting before\n",
1054  pthread_self(), myWaitNr, (myWaitNr - ms_nextThreadNr));
1055 #endif
1056  while(ms_nextThreadNr != myWaitNr)
1057  {
1059  }
1060 #ifdef DEBUG
1061  CAMsg::printMsg(LOG_DEBUG, "CAAccountingDBInterface: Thread %x with waitNr %Lu continues\n",
1062  pthread_self(), myWaitNr);
1063 #endif
1065  {
1066  //was the last waiting thread: reset the variables
1067  ms_threadWaitNr = 0;
1068  ms_nextThreadNr = 0;
1069  }
1070  //next complete array loop turn
1071  }
1072  }
1074  if(returnedConnection != NULL)
1075  {
1076  if(!(returnedConnection->checkConnectionStatus()))
1077  {
1078  if(returnedConnection->initDBConnection() != E_SUCCESS)
1079  {
1080  MONITORING_FIRE_PAY_EVENT(ev_pay_dbConnectionFailure);
1081  CAMsg::printMsg(LOG_WARNING, "CAAccountingDBInterface: Warning requested DB connection can not be established\n");
1082  /*returnedConnection->testAndResetOwner();
1083  return NULL;*/
1084  }
1085  else
1086  {
1087  MONITORING_FIRE_PAY_EVENT(ev_pay_dbConnectionSuccess);
1088  }
1089  }
1090  else
1091  {
1092  MONITORING_FIRE_PAY_EVENT(ev_pay_dbConnectionSuccess);
1093  }
1094  }
1095  return returnedConnection;
1096 }
SINT32 initDBConnection()
Initiates the database connection.
static volatile UINT64 ms_threadWaitNr
static volatile UINT64 ms_nextThreadNr
SINT32 wait()
Waits for a signal or for a timeout.

References checkConnectionStatus(), E_SUCCESS, initDBConnection(), CAMutex::lock(), MAX_DB_CONNECTIONS, MONITORING_FIRE_PAY_EVENT, ms_nextThreadNr, ms_pConnectionAvailable, ms_pDBConnectionPool, ms_threadWaitNr, CAMsg::printMsg(), testAndSetOwner(), CAMutex::unlock(), and CAConditionVariable::wait().

Referenced by CAAccountingInstance::__newSettlementTransaction(), CAAccountingInstance::cleanupTableEntry(), CAAccountingInstance::finishLoginProcess(), CAAccountingInstance::handleAccountCertificate_internal(), CAAccountingInstance::handleChallengeResponse_internal(), CAAccountingInstance::handleCostConfirmation_internal(), CAAccountingInstance::handleJapPacket_internal(), and CAAccountingInstance::settlementTransaction().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ getCostConfirmation()

SINT32 CAAccountingDBInterface::getCostConfirmation ( UINT64  accountNumber,
UINT8 cascadeId,
CAXMLCostConfirmation **  pCC,
bool &  a_bSettled 
)

Definition at line 195 of file CAAccountingDBInterface.cpp.

196 {
197  if(checkOwner())
198  {
199  return __getCostConfirmation(accountNumber, cascadeId, pCC, a_bSettled);
200  }
201  else
202  {
203  return E_UNKNOWN;
204  }
205 }
SINT32 __getCostConfirmation(UINT64 accountNumber, UINT8 *cascadeId, CAXMLCostConfirmation **pCC, bool &a_bSettled)
Gets the latest cost confirmation stored for the given user account.

References __getCostConfirmation(), checkOwner(), and E_UNKNOWN.

Referenced by CAAccountingInstance::handleChallengeResponse_internal(), and CAAccountingInstance::handleJapPacket_internal().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ getPrepaidAmount()

SINT32 CAAccountingDBInterface::getPrepaidAmount ( UINT64  accountNumber,
UINT8 cascadeId,
bool  a_bDelete 
)

Definition at line 736 of file CAAccountingDBInterface.cpp.

737 {
738  if(checkOwner())
739  {
740  return __getPrepaidAmount(accountNumber, cascadeId, a_bDelete);
741  }
742  else
743  {
744  return E_UNKNOWN;
745  }
746 }
SINT32 __getPrepaidAmount(UINT64 accountNumber, UINT8 *cascadeId, bool a_bDelete)

References __getPrepaidAmount(), checkOwner(), and E_UNKNOWN.

Referenced by CAAccountingInstance::__commitSettlementToDatabase(), CAAccountingInstance::handleAccountCertificate_internal(), CAAccountingInstance::handleChallengeResponse_internal(), and CAAccountingInstance::settlementTransaction().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ getUnsettledCostConfirmations()

SINT32 CAAccountingDBInterface::getUnsettledCostConfirmations ( CAXMLCostConfirmation ***  resultCCs,
UINT8 cascadeId,
UINT32 nrOfCCs,
UINT32  a_maxCCs 
)

Fills the CAQueue with all non-settled cost confirmations.

Definition at line 452 of file CAAccountingDBInterface.cpp.

453 {
454  if(checkOwner())
455  {
456  return __getUnsettledCostConfirmations(resultCCs, cascadeId, nrOfCCs, a_maxCCs);
457  }
458  else
459  {
460  return E_UNKNOWN;
461  }
462 }
SINT32 __getUnsettledCostConfirmations(CAXMLCostConfirmation ***resultCCs, UINT8 *cascadeId, UINT32 *nrOfCCs, UINT32 a_maxCCs)
Fills the CAQueue with pointer to all non-settled cost confirmations.

References __getUnsettledCostConfirmations(), checkOwner(), and E_UNKNOWN.

Referenced by CAAccountingInstance::__newSettlementTransaction(), and CAAccountingInstance::settlementTransaction().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ init()

SINT32 CAAccountingDBInterface::init ( )
static

Definition at line 1174 of file CAAccountingDBInterface.cpp.

1175 {
1176  UINT32 i;
1177  SINT32 dbConnStatus;
1178 
1180 
1181  ms_threadWaitNr = 0;
1182  ms_nextThreadNr = 0;
1183 
1184  if(ms_pDBConnectionPool != NULL)
1185  {
1186  for(i=0; i < MAX_DB_CONNECTIONS; i++)
1187  {
1188  if(ms_pDBConnectionPool[i] != NULL)
1189  {
1190  //CAMsg::printMsg(LOG_WARNING, "CAAccountingDBInterface: DBConnection: "
1191  // "Already initialized connection.\n");
1192  }
1194  dbConnStatus = ms_pDBConnectionPool[i]->initDBConnection();
1195 
1196  if(dbConnStatus != E_SUCCESS)
1197  {
1198  CAMsg::printMsg(LOG_CRIT, "CAAccountingDBInterface: DBConnection initialization: "
1199  "could not connect to Database.\n");
1200  return E_UNKNOWN;
1201  }
1202  }
1203  }
1204  else
1205  { //should never happen
1206  CAMsg::printMsg(LOG_CRIT, "CAAccountingDBInterface: DBConnection initialization failed.\n");
1207  return E_UNKNOWN;
1208  }
1209  return E_SUCCESS;
1210 }

References CAAccountingDBInterface(), E_SUCCESS, E_UNKNOWN, initDBConnection(), MAX_DB_CONNECTIONS, ms_nextThreadNr, ms_pConnectionAvailable, ms_pDBConnectionPool, ms_threadWaitNr, and CAMsg::printMsg().

Referenced by CAFirstMix::init(), and CACmdLnOptions::setAccountingDatabase().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ initDBConnection()

SINT32 CAAccountingDBInterface::initDBConnection ( )
private

Initiates the database connection.

This function is called inside the aiThread

Returns
E_NOT_CONNECTED if the connection could not be established
E_UNKNOWN if we are already connected
E_SUCCESS if all is OK

Definition at line 78 of file CAAccountingDBInterface.cpp.

79  {
80  if(m_bConnected)
81  {
82  return E_UNKNOWN;
83  }
84 
85  // Get database connection info from configfile and/or commandline
86  UINT8 host[255];
87  if(CALibProxytest::getOptions()->getDatabaseHost(host, 255) != E_SUCCESS)
88  {
89  CAMsg::printMsg(LOG_ERR, "CAAccountingDBInterface: Error, no Database Host!\n");
90  return E_UNKNOWN;
91  }
93  UINT8 dbName[255];
94  if(CALibProxytest::getOptions()->getDatabaseName(dbName, 255) != E_SUCCESS)
95  {
96  CAMsg::printMsg(LOG_ERR, "CAAccountingDBInterface: Error, no Database Name!\n");
97  return E_UNKNOWN;
98  }
99  UINT8 userName[255];
100  if(CALibProxytest::getOptions()->getDatabaseUsername(userName, 255) != E_SUCCESS)
101  {
102  CAMsg::printMsg(LOG_ERR, "CAAccountingDBInterface: Error, no Database Username!\n");
103  return E_UNKNOWN;
104  }
105  UINT8 password[255];
106  if(CALibProxytest::getOptions()->getDatabasePassword(password, 255) != E_SUCCESS)
107  {
108  CAMsg::printMsg(LOG_ERR, "CAAccountingDBInterface: Error, no Database Password!\n");
109  return E_UNKNOWN;
110  }
111 
112 
113  char port[20];
114  sprintf(port, "%i", tcp_port);
115  m_dbConn = PQsetdbLogin(
116  (char*)host, port, "", "",
117  (char*)dbName, (char*)userName, (char*)password
118  );
119  if(m_dbConn==NULL||PQstatus(m_dbConn) == CONNECTION_BAD)
120  {
122  LOG_ERR, "CAAccountingDBInterface: Could not connect to Database. Reason: %s\n",
123  PQerrorMessage(m_dbConn)
124  );
125  PQfinish(m_dbConn);
126  m_dbConn = NULL;
127  m_bConnected = false;
128  return E_NOT_CONNECTED;
129  }
130  m_bConnected = true;
131  return E_SUCCESS;
132  }
UINT16 getDatabasePort()
static CACmdLnOptions * getOptions()

References E_NOT_CONNECTED, E_SUCCESS, E_UNKNOWN, CACmdLnOptions::getDatabasePort(), CALibProxytest::getOptions(), m_bConnected, m_dbConn, and CAMsg::printMsg().

Referenced by getConnection(), and init().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ isDBConnected()

bool CAAccountingDBInterface::isDBConnected ( )
private

Definition at line 161 of file CAAccountingDBInterface.cpp.

162 {
163  return m_bConnected;
164 }

References m_bConnected.

◆ markAsSettled()

SINT32 CAAccountingDBInterface::markAsSettled ( UINT64  accountNumber,
UINT8 cascadeId,
UINT64  a_transferredBytes 
)

Marks this account as settled.

Todo:
what to do if there was a new CC stored while we were busy settling the old one?

Definition at line 535 of file CAAccountingDBInterface.cpp.

536 {
537  if(checkOwner())
538  {
539  return __markAsSettled(accountNumber, cascadeId, a_transferredBytes);
540  }
541  else
542  {
543  return E_UNKNOWN;
544  }
545 }
SINT32 __markAsSettled(UINT64 accountNumber, UINT8 *cascadeId, UINT64 a_transferredBytes)
Marks this account as settled.

References __markAsSettled(), checkOwner(), and E_UNKNOWN.

Referenced by CAAccountingInstance::__handleSettleResult(), and CAAccountingInstance::settlementTransaction().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ monitored_PQexec()

PGresult * CAAccountingDBInterface::monitored_PQexec ( PGconn *  conn,
const char *  query 
)
private

Definition at line 1246 of file CAAccountingDBInterface.cpp.

1247 {
1248  PGresult* result = NULL;
1249  result = PQexec(conn, query);
1250  if(!checkConnectionStatus())
1251  {
1252  MONITORING_FIRE_PAY_EVENT(ev_pay_dbConnectionFailure);
1253  }
1254  else
1255  {
1256  MONITORING_FIRE_PAY_EVENT(ev_pay_dbConnectionSuccess);
1257  }
1258  return result;
1259 }

References checkConnectionStatus(), and MONITORING_FIRE_PAY_EVENT.

Referenced by __checkCountAllQuery(), __clearAccountStatus(), __deleteCC(), __getAccountStatus(), __getCostConfirmation(), __getPrepaidAmount(), __getUnsettledCostConfirmations(), __markAsSettled(), __storeAccountStatus(), __storeCostConfirmation(), and __storePrepaidAmount().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ releaseConnection()

SINT32 CAAccountingDBInterface::releaseConnection ( CAAccountingDBInterface dbIf)
static

Definition at line 1104 of file CAAccountingDBInterface.cpp.

1105 {
1106  SINT32 ret;
1107  //@todo: implementation
1108  if(dbIf == NULL)
1109  {
1110  return E_UNKNOWN;
1111  }
1112  if(dbIf->m_pConnectionMutex == NULL)
1113  {
1114  CAMsg::printMsg(LOG_ERR, "CAAccountingDBInterface: DBConnection structure corrupt!\n");
1115  return E_UNKNOWN;
1116  }
1117  if(ms_pConnectionAvailable == NULL)
1118  {
1119  CAMsg::printMsg(LOG_ERR, "CAAccountingDBInterface: DBConnections not initialized. This should NEVER happen!\n");
1120  return E_UNKNOWN;
1121  }
1122 
1124  if(dbIf->testAndResetOwner())
1125  {
1127  {
1128  ms_nextThreadNr++;
1129 #ifdef DEBUG
1130  CAMsg::printMsg(LOG_DEBUG, "CAAccountingDBInterface: There are %Lu Threads waiting. Waking up thread with waitNr. %Lu\n",
1132 #endif
1133  //There are threads waiting
1135  }
1136  ret = E_SUCCESS;
1137  }
1138  else
1139  {
1140  ret = E_UNKNOWN;
1141  }
1143  return ret;
1144 }
SINT32 broadcast()
Signals this object.

References CAConditionVariable::broadcast(), E_SUCCESS, E_UNKNOWN, CAMutex::lock(), m_pConnectionMutex, ms_nextThreadNr, ms_pConnectionAvailable, ms_threadWaitNr, CAMsg::printMsg(), testAndResetOwner(), and CAMutex::unlock().

Referenced by CAAccountingInstance::__newSettlementTransaction(), CAAccountingInstance::cleanupTableEntry(), CAAccountingInstance::finishLoginProcess(), CAAccountingInstance::handleAccountCertificate_internal(), CAAccountingInstance::handleChallengeResponse_internal(), CAAccountingInstance::handleCostConfirmation_internal(), CAAccountingInstance::handleJapPacket_internal(), and CAAccountingInstance::settlementTransaction().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ storeAccountStatus()

SINT32 CAAccountingDBInterface::storeAccountStatus ( UINT64  a_accountNumber,
UINT32  a_statusCode 
)

Definition at line 816 of file CAAccountingDBInterface.cpp.

817 {
818  if(checkOwner())
819  {
820  return __storeAccountStatus(a_accountNumber, a_statusCode);
821  }
822  else
823  {
824  return E_UNKNOWN;
825  }
826 }
SINT32 __storeAccountStatus(UINT64 a_accountNumber, UINT32 a_statusCode)

References __storeAccountStatus(), checkOwner(), and E_UNKNOWN.

Referenced by CAAccountingInstance::__handleSettleResult(), and CAAccountingInstance::settlementTransaction().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ storeCostConfirmation()

SINT32 CAAccountingDBInterface::storeCostConfirmation ( CAXMLCostConfirmation &  cc,
UINT8 ccCascade 
)

Creates the tables we need in the DB.

Returns
E_SUCCESS if all is OK
E_UNKNOWN if the query could not be executed
E_NOT_CONNECTED if we are not connected to the DB

Definition at line 337 of file CAAccountingDBInterface.cpp.

338 {
339  if(checkOwner())
340  {
341  return __storeCostConfirmation(cc, ccCascade);
342  }
343  else
344  {
345  return E_UNKNOWN;
346  }
347 }
SINT32 __storeCostConfirmation(CAXMLCostConfirmation &cc, UINT8 *ccCascade)
stores a cost confirmation in the DB

References __storeCostConfirmation(), checkOwner(), and E_UNKNOWN.

Referenced by CAAccountingInstance::__handleSettleResult(), CAAccountingInstance::handleCostConfirmation_internal(), and CAAccountingInstance::settlementTransaction().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ storePrepaidAmount()

SINT32 CAAccountingDBInterface::storePrepaidAmount ( UINT64  accountNumber,
SINT32  prepaidBytes,
UINT8 cascadeId 
)

Definition at line 645 of file CAAccountingDBInterface.cpp.

646 {
647  if(checkOwner())
648  {
649  return __storePrepaidAmount(accountNumber, prepaidBytes, cascadeId);
650  }
651  else
652  {
653  return E_UNKNOWN;
654  }
655 }
SINT32 __storePrepaidAmount(UINT64 accountNumber, SINT32 prepaidBytes, UINT8 *cascadeId)

References __storePrepaidAmount(), checkOwner(), and E_UNKNOWN.

Referenced by CAAccountingInstance::__commitSettlementToDatabase(), CAAccountingInstance::cleanupTableEntry(), and CAAccountingInstance::settlementTransaction().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ terminateDBConnection()

SINT32 CAAccountingDBInterface::terminateDBConnection ( )
private

Terminates the database connection.

Returns
E_SUCCESS

Definition at line 170 of file CAAccountingDBInterface.cpp.

171 {
172  if(m_bConnected)
173  {
174  PQfinish(m_dbConn);
175  }
176  m_dbConn=NULL;
177  m_bConnected = false;
178  return E_SUCCESS;
179 }

References E_SUCCESS, m_bConnected, and m_dbConn.

Referenced by checkConnectionStatus(), cleanup(), and ~CAAccountingDBInterface().

Here is the caller graph for this function:

◆ testAndResetOwner()

bool CAAccountingDBInterface::testAndResetOwner ( )
private

Definition at line 1160 of file CAAccountingDBInterface.cpp.

1161 {
1162  bool success = false;
1164  if(!m_free && (m_owner == CAThread::getSelfID()))
1165  {
1166  m_free = true;
1167  m_owner = 0;
1168  success = true;
1169  }
1171  return success;
1172 }

References CAThread::getSelfID(), CAMutex::lock(), m_free, m_owner, m_pConnectionMutex, and CAMutex::unlock().

Referenced by releaseConnection().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ testAndSetOwner()

bool CAAccountingDBInterface::testAndSetOwner ( )
private

Definition at line 1146 of file CAAccountingDBInterface.cpp.

1147 {
1148  bool success = false;
1150  if(m_free)
1151  {
1152  m_free = false;
1154  success = true;
1155  }
1157  return success;
1158 }

References CAThread::getSelfID(), CAMutex::lock(), m_free, m_owner, m_pConnectionMutex, and CAMutex::unlock().

Referenced by getConnection().

Here is the call graph for this function:
Here is the caller graph for this function:

Friends And Related Function Documentation

◆ CAAccountingInstance

friend class CAAccountingInstance
friend

Definition at line 169 of file CAAccountingDBInterface.hpp.

Member Data Documentation

◆ m_bConnected

bool CAAccountingDBInterface::m_bConnected
private

◆ m_dbConn

PGconn* CAAccountingDBInterface::m_dbConn
private

◆ m_free

volatile bool CAAccountingDBInterface::m_free
private

◆ m_owner

volatile thread_id_t CAAccountingDBInterface::m_owner
private

◆ m_pConnectionMutex

CAMutex* CAAccountingDBInterface::m_pConnectionMutex
private

◆ m_protocolVersion

int CAAccountingDBInterface::m_protocolVersion
private

Definition at line 196 of file CAAccountingDBInterface.hpp.

◆ ms_nextThreadNr

volatile UINT64 CAAccountingDBInterface::ms_nextThreadNr = 0
staticprivate

Definition at line 210 of file CAAccountingDBInterface.hpp.

Referenced by getConnection(), init(), and releaseConnection().

◆ ms_pConnectionAvailable

CAConditionVariable * CAAccountingDBInterface::ms_pConnectionAvailable = NULL
staticprivate

Definition at line 204 of file CAAccountingDBInterface.hpp.

Referenced by cleanup(), getConnection(), init(), and releaseConnection().

◆ ms_pDBConnectionPool

CAAccountingDBInterface * CAAccountingDBInterface::ms_pDBConnectionPool
staticprivate

Definition at line 212 of file CAAccountingDBInterface.hpp.

Referenced by cleanup(), getConnection(), and init().

◆ ms_threadWaitNr

volatile UINT64 CAAccountingDBInterface::ms_threadWaitNr = 0
staticprivate

Definition at line 208 of file CAAccountingDBInterface.hpp.

Referenced by getConnection(), init(), and releaseConnection().


The documentation for this class was generated from the following files: