ATLAS Offline Software
Loading...
Searching...
No Matches
UserDatabase.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 "UserDatabase.h"
6#include "UserSession.h"
7#include "DatabaseHandler.h"
9#include "DatabaseRegistry.h"
10
12
13#include "StorageSvc/DbType.h"
14#include "StorageSvc/pool.h"
15
16#include <exception>
17
18static const std::string& emptyString = "";
19
21 const std::string& name,
23 APRMessaging("PersistencySvc::UserDB"),
24 m_session( session ),
25 m_catalog( session.fileCatalog() ),
26 m_transactionType( session.type() ),
27 m_registry( session.registry() ),
28 m_name( name ),
29 m_nameType( nameType ),
30 m_technology( 0 ),
31 m_technologySet( false ),
34 m_alreadyConnected( false ),
35 m_the_fid( "" ),
36 m_the_pfn( "" )
37{
38 this->checkInRegistry();
39}
40
41
44
45
46void
48{
49 if( !m_databaseHandler && m_transactionType != Io::INVALID ) {
50 // Check if the database is already connected
51 if( !checkInRegistry() ) {
52 // It is not. Connect !
53 switch( m_nameType ) {
55 if ( this->fid().empty() ) {
56 throw std::runtime_error( "PFN \"" + m_name + "\" is not existing (APR: \" UserDatabase::connectForRead \" from \" PersistencySvc \")" );
57 }
58 break;
59
61 if ( this->pfn().empty() ) {
62 throw std::runtime_error( "FID \"" + m_name + "\" is not existing in the catalog (APR: \" UserDatabase::connectForRead \" from \" PersistencySvc \")" );
63 }
64 break;
66 {
67 std::string lfn = m_name;
68 if ( this->fid().empty() ) {
69 throw std::runtime_error( "LFN \"" + m_name + "\" is not existing in the catalog (APR: \" UserDatabase::connectForRead \" from \" PersistencySvc \")" );
70 }
71 this->connectForRead();
72 m_registry.registerDatabaseHandler( m_databaseHandler, lfn );
73 }
74 return;
75 break;
76 default:
77 throw std::runtime_error( "Unknown database name type (APR: \" UserDatabase::connectForRead \" from \" PersistencySvc \")" );
78 };
79
80 // Now we have all the usefull information to open the file.
81 // Check the registry now that we have the FID (in case of ambiguous PFNs)
82 m_databaseHandler = m_registry.lookupByFID( m_the_fid );
83 if( !m_databaseHandler ) {
84 // still no luck - make a new connection
86 }
87 if( m_databaseHandler ) {
88 m_openMode = Io::READ;
89 }
90 else {
91 throw std::runtime_error( "Could not connect to the file (APR: \" UserDatabase::connectForRead \" from \" PersistencySvc \")" );
92 }
93 }
94 }
95}
96
97
98void*
99pool::UserDatabase::readObject( const Token& token, void* object )
100{
101 if( !m_databaseHandler) {
102 throw std::runtime_error( "Could not open a database for read object. (APR: \" UserDatabase::connectForWrite \" from \" PersistencySvc \")" );
103 }
104 return m_databaseHandler->readObject( token, object );
105}
106
107
108void
110{
111 if( !m_databaseHandler && m_transactionType != Io::INVALID ) {
112 if ( m_transactionType != Io::WRITE && m_transactionType != Io::APPEND ) {
113 throw std::runtime_error( "Could not open a database for write outside an update transaction. (APR: \" UserDatabase::connectForWrite \" from \" PersistencySvc \")" );
114 }
115
116 if ( this->checkInRegistry() ) {
117 if ( m_openMode == Io::READ ) {
118 throw std::runtime_error( "Could not open a database for write that is already connected for read. (APR: \" UserDatabase::connectForWrite \" from \" PersistencySvc \")" );
119 }
120 }
121 else { // The database is not yet connected.
122 bool dbRegistered = false;
123 switch( m_nameType ) {
126 if ( this->fid().empty() ) {
127 // Check if the technology is already set
128 if( ! m_technologySet ) {
129 throw std::runtime_error( "The back end technology has not been specified (APR: \" UserDatabase::connectForWrite \" from \" PersistencySvc \")" );
130 }
131 // register in the catalog
132 pool::DbType dbType( m_technology );
133 pool::DbType dbTypeMajor( dbType.majorType() );
134 FileCatalogUtils::registerPFN( m_catalog, m_the_pfn.substr(0, m_the_pfn.find('?')), dbTypeMajor.storageName(), m_the_fid );
135 ATH_MSG_DEBUG("registered PFN: " << m_the_pfn << " with FID:" << m_the_fid);
136 dbRegistered = true;
137 }
138 break;
141 if ( this->pfn().empty() ) {
142 throw std::runtime_error( "Could not find the FID \"" + m_name + "\" in the file catalog (APR: \" UserDatabase::connectForWrite \" from \" PersistencySvc \")" );
143 }
144 break;
146 {
147 std::string lfn = m_name;
148 if ( this->fid().empty() ) {
149 throw std::runtime_error( "Could not find the LFN \"" + m_name + "\" in the file catalog (APR: \" UserDatabase::connectForWrite \" from \" PersistencySvc \")" );
150 }
151 this->connectForWrite();
152 m_registry.registerDatabaseHandler( m_databaseHandler, lfn );
153 }
154 return;
155 break;
156 default:
157 throw std::runtime_error( "Unknown database name type (APR: \" UserDatabase::connectForWrite \" from \" PersistencySvc \")" );
158 };
159
160 m_databaseHandler = m_session.microSessionManager( m_technology ).connect( m_transactionType, m_the_fid, m_the_pfn );
161 if( !m_databaseHandler ) {
162 if( dbRegistered ) {
163 // creation failed, remove entry from the in-memory catalog
164 m_catalog.deleteFID( m_the_fid );
165 }
166 throw std::runtime_error( "Could not connect to the file (APR: \" UserDatabase::connectForWrite \" from \" PersistencySvc \")" );
167 }
168 m_openMode = m_transactionType == Io::WRITE ? Io::WRITE : Io::APPEND;
169 } // Connection established
170
171 } // Database handler retrieved
172}
173
174
175Token*
176pool::UserDatabase::writeObject( const std::string& containerName,
177 long minorTechnology,
178 const void* object,
179 const RootType& type )
180{
181 if( !m_databaseHandler) {
182 throw std::runtime_error( "Could not open a database for write object. (APR: \" UserDatabase::connectForWrite \" from \" PersistencySvc \")" );
183 }
184 return m_databaseHandler->writeObject( containerName, minorTechnology, object, type );
185}
186
187
188void
190{
191 if ( m_databaseHandler ) {
192 m_session.microSessionManager( m_technology ).disconnect( m_databaseHandler );
193 m_openMode = Io::INVALID;
194 }
195}
196
197
198Io::IoFlag
200{
201 return m_openMode;
202}
203
204
205const std::string&
207{
208 if ( m_databaseHandler ) return m_databaseHandler->fid();
209 else {
211 else if ( !m_the_fid.empty() ) return m_the_fid;
212 else {
214 std::string technology;
215 FileCatalogUtils::lookupFileByPFN( m_catalog, m_name.substr(0, m_name.find('?')), m_the_fid, technology );
216 ATH_MSG_DEBUG("lookupPFN: " << m_name << " returned FID: '" << m_the_fid << "' tech=" << technology);
217 if ( ! m_the_fid.empty() ) {
218 if( technology.empty() ) {
220 ATH_MSG_DEBUG("Retrying 'connect' using assumed PFN " << m_name << " as LFN (no tech found in PFC)" );
221 return m_the_fid;
222 }
225 m_alreadyConnected = true;
226 }
227 else {
228 if( m_transactionType != Io::WRITE ) { // Fetch the FID from the db itself !
229 if( !m_technologySet ) {
230 ATH_MSG_DEBUG("Opening database '" << m_name << "' with no technology set");
232 m_technologySet = true;
233 }
234 m_the_fid = m_session.microSessionManager( m_technology ).fidForPfn( m_name );
235 if( ! m_the_fid.empty() ) {
236 // sanity check - verify that the FID is not registered in PFC under a different name
237 std::string pfn, tech;
239 if( !pfn.empty() ) {
240 ATH_MSG_WARNING("Opening file '" << m_name << "' which is already registered in the Catalog as '" << pfn
241 <<"' (GUID " << m_the_fid << ") - this is not supported and may even lead to a crash!" );
242 }
244 m_alreadyConnected = true;
245 }
246 }
247 }
248 } /* not PFN */
250 m_the_fid = m_catalog.lookupLFN( m_name );
251 }
252 if ( ! m_the_fid.empty() ) {
255 }
256 return m_the_fid;
257 }
258 return emptyString;
259 }
260}
261
262
263const std::string&
265{
266 if( m_databaseHandler ) return m_databaseHandler->pfn();
268 if( ! m_the_pfn.empty() ) return m_the_pfn;
269
271 m_the_fid = m_catalog.lookupLFN( m_name );
272 if ( ! m_the_fid.empty() ) {
275 // go from FID=>PFN in the next step
276 }
277 }
279 std::string technology;
281 if( !m_the_pfn.empty() ) {
284 m_alreadyConnected = true;
285 }
286 return m_the_pfn;
287 }
288 return emptyString;
289}
290
291bool
293{
294 if ( m_alreadyConnected ) return false;
295 else {
296 pool::DbType dbType( technology );
297 m_technology = dbType.majorType();
298 m_technologySet = true;
299 return true;
300 }
301}
302
303
304std::vector< std::string >
306{
307 std::vector< std::string > containers;
308 if ( m_databaseHandler ) {
309 containers = m_databaseHandler->containers();
310 }
311 return containers;
312}
313
314
316pool::UserDatabase::containerHandle( const std::string& name )
317{
318 pool::IContainer* container = 0;
319 if ( m_databaseHandler ) {
320 container = m_databaseHandler->container( name );
321 }
322 return container;
323}
324
325
326bool
328{
329 // Check first if the database is already connected.
330 switch( m_nameType ) {
332 m_databaseHandler = m_registry.lookupByPFN( m_name );
333 break;
335 m_databaseHandler = m_registry.lookupByFID( m_name );
336 break;
338 m_databaseHandler = m_registry.lookupByLFN( m_name );
339 break;
340 default:
341 throw std::runtime_error( "Only PFN, LFN and FID database types are currently supported (APR: \" UserDatabase::checkInRegistry \" from \" PersistencySvc \")" );
342 };
343 if ( m_databaseHandler ) {
344 m_alreadyConnected = true;
345 m_technology = m_databaseHandler->technology();
346 m_openMode = m_databaseHandler->accessMode();
350 return true;
351 }
352 else return false;
353}
354
357{
358 return m_databaseHandler? &m_databaseHandler->fileDescriptor() : nullptr;
359}
360
361
362bool
363pool::UserDatabase::attributeOfType( const std::string& attributeName,
364 void* data,
365 const std::type_info& typeInfo,
366 const std::string& option )
367{
368 if ( ! m_databaseHandler ) return false;
369 else return m_databaseHandler->attribute( attributeName, data, typeInfo, option );
370}
371
372
373bool
374pool::UserDatabase::setAttributeOfType( const std::string& attributeName,
375 const void* data,
376 const std::type_info& typeInfo,
377 const std::string& option )
378{
379 if ( ! m_databaseHandler ) return false;
380 else return m_databaseHandler->setAttribute( attributeName, data, typeInfo, option );
381}
#define ATH_MSG_DEBUG(x,...)
#define ATH_MSG_WARNING(x,...)
TTypeAdapter RootType
Definition RootType.h:211
static const std::string & emptyString
static const Attributes_t empty
This class provides a token that identifies in a unique way objects on the persistent storage.
Definition Token.h:22
APRMessaging(const std::string &name)
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.
IContainer is the base class for container objects.
Definition IContainer.h:23
Token * writeObject(const std::string &containerName, long minorTechnology, const void *object, const RootType &type)
Writes an object and returns a token.
virtual const std::string & pfn() override
Returns the physical file name of this database.
UserDatabase(UserSession &session, const std::string &name, const DatabaseSpecification::NameType nameType)
Constructor.
std::string m_the_fid
Other names used.
Io::IoFlag m_transactionType
Transaction type (read/update).
std::string m_the_pfn
virtual FileDescriptor * fileDescriptor() override final
Expose FileDescriptor object for the technology specific DB implementation.
virtual void disconnect() override
Disconnects from the database.
std::string m_name
The database name.
virtual bool attributeOfType(const std::string &attributeName, void *data, const std::type_info &typeInfo, const std::string &option) override
The method returning the attribute data given a name.
virtual void connectForWrite() override
Connects explicitly to the database for write/update operations.
virtual bool setAttributeOfType(const std::string &attributeName, const void *data, const std::type_info &typeInfo, const std::string &option) override
The method setting the attribute data given a name.
DatabaseRegistry & m_registry
Reference to the database registry.
bool m_alreadyConnected
Flag indicating whether a connection has been already made once.
bool checkInRegistry()
Checks in the registry if the database handler already exists.
virtual std::vector< std::string > containers() override
Returns the names of the containers in this database.
Gaudi::IFileCatalog & m_catalog
Reference to the file catalog.
UserSession & m_session
Reference to the session.
DatabaseSpecification::NameType m_nameType
The database name spacification.
long m_technology
The technology identifier of the database.
virtual Io::IoFlag openMode() const override
Returns the opening mode. It can be used to check whether the database is connected.
virtual IContainer * containerHandle(const std::string &name) override
Returns a pointer to a container object. The user acquires ownership of that object.
void * readObject(const Token &token, void *object=0)
Reads an object given a token.
virtual ~UserDatabase()
Destructor.
virtual bool setTechnology(long technology) override
Sets the technology identifier for this database.
Io::IoFlag m_openMode
Current open mode.
virtual const std::string & fid() override
Returns the file identifier of this database.
bool m_technologySet
Checks if the technology identifier has been set.
virtual void connectForRead() override
Connects explicitly to the database for read operations.
DatabaseHandler * m_databaseHandler
The underlying database handler.
UserSession is an implementation of the ISession interface.
Definition UserSession.h:27
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 long long int INVALID
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...
Definition IDatabase.h:24
@ FID
Physical File Name.
Definition IDatabase.h:26
@ LFN
File IDentifier.
Definition IDatabase.h:27