00001 #include "CondCore/ORA/interface/Database.h"
00002 #include "CondCore/ORA/interface/Transaction.h"
00003 #include "CondCore/ORA/interface/Exception.h"
00004 #include "CondCore/ORA/interface/Handle.h"
00005 #include "DatabaseSession.h"
00006 #include "DatabaseContainer.h"
00007 #include "TransactionCache.h"
00008 #include "ContainerSchema.h"
00009 #include "IDatabaseSchema.h"
00010 #include "ClassUtils.h"
00011
00012 namespace ora {
00013
00014 class DatabaseImpl {
00015 public:
00016 DatabaseImpl():
00017 m_session(0),
00018 m_transaction(0){
00019 m_session.reset( new DatabaseSession );
00020 m_transaction.reset( new Transaction( *m_session ));
00021 }
00022
00023 DatabaseImpl(boost::shared_ptr<ConnectionPool>& connectionPool):
00024 m_session(0),
00025 m_transaction(0){
00026 m_session.reset( new DatabaseSession( connectionPool ) );
00027 m_transaction.reset( new Transaction( *m_session )) ;
00028 }
00029
00030 ~DatabaseImpl(){
00031 }
00032
00033 std::auto_ptr<DatabaseSession> m_session;
00034 std::auto_ptr<Transaction> m_transaction;
00035 };
00036
00037 std::string nameFromClass( const Reflex::Type& contType ){
00038 return contType.Name( Reflex::SCOPED );
00039 }
00040
00041 Container getContainerFromSession( const std::string& name, const Reflex::Type& contType, DatabaseSession& session ){
00042 Handle<DatabaseContainer> contHandle = session.containerHandle( name );
00043 if( !contHandle ){
00044 if( session.configuration().properties().getFlag( Configuration::automaticDatabaseCreation()) ||
00045 session.configuration().properties().getFlag( Configuration::automaticContainerCreation() ) ){
00046 contHandle = session.createContainer( name, contType );
00047 } else {
00048 throwException("Container \""+name+"\" does not exist in the database.",
00049 "Database::insertItem");
00050 }
00051 }
00052
00053 return Container( contHandle );
00054 }
00055 }
00056
00057 std::string ora::Database::nameForContainer( const std::type_info& typeInfo ){
00058 Reflex::Type contType = ClassUtils::lookupDictionary( typeInfo );
00059 return nameFromClass( contType );
00060 }
00061
00062 std::string ora::Database::nameForContainer( const std::string& className ){
00063 return className;
00064 }
00065
00066 ora::Database::Database():
00067 m_impl( new DatabaseImpl ){
00068 }
00069
00070 ora::Database::Database( const Database& rhs ):
00071 m_impl( rhs.m_impl ){
00072 }
00073
00074 ora::Database::Database(boost::shared_ptr<ConnectionPool>& connectionPool):
00075 m_impl( new DatabaseImpl( connectionPool) ){
00076 }
00077
00078 ora::Database::~Database(){
00079 disconnect();
00080 }
00081
00082 ora::Database& ora::Database::operator=( const Database& rhs ){
00083 if( this != &rhs ) m_impl = rhs.m_impl;
00084 return *this;
00085 }
00086
00087 ora::Configuration& ora::Database::configuration(){
00088 return m_impl->m_session->configuration();
00089 }
00090
00091 bool ora::Database::connect( const std::string& connectionString,
00092 bool readOnly ){
00093 return m_impl->m_session->connect( connectionString, readOnly );
00094 }
00095
00096 bool ora::Database::connect( const std::string& connectionString,
00097 const std::string& asRole,
00098 bool readOnly ){
00099 return m_impl->m_session->connect( connectionString, asRole, readOnly );
00100 }
00101
00102 void ora::Database::disconnect(){
00103 m_impl->m_session->disconnect();
00104 }
00105
00106 bool ora::Database::isConnected() {
00107 return m_impl->m_session->isConnected();
00108 }
00109
00110 const std::string& ora::Database::connectionString() {
00111 return m_impl->m_session->connectionString();
00112 }
00113
00114 ora::Transaction& ora::Database::transaction(){
00115 if(!m_impl->m_session->isConnected()) {
00116 throwException("No database storage connected.","Database::transaction");
00117 }
00118 return *m_impl->m_transaction;
00119 }
00120
00121 void ora::Database::checkTransaction(){
00122 if(!m_impl->m_session->isConnected()) {
00123 throwException("No database storage connected.","Database::checkTransaction");
00124 }
00125 if(!m_impl->m_transaction->isActive()) {
00126 throwException("Transaction is not active.","Database::checkTransaction");
00127 }
00128 }
00129
00130 bool ora::Database::exists(){
00131 checkTransaction();
00132 return m_impl->m_session->exists();
00133 }
00134
00135 bool ora::Database::create( std::string userSchemaVersion ){
00136 bool created = false;
00137 if( !exists()){
00138 m_impl->m_session->create( userSchemaVersion );
00139 created = true;
00140 }
00141 return created;
00142 }
00143
00144 bool ora::Database::drop(){
00145 bool dropped = false;
00146 if( exists()){
00147 open();
00148 const std::map<int, Handle<DatabaseContainer> >& conts = m_impl->m_session->containers();
00149 for(std::map<int, Handle<DatabaseContainer> >::const_iterator iC = conts.begin();
00150 iC != conts.end(); iC++ ){
00151 iC->second->drop();
00152 }
00153 m_impl->m_session->drop();
00154 dropped = true;
00155 }
00156 return dropped;
00157 }
00158
00159 void ora::Database::setAccessPermission( const std::string& principal, bool forWrite ){
00160 if( exists()){
00161 open();
00162 m_impl->m_session->setAccessPermission( principal, forWrite );
00163 const std::map<int, Handle<DatabaseContainer> >& conts = m_impl->m_session->containers();
00164 for(std::map<int, Handle<DatabaseContainer> >::const_iterator iC = conts.begin();
00165 iC != conts.end(); iC++ ){
00166 iC->second->setAccessPermission( principal, forWrite );
00167 }
00168 }
00169 }
00170
00171 void ora::Database::open( bool writingAccess ){
00172 checkTransaction();
00173 if( !m_impl->m_session->exists() ){
00174 if( writingAccess && m_impl->m_session->configuration().properties().getFlag( Configuration::automaticDatabaseCreation() ) ){
00175 m_impl->m_session->create();
00176 } else {
00177 throwException("Database does not exists in \""+m_impl->m_session->connectionString()+"\"","Database::open");
00178 }
00179 }
00180 m_impl->m_session->open();
00181 }
00182
00183 ora::Version ora::Database::schemaVersion( bool userSchema ){
00184 checkTransaction();
00185 if( !m_impl->m_session->exists() ){
00186 throwException("Database does not exists in \""+m_impl->m_session->connectionString()+"\"","Database::schemaVersion");
00187 }
00188 return Version::fromString( m_impl->m_session->schemaVersion( userSchema ) );
00189 }
00190
00191 std::set< std::string > ora::Database::containers() {
00192 open();
00193 std::set< std::string > contList;
00194 const std::map<int, Handle<DatabaseContainer> >& conts = m_impl->m_session->containers();
00195 for(std::map<int, Handle<DatabaseContainer> >::const_iterator iC = conts.begin();
00196 iC != conts.end(); iC++ ){
00197 contList.insert( iC->second->name() );
00198 }
00199 return contList;
00200 }
00201
00202 ora::Container ora::Database::createContainer( const std::string& name,
00203 const std::type_info& typeInfo ){
00204 open( true );
00205 if( m_impl->m_session->containerHandle( name ) ){
00206 throwException("Container with name \""+name+"\" already exists in the database.",
00207 "Database::createContainer");
00208 }
00209 Reflex::Type contType = ClassUtils::lookupDictionary( typeInfo );
00210 Handle<DatabaseContainer> cont = m_impl->m_session->createContainer( name, contType );
00211 return Container( cont );
00212 }
00213
00214 ora::Container ora::Database::createContainer( const std::type_info& typeInfo ){
00215 open( true );
00216 Reflex::Type contType = ClassUtils::lookupDictionary( typeInfo );
00217 std::string name = nameFromClass( contType );
00218 if( m_impl->m_session->containerHandle( name ) ){
00219 throwException("Container with name \""+name+"\" already exists in the database.",
00220 "Database::createContainer");
00221 }
00222 Handle<DatabaseContainer> cont = m_impl->m_session->createContainer( name, contType );
00223 return Container( cont );
00224 }
00225
00226 ora::Container ora::Database::createContainer( const std::string& className,
00227 std::string name ){
00228 open( true );
00229 Reflex::Type contType = ClassUtils::lookupDictionary( className );
00230 if( name.empty() ) name = nameForContainer( className );
00231 if( m_impl->m_session->containerHandle( name ) ){
00232 throwException("Container with name \""+name+"\" already exists in the database.",
00233 "Database::createContainer");
00234 }
00235 Handle<DatabaseContainer> cont = m_impl->m_session->createContainer( name, contType );
00236 return Container( cont );
00237 }
00238
00239 ora::Container ora::Database::getContainer( const std::string& containerName,
00240 const std::type_info& typeInfo){
00241 open( true );
00242 Reflex::Type objType = ClassUtils::lookupDictionary( typeInfo );
00243 return getContainerFromSession( containerName, objType, *m_impl->m_session );
00244 }
00245
00246 ora::Container ora::Database::getContainer( const std::type_info& typeInfo ){
00247 open( true );
00248 Reflex::Type objType = ClassUtils::lookupDictionary( typeInfo );
00249 std::string contName = nameFromClass( objType );
00250 return getContainerFromSession( contName, objType, *m_impl->m_session);
00251 }
00252
00253 bool ora::Database::dropContainer( const std::string& name ){
00254 open();
00255 if( !m_impl->m_session->containerHandle( name ) ){
00256 return false;
00257 }
00258 m_impl->m_session->dropContainer( name );
00259 return true;
00260 }
00261
00262 bool ora::Database::lockContainer( const std::string& name ){
00263 open();
00264 Handle<DatabaseContainer> cont = m_impl->m_session->containerHandle( name );
00265 if( !cont ){
00266 throwException("Container \""+name+"\" does not exist in the database.",
00267 "Database::lockContainer");
00268 }
00269 return cont->lock();
00270 }
00271
00272 ora::Container ora::Database::containerHandle( const std::string& name ){
00273 open();
00274 Handle<DatabaseContainer> cont = m_impl->m_session->containerHandle( name );
00275 if( !cont ){
00276 throwException("Container \""+name+"\" does not exist in the database.",
00277 "Database::containerHandle");
00278 }
00279 return Container( cont );
00280 }
00281
00282 ora::Container ora::Database::containerHandle( int contId ){
00283 open();
00284 Handle<DatabaseContainer> cont = m_impl->m_session->containerHandle( contId );
00285 if( !cont ){
00286 std::stringstream messg;
00287 messg << "Container with id=" << contId << " not found in the database.";
00288 throwException(messg.str(),
00289 "Database::containerHandle");
00290 }
00291 return Container( cont );
00292 }
00293
00294 ora::Object ora::Database::fetchItem(const OId& oid){
00295 Container cont = containerHandle( oid.containerId() );
00296 return cont.fetchItem( oid.itemId() );
00297 }
00298
00299 ora::OId ora::Database::insertItem(const std::string& containerName,
00300 const Object& dataObject ){
00301 open( true );
00302 Container cont = getContainerFromSession( containerName, dataObject.type(), *m_impl->m_session );
00303 int itemId = cont.insertItem( dataObject );
00304 return OId( cont.id(), itemId );
00305 }
00306
00307 void ora::Database::updateItem(const OId& oid,
00308 const Object& dataObject ){
00309 open();
00310 Container cont = containerHandle( oid.containerId() );
00311 cont.updateItem( oid.itemId(), dataObject );
00312 }
00313
00314 void ora::Database::erase(const OId& oid){
00315 open();
00316 Container cont = containerHandle( oid.containerId() );
00317 cont.erase( oid.itemId() );
00318 }
00319
00320 void ora::Database::flush(){
00321 open();
00322 const std::map<int,Handle<DatabaseContainer> >& containers = m_impl->m_session->containers();
00323 for( std::map<int,Handle<DatabaseContainer> >::const_iterator iCont = containers.begin();
00324 iCont != containers.end(); ++iCont ){
00325 iCont->second->flush();
00326 }
00327 }
00328
00329 void ora::Database::setObjectName( const std::string& name, const OId& oid ){
00330 open( true );
00331 m_impl->m_session->setObjectName( name, oid.containerId(), oid.itemId() );
00332 }
00333
00334 bool ora::Database::eraseObjectName( const std::string& name ){
00335 open();
00336 return m_impl->m_session->eraseObjectName( name );
00337 }
00338
00339 bool ora::Database::eraseAllNames(){
00340 open();
00341 return m_impl->m_session->eraseAllNames();
00342 }
00343
00344 bool ora::Database::getItemId( const std::string& name, ora::OId& destination ){
00345 open();
00346 return m_impl->m_session->getItemId( name, destination );
00347 }
00348
00349 boost::shared_ptr<void> ora::Database::getTypedObjectByName( const std::string& name, const std::type_info& typeInfo ){
00350 open();
00351 Reflex::Type objType = ClassUtils::lookupDictionary( typeInfo );
00352 return m_impl->m_session->fetchTypedObjectByName( name, objType );
00353 }
00354
00355 ora::Object ora::Database::fetchItemByName( const std::string& name ){
00356 open();
00357 return m_impl->m_session->fetchObjectByName( name );
00358 }
00359
00360 bool ora::Database::getNamesForObject( const ora::OId& oid,
00361 std::vector<std::string>& destination ){
00362 checkTransaction();
00363 if( !m_impl->m_session->exists() ){
00364 throwException("Database does not exists in \""+m_impl->m_session->connectionString()+"\"","Database::getNamesForObject");
00365 }
00366 return m_impl->m_session->getNamesForObject( oid.containerId(), oid.itemId(), destination );
00367 }
00368
00369 bool ora::Database::listObjectNames( std::vector<std::string>& destination ){
00370 checkTransaction();
00371 if( !m_impl->m_session->exists() ){
00372 throwException("Database does not exists in \""+m_impl->m_session->connectionString()+"\"","Database::listObjectNames");
00373 }
00374 return m_impl->m_session->listObjectNames( destination );
00375 }
00376
00377 ora::DatabaseUtility ora::Database::utility(){
00378 checkTransaction();
00379 Handle<DatabaseUtilitySession> utilSession = m_impl->m_session->utility();
00380 return DatabaseUtility( utilSession );
00381 }
00382
00383 ora::SharedSession& ora::Database::storageAccessSession(){
00384 return m_impl->m_session->storageAccessSession();
00385 }
00386