/*
* 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: database.cc
*
* MODULE: rasodmg
* CLASS: r_Database
*
* COMMENTS:
* None
*/
static const char rcsid[] = "@(#)rasodmg, r_Database: $Id: database.cc,v 1.47 2005/09/03 20:39:35 rasdev Exp $";
#ifdef __VISUALC__
#ifndef __EXECUTABLE__
#define __EXECUTABLE__
#define DATABASE_NOT_SET
#endif
#endif
#include "rasodmg/database.hh"
#include "rasodmg/transaction.hh"
#include "clientcomm/clientcomm.hh"
#ifdef DATABASE_NOT_SET
#undef __EXECUTABLE__
#endif
#include
// At the beginning, no database is actually opened.
r_Database* r_Database::actual_database = 0;
r_Database::r_Database()
: db_status( not_open ),
rasmgrName(0),
userName(0),
plainPass(0),
communication(0)
{
}
r_Database::r_Database( const char* name ) throw(r_Error)
: db_status( not_open ),
userName(0),
plainPass(0),
communication(0)
{
if(!name)
{
RMInit::logOut << "Error: null database name." << std::endl;
throw r_Error(r_Error::r_Error_NameInvalid);
}
this->rasmgrName = strdup( name );
}
r_Type*
r_Database::get_type_schema(const char* typeName, type_schema typeType) throw (r_Error)
{
r_Type* retval = 0;
if ((typeName == NULL) || (strlen(typeName) == 0))
throw r_Error(r_Error::r_Error_NameInvalid);
else if ((typeType != COLLECTION ) && (typeType != MARRAY))
throw r_Error(r_Error::r_Error_TypeInvalid);
else if (r_Database::actual_database != NULL)
throw r_Error(r_Error::r_Error_DatabaseClosed);
else if (r_Database::actual_database->get_status() != r_Database::not_open)
throw r_Error(r_Error::r_Error_DatabaseClosed);
else if (r_Transaction::actual_transaction != NULL)
throw r_Error(r_Error::r_Error_TransactionNotOpen);
else if (r_Transaction::actual_transaction->get_status() == r_Transaction::active)
throw r_Error(r_Error::r_Error_TransactionNotOpen);
else
{
ClientComm::r_Type_Type type;
if (typeType == COLLECTION)
type = ClientComm::r_SetType_Type;
else
type = ClientComm::r_MDDType_Type;
char* temp = r_Database::actual_database->communication->getTypeStructure( typeName, type );
retval = r_Type::get_any_type(temp);
delete [] temp;
temp = 0;
}
return retval;
}
r_Database::~r_Database()
{
if( db_status != not_open )
close();
if( rasmgrName )
free( rasmgrName );
if( userName )
free( userName );
if( plainPass )
free( plainPass );
}
void
r_Database::open( const char* database_name, access_status new_status )
throw( r_Error )
{
if( db_status != not_open || actual_database )
{
r_Error err = r_Error(r_Error::r_Error_DatabaseOpen);
throw err;
}
if(!database_name)
{
RMInit::logOut << "r_Database::open(name, new_status) name is null" << std::endl;
throw r_Error(r_Error::r_Error_NameInvalid);
}
// While instantiating the communication object, the first connection to
// the server is established. Any exception is given through to the caller
// of open(...).
try
{
communication = ClientComm::createObject( rasmgrName, rasmgrPort );
if( userName && plainPass )
communication->setUserIdentification( userName, plainPass );
}
catch( ... )
{
if(communication)
delete communication;
throw; // re-throw the exception (r_Error_HostInvalid, r_Error_ServerInvalid)
}
// open database
unsigned int status=0;
try
{
status = communication->openDB( (char*)database_name );
}
catch( ... )
{
if(communication)
delete communication;
throw;
}
if( status )
{
// translate error values into exceptions
r_Error err;
switch( status )
{
case 1:
err = r_Error( r_Error::r_Error_ClientUnknown );
break;
case 2:
err = r_Error( r_Error::r_Error_DatabaseUnknown );
break;
case 3:
err = r_Error( r_Error::r_Error_DatabaseOpen );
break;
case 4:
err = r_Error( r_Error::r_Error_RpcInterfaceIncompatible );
break;
case CONNECTIONCLOSED:
err = r_Error(CONNECTIONCLOSED);
break;
default:
err = r_Error( r_Error::r_Error_General );
}
if(communication)
delete communication;
throw err;
}
actual_database = this;
db_status = new_status;
}
void
r_Database::close()
{
if( db_status != not_open )
{
// if a communication object exists, close and delete it
if( communication )
{
// abort any open TA -- PB 2005-sep-02
// This is quite a hack (borrowed from fastscale.cc):
// Actual transaction is a pointer to this in a TA.
// Since the TA was allocated by the application program
// it should be save to use it like this.
if (r_Transaction::actual_transaction != 0)
{ // make _very_ sure we have sequential evaluation -> nested ifs
if (r_Transaction::actual_transaction->get_status() == r_Transaction::active)
r_Transaction::actual_transaction->abort();
}
communication->closeDB();
delete communication;
communication = 0;
}
db_status = not_open;
actual_database = 0;
}
}
void
r_Database::create( const char* name ) throw( r_Error )
{
// this operation is not supported through this interface; use rasdl
throw( r_Error(803)); // Access denied, no permission
}
void
r_Database::destroy( const char* name ) throw( r_Error )
{
// this operation is not supported through this interface; use rasdl
throw( r_Error(803)); // Access denied, no permission
}
void
r_Database::set_servername( const char* name, int port ) throw (r_Error)
{
//We let the name of the function as it is, but it's about the rasmgr name
if(!name)
{
RMInit::logOut << "r_Database::set_servername(name, port) name is null" << std::endl;
throw r_Error(r_Error::r_Error_NameInvalid);
}
if( rasmgrName)
free( rasmgrName );
rasmgrName = strdup( name );
rasmgrPort = port;
}
void
r_Database::set_useridentification( const char* name, const char *plain_pass ) throw(r_Error)
{
if(!name)
{
RMInit::logOut << "r_Database::set_useridentification(name, plain_pass) name is null" << std::endl;
throw r_Error(r_Error::r_Error_NameInvalid);
}
if(!plain_pass)
{
RMInit::logOut << "r_Database::set_useridentification(name, plain_pass) plain_pass is null" << std::endl;
throw r_Error(r_Error::r_Error_NameInvalid);
}
if (userName)
free(userName);
if (plainPass)
free(plainPass);
userName = strdup( name );
plainPass = strdup( plain_pass );
}
void
r_Database::set_object_name( r_Object &obj, const char* name ) throw(r_Error)
{
obj.set_object_name( name );
}
r_Ref_Any
r_Database::lookup_object( const char* name ) const throw( r_Error )
{
r_Ref_Any returnValue;
if( db_status == not_open )
{
r_Error err = r_Error( r_Error::r_Error_DatabaseClosed );
throw err;
}
if(!name)
{
RMInit::logOut << "r_Database::lookup_object(name) name is null" << std::endl;
throw r_Error(r_Error::r_Error_NameInvalid);
}
if( !r_Transaction::actual_transaction
|| r_Transaction::actual_transaction->get_status() != r_Transaction::active )
{
r_Error err = r_Error( r_Error::r_Error_TransactionNotOpen );
throw err;
}
try
{
// get collection
returnValue = communication->getCollOIdsByName( name );
}
catch( ... )
{
throw; // re-throw the exception
}
return returnValue;
}
r_Ref_Any
r_Database::lookup_object( const r_OId& oid ) const throw( r_Error )
{
r_Ref_Any returnValue;
if( db_status == not_open )
{
r_Error err = r_Error( r_Error::r_Error_DatabaseClosed );
throw err;
}
if( !r_Transaction::actual_transaction
|| r_Transaction::actual_transaction->get_status() != r_Transaction::active )
{
r_Error err = r_Error( r_Error::r_Error_TransactionNotOpen );
throw err;
}
try
{
// determine type of object and get it
if( communication->getObjectType( oid ) == 1 )
returnValue = communication->getMDDByOId( oid );
else
returnValue = communication->getCollOIdsByOId( oid );
}
catch( ... )
{
throw; // re-throw the exception
}
return returnValue;
}
void
r_Database::set_transfer_format( r_Data_Format format, const char *formatParams ) throw( r_Error )
{
unsigned short result;
if ( db_status == not_open )
{
r_Error err = r_Error( r_Error::r_Error_DatabaseClosed );
throw (err);
}
//keeps from crashing in rpc on linux
if (formatParams == 0)
formatParams = "";
result = communication->setTransferFormat(format, formatParams);
switch (result)
{
case 1:
{
r_Error err = r_Error( r_Error::r_Error_ClientUnknown );
throw(err);
}
break;
case 2:
{
r_Error err = r_Error( r_Error::r_Error_FeatureNotSupported );
throw(err);
}
break;
default:
break;
}
}
void
r_Database::set_storage_format( r_Data_Format format, const char *formatParams ) throw( r_Error )
{
unsigned short result;
if ( db_status == not_open )
{
r_Error err( r_Error::r_Error_DatabaseClosed );
throw(err);
}
//keeps from crashing in rpc on linux
if (formatParams == 0)
formatParams = "";
result = communication->setStorageFormat(format, formatParams);
switch (result)
{
case 1:
{
r_Error err( r_Error::r_Error_ClientUnknown );
throw(err);
}
break;
case 2:
{
r_Error err( r_Error::r_Error_FeatureNotSupported );
throw(err);
}
break;
default:
break;
}
}
const r_OId
r_Database::get_new_oid( unsigned short objType ) const throw(r_Error)
{
return communication->getNewOId( objType );
}
void r_Database::insertColl( const char* collName, const char* typeName, const r_OId& oid ) throw( r_Error )
{
communication->insertColl(collName,typeName,oid );
}
void r_Database::removeObjFromColl( const char* name, const r_OId& oid ) throw ( r_Error )
{
communication->removeObjFromColl(name,oid);
}
ClientComm* r_Database::getComm()
{
return communication;
}