+++ /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 <stdlib.h>
-#include <locale.h>
-
-#include <string>
-#include <algorithm>
-
-#include <anna/core/tracing/TraceMethod.hpp>
-
-#include <anna/xml/Node.hpp>
-#include <anna/xml/Attribute.hpp>
-
-#include <anna/comm/INetAddress.hpp>
-
-#include <anna/dbms/Database.hpp>
-#include <anna/dbms/Statement.hpp>
-#include <anna/dbms/FailRecoveryHandler.hpp>
-#include <anna/dbms/internal/sccs.hpp>
-#include <anna/dbms/Float.hpp>
-#include <anna/dbms/StatementTranslator.hpp>
-
-using namespace std;
-using namespace anna;
-using namespace anna::dbms;
-
-Database::Database(const char* className, const char* dbmsName) :
- Component(className),
- a_name((dbmsName == NULL) ? "local" : dbmsName),
- a_type((dbmsName == NULL) ? Type::Local : Type::Remote),
- a_failRecoveryHandler(NULL),
- a_statementTranslator(NULL) {
- dbms::sccs::activate();
-}
-
-Database::~Database() {
- stop();
-}
-
-void Database::do_initialize()
-throw(RuntimeException) {
- LOGMETHOD(TraceMethod tm("dbms::Database", "do_initialize", ANNA_FILE_LOCATION));
- int counter(0);
- bool error = false;
-
- for(connection_iterator iic = connection_begin(), maxiic = connection_end(); iic != maxiic; iic ++) {
- try {
- connection(iic)->open();
- counter ++;
- } catch(Exception& ex) {
- ex.trace();
- error = true;
- }
- }
-
- if(counter == 0 && error == true) {
- string msg(asString());
- msg += " | No available connections";
- throw RuntimeException(msg, ANNA_FILE_LOCATION);
- }
-
- LOGINFORMATION(
- Logger::information(asString(), ANNA_FILE_LOCATION);
- );
-}
-
-void Database::do_stop()
-throw() {
- LOGMETHOD(TraceMethod tm("dbms::Database", "do_stop", ANNA_FILE_LOCATION));
-
- try {
- Connection* _connection;
-
- for(connection_iterator iic = connection_begin(), maxiic = connection_end(); iic != maxiic; iic ++) {
- _connection = connection(iic);
- _connection->close();
- delete _connection;
- }
-
- a_connections.clear();
- } catch(Exception& ex) {
- ex.trace();
- a_connections.clear();
- }
-}
-
-/**
- * Para evitar que todos los clones usen la misma conexion a la base de datos, se realiza en
- * cada uno de ellos una re-conexion, es decir, se cierra la original (abierta por el proceso
- * padre) y se abre una nueva conexion con los mismos parametros y contra la misma base de datos.
- */
-void Database::do_cloneChild()
-throw(RuntimeException) {
- LOGMETHOD(TraceMethod tm("dbms::Database", "do_cloneChild", ANNA_FILE_LOCATION));
-
- for(connection_iterator ii = connection_begin(), maxii = connection_end(); ii != maxii; ii ++) {
- dbms::Connection* conn = connection(ii);
- LOGDEBUG(
- string msg("dbms::Database::do_cloneChild | ");
- msg += conn->asString();
- Logger::debug(msg, ANNA_FILE_LOCATION);
- );
- recover(*conn, 0);
- }
-}
-
-Connection* Database::createConnection(const char* name, const char* user, const char* password)
-throw(RuntimeException, DatabaseException) {
- Guard guard(this, "dbms::Database (createConnection)");
-
- if(a_connections.size() >= MaxConnection) {
- string msg("Database::createConnection | ");
- msg += asString();
- msg += functions::asText(" | Cannot create more than %d connections per database", MaxConnection);
- throw RuntimeException(msg, ANNA_FILE_LOCATION);
- }
-
- for(connection_iterator ii = connection_begin(), maxii = connection_end(); ii != maxii; ii ++) {
- if(connection(ii)->getName() == name) {
- string msg("Database::createConnection | ");
- msg += asString();
- msg += " | Connection: ";
- msg += name;
- msg += " | Previously registered";
- throw RuntimeException(msg, ANNA_FILE_LOCATION);
- }
- }
-
- string strname(name);
- Connection* result = allocateConnection(strname, user, password);
-
- if(result == NULL) {
- string msg(asString());
- msg += " | ";
- msg += strname;
- msg += " | Unable to instance connection";
- throw RuntimeException(msg, ANNA_FILE_LOCATION);
- }
-
- LOGDEBUG(
- string msg("dbms::Database::createConnection | ");
- msg += result->asString();
- Logger::write(Logger::Debug, msg, ANNA_FILE_LOCATION);
- );
-
- if(getState() == Component::State::Running) {
- try {
- result->open();
- a_connections.push_back(result);
- } catch(RuntimeException& ex) {
- ex.trace();
- delete result;
- throw;
- } catch(DatabaseException& edbms) {
- edbms.trace();
- delete result;
- throw;
- }
- } else
- a_connections.push_back(result);
-
- return result;
-}
-
-Connection& Database::findConnection(const char* name)
-throw(RuntimeException) {
- Guard guard(this, "dbms::Database (findConnection)");
- Connection* result = NULL;
-
- for(connection_iterator ii = connection_begin(), maxii = connection_end(); ii != maxii; ii ++) {
- if(anna_strcmp(connection(ii)->getName().c_str(), name) == 0) {
- result = connection(ii);
- break;
- }
- }
-
- if(result == NULL) {
- string msg("Database::findConnection | ");
- msg += asString();
- msg += " | Conexion: ";
- msg += name;
- msg += " | Unregistered";
- throw RuntimeException(msg, ANNA_FILE_LOCATION);
- }
-
- if(result->isAvailable() == false || result->isEnabled() == false) {
- string msg("Database::findConnection | ");
- msg += asString();
- msg += " | Connection: ";
- msg += name;
- msg += " | Unavailable";
- throw RuntimeException(msg, ANNA_FILE_LOCATION);
- }
-
- LOGDEBUG(
- string msg("Database::findConnection | ");
- msg += result->asString();
- Logger::debug(msg, ANNA_FILE_LOCATION);
- );
- return *result;
-}
-
-Statement* Database::createStatement(const char* name, const char* expression, const bool isCritical)
-throw(RuntimeException) {
- if(findStatement(name) != NULL)
- throw RuntimeException(functions::asString("Sentence: %s | Name already in use", name), ANNA_FILE_LOCATION);
-
- Guard guard(this, "dbms::Database::createStatement");
-
- if(a_statementTranslator != NULL)
- expression = a_statementTranslator->apply(expression);
-
- Statement* result = allocateStatement(name, expression, isCritical);
- LOGDEBUG(
- string msg("dbms::Database::createStatement | ");
- msg += result->asString();
-
- if(a_statementTranslator != NULL) {
- msg += " | Translator: ";
- msg += a_statementTranslator->getName();
- }
- Logger::debug(msg, ANNA_FILE_LOCATION);
- );
- a_statements.push_back(result);
- return result;
-}
-
-Statement* Database::findStatement(const char* name)
-throw() {
- Guard guard(this, "dbms::Database::findStatement");
- vector <Statement*>::iterator ii, maxii;
- Statement* result(NULL);
-
- for(ii = a_statements.begin(), maxii = a_statements.end(); ii != maxii; ii ++) {
- if(anna_strcmp((*ii)->getName().c_str(), name) == 0) {
- result = *ii;
- break;
- }
- }
-
- return result;
-}
-
-void Database::releaseStatement(Statement* statement)
-throw() {
- if(statement == NULL) {
- Logger::write(Logger::Warning, asString(), "Cannot release a NULL SQL sentence", ANNA_FILE_LOCATION);
- return;
- }
-
- LOGDEBUG(
- string msg("dbms::Database::releaseStatement | ");
- msg += statement->asString();
- Logger::debug(msg, ANNA_FILE_LOCATION);
- );
- Guard guard(this, "dbms::Database::releaseStatement");
- vector <Statement*>::iterator end = a_statements.end();
- vector <Statement*>::iterator ii = find(a_statements.begin(), end, statement);
-
- if(ii != end) {
- a_statements.erase(ii);
- delete statement;
- }
-}
-
-void Database::recover(Connection& connection, const int tryCounter)
-throw(RuntimeException) {
- try {
- connection.close();
- connection.open();
- } catch(DatabaseException& edbms) {
- edbms.trace();
-
- if(a_failRecoveryHandler != NULL)
- a_failRecoveryHandler->apply(connection, tryCounter);
- }
-}
-
-string Database::asString() const
-throw() {
- string result("dbms::Database { ");
- result += Component::asString();
-
- if(a_type == Type::Local)
- result += " | Type: Local";
- else {
- result += " | Type: Remote | Name: ";
- result += a_name;
- }
-
- return result += " }";
-}
-
-xml::Node* Database::asXML(xml::Node* parent) const
-throw() {
- parent = Component::asXML(parent);
- xml::Node* result = parent->createChild("dbms.Database");
- xml::Node* node;
- result->createAttribute("Type", (a_type == Type::Local) ? "Local" : "Remote");
-
- if(a_type != Type::Local)
- result->createAttribute("Name", a_name);
-
- if(a_statementTranslator != NULL)
- result->createAttribute("Translator", a_statementTranslator->getName());
-
- node = result-> createChild("Connections");
-
- for(const_connection_iterator ii = connection_begin(), maxii = connection_end(); ii != maxii; ii ++)
- connection(ii)->asXML(node);
-
- node = result-> createChild("Statements");
-
- for(const_statement_iterator ii = statement_begin(), maxii = statement_end(); ii != maxii; ii ++)
- statement(ii)->asXML(node);
-
- return result;
-}
-