1 // ANNA - Anna is Not Nothingness Anymore //
3 // (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo //
5 // See project site at http://redmine.teslayout.com/projects/anna-suite //
6 // See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE //
9 #include <anna/config/defines.hpp>
10 #include <anna/core/tracing/TraceMethod.hpp>
12 #include <anna/xml/Node.hpp>
13 #include <anna/xml/Attribute.hpp>
15 #include <anna/dbms/Connection.hpp>
16 #include <anna/dbms/Database.hpp>
17 #include <anna/dbms/Statement.hpp>
18 #include <anna/dbms/Statement.hpp>
23 //-----------------------------------------------------------------------------------------------------------
24 // (1) Si no tiene variables de salida => consideramos que es un update, insert o delete.
25 //-----------------------------------------------------------------------------------------------------------
26 dbms::ResultCode dbms::Connection::execute(Statement* statement)
27 throw(RuntimeException, dbms::DatabaseException) {
28 if(statement == NULL) {
29 string msg(asString());
30 msg += " | Cannot execute a NULL sentence";
31 throw RuntimeException(msg, ANNA_FILE_LOCATION);
34 LOGMETHOD(TraceMethod ttmm("dbms::Connection", "execute", ANNA_FILE_LOCATION));
36 string msg("Using Connection | ");
38 Logger::debug(msg, ANNA_FILE_LOCATION)
40 Guard guard(statement, "Statement from dbms::Connection::execute");
41 const Microsecond init = functions::hardwareClock();
43 if(statement->a_prepared == false) {
44 statement->prepare(this);
45 statement->a_prepared = true;
49 string msg("dbms::Connection::execute | ");
50 msg += statement->asString();
51 Logger::debug(msg, ANNA_FILE_LOCATION);
54 if(statement->requiresCommit() == true && a_rollbackPending == true) { // (1)
55 string msg("dbms::Connection::execute | ");
57 msg += " | Connection has pending ROLLBACKS for execution";
58 throw RuntimeException(msg, ANNA_FILE_LOCATION);
65 result = statement->execute(this);
67 if(result.lostConnection() == false)
70 string msg = asString();
72 msg += statement->asString();
74 msg += result.asString();
75 Logger::alert(msg, ANNA_FILE_LOCATION);
76 a_database.recover(*this, ++ tryCounter);
79 statement->measureTiming(init, functions::hardwareClock());
81 if(result.successful() == false && result.notFound() == false) {
82 string msg(asString());
83 msg += " | Sentence: ";
84 msg += statement->getName();
85 Logger::write(Logger::Error, msg, result.asString(), ANNA_FILE_LOCATION);
88 if(statement->requiresCommit() == true) { // (1)
89 if(result.successful() == false) {
90 if(statement->isCritical() == true) {
91 a_rollbackPending = true;
92 throw DatabaseException(statement->getName(), result, ANNA_FILE_LOCATION);
97 if(a_maxCommitPending > 0 && a_commitPending > a_maxCommitPending) {
100 a_rollbackPending = false;
108 //------------------------------------------------------------------------------------------------
109 // (1) Esto no es estrictamente necesario, pero lo hacemos para que no nos despisten las trazas
110 // y los volcados de contexto.
111 //------------------------------------------------------------------------------------------------
112 void dbms::Connection::commit()
113 throw(RuntimeException, dbms::DatabaseException) {
115 string msg("dbms::Connection::commit | ");
117 Logger::information(msg, ANNA_FILE_LOCATION);
120 if(isAvailable() == false) {
121 string msg(asString());
122 msg += " | Unavailable connection";
123 throw RuntimeException(msg, ANNA_FILE_LOCATION);
127 a_commitPending = 0; // (1)
128 a_rollbackPending = false;
131 //------------------------------------------------------------------------------------------------
132 // (1) Esto no es estrictamente necesario, pero lo hacemos para que no nos despisten las trazas
133 // y los volcados de contexto.
134 //------------------------------------------------------------------------------------------------
135 void dbms::Connection::rollback()
138 string msg("dbms::Connection::rollback | ");
140 Logger::warning(msg, ANNA_FILE_LOCATION);
143 if(isAvailable() == false) {
144 string msg(asString());
145 msg += " | Unavailable connection";
146 throw RuntimeException(msg, ANNA_FILE_LOCATION);
151 a_rollbackPending = false; // (1)
154 void dbms::Connection::lock()
155 throw(RuntimeException) {
156 if(isAvailable() == false) {
157 string msg(asString());
158 msg += " | Unavailable connection";
159 throw RuntimeException(msg, ANNA_FILE_LOCATION);
162 comm::Resource::lock();
164 if(a_lockingCounter ++ == 0) {
166 a_rollbackPending = false;
169 if(do_beginTransaction() == true)
171 } catch(dbms::DatabaseException& edb) {
172 throw RuntimeException(edb);
177 string msg("dbms::Connection::lock | ");
179 Logger::debug(msg, ANNA_FILE_LOCATION)
183 void dbms::Connection::unlock()
186 string msg("dbms::Connection::unlock | ");
188 Logger::debug(msg, ANNA_FILE_LOCATION)
191 if(-- a_lockingCounter <= 0) {
192 a_lockingCounter = 0;
195 if(a_rollbackPending == true)
197 else if(a_commitPending > 0)
199 } catch(Exception& ex) {
200 Logger::emergency(ex.getText(), ex.getFromFile(), ex.getFromLine());
204 comm::Resource::unlock();
207 string dbms::Connection::asString() const
209 string result("dbms::Connection { ");
210 result += comm::Resource::asString();
212 result += a_database.asString();
213 result += " | user: ";
215 result += functions::asText(" | LockingCounter: ", a_lockingCounter);
216 result += functions::asText(" | password: ******* | CommitPending: ", a_commitPending);
217 result += functions::asText(" | RollbackPending: ", a_rollbackPending);
218 return result += " }";
221 xml::Node* dbms::Connection::asXML(xml::Node* parent) const
223 xml::Node* result = comm::Resource::asXML(parent);
224 result->createAttribute("User", a_user);
225 result->createAttribute("LockingCounter", a_lockingCounter);
226 result->createAttribute("CommitPending", a_commitPending);
227 result->createAttribute("RollbackPending", functions::asString(a_rollbackPending));