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.transactionType() ),
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
51
52void
54{
55 if( !m_databaseHandler && m_transactionType != Io::INVALID ) {
56 // Check if the database is already connected
57 if( !checkInRegistry() ) {
58 // It is not. Connect !
59 switch( m_nameType ) {
61 if ( this->fid().empty() ) {
62 throw std::runtime_error( "PFN \"" + m_name + "\" is not existing (APR: \" UserDatabase::connectForRead \" from \" PersistencySvc \")" );
63 }
64 break;
65
67 if ( this->pfn().empty() ) {
68 throw std::runtime_error( "FID \"" + m_name + "\" is not existing in the catalog (APR: \" UserDatabase::connectForRead \" from \" PersistencySvc \")" );
69 }
70 break;
72 {
73 std::string lfn = m_name;
74 if ( this->fid().empty() ) {
75 throw std::runtime_error( "LFN \"" + m_name + "\" is not existing in the catalog (APR: \" UserDatabase::connectForRead \" from \" PersistencySvc \")" );
76 }
77 this->connectForRead();
78 m_registry.registerDatabaseHandler( m_databaseHandler, lfn );
79 }
80 return;
81 break;
82 default:
83 throw std::runtime_error( "Unknown database name type (APR: \" UserDatabase::connectForRead \" from \" PersistencySvc \")" );
84 };
85
86 // Now we have all the usefull information to open the file.
87 // Check the registry now that we have the FID (in case of ambiguous PFNs)
88 m_databaseHandler = m_registry.lookupByFID( m_the_fid );
89 if( !m_databaseHandler ) {
90 // still no luck - make a new connection
92 }
93 if( m_databaseHandler ) {
94 m_openMode = Io::READ;
95 }
96 else {
97 throw std::runtime_error( "Could not connect to the file (APR: \" UserDatabase::connectForRead \" from \" PersistencySvc \")" );
98 }
99 }
100 }
101}
102
103
104void
106{
107 if( !m_databaseHandler && m_transactionType != Io::INVALID ) {
108 if ( m_transactionType != Io::WRITE && m_transactionType != Io::APPEND ) {
109 throw std::runtime_error( "Could not open a database for write outside an update transaction. (APR: \" UserDatabase::connectForWrite \" from \" PersistencySvc \")" );
110 }
111
112 if ( this->checkInRegistry() ) {
113 if ( m_openMode == Io::READ ) {
114 throw std::runtime_error( "Could not open a database for write that is already connected for read. (APR: \" UserDatabase::connectForWrite \" from \" PersistencySvc \")" );
115 }
116 }
117 else { // The database is not yet connected.
118 bool dbRegistered = false;
119 switch( m_nameType ) {
122 if ( this->fid().empty() ) {
123 // Check if the technology is already set
124 if( ! m_technologySet ) {
125 throw std::runtime_error( "The back end technology has not been specified (APR: \" UserDatabase::connectForWrite \" from \" PersistencySvc \")" );
126 }
127 // register in the catalog
128 pool::DbType dbType( m_technology );
129 pool::DbType dbTypeMajor( dbType.majorType() );
130 m_catalog.registerPFN( m_the_pfn.substr(0, m_the_pfn.find('?')), dbTypeMajor.storageName(), m_the_fid );
131 ATH_MSG_DEBUG("registered PFN: " << m_the_pfn << " with FID:" << m_the_fid);
132 dbRegistered = true;
133 }
134 break;
137 if ( this->pfn().empty() ) {
138 throw std::runtime_error( "Could not find the FID \"" + m_name + "\" in the file catalog (APR: \" UserDatabase::connectForWrite \" from \" PersistencySvc \")" );
139 }
140 break;
142 {
143 std::string lfn = m_name;
144 if ( this->fid().empty() ) {
145 throw std::runtime_error( "Could not find the LFN \"" + m_name + "\" in the file catalog (APR: \" UserDatabase::connectForWrite \" from \" PersistencySvc \")" );
146 }
147 this->connectForWrite();
148 m_registry.registerDatabaseHandler( m_databaseHandler, lfn );
149 }
150 return;
151 break;
152 default:
153 throw std::runtime_error( "Unknown database name type (APR: \" UserDatabase::connectForWrite \" from \" PersistencySvc \")" );
154 };
155
156 m_databaseHandler = m_session.microSessionManager( m_technology ).connect( m_transactionType, m_the_fid, m_the_pfn );
157 if( !m_databaseHandler ) {
158 if( dbRegistered ) {
159 // creation failed, remove entry from the in-memory catalog
160 m_catalog.deleteFID( m_the_fid );
161 }
162 throw std::runtime_error( "Could not connect to the file (APR: \" UserDatabase::connectForWrite \" from \" PersistencySvc \")" );
163 }
164 m_openMode = m_transactionType == Io::WRITE ? Io::WRITE : Io::APPEND;
165 } // Connection established
166
167 } // Database handler retrieved
168}
169
170
171void
173{
174 if ( m_databaseHandler ) {
175 m_session.microSessionManager( m_technology ).disconnect( m_databaseHandler );
176 m_openMode = Io::INVALID;
177 }
178}
179
180
181Io::IoFlag
183{
184 return m_openMode;
185}
186
187
188const std::string&
190{
191 if ( m_databaseHandler ) return m_databaseHandler->fid();
192 else {
194 else if ( ! m_the_fid.empty() ) return m_the_fid;
195 else {
197 std::string technology;
198 m_catalog.lookupFileByPFN( m_name.substr(0, m_name.find('?')), m_the_fid, technology );
199 ATH_MSG_DEBUG("lookupPFN: " << m_name << " returned FID: '" << m_the_fid << "' tech=" << technology);
200 if ( ! m_the_fid.empty() ) {
201 if( technology.empty() ) {
203 ATH_MSG_DEBUG("Retrying 'connect' using assumed PFN " << m_name << " as LFN (no tech found in PFC)" );
204 return m_the_fid;
205 }
208 m_alreadyConnected = true;
209 }
210 else {
211 if( m_transactionType != Io::WRITE ) { // Fetch the FID from the db itself !
212 if( !m_technologySet ) {
213 ATH_MSG_DEBUG("Opening database '" << m_name << "' with no technology set");
215 m_technologySet = true;
216 }
217 m_the_fid = m_session.microSessionManager( m_technology ).fidForPfn( m_name );
218 if( ! m_the_fid.empty() ) {
219 // sanity check - verify that the FID is not registered in PFC under a different name
220 std::string pfn, tech;
221 m_catalog.getFirstPFN( m_the_fid, pfn, tech );
222 if( !pfn.empty() ) {
223 ATH_MSG_WARNING("Opening file '" << m_name << "' which is already registered in the Catalog as '" << pfn
224 <<"' (GUID " << m_the_fid << ") - this is not supported and may even lead to a crash!" );
225 }
227 m_alreadyConnected = true;
228 }
229 }
230 }
231 } /* not PFN */
233 m_the_fid = m_catalog.lookupLFN( m_name );
234 }
235 if ( ! m_the_fid.empty() ) {
238 }
239 return m_the_fid;
240 }
241 return emptyString;
242 }
243}
244
245
246const std::string&
248{
249 if( m_databaseHandler ) return m_databaseHandler->pfn();
251 if( ! m_the_pfn.empty() ) return m_the_pfn;
252
254 m_the_fid = m_catalog.lookupLFN( m_name );
255 if ( ! m_the_fid.empty() ) {
258 // go from FID=>PFN in the next step
259 }
260 }
262 std::string technology;
263 m_catalog.getFirstPFN( m_name, m_the_pfn, technology );
264 if( !m_the_pfn.empty() ) {
267 m_alreadyConnected = true;
268 }
269 return m_the_pfn;
270 }
271 return emptyString;
272}
273
274
275bool
277{
278 if ( m_alreadyConnected ) return false;
279 else {
280 pool::DbType dbType( technology );
281 m_technology = dbType.majorType();
282 m_technologySet = true;
283 return true;
284 }
285}
286
287
288long
290{
291 return m_technology;
292}
293
294
295std::vector< std::string >
297{
298 std::vector< std::string > containers;
299 if ( m_databaseHandler ) {
300 containers = m_databaseHandler->containers();
301 }
302 return containers;
303}
304
305
307pool::UserDatabase::containerHandle( const std::string& name )
308{
309 pool::IContainer* container = 0;
310 if ( m_databaseHandler ) {
311 container = m_databaseHandler->container( name );
312 }
313 return container;
314}
315
316
317bool
319{
320 // Check first if the database is already connected.
321 switch( m_nameType ) {
323 m_databaseHandler = m_registry.lookupByPFN( m_name );
324 break;
326 m_databaseHandler = m_registry.lookupByFID( m_name );
327 break;
329 m_databaseHandler = m_registry.lookupByLFN( m_name );
330 break;
331 default:
332 throw std::runtime_error( "Only PFN, LFN and FID database types are currently supported (APR: \" UserDatabase::checkInRegistry \" from \" PersistencySvc \")" );
333 };
334 if ( m_databaseHandler ) {
335 m_alreadyConnected = true;
336 m_technology = m_databaseHandler->technology();
337 if ( m_databaseHandler->accessMode() == Io::APPEND ) {
338 m_openMode = Io::APPEND;
339 }
340 else if ( m_databaseHandler->accessMode() == Io::WRITE ) {
341 m_openMode = Io::WRITE;
342 }
343 else {
344 m_openMode = Io::READ;
345 }
349 return true;
350 }
351 else return false;
352}
353
354
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,...)
static const std::string & emptyString
static const Attributes_t empty
APRMessaging(const std::string &name)
DatabaseHandler is a class taking care of the micro-connections and the micro transactions for a give...
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
ITechnologySpecificAttributes is the interface for an object holding technology-specific attributes.
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
DatabaseHandler & databaseHandler()
Returns the database handler.
virtual ITechnologySpecificAttributes & technologySpecificAttributes() override
Returns the object holding the technology specific attributes.
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 actual 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 actual 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.
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.
virtual ~UserDatabase()
Destructor.
virtual long technology() const override
Returns the technology identifier for this database.
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
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