+++ /dev/null
-// ANNA - Anna is Not Nothingness Anymore //
-// //
-// (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo //
-// //
-// See project site at http://redmine.teslayout.com/projects/anna-suite //
-// See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE //
-
-
-#include <anna/config/defines.hpp>
-#include <anna/core/tracing/TraceMethod.hpp>
-
-#include <anna/xml/Node.hpp>
-#include <anna/xml/Attribute.hpp>
-
-#include <anna/dbms/Connection.hpp>
-#include <anna/dbms/Database.hpp>
-#include <anna/dbms/Statement.hpp>
-#include <anna/dbms/Statement.hpp>
-
-using namespace std;
-using namespace anna;
-
-//-----------------------------------------------------------------------------------------------------------
-// (1) Si no tiene variables de salida => consideramos que es un update, insert o delete.
-//-----------------------------------------------------------------------------------------------------------
-dbms::ResultCode dbms::Connection::execute(Statement* statement)
-throw(RuntimeException, dbms::DatabaseException) {
- if(statement == NULL) {
- string msg(asString());
- msg += " | Cannot execute a NULL sentence";
- throw RuntimeException(msg, ANNA_FILE_LOCATION);
- }
-
- LOGMETHOD(TraceMethod ttmm("dbms::Connection", "execute", ANNA_FILE_LOCATION));
- LOGDEBUG(
- string msg("Using Connection | ");
- msg += asString();
- Logger::debug(msg, ANNA_FILE_LOCATION)
- );
- Guard guard(statement, "Statement from dbms::Connection::execute");
- const Microsecond init = functions::hardwareClock();
-
- if(statement->a_prepared == false) {
- statement->prepare(this);
- statement->a_prepared = true;
- }
-
- LOGDEBUG(
- string msg("dbms::Connection::execute | ");
- msg += statement->asString();
- Logger::debug(msg, ANNA_FILE_LOCATION);
- );
-
- if(statement->requiresCommit() == true && a_rollbackPending == true) { // (1)
- string msg("dbms::Connection::execute | ");
- msg += asString();
- msg += " | Connection has pending ROLLBACKS for execution";
- throw RuntimeException(msg, ANNA_FILE_LOCATION);
- }
-
- ResultCode result;
- int tryCounter = 0;
-
- while(true) {
- result = statement->execute(this);
-
- if(result.lostConnection() == false)
- break;
-
- string msg = asString();
- msg += " | ";
- msg += statement->asString();
- msg += " | ";
- msg += result.asString();
- Logger::alert(msg, ANNA_FILE_LOCATION);
- a_database.recover(*this, ++ tryCounter);
- }
-
- statement->measureTiming(init, functions::hardwareClock());
-
- if(result.successful() == false && result.notFound() == false) {
- string msg(asString());
- msg += " | Sentence: ";
- msg += statement->getName();
- Logger::write(Logger::Error, msg, result.asString(), ANNA_FILE_LOCATION);
- }
-
- if(statement->requiresCommit() == true) { // (1)
- if(result.successful() == false) {
- if(statement->isCritical() == true) {
- a_rollbackPending = true;
- throw DatabaseException(statement->getName(), result, ANNA_FILE_LOCATION);
- }
- } else {
- a_commitPending ++;
-
- if(a_maxCommitPending > 0 && a_commitPending > a_maxCommitPending) {
- commit();
- a_commitPending = 0;
- a_rollbackPending = false;
- }
- }
- }
-
- return result;
-}
-
-//------------------------------------------------------------------------------------------------
-// (1) Esto no es estrictamente necesario, pero lo hacemos para que no nos despisten las trazas
-// y los volcados de contexto.
-//------------------------------------------------------------------------------------------------
-void dbms::Connection::commit()
-throw(RuntimeException, dbms::DatabaseException) {
- LOGINFORMATION(
- string msg("dbms::Connection::commit | ");
- msg += asString();
- Logger::information(msg, ANNA_FILE_LOCATION);
- );
-
- if(isAvailable() == false) {
- string msg(asString());
- msg += " | Unavailable connection";
- throw RuntimeException(msg, ANNA_FILE_LOCATION);
- }
-
- do_commit();
- a_commitPending = 0; // (1)
- a_rollbackPending = false;
-}
-
-//------------------------------------------------------------------------------------------------
-// (1) Esto no es estrictamente necesario, pero lo hacemos para que no nos despisten las trazas
-// y los volcados de contexto.
-//------------------------------------------------------------------------------------------------
-void dbms::Connection::rollback()
-throw() {
- LOGWARNING(
- string msg("dbms::Connection::rollback | ");
- msg += asString();
- Logger::warning(msg, ANNA_FILE_LOCATION);
- );
-
- if(isAvailable() == false) {
- string msg(asString());
- msg += " | Unavailable connection";
- throw RuntimeException(msg, ANNA_FILE_LOCATION);
- }
-
- do_rollback();
- a_commitPending = 0;
- a_rollbackPending = false; // (1)
-}
-
-void dbms::Connection::lock()
-throw(RuntimeException) {
- if(isAvailable() == false) {
- string msg(asString());
- msg += " | Unavailable connection";
- throw RuntimeException(msg, ANNA_FILE_LOCATION);
- }
-
- comm::Resource::lock();
-
- if(a_lockingCounter ++ == 0) {
- a_commitPending = 0;
- a_rollbackPending = false;
-
- try {
- if(do_beginTransaction() == true)
- a_commitPending = 1;
- } catch(dbms::DatabaseException& edb) {
- throw RuntimeException(edb);
- }
- }
-
- LOGDEBUG(
- string msg("dbms::Connection::lock | ");
- msg += asString();
- Logger::debug(msg, ANNA_FILE_LOCATION)
- );
-}
-
-void dbms::Connection::unlock()
-throw() {
- LOGDEBUG(
- string msg("dbms::Connection::unlock | ");
- msg += asString();
- Logger::debug(msg, ANNA_FILE_LOCATION)
- );
-
- if(-- a_lockingCounter <= 0) {
- a_lockingCounter = 0;
-
- try {
- if(a_rollbackPending == true)
- rollback();
- else if(a_commitPending > 0)
- commit();
- } catch(Exception& ex) {
- Logger::emergency(ex.getText(), ex.getFromFile(), ex.getFromLine());
- }
- }
-
- comm::Resource::unlock();
-}
-
-string dbms::Connection::asString() const
-throw() {
- string result("dbms::Connection { ");
- result += comm::Resource::asString();
- result += " | ";
- result += a_database.asString();
- result += " | user: ";
- result += a_user;
- result += functions::asText(" | LockingCounter: ", a_lockingCounter);
- result += functions::asText(" | password: ******* | CommitPending: ", a_commitPending);
- result += functions::asText(" | RollbackPending: ", a_rollbackPending);
- return result += " }";
-}
-
-xml::Node* dbms::Connection::asXML(xml::Node* parent) const
-throw() {
- xml::Node* result = comm::Resource::asXML(parent);
- result->createAttribute("User", a_user);
- result->createAttribute("LockingCounter", a_lockingCounter);
- result->createAttribute("CommitPending", a_commitPending);
- result->createAttribute("RollbackPending", functions::asString(a_rollbackPending));
- return result;
-}
-