00001 #include "CondCore/ORA/interface/Exception.h"
00002 #include "CondCore/ORA/interface/Monitoring.h"
00003 #include "DatabaseSession.h"
00004 #include "IDatabaseSchema.h"
00005 #include "Sequences.h"
00006 #include "MappingDatabase.h"
00007 #include "TransactionCache.h"
00008 #include "DatabaseContainer.h"
00009 #include "ClassUtils.h"
00010 #include "MappingRules.h"
00011 #include "DatabaseUtilitySession.h"
00012
00013 #include "RelationalAccess/IConnectionServiceConfiguration.h"
00014 #include "RelationalAccess/ISessionProxy.h"
00015 #include "RelationalAccess/ITransaction.h"
00016
00017 ora::ContainerUpdateTable::ContainerUpdateTable():
00018 m_table(){
00019 }
00020
00021 ora::ContainerUpdateTable::~ContainerUpdateTable(){
00022 }
00023
00024 void ora::ContainerUpdateTable::takeNote( int contId,
00025 unsigned int size ){
00026 std::map<int, unsigned int>::iterator iC = m_table.find( contId );
00027 if( iC == m_table.end() ){
00028 iC = m_table.insert( std::make_pair( contId, 0 ) ).first;
00029 }
00030 iC->second = size;
00031 }
00032
00033 void ora::ContainerUpdateTable::remove( int contId ){
00034 m_table.erase( contId );
00035 }
00036
00037 const std::map<int, unsigned int>& ora::ContainerUpdateTable::table(){
00038 return m_table;
00039 }
00040
00041 void ora::ContainerUpdateTable::clear(){
00042 m_table.clear();
00043 }
00044
00045 ora::DatabaseSession::DatabaseSession():
00046 m_connectionPool( new ConnectionPool ),
00047 m_dbSession(),
00048 m_connectionString( "" ),
00049 m_schema(),
00050 m_contIdSequence(),
00051 m_mappingDb(),
00052 m_transactionCache(),
00053 m_containerUpdateTable(),
00054 m_configuration(),
00055 m_monitoring(0){
00056
00057 m_connectionPool->configuration().setConnectionTimeOut(0);
00058 }
00059
00060 ora::DatabaseSession::DatabaseSession(boost::shared_ptr<ConnectionPool>& connectionPool ):
00061 m_connectionPool( connectionPool ),
00062 m_dbSession(),
00063 m_connectionString( "" ),
00064 m_schema(),
00065 m_contIdSequence(),
00066 m_mappingDb(),
00067 m_transactionCache(),
00068 m_containerUpdateTable(),
00069 m_configuration(),
00070 m_monitoring(0){
00071 }
00072
00073 ora::DatabaseSession::~DatabaseSession(){
00074 disconnect();
00075 }
00076
00077 bool ora::DatabaseSession::connect( const std::string& connectionString,
00078 bool readOnly ){
00079 m_dbSession = m_connectionPool->connect( connectionString, readOnly?coral::ReadOnly:coral::Update );
00080 if(m_dbSession.isValid()) {
00081 m_connectionString = connectionString;
00082 if( ora::Monitoring::isEnabled() ){
00083 m_monitoring = ora::Monitoring::get().startSession( connectionString );
00084 }
00085 }
00086 return isConnected();
00087 }
00088
00089 void ora::DatabaseSession::clearTransaction(){
00090 m_transactionCache.reset();
00091 m_mappingDb.reset();
00092 m_contIdSequence.reset();
00093 m_schema.reset();
00094 m_containerUpdateTable.clear();
00095 }
00096
00097 void ora::DatabaseSession::disconnect(){
00098 if( isConnected() ){
00099 if( isTransactionActive()) rollbackTransaction();
00100 }
00101 clearTransaction();
00102 m_dbSession.close();
00103 m_connectionString.clear();
00104 if(m_monitoring) m_monitoring->stop();
00105 }
00106
00107 bool ora::DatabaseSession::isConnected(){
00108 return m_dbSession.isValid();
00109 }
00110
00111 const std::string& ora::DatabaseSession::connectionString(){
00112 return m_connectionString;
00113 }
00114
00115 void ora::DatabaseSession::startTransaction( bool readOnly ){
00116 if( !m_transactionCache.get() ){
00117 m_dbSession.get().transaction().start( readOnly );
00118 m_schema.reset( IDatabaseSchema::createSchemaHandle( m_dbSession.get().nominalSchema() ));
00119 m_contIdSequence.reset( new NamedSequence( MappingRules::sequenceNameForContainerId(), *m_schema ));
00120 m_mappingDb.reset( new MappingDatabase( *m_schema ));
00121 m_transactionCache.reset( new TransactionCache );
00122 if(m_monitoring) {
00123 m_monitoring->newTransaction();
00124 }
00125 }
00126 }
00127
00128 void ora::DatabaseSession::commitTransaction(){
00129 if( m_transactionCache.get() ){
00130 m_schema->containerHeaderTable().updateNumberOfObjects( m_containerUpdateTable.table() );
00131 m_dbSession.get().transaction().commit();
00132 clearTransaction();
00133 if(m_monitoring) {
00134 m_monitoring->stopTransaction();
00135 }
00136 }
00137 }
00138
00139 void ora::DatabaseSession::rollbackTransaction(){
00140 if( m_transactionCache.get() ){
00141 m_dbSession.get().transaction().rollback();
00142 clearTransaction();
00143 if(m_monitoring) {
00144 m_monitoring->stopTransaction(false);
00145 }
00146 }
00147 }
00148
00149 bool ora::DatabaseSession::isTransactionActive( bool checkIfReadOnly ){
00150 bool ret = false;
00151 if( m_dbSession.get().transaction().isActive() ){
00152 if( checkIfReadOnly ){
00153 if( m_dbSession.get().transaction().isReadOnly() ) ret = true;
00154 } else {
00155 ret = true;
00156 }
00157 }
00158 return ret;
00159 }
00160
00161 bool ora::DatabaseSession::exists(){
00162 if(!m_transactionCache->dbExistsLoaded()){
00163 m_transactionCache->setDbExists( m_schema->exists() );
00164 }
00165 return m_transactionCache->dbExists();
00166 }
00167
00168 void ora::DatabaseSession::create( const std::string& userSchemaVersion ){
00169 m_schema->create( userSchemaVersion );
00170 m_contIdSequence->create();
00171 m_mappingDb->setUp();
00172 m_transactionCache->setDbExists( true );
00173 }
00174
00175 void ora::DatabaseSession::drop(){
00176 if(!testDropPermission()){
00177 throwException("Drop permission has been denied for the current user.",
00178 "DatabaseSession::drop");
00179 }
00180 m_schema->drop();
00181 m_transactionCache->dropDatabase();
00182 }
00183
00184 void ora::DatabaseSession::setAccessPermission( const std::string& principal,
00185 bool forWrite ){
00186 m_schema->setAccessPermission( principal, forWrite );
00187 }
00188
00189 bool ora::DatabaseSession::testDropPermission(){
00190 if(!m_transactionCache->dropPermissionLoaded()){
00191 m_transactionCache->setDropPermission( m_schema->testDropPermission() );
00192 }
00193 return m_transactionCache->dropPermission();
00194 }
00195
00196 void ora::DatabaseSession::open(){
00197 if(!m_transactionCache->isLoaded()){
00198 std::map<std::string, ContainerHeaderData> containersData;
00199 m_schema->containerHeaderTable().getContainerData( containersData );
00200 for(std::map<std::string, ContainerHeaderData>::iterator iC = containersData.begin();
00201 iC != containersData.end(); ++iC){
00202 Handle<DatabaseContainer> container( new DatabaseContainer( iC->second.id, iC->first,
00203 iC->second.className,
00204 iC->second.numberOfObjects, *this ) );
00205 m_transactionCache->addContainer( iC->second.id, iC->first, container );
00206 }
00207 m_schema->mainTable().getParameters( m_transactionCache->dbParams() );
00208 m_transactionCache->setLoaded();
00209 }
00210 }
00211
00212 std::string ora::DatabaseSession::schemaVersion( bool userSchema ){
00213 std::map<std::string,std::string>& params = m_transactionCache->dbParams();
00214 std::string version("");
00215 std::string paramName = IMainTable::versionParameterName();
00216 if(userSchema ) paramName = IMainTable::userSchemaVersionParameterName();
00217 std::map<std::string,std::string>::const_iterator iPar = params.find( paramName );
00218 if( iPar != params.end() ){
00219 version = iPar->second;
00220 }
00221 return version;
00222 }
00223
00224 ora::Handle<ora::DatabaseContainer> ora::DatabaseSession::addContainer( const std::string& containerName,
00225 const std::string& className ){
00226 int newContId = m_contIdSequence->getNextId( true );
00227 m_schema->containerHeaderTable().addContainer( newContId, containerName, className );
00228 Handle<DatabaseContainer> container( new DatabaseContainer( newContId, containerName,
00229 className, 0, *this ) );
00230 m_transactionCache->addContainer( newContId, containerName, container );
00231 return container;
00232 }
00233
00234
00235 ora::Handle<ora::DatabaseContainer> ora::DatabaseSession::createContainer( const std::string& containerName,
00236 const Reflex::Type& type ){
00237
00238 int newContId = m_contIdSequence->getNextId( true );
00239 Handle<DatabaseContainer> newCont ( new DatabaseContainer( newContId, containerName, type, *this ) );
00240 m_transactionCache->addContainer( newContId, containerName, newCont );
00241 newCont->create();
00242 return newCont;
00243 }
00244
00245 void ora::DatabaseSession::dropContainer( const std::string& name ){
00246 Handle<DatabaseContainer> cont = m_transactionCache->getContainer( name );
00247 m_transactionCache->eraseContainer( cont->id(), name );
00248 cont->drop();
00249 }
00250
00251 ora::Handle<ora::DatabaseContainer> ora::DatabaseSession::containerHandle( const std::string& name ){
00252 return m_transactionCache->getContainer( name );
00253 }
00254
00255 ora::Handle<ora::DatabaseContainer> ora::DatabaseSession::containerHandle( int contId ){
00256 return m_transactionCache->getContainer( contId );
00257 }
00258
00259 const std::map<int, ora::Handle<ora::DatabaseContainer> >& ora::DatabaseSession::containers(){
00260 return m_transactionCache->containers();
00261 }
00262
00263 void ora::DatabaseSession::setObjectName( const std::string& name,
00264 int containerId,
00265 int itemId ){
00266 m_schema->namingServiceTable().setObjectName( name, containerId, itemId );
00267 }
00268
00269 bool ora::DatabaseSession::eraseObjectName( const std::string& name ){
00270 return m_schema->namingServiceTable().eraseObjectName( name );
00271 }
00272
00273 bool ora::DatabaseSession::eraseAllNames(){
00274 return m_schema->namingServiceTable().eraseAllNames();
00275 }
00276
00277 ora::Object ora::DatabaseSession::fetchObjectByName( const std::string& name ){
00278 ora::Object ret;
00279 std::pair<int,int> oid;
00280 if( m_schema->namingServiceTable().getObjectByName( name, oid ) ){
00281 ora::Handle<ora::DatabaseContainer> cont = containerHandle( oid.first );
00282 if( cont ) ret = Object( cont->fetchItem( oid.second ), cont->type() );
00283 }
00284 return ret;
00285 }
00286
00287 bool ora::DatabaseSession::getItemId( const std::string& name, ora::OId& destination ){
00288 std::pair<int,int> oidData;
00289 if( m_schema->namingServiceTable().getObjectByName( name, oidData ) ){
00290 destination = OId( oidData.first, oidData.second );
00291 return true;
00292 }
00293 return false;
00294 }
00295
00296 boost::shared_ptr<void> ora::DatabaseSession::fetchTypedObjectByName( const std::string& name,
00297 const Reflex::Type& asType ){
00298 boost::shared_ptr<void> ret = m_transactionCache->getNamedReference( name );
00299 if( !ret.get() ){
00300 std::pair<int,int> oid;
00301 if( m_schema->namingServiceTable().getObjectByName( name, oid ) ){
00302 ora::Handle<ora::DatabaseContainer> cont = containerHandle( oid.first );
00303 void* ptr = 0;
00304 if( cont ) {
00305 ptr = cont->fetchItemAsType( oid.second, asType );
00306 if( ptr) ret = boost::shared_ptr<void>( ptr, RflxDeleter( cont->type() ) );
00307 }
00308 }
00309 if( ret.get() ) m_transactionCache->setNamedReference( name, ret );
00310 }
00311 return ret;
00312 }
00313
00314 bool ora::DatabaseSession::getNamesForContainer( int containerId,
00315 std::vector<std::string>& destination ){
00316 return m_schema->namingServiceTable().getNamesForContainer( containerId, destination );
00317 }
00318
00319 bool ora::DatabaseSession::getNamesForObject( int containerId,
00320 int itemId,
00321 std::vector<std::string>& destination ){
00322 return m_schema->namingServiceTable().getNamesForObject( containerId, itemId, destination );
00323 }
00324
00325 bool ora::DatabaseSession::listObjectNames( std::vector<std::string>& destination ){
00326
00327 return m_schema->namingServiceTable().getAllNames( destination );
00328 }
00329
00330 ora::Handle<ora::DatabaseUtilitySession> ora::DatabaseSession::utility(){
00331 if( !m_transactionCache->utility() ){
00332 Handle<DatabaseUtilitySession> util ( new DatabaseUtilitySession( *this ) );
00333 m_transactionCache->setUtility( util );
00334 }
00335 return m_transactionCache->utility();
00336 }
00337
00338 ora::IDatabaseSchema& ora::DatabaseSession::schema(){
00339 return *m_schema;
00340 }
00341
00342 ora::NamedSequence& ora::DatabaseSession::containerIdSequence(){
00343 return *m_contIdSequence;
00344 }
00345
00346 ora::MappingDatabase& ora::DatabaseSession::mappingDatabase(){
00347 return *m_mappingDb;
00348 }
00349
00350 ora::Configuration& ora::DatabaseSession::configuration(){
00351 return m_configuration;
00352 }
00353
00354 ora::SharedSession& ora::DatabaseSession::storageAccessSession(){
00355 return m_dbSession;
00356 }
00357
00358 boost::shared_ptr<ora::ConnectionPool>& ora::DatabaseSession::connectionPool(){
00359 return m_connectionPool;
00360 }
00361
00362 ora::ContainerUpdateTable& ora::DatabaseSession::containerUpdateTable(){
00363 return m_containerUpdateTable;
00364 }