/* * 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 . * * Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / rasdaman GmbH. * * For more information please see * or contact Peter Baumann via . / /** * SOURCE: object.cc * * MODULE: rasodmg * CLASS: r_Object * * COMMENTS: * None */ #include "mymalloc/mymalloc.h" static const char rcsid[] = "@(#)rasodmg, r_Object: $Id: object.cc,v 1.37 2002/08/19 14:09:32 schatz Exp $"; #include "raslib/rmdebug.hh" #include "raslib/type.hh" #include "raslib/error.hh" #include "rasodmg/object.hh" #ifdef __VISUALC__ #ifndef __EXECUTABLE__ #define __EXECUTABLE__ #define OBJECT_NOT_SET #endif #endif #include "rasodmg/transaction.hh" #include "rasodmg/database.hh" #include "clientcomm/clientcomm.hh" #ifdef OBJECT_NOT_SET #undef __EXECUTABLE__ #endif #include // At the beginning, next and last object types/status are not specified. r_Object::ObjectStatus r_Object::next_object_status = r_Object::no_status; r_Object::ObjectType r_Object::next_object_type = r_Object::no_object; char* r_Object::next_object_type_name = 0; r_OId r_Object::next_object_oid = r_OId(); r_Object::ObjectType r_Object::last_object_type = r_Object::no_object; r_Object::r_Object() : object_status( next_object_status ), object_name(0), type_name(0), type_structure(0), type_schema(0), oid() { RMDBCLASS( "r_Object", "r_Object()", "rasodmg", __FILE__, __LINE__ ) if( next_object_type_name ) type_name = strdup( next_object_type_name ); if( next_object_type == persistent_object ) RMInit::logOut << "Error: A peristent object is constructed with default constructor." << std::endl; else object_type = transient_object; internal_obj_type = 0; // reset next object type/status r_Object::next_object_type = no_object; r_Object::next_object_status = no_status; r_Object::next_object_type_name = 0; r_Object::next_object_oid = r_OId(); } r_Object::r_Object( unsigned short objType ) throw(r_Error) : object_status( next_object_status ), object_name(0), type_name(0), type_structure(0), type_schema(0), oid() { RMDBCLASS( "r_Object", "r_Object( unsigned short )", "rasodmg", __FILE__, __LINE__ ) if( next_object_type_name ) type_name = strdup( next_object_type_name ); if( next_object_type == persistent_object ) { if( r_Transaction::actual_transaction == 0 ) { RMInit::logOut << "Error: Tried to create a persistent object outside a transaction." << std::endl; throw r_Error(r_Error::r_Error_TransactionNotOpen); } object_type = persistent_object; switch( object_status ) { case created: // In case the object is newly created, get a new oid and assign it to the object. oid = r_Database::actual_database->get_new_oid( objType ); break; case read: case transient: // In case the object is read from db, use the oid stored in next_object_oid. oid = next_object_oid; break; default: RMDBGONCE(0, RMDebug::module_raslib, "r_Object", "r_Object(objType) bad object_status " << object_status); break; } // Add the object to the list of persistent objects in the current transaction. if( oid.is_valid() ) r_Transaction::actual_transaction->add_object_list( r_Ref( oid, this ) ); else r_Transaction::actual_transaction->add_object_list( r_Ref( this ) ); } else object_type = transient_object; internal_obj_type = objType; // reset next object type/status r_Object::next_object_type = no_object; r_Object::next_object_status = no_status; r_Object::next_object_type_name = 0; r_Object::next_object_oid = r_OId(); } /* OBSOLETE r_Object::r_Object( unsigned short objType, const char* name ) throw(r_Error) : object_status( next_object_status ), object_name( strdup(name) ), type_name(0), type_structure(0), type_schema(0), oid() { RMANDEBUGOUT( "r_Object::r_Object( const char* name)" ) if( next_object_type_name ) type_name = strdup( next_object_type_name ); if( next_object_type == persistent_object ) { if( r_Transaction::actual_transaction == 0 ) { RMInit::logOut << "Error: Tried to create a persistent object outside a transaction." << std::endl; throw r_Error(r_Error::r_Error_TransactionNotOpen); } object_type = persistent_object; // get a new oid and assign it to the object // oid = r_Database::actual_database->get_new_oid( objType ); // add the object to the list of persistent objects in the actual transaction r_Transaction::actual_transaction->add_object_list( r_Ref( this ) ); } else object_type = transient_object; // reset next object type/status r_Object::next_object_type = no_object; r_Object::next_object_status = no_status; r_Object::next_object_type_name = 0; r_Object::next_object_oid = r_OId(); } */ r_Object::r_Object( const r_Object& obj, unsigned short objType ) throw(r_Error) : object_status( next_object_status ), object_name(0), type_name(0), type_structure(0), type_schema(0), oid() { RMDBCLASS( "r_Object", "r_Object( const r_Object& )", "rasodmg", __FILE__, __LINE__ ) if( next_object_type_name ) type_name = strdup( next_object_type_name ); if( next_object_type == persistent_object ) { if( r_Transaction::actual_transaction == 0 ) { RMInit::logOut << "Error: Tried to create a persistent object outside a transaction." << std::endl; throw r_Error(r_Error::r_Error_TransactionNotOpen); } object_type = persistent_object; switch( object_status ) { case created: // In case the object is newly created, get a new oid and assign it to the object. oid = r_Database::actual_database->get_new_oid( objType ); break; case read: case transient: // In case the object is read from db, use the oid stored in next_object_oid. oid = next_object_oid; break; default: RMDBGONCE(0, RMDebug::module_raslib, "r_Object", "r_Object(obj, objType) bad object_status " << object_status); break; } // Add the object to the list of persistent objects in the actual transaction. if( oid.is_valid() ) r_Transaction::actual_transaction->add_object_list( r_Ref( oid, this ) ); else r_Transaction::actual_transaction->add_object_list( r_Ref( this ) ); } else object_type = transient_object; internal_obj_type = objType; // reset next object type/status r_Object::next_object_type = no_object; r_Object::next_object_status = no_status; r_Object::next_object_type_name = 0; r_Object::next_object_oid = r_OId(); if( obj.object_name ) object_name = strdup( obj.object_name ); if( obj.type_name && !type_name ) type_name = strdup( obj.type_name ); if( obj.type_structure ) type_structure = strdup( obj.type_structure ); } void r_Object::set_type_schema(const r_Type* tyy) throw (r_Error) { if (type_schema) { RMInit::logOut << "r_Object::set_type_schema(" << tyy->name() << ") this object has already a type" << std::endl; throw r_Error(ILLEGALARGUMENT); } type_schema = tyy->clone(); } /************************************************************* * Method name...: ~r_Object() * * Arguments.....: * none * Return value..: * none * Description...: Destructor. ************************************************************/ r_Object::~r_Object() { RMDBCLASS( "r_Object", "~r_Object()", "rasodmg", __FILE__, __LINE__ ) // Free memory in the transient case. In the persistent case, r_deactivate() // is invoked at the commit/abort point. if( test_type( transient_object ) ) r_deactivate(); object_status = deleted; // store the object type for the delete operator r_Object::last_object_type = object_type; } /************************************************************* * Method name...: r_deactivate() * * Arguments.....: * none * Return value..: * none * Description...: This method is called when the object leaves * the application cache. It frees all dynamic * memory allocated within the class. ************************************************************/ void r_Object::r_deactivate() { RMDBCLASS( "r_Object", "r_deactivate()", "rasodmg", __FILE__, __LINE__ ) if( type_schema ) { delete type_schema; type_schema = 0; } if( object_name ) { free( object_name ); object_name = 0; } if( type_name ) { free( type_name ); type_name = 0; } if( type_structure ) { delete [] type_structure; type_structure = 0; } oid.r_deactivate(); } /************************************************************* * Method name...: operator new( size_t size ) * * Arguments.....: * none * Return value..: * none * Description...: New operator set the next_object_type and * allocates memory for the object. ************************************************************/ void* r_Object::operator new( size_t size ) { RMDBCLASS( "r_Object", "operator new( size_t )", "rasodmg", __FILE__, __LINE__ ) r_Object::next_object_type = transient_object; r_Object::next_object_status = created; r_Object::next_object_type_name = 0; r_Object::next_object_oid = r_OId(); void* a = mymalloc( size ); return a; } /************************************************************* * Method name...: operator new( size_t size, * r_Database *database, * const char* type_name ) * * Arguments.....: * none * Return value..: * none * Description...: New operator set the next_object_type and * allocates memory for the object. ************************************************************/ void* r_Object::operator new( size_t size, r_Database* /*database*/, const char* type_name ) { RMDBCLASS( "r_Object", "operator new( size_t, r_Database, const char* )", "rasodmg", __FILE__, __LINE__ ) r_Object::next_object_type = persistent_object; r_Object::next_object_status = created; r_Object::next_object_type_name = (char*)type_name; r_Object::next_object_oid = r_OId(); void* a = mymalloc( size ); return a; } void* r_Object::operator new( size_t size, const char* type_name ) { RMDBCLASS( "r_Object", "operator new( size_t, const char* )", "rasodmg", __FILE__, __LINE__ ) r_Object::next_object_type = transient_object; r_Object::next_object_status = created; r_Object::next_object_type_name = (char*)type_name; r_Object::next_object_oid = r_OId(); void* a = mymalloc( size ); return a; } /************************************************************* * Method name...: operator delete( void* obj_ptr ) * * Arguments.....: * none * Return value..: * none * Description...: Delete operator. * Transient objects are deleted immediately from * main memory. * Persistent objects have been marked as deleted in * the destructor. Further accesses through a r_Ref raise * an exception. Main memory is freed after the transaction * commits. ************************************************************/ void r_Object::operator delete( void* obj_ptr ) { RMDBCLASS( "r_Object", "operator delete()", "rasodmg", __FILE__, __LINE__ ) if( r_Object::last_object_type == transient_object ) free( obj_ptr ); r_Object::last_object_type = no_object; } /************************************************************* * Method name...: test_status( ObjectStatus status ) * * Arguments.....: * none * Return value..: * none * Description...: Tests if status matches the object status. If so * in returns 1, otherwise 0. ************************************************************/ int r_Object::test_status( ObjectStatus status ) { return ( status == object_status ); } /************************************************************* * Method name...: test_type( ObjectType type ) * * Arguments.....: * none * Return value..: * none * Description...: Tests if type matches the object type. If so * in returns 1, otherwise 0. ************************************************************/ int r_Object::test_type( ObjectType type ) { return ( type == object_type ); } /************************************************************* * Method name...: operator new( size_t size, * r_Database *database, * ObjectStatus status ) * * Arguments.....: * none * Return value..: * none * Description...: New operator set the next_object_type to * persistent object and the next_object_status to the * given status. Memory for the object is allocated. ************************************************************/ void* r_Object::operator new( size_t size, r_Database* /*database*/, ObjectStatus status, const r_OId& oid ) { RMDBCLASS( "r_Object", "operator new( size_t, r_Database, ObjectStatus )", "rasodmg", __FILE__, __LINE__ ) r_Object::next_object_type = persistent_object; r_Object::next_object_status = status; r_Object::next_object_type_name = 0; r_Object::next_object_oid = oid; void* a = mymalloc( size ); return a; } const r_Type* r_Object::get_type_schema() { if( !type_schema ) { // If type structure not known then try to get it from the server if ( (type_structure == NULL) || (strlen(type_structure) == 0) ) { ClientComm::r_Type_Type typeType = (ClientComm::r_Type_Type)0; // we need an open database and an active transaction if ( r_Database::actual_database == NULL ) return NULL; else { if ( r_Database::actual_database->get_status() == r_Database::not_open ) return NULL; } if ( r_Transaction::actual_transaction == NULL) return NULL; else { if ( r_Transaction::actual_transaction->get_status() != r_Transaction::active ) return NULL; } // set the object type and contact the database if the type name is defined. if ( internal_obj_type == 1 ) typeType = ClientComm::r_MDDType_Type; else if ( internal_obj_type == 2 ) typeType = ClientComm::r_SetType_Type; if ( (type_name == NULL) || (strlen(type_name) == 0) || (typeType == 0) ) return NULL; try { type_structure = r_Database::actual_database->getComm()->getTypeStructure( type_name, typeType ); } catch(r_Error& errObj) { RMInit::logOut << "r_Object::get_type_schema() failed retriving typestructure" << std::endl; RMInit::logOut << "Error " << errObj.get_errorno() << " : " << errObj.what() << std::endl; return NULL; } } type_schema = r_Type::get_any_type( type_structure ); } return type_schema; } void r_Object::update_obj_in_db() { RMInit::logOut << " dummy implementation " << std::flush; } void r_Object::load_obj_from_db() { RMInit::logOut << " dummy implementation " << std::flush; } void r_Object::delete_obj_from_db() { RMDBCLASS( "r_Object", "delete_obj_from_db()", "rasodmg", __FILE__, __LINE__ ) if( object_name && strlen( object_name ) ) { RMInit::logOut << object_name << "... " << std::flush; // delete myself from the database r_Database::actual_database->getComm()->deleteCollByName( object_name ); } else { RMInit::logOut << "no name - take oid ... " << std::flush; if( oid.get_local_oid() ) // delete myself from the database r_Database::actual_database->getComm()->deleteObjByOId( oid ); else RMInit::logOut << " no oid ... FAILED" << std::flush; } } void r_Object::initialize_oid( const r_OId& initOId ) { oid = initOId; }