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(){
00130 bool created = false;
00131 if( !exists()){
00132 m_impl->m_session->create();
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::open( bool writingAccess ){
00154 checkTransaction();
00155 if( !m_impl->m_session->exists() ){
00156 if( writingAccess && m_impl->m_session->configuration().properties().getFlag( Configuration::automaticDatabaseCreation() ) ){
00157 m_impl->m_session->create();
00158 } else {
00159 throwException("Database does not exists in \""+m_impl->m_session->connectionString()+"\"","Database::open");
00160 }
00161 }
00162 m_impl->m_session->open();
00163 }
00164
00165 std::set< std::string > ora::Database::containers() {
00166 open();
00167 std::set< std::string > contList;
00168 const std::map<int, Handle<DatabaseContainer> >& conts = m_impl->m_session->containers();
00169 for(std::map<int, Handle<DatabaseContainer> >::const_iterator iC = conts.begin();
00170 iC != conts.end(); iC++ ){
00171 contList.insert( iC->second->name() );
00172 }
00173 return contList;
00174 }
00175
00176 ora::Container ora::Database::createContainer( const std::string& name,
00177 const std::type_info& typeInfo ){
00178 open( true );
00179 if( m_impl->m_session->containerHandle( name ) ){
00180 throwException("Container with name \""+name+"\" already exists in the database.",
00181 "Database::createContainer");
00182 }
00183 Reflex::Type contType = ClassUtils::lookupDictionary( typeInfo );
00184 Handle<DatabaseContainer> cont = m_impl->m_session->createContainer( name, contType );
00185 return Container( cont );
00186 }
00187
00188 ora::Container ora::Database::createContainer( const std::type_info& typeInfo ){
00189 open( true );
00190 Reflex::Type contType = ClassUtils::lookupDictionary( typeInfo );
00191 std::string name = nameFromClass( contType );
00192 if( m_impl->m_session->containerHandle( name ) ){
00193 throwException("Container with name \""+name+"\" already exists in the database.",
00194 "Database::createContainer");
00195 }
00196 Handle<DatabaseContainer> cont = m_impl->m_session->createContainer( name, contType );
00197 return Container( cont );
00198 }
00199
00200 ora::Container ora::Database::createContainer( const std::string& className,
00201 std::string name ){
00202 open( true );
00203 Reflex::Type contType = ClassUtils::lookupDictionary( className );
00204 if( name.empty() ) name = nameForContainer( className );
00205 if( m_impl->m_session->containerHandle( name ) ){
00206 throwException("Container with name \""+name+"\" already exists in the database.",
00207 "Database::createContainer");
00208 }
00209 Handle<DatabaseContainer> cont = m_impl->m_session->createContainer( name, contType );
00210 return Container( cont );
00211 }
00212
00213 ora::Container ora::Database::getContainer( const std::string& containerName,
00214 const std::type_info& typeInfo){
00215 open( true );
00216 Reflex::Type objType = ClassUtils::lookupDictionary( typeInfo );
00217 return getContainerFromSession( containerName, objType, *m_impl->m_session );
00218 }
00219
00220 ora::Container ora::Database::getContainer( const std::type_info& typeInfo ){
00221 open( true );
00222 Reflex::Type objType = ClassUtils::lookupDictionary( typeInfo );
00223 std::string contName = nameFromClass( objType );
00224 return getContainerFromSession( contName, objType, *m_impl->m_session);
00225 }
00226
00227 bool ora::Database::dropContainer( const std::string& name ){
00228 open();
00229 if( !m_impl->m_session->containerHandle( name ) ){
00230 return false;
00231 }
00232 m_impl->m_session->dropContainer( name );
00233 return true;
00234 }
00235
00236 ora::Container ora::Database::containerHandle( const std::string& name ){
00237 open();
00238 Handle<DatabaseContainer> cont = m_impl->m_session->containerHandle( name );
00239 if( !cont ){
00240 throwException("Container \""+name+"\" does not exist in the database.",
00241 "Database::containerHandle");
00242 }
00243 return Container( cont );
00244 }
00245
00246 ora::Container ora::Database::containerHandle( int contId ){
00247 open();
00248 Handle<DatabaseContainer> cont = m_impl->m_session->containerHandle( contId );
00249 if( !cont ){
00250 std::stringstream messg;
00251 messg << "Container with id=" << contId << " not found in the database.";
00252 throwException(messg.str(),
00253 "Database::containerHandle");
00254 }
00255 return Container( cont );
00256 }
00257
00258 ora::Object ora::Database::fetchItem(const OId& oid){
00259 Container cont = containerHandle( oid.containerId() );
00260 return cont.fetchItem( oid.itemId() );
00261 }
00262
00263 ora::OId ora::Database::insertItem(const std::string& containerName,
00264 const Object& dataObject ){
00265 open( true );
00266 Container cont = getContainerFromSession( containerName, dataObject.type(), *m_impl->m_session );
00267 int itemId = cont.insertItem( dataObject );
00268 return OId( cont.id(), itemId );
00269 }
00270
00271 void ora::Database::updateItem(const OId& oid,
00272 const Object& dataObject ){
00273 open();
00274 Container cont = containerHandle( oid.containerId() );
00275 cont.updateItem( oid.itemId(), dataObject );
00276 }
00277
00278 void ora::Database::erase(const OId& oid){
00279 open();
00280 Container cont = containerHandle( oid.containerId() );
00281 cont.erase( oid.itemId() );
00282 }
00283
00284 void ora::Database::flush(){
00285 open();
00286 const std::map<int,Handle<DatabaseContainer> >& containers = m_impl->m_session->containers();
00287 for( std::map<int,Handle<DatabaseContainer> >::const_iterator iCont = containers.begin();
00288 iCont != containers.end(); ++iCont ){
00289 iCont->second->flush();
00290 }
00291 }
00292
00293 void ora::Database::setObjectName( const std::string& name, const OId& oid ){
00294 open( true );
00295 m_impl->m_session->setObjectName( name, oid.containerId(), oid.itemId() );
00296 }
00297
00298 bool ora::Database::eraseObjectName( const std::string& name ){
00299 open();
00300 return m_impl->m_session->eraseObjectName( name );
00301 }
00302
00303 bool ora::Database::eraseAllNames(){
00304 open();
00305 return m_impl->m_session->eraseAllNames();
00306 }
00307
00308 bool ora::Database::getItemId( const std::string& name, ora::OId& destination ){
00309 open();
00310 return m_impl->m_session->getItemId( name, destination );
00311 }
00312
00313 boost::shared_ptr<void> ora::Database::getTypedObjectByName( const std::string& name, const std::type_info& typeInfo ){
00314 open();
00315 Reflex::Type objType = ClassUtils::lookupDictionary( typeInfo );
00316 return m_impl->m_session->fetchTypedObjectByName( name, objType );
00317 }
00318
00319 ora::Object ora::Database::fetchItemByName( const std::string& name ){
00320 open();
00321 return m_impl->m_session->fetchObjectByName( name );
00322 }
00323
00324 bool ora::Database::getNamesForObject( const ora::OId& oid,
00325 std::vector<std::string>& destination ){
00326 open();
00327 return m_impl->m_session->getNamesForObject( oid.containerId(), oid.itemId(), destination );
00328 }
00329
00330 bool ora::Database::listObjectNames( std::vector<std::string>& destination ){
00331 open();
00332 return m_impl->m_session->listObjectNames( destination );
00333 }
00334
00335 ora::DatabaseUtility ora::Database::utility(){
00336 checkTransaction();
00337 Handle<DatabaseUtilitySession> utilSession = m_impl->m_session->utility();
00338 return DatabaseUtility( utilSession );
00339 }
00340
00341 ora::SharedSession& ora::Database::storageAccessSession(){
00342 return m_impl->m_session->storageAccessSession();
00343 }
00344