diff options
Diffstat (limited to 'rasodmg/transaction.cc')
-rw-r--r-- | rasodmg/transaction.cc | 377 |
1 files changed, 377 insertions, 0 deletions
diff --git a/rasodmg/transaction.cc b/rasodmg/transaction.cc new file mode 100644 index 0000000..792b8d9 --- /dev/null +++ b/rasodmg/transaction.cc @@ -0,0 +1,377 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * SOURCE: transaction.cc + * + * MODULE: rasodmg + * CLASS: r_Transaction + * + * COMMENTS: + * None +*/ + +static const char rcsid[] = "@(#)rasodmg, r_Transaction: $Id: transaction.cc,v 1.38 2005/09/03 20:39:35 rasdev Exp $"; + + +#ifdef __VISUALC__ + #ifndef __EXECUTABLE__ + #define __EXECUTABLE__ + #define TRANSACTION_NOT_SET + #endif +#endif + +#include "rasodmg/transaction.hh" +#include "rasodmg/database.hh" + +#include "raslib/rmdebug.hh" +#include "raslib/scalar.hh" +#include "clientcomm/clientcomm.hh" + +#ifdef __VISUALC__ + #ifdef TRANSACTION_NOT_SET + #undef __EXECUTABLE__ + #endif + + template class r_Set< r_Ref<r_Object> >; +#endif + +#include <iostream> + +// Initially there is no transaction active. +r_Transaction* r_Transaction::actual_transaction = 0; + + + +r_Transaction::r_Transaction() + : ta_state( inactive ), ta_mode( read_write ) +{ +} + + + +r_Transaction::~r_Transaction() +{ + if( ta_state == active ) + abort(); +} + + + +void +r_Transaction::begin( r_Transaction::r_TAMode mode ) throw( r_Error ) +{ + // check if no other transaction is running + if( ta_state != inactive || actual_transaction ) + { + r_Error err = r_Error( r_Error::r_Error_TransactionOpen ); + throw err; + } + + // check if a database is opened + if( r_Database::actual_database == 0 ) + { + r_Error err = r_Error( r_Error::r_Error_DatabaseClosed ); + throw err; + } + + ta_state = active; + + // if a database is opened, a communication object is existing + //r_Database::actual_database->communication->openTA( mode == read_only ? 1 : 0 ); + r_Database::actual_database->getComm()->openTA( mode == read_only ? 1 : 0 ); + + actual_transaction = this; + ta_mode = mode; +} + + + +void +r_Transaction::commit() throw( r_Error ) +{ + if( ta_state != active ) + { + throw( new r_Error( r_Error::r_Error_TransactionNotOpen ) ); + } + else + { + RMInit::logOut << std::endl << "Commit Log:" << std::endl; + + // + // Commit list of r_Object references. + // + + r_Iterator< r_Ref<r_Object> > iter = object_list.create_iterator(); + + for( iter.reset(); iter.not_done(); iter++ ) + { + if( (*iter)->get_oid().is_valid() ) + { + RMInit::logOut << " Object " << (*iter)->get_oid() << " " << std::flush; + + switch( (*iter)->get_status() ) + { + case r_Object::deleted: + RMInit::logOut << "state DELETED, deleting ... " << std::flush; + (*iter)->r_Object::delete_obj_from_db(); + RMInit::logOut << "OK" << std::endl; + break; + + case r_Object::created: + RMInit::logOut << "state CREATED, writing ... " << std::flush; + (*iter)->insert_obj_into_db(); + RMInit::logOut << "OK" << std::endl; + break; + + case r_Object::modified: + RMInit::logOut << "state MODIFIED, modifying ... " << std::endl; + (*iter)->update_obj_in_db(); + break; + + case r_Object::read: + RMInit::logOut << "state READ, OK" << std::endl; + break; + + case r_Object::transient: + RMInit::logOut << "state TRANSIENT, OK" << std::endl; + break; + + default: + RMInit::logOut << "state UNKNOWN" << std::endl; + break; + } + } + else + RMInit::logOut << " Object with no oid, state TRANSIENT query result" << std::endl; + } + + // Don't do the r_deactivate() in the first loop because if a collection is not + // before its elements in the list, it tries to save non existing objects. + + for( iter.reset(); iter.not_done(); iter++ ) + { + if( !(*iter)->test_status( r_Object::deleted ) ) + (*iter)->r_deactivate(); + + (*iter)->r_Object::r_deactivate(); + + free( (*iter).get_memory_ptr() ); + } + + object_list.remove_all(); + + // + // Commit list of non-r_Object references. + // + + r_Iterator< GenRefElement* > iter2 = non_object_list.create_iterator(); + + for( iter2.reset(); iter2.not_done(); iter2++ ) + { + RMInit::logOut << " Value " << std::flush; + + switch( (*iter2)->type ) + { + case POINT: + RMInit::logOut << "transient Point DELETED" << std::endl; + delete ((r_Point*)(*iter2)->ref); + break; + + case SINTERVAL: + RMInit::logOut << "transient Sinterval DELETED" << std::endl; + delete ((r_Sinterval*)(*iter2)->ref); + break; + + case MINTERVAL: + RMInit::logOut << "transient Minterval DELETED" << std::endl; + delete ((r_Minterval*)(*iter2)->ref); + break; + + case OID: + RMInit::logOut << "transient OId DELETED" << std::endl; + delete ((r_OId*)(*iter2)->ref); + break; + + default: + RMInit::logOut << "transient Scalar DELETED" << std::endl; + delete ((r_Scalar*)(*iter2)->ref); + break; + } + + delete *iter2; + } + + non_object_list.remove_all(); + + + // + // commit transaction on the server + // + +// r_Database::actual_database->communication->commitTA(); + r_Database::actual_database->getComm()->commitTA(); + + ta_state = inactive; + actual_transaction = 0; + } +} + + + +void +r_Transaction::abort() +{ + if( ta_state != active ) + { + throw( r_Error( r_Error::r_Error_TransactionNotOpen ) ); + } + else + { + RMInit::logOut << std::endl << "Abort Log:" << std::endl; + + // + // Abort list of r_Object references. + // + + r_Iterator< r_Ref<r_Object> > iter = object_list.create_iterator(); + + for( iter.reset(); iter.not_done(); iter++ ) + { + RMInit::logOut << " Object DELETED" << std::endl; + + if( !(*iter)->test_status( r_Object::deleted ) ) + (*iter)->r_deactivate(); + + (*iter)->r_Object::r_deactivate(); + + free( (*iter).get_memory_ptr() ); + } + + object_list.remove_all(); + + // + // Abort list of non-r_Object references. + // + + r_Iterator< GenRefElement* > iter2 = non_object_list.create_iterator(); + + for( iter2.reset(); iter2.not_done(); iter2++ ) + { + switch( (*iter2)->type ) + { + case POINT: + RMInit::logOut << " Transient Point DELETED" << std::endl; + delete ((r_Point*)(*iter2)->ref); + break; + + case SINTERVAL: + RMInit::logOut << " Transient Sinterval DELETED" << std::endl; + delete ((r_Sinterval*)(*iter2)->ref); + break; + + case MINTERVAL: + RMInit::logOut << " Transient Minterval DELETED" << std::endl; + delete ((r_Minterval*)(*iter2)->ref); + break; + + case OID: + RMInit::logOut << " Transient OId DELETED" << std::endl; + delete ((r_OId*)(*iter2)->ref); + break; + + default: + RMInit::logOut << " Transient Scalar DELETED" << std::endl; + delete ((r_Scalar*)(*iter2)->ref); + break; + } + + delete *iter2; + } + + non_object_list.remove_all(); + + // + // Abort transaction on the server. + // + if (r_Database::actual_database) +// r_Database::actual_database->communication->abortTA(); + r_Database::actual_database->getComm()->abortTA(); + else + RMInit::logOut << " Database was already closed. Please abort every transaction before closing the database. Please also check for any try/catches with a close database but without transaction abort." << std::endl; + + ta_state = inactive; + actual_transaction = 0; + } +} + + + +r_Ref_Any +r_Transaction::load_object( const r_OId& oid ) +{ + // check, if object is already loaded + unsigned int found = 0; + r_Iterator< r_Ref<r_Object> > iter = object_list.create_iterator(); + + iter.reset(); + while( iter.not_done() && !found ) + { + found = ( (*iter)->get_oid() == oid ); + if( !found ) iter++; + } + + if( found ) + { + // return reference of loaded object + RMDBGONCE(4, RMDebug::module_rasodmg, "r_Transaction", "load_object( oid ) - object already loaded") + return *iter; + } + else + { + // load object and return reference + RMDBGONCE(4, RMDebug::module_rasodmg, "r_Transaction", "load_object( oid ) - load object") + return r_Database::actual_database->lookup_object( oid ); + } +} + + + +void +r_Transaction::add_object_list( const r_Ref<r_Object> &obj ) +{ + object_list.insert_element( obj ); +} + + + +void +r_Transaction::add_object_list( GenRefType type, void* ref ) +{ + GenRefElement* element = new GenRefElement; + + element->type = type; + element->ref = ref; + + non_object_list.insert_element( element ); +} + |