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 void ora::Database::disconnect(){
00097 m_impl->m_session->disconnect();
00098 }
00099
00100 bool ora::Database::isConnected() {
00101 return m_impl->m_session->isConnected();
00102 }
00103
00104 const std::string& ora::Database::connectionString() {
00105 return m_impl->m_session->connectionString();
00106 }
00107
00108 ora::Transaction& ora::Database::transaction(){
00109 if(!m_impl->m_session->isConnected()) {
00110 throwException("No database storage connected.","Database::transaction");
00111 }
00112 return *m_impl->m_transaction;
00113 }
00114
00115 void ora::Database::checkTransaction(){
00116 if(!m_impl->m_session->isConnected()) {
00117 throwException("No database storage connected.","Database::checkTransaction");
00118 }
00119 if(!m_impl->m_transaction->isActive()) {
00120 throwException("Transaction is not active.","Database::checkTransaction");
00121 }
00122 }
00123
00124 bool ora::Database::exists(){
00125 checkTransaction();
00126 return m_impl->m_session->exists();
00127 }
00128
00129 bool ora::Database::create( std::string userSchemaVersion ){
00130 bool created = false;
00131 if( !exists()){
00132 m_impl->m_session->create( userSchemaVersion );
00133 created = true;
00134 }
00135 return created;
00136 }
00137
00138 bool ora::Database::drop(){
00139 bool dropped = false;
00140 if( exists()){
00141 open();
00142 const std::map<int, Handle<DatabaseContainer> >& conts = m_impl->m_session->containers();
00143 for(std::map<int, Handle<DatabaseContainer> >::const_iterator iC = conts.begin();
00144 iC != conts.end(); iC++ ){
00145 iC->second->drop();
00146 }
00147 m_impl->m_session->drop();
00148 dropped = true;
00149 }
00150 return dropped;
00151 }
00152
00153 void ora::Database::setAccessPermission( const std::string& principal, bool forWrite ){
00154 if( exists()){
00155 open();
00156 m_impl->m_session->setAccessPermission( principal, forWrite );
00157 const std::map<int, Handle<DatabaseContainer> >& conts = m_impl->m_session->containers();
00158 for(std::map<int, Handle<DatabaseContainer> >::const_iterator iC = conts.begin();
00159 iC != conts.end(); iC++ ){
00160 iC->second->setAccessPermission( principal, forWrite );
00161 }
00162 }
00163 }
00164
00165 void ora::Database::open( bool writingAccess ){
00166 checkTransaction();
00167 if( !m_impl->m_session->exists() ){
00168 if( writingAccess && m_impl->m_session->configuration().properties().getFlag( Configuration::automaticDatabaseCreation() ) ){
00169 m_impl->m_session->create();
00170 } else {
00171 throwException("Database does not exists in \""+m_impl->m_session->connectionString()+"\"","Database::open");
00172 }
00173 }
00174 m_impl->m_session->open();
00175 }
00176
00177 ora::Version ora::Database::schemaVersion( bool userSchema ){
00178 checkTransaction();
00179 if( !m_impl->m_session->exists() ){
00180 throwException("Database does not exists in \""+m_impl->m_session->connectionString()+"\"","Database::schemaVersion");
00181 }
00182 return Version::fromString( m_impl->m_session->schemaVersion( userSchema ) );
00183 }
00184
00185 std::set< std::string > ora::Database::containers() {
00186 open();
00187 std::set< std::string > contList;
00188 const std::map<int, Handle<DatabaseContainer> >& conts = m_impl->m_session->containers();
00189 for(std::map<int, Handle<DatabaseContainer> >::const_iterator iC = conts.begin();
00190 iC != conts.end(); iC++ ){
00191 contList.insert( iC->second->name() );
00192 }
00193 return contList;
00194 }
00195
00196 ora::Container ora::Database::createContainer( const std::string& name,
00197 const std::type_info& typeInfo ){
00198 open( true );
00199 if( m_impl->m_session->containerHandle( name ) ){
00200 throwException("Container with name \""+name+"\" already exists in the database.",
00201 "Database::createContainer");
00202 }
00203 Reflex::Type contType = ClassUtils::lookupDictionary( typeInfo );
00204 Handle<DatabaseContainer> cont = m_impl->m_session->createContainer( name, contType );
00205 return Container( cont );
00206 }
00207
00208 ora::Container ora::Database::createContainer( const std::type_info& typeInfo ){
00209 open( true );
00210 Reflex::Type contType = ClassUtils::lookupDictionary( typeInfo );
00211 std::string name = nameFromClass( contType );
00212 if( m_impl->m_session->containerHandle( name ) ){
00213 throwException("Container with name \""+name+"\" already exists in the database.",
00214 "Database::createContainer");
00215 }
00216 Handle<DatabaseContainer> cont = m_impl->m_session->createContainer( name, contType );
00217 return Container( cont );
00218 }
00219
00220 ora::Container ora::Database::createContainer( const std::string& className,
00221 std::string name ){
00222 open( true );
00223 Reflex::Type contType = ClassUtils::lookupDictionary( className );
00224 if( name.empty() ) name = nameForContainer( className );
00225 if( m_impl->m_session->containerHandle( name ) ){
00226 throwException("Container with name \""+name+"\" already exists in the database.",
00227 "Database::createContainer");
00228 }
00229 Handle<DatabaseContainer> cont = m_impl->m_session->createContainer( name, contType );
00230 return Container( cont );
00231 }
00232
00233 ora::Container ora::Database::getContainer( const std::string& containerName,
00234 const std::type_info& typeInfo){
00235 open( true );
00236 Reflex::Type objType = ClassUtils::lookupDictionary( typeInfo );
00237 return getContainerFromSession( containerName, objType, *m_impl->m_session );
00238 }
00239
00240 ora::Container ora::Database::getContainer( const std::type_info& typeInfo ){
00241 open( true );
00242 Reflex::Type objType = ClassUtils::lookupDictionary( typeInfo );
00243 std::string contName = nameFromClass( objType );
00244 return getContainerFromSession( contName, objType, *m_impl->m_session);
00245 }
00246
00247 bool ora::Database::dropContainer( const std::string& name ){
00248 open();
00249 if( !m_impl->m_session->containerHandle( name ) ){
00250 return false;
00251 }
00252 m_impl->m_session->dropContainer( name );
00253 return true;
00254 }
00255
00256 bool ora::Database::lockContainer( const std::string& name ){
00257 open();
00258 Handle<DatabaseContainer> cont = m_impl->m_session->containerHandle( name );
00259 if( !cont ){
00260 throwException("Container \""+name+"\" does not exist in the database.",
00261 "Database::lockContainer");
00262 }
00263 return cont->lock();
00264 }
00265
00266 ora::Container ora::Database::containerHandle( const std::string& name ){
00267 open();
00268 Handle<DatabaseContainer> cont = m_impl->m_session->containerHandle( name );
00269 if( !cont ){
00270 throwException("Container \""+name+"\" does not exist in the database.",
00271 "Database::containerHandle");
00272 }
00273 return Container( cont );
00274 }
00275
00276 ora::Container ora::Database::containerHandle( int contId ){
00277 open();
00278 Handle<DatabaseContainer> cont = m_impl->m_session->containerHandle( contId );
00279 if( !cont ){
00280 std::stringstream messg;
00281 messg << "Container with id=" << contId << " not found in the database.";
00282 throwException(messg.str(),
00283 "Database::containerHandle");
00284 }
00285 return Container( cont );
00286 }
00287
00288 ora::Object ora::Database::fetchItem(const OId& oid){
00289 Container cont = containerHandle( oid.containerId() );
00290 return cont.fetchItem( oid.itemId() );
00291 }
00292
00293 ora::OId ora::Database::insertItem(const std::string& containerName,
00294 const Object& dataObject ){
00295 open( true );
00296 Container cont = getContainerFromSession( containerName, dataObject.type(), *m_impl->m_session );
00297 int itemId = cont.insertItem( dataObject );
00298 return OId( cont.id(), itemId );
00299 }
00300
00301 void ora::Database::updateItem(const OId& oid,
00302 const Object& dataObject ){
00303 open();
00304 Container cont = containerHandle( oid.containerId() );
00305 cont.updateItem( oid.itemId(), dataObject );
00306 }
00307
00308 void ora::Database::erase(const OId& oid){
00309 open();
00310 Container cont = containerHandle( oid.containerId() );
00311 cont.erase( oid.itemId() );
00312 }
00313
00314 void ora::Database::flush(){
00315 open();
00316 const std::map<int,Handle<DatabaseContainer> >& containers = m_impl->m_session->containers();
00317 for( std::map<int,Handle<DatabaseContainer> >::const_iterator iCont = containers.begin();
00318 iCont != containers.end(); ++iCont ){
00319 iCont->second->flush();
00320 }
00321 }
00322
00323 void ora::Database::setObjectName( const std::string& name, const OId& oid ){
00324 open( true );
00325 m_impl->m_session->setObjectName( name, oid.containerId(), oid.itemId() );
00326 }
00327
00328 bool ora::Database::eraseObjectName( const std::string& name ){
00329 open();
00330 return m_impl->m_session->eraseObjectName( name );
00331 }
00332
00333 bool ora::Database::eraseAllNames(){
00334 open();
00335 return m_impl->m_session->eraseAllNames();
00336 }
00337
00338 bool ora::Database::getItemId( const std::string& name, ora::OId& destination ){
00339 open();
00340 return m_impl->m_session->getItemId( name, destination );
00341 }
00342
00343 boost::shared_ptr<void> ora::Database::getTypedObjectByName( const std::string& name, const std::type_info& typeInfo ){
00344 open();
00345 Reflex::Type objType = ClassUtils::lookupDictionary( typeInfo );
00346 return m_impl->m_session->fetchTypedObjectByName( name, objType );
00347 }
00348
00349 ora::Object ora::Database::fetchItemByName( const std::string& name ){
00350 open();
00351 return m_impl->m_session->fetchObjectByName( name );
00352 }
00353
00354 bool ora::Database::getNamesForObject( const ora::OId& oid,
00355 std::vector<std::string>& destination ){
00356 open();
00357 return m_impl->m_session->getNamesForObject( oid.containerId(), oid.itemId(), destination );
00358 }
00359
00360 bool ora::Database::listObjectNames( std::vector<std::string>& destination ){
00361 open();
00362 return m_impl->m_session->listObjectNames( destination );
00363 }
00364
00365 ora::DatabaseUtility ora::Database::utility(){
00366 checkTransaction();
00367 Handle<DatabaseUtilitySession> utilSession = m_impl->m_session->utility();
00368 return DatabaseUtility( utilSession );
00369 }
00370
00371 ora::SharedSession& ora::Database::storageAccessSession(){
00372 return m_impl->m_session->storageAccessSession();
00373 }
00374