ATLAS Offline Software
Loading...
Searching...
No Matches
Database/AthenaPOOL/PoolSvc/src/Database.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
5#include "Database.h"
6#include "SessionTool.h"
7#include "DatabaseHandler.h"
9#include "DatabaseRegistry.h"
10
12
13#include "StorageSvc/DbType.h"
14
15#include <exception>
16
17static const std::string& emptyString = "";
18
20 const std::string& name,
21 const Specification::NameType nameType ):
22 AthMessaging("PoolSvc.Database"),
23 m_session( session ),
24 m_catalog( session.fileCatalog() ),
25 m_transactionType( session.openMode() ),
26 m_registry( session.registry() ),
27 m_name( name ),
28 m_nameType( nameType ),
29 m_technology( 0 ),
30 m_technologySet( false ),
32 m_openMode( Io::INVALID ),
33 m_alreadyConnected( false ),
34 m_the_fid( "" ),
35 m_the_pfn( "" )
36{
37 this->checkInRegistry();
38}
39
40
43
44
45void
47{
48 if( !m_databaseHandler && m_transactionType != Io::INVALID ) {
49 // Check if the database is already connected
50 if( !checkInRegistry() ) {
51 // It is not. Connect !
52 switch( m_nameType ) {
54 if ( this->fid().empty() ) {
55 throw std::runtime_error( "PFN \"" + m_name + "\" is not existing (APR: \" Database::connectForRead \" from \" PersistencySvc \")" );
56 }
57 break;
58
60 if ( this->pfn().empty() ) {
61 throw std::runtime_error( "FID \"" + m_name + "\" is not existing in the catalog (APR: \" Database::connectForRead \" from \" PersistencySvc \")" );
62 }
63 break;
65 {
66 std::string lfn = m_name;
67 if ( this->fid().empty() ) {
68 throw std::runtime_error( "LFN \"" + m_name + "\" is not existing in the catalog (APR: \" Database::connectForRead \" from \" PersistencySvc \")" );
69 }
70 this->connectForRead();
71 m_registry.registerDatabaseHandler( m_databaseHandler, lfn );
72 }
73 return;
74 break;
75 default:
76 throw std::runtime_error( "Unknown database name type (APR: \" Database::connectForRead \" from \" PersistencySvc \")" );
77 };
78
79 // Now we have all the usefull information to open the file.
80 // Check the registry now that we have the FID (in case of ambiguous PFNs)
81 m_databaseHandler = m_registry.lookupByFID( m_the_fid );
82 if( !m_databaseHandler ) {
83 // still no luck - make a new connection
85 }
86 if( m_databaseHandler ) {
87 m_openMode = Io::READ;
88 }
89 else {
90 throw std::runtime_error( "Could not connect to the file (APR: \" Database::connectForRead \" from \" PersistencySvc \")" );
91 }
92 }
93 }
94}
95
96
97void*
98Database::readObject( const Token& token, void* object )
99{
100 if( !m_databaseHandler) {
101 throw std::runtime_error( "Could not open a database for read object. (APR: \" Database::connectForWrite \" from \" PersistencySvc \")" );
102 }
103 return m_databaseHandler->readObject( token, object );
104}
105
106
107void
109{
110 if( !m_databaseHandler && m_transactionType != Io::INVALID ) {
111 if ( m_transactionType != Io::WRITE && m_transactionType != Io::APPEND ) {
112 throw std::runtime_error( "Could not open a database for write outside an update transaction. (APR: \" Database::connectForWrite \" from \" PersistencySvc \")" );
113 }
114
115 if ( this->checkInRegistry() ) {
116 if ( m_openMode == Io::READ ) {
117 throw std::runtime_error( "Could not open a database for write that is already connected for read. (APR: \" Database::connectForWrite \" from \" PersistencySvc \")" );
118 }
119 }
120 else { // The database is not yet connected.
121 bool dbRegistered = false;
122 switch( m_nameType ) {
125 if ( this->fid().empty() ) {
126 // Check if the technology is already set
127 if( ! m_technologySet ) {
128 throw std::runtime_error( "The back end technology has not been specified (APR: \" Database::connectForWrite \" from \" PersistencySvc \")" );
129 }
130 // register in the catalog
131 pool::DbType dbType( m_technology );
132 pool::DbType dbTypeMajor( dbType.majorType() );
133 FileCatalogUtils::registerPFN( m_catalog, m_the_pfn.substr(0, m_the_pfn.find('?')), dbTypeMajor.storageName(), m_the_fid );
134 ATH_MSG_DEBUG("registered PFN: " << m_the_pfn << " with FID:" << m_the_fid);
135 dbRegistered = true;
136 }
137 break;
140 if ( this->pfn().empty() ) {
141 throw std::runtime_error( "Could not find the FID \"" + m_name + "\" in the file catalog (APR: \" Database::connectForWrite \" from \" PersistencySvc \")" );
142 }
143 break;
145 {
146 std::string lfn = m_name;
147 if ( this->fid().empty() ) {
148 throw std::runtime_error( "Could not find the LFN \"" + m_name + "\" in the file catalog (APR: \" Database::connectForWrite \" from \" PersistencySvc \")" );
149 }
150 this->connectForWrite();
151 m_registry.registerDatabaseHandler( m_databaseHandler, lfn );
152 }
153 return;
154 break;
155 default:
156 throw std::runtime_error( "Unknown database name type (APR: \" Database::connectForWrite \" from \" PersistencySvc \")" );
157 };
158
159 m_databaseHandler = m_session.microSessionManager( m_technology ).connect( m_transactionType, m_the_fid, m_the_pfn );
160 if( !m_databaseHandler ) {
161 if( dbRegistered ) {
162 // creation failed, remove entry from the in-memory catalog
163 m_catalog.deleteFID( m_the_fid );
164 }
165 throw std::runtime_error( "Could not connect to the file (APR: \" Database::connectForWrite \" from \" PersistencySvc \")" );
166 }
167 m_openMode = m_transactionType == Io::WRITE ? Io::WRITE : Io::APPEND;
168 } // Connection established
169
170 } // Database handler retrieved
171}
172
173
174Token*
175Database::writeObject( const std::string& containerName,
176 long minorTechnology,
177 const void* object,
178 const RootType& type )
179{
180 if( !m_databaseHandler) {
181 throw std::runtime_error( "Could not open a database for write object. (APR: \" Database::connectForWrite \" from \" PersistencySvc \")" );
182 }
183 return m_databaseHandler->writeObject( containerName, minorTechnology, object, type );
184}
185
186
187void
189{
190 if ( m_databaseHandler ) {
191 m_session.microSessionManager( m_technology ).disconnect( m_databaseHandler );
192 m_openMode = Io::INVALID;
193 }
194}
195
196
197Io::IoFlag
199{
200 return m_openMode;
201}
202
203
204const std::string&
206{
207 if ( m_databaseHandler ) return m_databaseHandler->fid();
208 else {
209 if ( m_nameType == Specification::FID ) return m_name;
210 else if ( !m_the_fid.empty() ) return m_the_fid;
211 else {
213 std::string technology;
214 FileCatalogUtils::lookupFileByPFN( m_catalog, m_name.substr(0, m_name.find('?')), m_the_fid, technology );
215 ATH_MSG_DEBUG("lookupPFN: " << m_name << " returned FID: '" << m_the_fid << "' tech=" << technology);
216 if ( ! m_the_fid.empty() ) {
217 if( technology.empty() ) {
219 ATH_MSG_DEBUG("Retrying 'connect' using assumed PFN " << m_name << " as LFN (no tech found in PFC)" );
220 return m_the_fid;
221 }
224 m_alreadyConnected = true;
225 }
226 else {
227 if( m_transactionType != Io::WRITE ) { // Fetch the FID from the db itself !
228 if( !m_technologySet ) {
229 ATH_MSG_DEBUG("Opening database '" << m_name << "' with no technology set");
231 m_technologySet = true;
232 }
233 m_the_fid = m_session.microSessionManager( m_technology ).fidForPfn( m_name );
234 if( ! m_the_fid.empty() ) {
235 // sanity check - verify that the FID is not registered in PFC under a different name
236 std::string pfn, tech;
238 if( !pfn.empty() ) {
239 ATH_MSG_WARNING("Opening file '" << m_name << "' which is already registered in the Catalog as '" << pfn
240 <<"' (GUID " << m_the_fid << ") - this is not supported and may even lead to a crash!" );
241 }
243 m_alreadyConnected = true;
244 }
245 }
246 }
247 } /* not PFN */
248 else if ( m_nameType == Specification::LFN ) {
249 m_the_fid = m_catalog.lookupLFN( m_name );
250 }
251 if ( ! m_the_fid.empty() ) {
254 }
255 return m_the_fid;
256 }
257 return emptyString;
258 }
259}
260
261
262const std::string&
264{
265 if( m_databaseHandler ) return m_databaseHandler->pfn();
266 if( m_nameType == Specification::PFN ) return m_name;
267 if( ! m_the_pfn.empty() ) return m_the_pfn;
268
270 m_the_fid = m_catalog.lookupLFN( m_name );
271 if ( ! m_the_fid.empty() ) {
274 // go from FID=>PFN in the next step
275 }
276 }
278 std::string technology;
280 if( !m_the_pfn.empty() ) {
283 m_alreadyConnected = true;
284 }
285 return m_the_pfn;
286 }
287 return emptyString;
288}
289
290bool
291Database::setTechnology( long technology )
292{
293 if ( m_alreadyConnected ) return false;
294 else {
295 pool::DbType dbType( technology );
296 m_technology = dbType.majorType();
297 m_technologySet = true;
298 return true;
299 }
300}
301
302
303std::vector< std::string >
305{
306 std::vector< std::string > containers;
307 if ( m_databaseHandler ) {
308 containers = m_databaseHandler->containers();
309 }
310 return containers;
311}
312
313
315Database::containerHandle( const std::string& name )
316{
317 Container* container = 0;
318 if ( m_databaseHandler ) {
319 container = m_databaseHandler->container( name );
320 }
321 return container;
322}
323
324
325bool
327{
328 // Check first if the database is already connected.
329 switch( m_nameType ) {
331 m_databaseHandler = m_registry.lookupByPFN( m_name );
332 break;
334 m_databaseHandler = m_registry.lookupByFID( m_name );
335 break;
337 m_databaseHandler = m_registry.lookupByLFN( m_name );
338 break;
339 default:
340 throw std::runtime_error( "Only PFN, LFN and FID database types are currently supported (APR: \" Database::checkInRegistry \" from \" PersistencySvc \")" );
341 };
342 if ( m_databaseHandler ) {
343 m_alreadyConnected = true;
344 m_technology = m_databaseHandler->technology();
345 m_openMode = m_databaseHandler->accessMode();
349 return true;
350 }
351 else return false;
352}
353
356{
357 return m_databaseHandler? &m_databaseHandler->fileDescriptor() : nullptr;
358}
359
360
361bool
362Database::attributeOfType( const std::string& attributeName,
363 void* data,
364 const std::type_info& typeInfo,
365 const std::string& option )
366{
367 if ( ! m_databaseHandler ) return false;
368 else return m_databaseHandler->attribute( attributeName, data, typeInfo, option );
369}
370
371
372bool
373Database::setAttributeOfType( const std::string& attributeName,
374 const void* data,
375 const std::type_info& typeInfo,
376 const std::string& option )
377{
378 if ( ! m_databaseHandler ) return false;
379 else return m_databaseHandler->setAttribute( attributeName, data, typeInfo, option );
380}
#define ATH_MSG_DEBUG(x,...)
#define ATH_MSG_WARNING(x,...)
static const std::string & emptyString
TTypeAdapter RootType
Definition RootType.h:211
static const Attributes_t empty
AthMessaging(IMessageSvc *msgSvc, const std::string &name)
Constructor.
Container * containerHandle(const std::string &name)
Returns a pointer to a container object. The user acquires ownership of that object.
Specification::NameType m_nameType
The database name spacification.
long m_technology
The technology identifier of the database.
Io::IoFlag m_openMode
Current open mode.
bool checkInRegistry()
Checks in the registry if the database handler already exists.
void disconnect()
Disconnects from the database.
Io::IoFlag openMode() const
Returns the opening mode. It can be used to check whether the database is connected.
void connectForRead()
Connects explicitly to the database for read operations.
bool setAttributeOfType(const std::string &attributeName, const void *data, const std::type_info &typeInfo, const std::string &option)
Database(SessionTool &session, const std::string &name, const Specification::NameType nameType)
Constructor.
const std::string & fid()
Returns the file identifier of this database.
const std::string & pfn()
Returns the physical file name of this database.
std::vector< std::string > containers()
Returns the names of the containers in this database.
std::string m_name
The database name.
bool setTechnology(long technology)
Sets the technology identifier for this database.
SessionTool & m_session
Reference to the session.
void connectForWrite()
Connects explicitly to the database for write/update operations.
DatabaseRegistry & m_registry
Reference to the database registry.
void * readObject(const Token &token, void *object=0)
Reads an object given a token.
std::string m_the_fid
Other names used.
bool attributeOfType(const std::string &attributeName, void *data, const std::type_info &typeInfo, const std::string &option)
DatabaseHandler * m_databaseHandler
The underlying database handler.
pool::FileDescriptor * fileDescriptor()
bool m_alreadyConnected
Flag indicating whether a connection has been already made once.
Token * writeObject(const std::string &containerName, long minorTechnology, const void *object, const RootType &type)
Writes an object and returns a token.
Io::IoFlag m_transactionType
Transaction type (read/update).
Gaudi::IFileCatalog & m_catalog
Reference to the file catalog.
bool m_technologySet
Checks if the technology identifier has been set.
This class provides a token that identifies in a unique way objects on the persistent storage.
Definition Token.h:22
const std::string storageName() const
Human readable storage type.
int majorType() const
Access to major type.
Definition DbType.h:67
static DbType getType(const std::string &name)
Access known storage type object by name.
void registerPFN(Gaudi::IFileCatalog &fc, const std::string &pfn, const std::string &ftype, std::string &fid)
Register PFN, assign new FID if not given. Throws if the PFN is already registered.
void lookupFileByPFN(const Gaudi::IFileCatalog &fc, const std::string &pfn, std::string &fid, std::string &tech)
Get FID and filetype for a given PFN.
void getFirstPFN(const Gaudi::IFileCatalog &fc, const std::string &fid, std::string &pfn, std::string &tech)
Get the first PFN + filetype for the given FID.
static const DbType ROOT_StorageType
Definition DbType.h:85
NameType
Enumeration type specifying the database name field, wherever the latter is used in methods accessing...