ATLAS Offline Software
Toggle main menu visibility
Loading...
Searching...
No Matches
Database
ConnectionManagement
DBReplicaSvc
src
DBReplicaSvc.cxx
Go to the documentation of this file.
1
/*
2
Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3
*/
4
5
// DBReplicaSvc.cxx - service implementing CORAL IReplicaSortingAlgorithm
6
// Richard Hawkings, started 24/4/07
7
8
#include "
DBReplicaSvc.h
"
9
10
#include "
PathResolver/PathResolver.h
"
11
12
#include <fstream>
13
#include <cstring>
14
15
#include "RelationalAccess/ConnectionService.h"
16
#include "RelationalAccess/IConnectionServiceConfiguration.h"
17
#include "RelationalAccess/IWebCacheControl.h"
18
#include "RelationalAccess/IDatabaseServiceSet.h"
19
#include "RelationalAccess/IDatabaseServiceDescription.h"
20
21
StatusCode
DBReplicaSvc::initialize
() {
22
23
// determine the hostname (or override if from joboption)
24
m_hostname
=
m_testhost
;
25
// if nothing set on job-options, try environment variable ATLAS_CONDDB
26
if
(
m_hostname
.empty()) {
27
const
char
* chost=getenv(
"ATLAS_CONDDB"
);
28
if
(chost)
m_hostname
=chost;
29
}
30
// if ATLAS_CONDDB not set, try environment variable HOSTNAME
31
if
(
m_hostname
.empty()) {
32
const
char
* chost=getenv(
"HOSTNAME"
);
33
if
(chost)
m_hostname
=chost;
34
// check if the returned host has a .
35
if
(
m_hostname
.find(
'.'
)==std::string::npos) {
36
ATH_MSG_DEBUG
(
"HOSTNAME "
<<
m_hostname
37
<<
" has no domain - try hostname --fqdn"
);
38
m_hostname
=
"unknown"
;
39
#ifndef __APPLE__
40
system(
"hostname --fqdn > hostnamelookup.tmp"
);
41
#else
42
// Unfortunately Leopard doesn't understand the -f option to hostname, only Snow Leopard does
43
system(
"hostname > hostnamelookup.tmp"
);
44
#endif
45
std::ifstream infile;
46
infile.open(
"hostnamelookup.tmp"
);
47
if
(infile) {
48
infile >>
m_hostname
;
49
ATH_MSG_DEBUG
(
"HOSTNAME from fqdn: "
<<
m_hostname
);
50
}
else
{
51
m_hostname
=
"unknown"
;
52
}
53
}
54
}
55
// check if FRONTIER_SERVER is set, if so, allow generic replicas
56
const
char
* cfrontier=getenv(
"FRONTIER_SERVER"
);
57
if
(
m_usecoolfrontier
&& cfrontier && strcmp(cfrontier,
""
)!=0) {
58
ATH_MSG_INFO
(
"Frontier server at "
<< cfrontier
59
<<
" will be considered for COOL data"
);
60
m_frontiergen
=
true
;
61
}
62
StatusCode
sc
=
readConfig
();
63
if
(!
m_usecoolsqlite
) {
64
ATH_MSG_INFO
(
"COOL SQLite replicas will be excluded"
);
65
}
else
if
(
m_coolsqlitepattern
!=
""
) {
66
ATH_MSG_INFO
(
"COOL SQLite replicas will be excluded if matching pattern "
67
<<
m_coolsqlitepattern
);
68
}
69
if
(!
m_usecoolfrontier
)
70
ATH_MSG_INFO
(
"COOL Frontier replicas will be excluded"
);
71
if
(!
m_usegeomsqlite
)
72
ATH_MSG_INFO
(
"Geometry SQLite replicas will be excluded"
);
73
if
(
m_nofailover
)
74
ATH_MSG_INFO
(
"Failover to secondary replicas disabled"
);
75
//Other coral configuration settting:
76
77
m_context
= &coral::Context::instance();
78
if
(
m_context
==
nullptr
) {
79
ATH_MSG_FATAL
(
"Failed to access CORAL Context"
);
80
return
(StatusCode::FAILURE);
81
}
82
83
coral::ConnectionService conSvcH;
84
coral::IConnectionServiceConfiguration& csConfig = conSvcH.configuration();
85
csConfig.setReplicaSortingAlgorithm(*
this
);
86
ATH_MSG_DEBUG
(
"Successfully setup replica sorting algorithm"
);
87
88
csConfig.setConnectionRetrialPeriod(
m_retrialPeriod
);
89
csConfig.setConnectionRetrialTimeOut(
m_retrialTimeOut
);
90
if
(
m_connClean
) {
91
csConfig.enablePoolAutomaticCleanUp();
92
csConfig.setConnectionTimeOut(
m_timeOut
);
93
}
else
{
94
csConfig.disablePoolAutomaticCleanUp();
95
csConfig.setConnectionTimeOut(0);
96
}
97
ATH_MSG_INFO
(
"Set connectionsvc retry/timeout/IDLE timeout to "
<<
m_retrialPeriod
<<
"/"
<<
m_retrialTimeOut
<<
"/"
<<
m_timeOut
98
<<
" seconds with connection cleanup "
99
<< (csConfig.isPoolAutomaticCleanUpEnabled() ?
"enabled"
:
"disabled"
));
100
// set Frontier web cache compression level
101
coral::IWebCacheControl& webCache = conSvcH.webCacheControl();
102
webCache.setCompressionLevel(
m_frontierComp
);
103
ATH_MSG_INFO
(
"Frontier compression level set to "
<< webCache.compressionLevel());
104
105
return
sc
;
106
}
107
108
StatusCode
DBReplicaSvc::readConfig
() {
109
110
// try to locate the file using pathresolver
111
std::string
file
=
PathResolver::find_file
(
m_configfile
,
"DATAPATH"
);
112
if
(
file
.empty()) {
113
ATH_MSG_ERROR
(
"Cannot locate configuration file "
<<
m_configfile
);
114
return
StatusCode::FAILURE;
115
}
116
// open and read the file
117
ATH_MSG_INFO
(
"Read replica configuration from "
<<
file
);
118
FILE* p_inp=fopen(
file
.c_str(),
"r"
);
119
if
(p_inp==
nullptr
) {
120
ATH_MSG_ERROR
(
"Cannot open configuration file"
);
121
return
StatusCode::FAILURE;
122
}
123
// buffer for reading line
124
const
unsigned
int
bufsize=999;
125
char
p_buf[bufsize];
126
while
(!feof(p_inp)) {
127
char
* p_line=fgets(p_buf,bufsize,p_inp);
128
if
(p_line!=NULL && p_line[0]!=
'#'
) {
129
std::string buf=std::string(p_line);
130
std::string::size_type iofs1=0;
131
// analyse based on spaces as separator
132
bool
sequal=
false
;
133
std::vector<std::string> domains;
134
std::vector<std::string> servers;
135
while
(iofs1<buf.size()) {
136
std::string::size_type iofs2=buf.find(
' '
,iofs1);
137
// allow for trailing linefeed
138
if
(iofs2==std::string::npos) iofs2=buf.size()-1;
139
std::string token=buf.substr(iofs1,iofs2-iofs1);
140
// skip empty or space tokens
141
if
(token!=
""
&& token!=
" "
) {
142
if
(token==
"="
) {
143
sequal=
true
;
144
}
else
if
(!sequal) {
145
// token is a domain name
146
domains.push_back(std::move(token));
147
}
else
{
148
// token is a server name
149
if
(!
m_nofailover
|| servers.size()==0 || token==
"atlas_dd"
)
150
servers.push_back(std::move(token));
151
}
152
}
153
iofs1=iofs2+1;
154
}
155
// check the list of domains against the hostname to see if this
156
// set of servers is appropriate
157
bool
useit=
false
;
158
unsigned
int
bestlen=0;
159
for
(
const
std::string& d : domains) {
160
std::string::size_type len=d.size();
161
std::string::size_type hlen=
m_hostname
.size();
162
if
(hlen>=len && d==
m_hostname
.substr(hlen-len,len)) {
163
if
(len>bestlen) {
164
useit=
true
;
165
bestlen=len;
166
}
167
}
168
// for 'default' domain name, add the servers as a last resort
169
// if nothing has been found so far
170
if
(
"default"
==d &&
m_servermap
.empty()) {
171
ATH_MSG_INFO
(
"No specific match for domain found - use default fallback"
);
172
useit=
true
;
173
bestlen=0;
174
}
175
}
176
if
(useit) {
177
// assign these servers, priority based on position in list
178
// and length of match of domain name
179
for
(
unsigned
int
i=0;i<servers.size();++i) {
180
int
priority=i*5-100*bestlen;
181
// only add ATLF Frontier generic servers if allowed
182
if
(servers[i]!=
"ATLF"
||
m_frontiergen
) {
183
// give generic Frontier server higher (more negative) priority
184
// so it will be preferred over DBRelaese SQLite file
185
if
(servers[i]==
"ATLF"
) priority-=2000;
186
m_servermap
.push_back(
ServerPair
(servers[i],priority));
187
ATH_MSG_DEBUG
(
"Candidate server "
<< servers[i] <<
188
" (priority "
<< priority <<
")"
);
189
}
190
}
191
}
192
}
193
}
194
fclose(p_inp);
195
msg
() << MSG::INFO <<
"Total of "
<<
m_servermap
.size() <<
196
" servers found for host "
<<
m_hostname
<<
" ["
;
197
for
(
const
auto
& [name, pri] :
m_servermap
) {
198
msg
() << name <<
" "
;
199
}
200
msg
() <<
"]"
<<
endmsg
;
201
return
StatusCode::SUCCESS;
202
}
203
204
void
DBReplicaSvc::sort
(std::vector<const coral::IDatabaseServiceDescription*>& replicaSet) {
205
// if only one replica offered, return immediately
206
// this helps for online, where explicit configuration file is given
207
// that does not match any of the standard dbreplica.config entries
208
if
(replicaSet.size()<=1)
return
;
209
210
// loop through all the offered replicas
211
std::map<int,const coral::IDatabaseServiceDescription*> primap;
212
for
(
const
coral::IDatabaseServiceDescription* dbdescr : replicaSet) {
213
214
const
std::string conn=dbdescr->connectionString();
215
ATH_MSG_DEBUG
(
"Replica connection string: "
<< conn);
216
if
(conn.find(
"sqlite_file"
)!=std::string::npos) {
217
// include SQLite files unless they are vetoed
218
// COOL SQLIte files recognised by ALLP in connection string
219
// vetoed if use-SQlite flag not set, or pattern is found in
220
// SQLite filename
221
// Geometry SQLite files recognised by geomDB in connection string
222
if
(!( ((
m_usecoolsqlite
==
false
||
223
(
m_coolsqlitepattern
!=
""
&&
224
conn.find(
m_coolsqlitepattern
)!=std::string::npos))
225
&& conn.find(
"ALLP"
)!=std::string::npos)
226
|| ((
m_usegeomsqlite
==
false
||
227
(
m_coolsqlitepattern
!=
""
&&
228
conn.find(
m_coolsqlitepattern
)!=std::string::npos))
229
&& conn.find(
"geomDB"
)!=std::string::npos))) {
230
// local sqlite files get -9999, DB release ones
231
// (identified with path starting / or containing DBRelease)
232
// get -999, so local one will be tried first if present
233
if
(conn.find(
"sqlite_file:/"
)!=std::string::npos ||
234
conn.find(
"DBRelease"
)!=std::string::npos) {
235
primap[-999]=dbdescr;
236
}
else
{
237
primap[-9999]=dbdescr;
238
}
239
}
240
}
else
{
241
// define priority for technologies with this server (lower = better)
242
bool
veto
=
false
;
243
int
spri=5;
// default for Oracle
244
if
(conn.find(
"frontier:"
)!=std::string::npos) {
245
spri=3;
// use frontier before oracle
246
// dont use frontier servers if disabled, or generic Frontier server
247
// is specified (via '()' in server definition) and FRONTIER_SERVER
248
// env variable is not set
249
if
(!
m_usecoolfrontier
||
250
(conn.find(
"()"
)!=std::string::npos &&
m_frontiergen
==
false
))
251
veto
=
true
;
252
}
253
// extract the server name (assuming URLs "techno://server/schema")
254
std::string::size_type ipos1=conn.find(
"://"
);
255
std::string::size_type ipos2=conn.find(
'/'
,ipos1+3);
256
// for Frontier, have to remove the (..) part after the server name
257
// e.g. frontier://ATLAS_COOLPROD/(serverurl=http://xyzfrontier.cern.ch:8000/atlr)/schema
258
std::string::size_type ipos3=conn.find(
'('
,ipos1+3);
259
if
(ipos3!=std::string::npos && ipos3<ipos2) ipos2=ipos3;
260
if
(ipos1!=std::string::npos && ipos2!=std::string::npos && !
veto
) {
261
const
std::string server=conn.substr(ipos1+3,ipos2-ipos1-3);
262
// check if this server is on list of replicas to use for domain
263
// if so, add it with its associated priority
264
for
(
const
auto
& [name, pri] :
m_servermap
) {
265
if
(name==server) {
266
primap[pri+spri]=dbdescr;
267
}
268
}
269
}
270
}
271
}
272
// now create sorted list
273
replicaSet.clear();
274
for
(
const
auto
& [pri, db] : primap) {
275
replicaSet.push_back(db);
276
ATH_MSG_DEBUG
(
"Allowed replica to try (priority "
<< pri <<
") : "
<< db->connectionString());
277
}
278
if
(replicaSet.empty()) {
279
ATH_MSG_ERROR
(
"No matching replicas found"
);
280
}
281
ATH_MSG_DEBUG
(
"Retained total of "
<< replicaSet.size() <<
" replicas"
);
282
}
endmsg
#define endmsg
Definition
AnalysisConfig_Ntuple.cxx:54
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition
AthMsgStreamMacros.h:33
ATH_MSG_FATAL
#define ATH_MSG_FATAL(x)
Definition
AthMsgStreamMacros.h:34
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition
AthMsgStreamMacros.h:31
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition
AthMsgStreamMacros.h:29
DBReplicaSvc.h
sc
static Double_t sc
Definition
LArPhysWaveHECTool.cxx:37
PathResolver.h
DBReplicaSvc::m_retrialTimeOut
Gaudi::Property< int > m_retrialTimeOut
ConnectionRetrialTimeOut, the retrial time out for CORAL Connection Service: default = 300 seconds.
Definition
DBReplicaSvc.h:40
DBReplicaSvc::m_frontiergen
bool m_frontiergen
Definition
DBReplicaSvc.h:50
DBReplicaSvc::m_hostname
std::string m_hostname
Definition
DBReplicaSvc.h:51
DBReplicaSvc::m_connClean
Gaudi::Property< bool > m_connClean
ConnectionCleanUp - whether to use CORAL connection management thread: default = false.
Definition
DBReplicaSvc.h:44
DBReplicaSvc::initialize
virtual StatusCode initialize() override
Definition
DBReplicaSvc.cxx:21
DBReplicaSvc::m_testhost
Gaudi::Property< std::string > m_testhost
Definition
DBReplicaSvc.h:30
DBReplicaSvc::m_usegeomsqlite
Gaudi::Property< bool > m_usegeomsqlite
Definition
DBReplicaSvc.h:34
DBReplicaSvc::m_context
coral::Context * m_context
Definition
DBReplicaSvc.h:49
DBReplicaSvc::sort
void sort(std::vector< const coral::IDatabaseServiceDescription * > &replicaSet) override
Definition
DBReplicaSvc.cxx:204
DBReplicaSvc::m_timeOut
Gaudi::Property< int > m_timeOut
ConnectionTimeOut, the time out for CORAL Connection Service: default = 5 seconds.
Definition
DBReplicaSvc.h:42
DBReplicaSvc::ServerPair
std::pair< std::string, int > ServerPair
Definition
DBReplicaSvc.h:52
DBReplicaSvc::m_frontierComp
Gaudi::Property< int > m_frontierComp
Frontier proprties, compression level and list of schemas to be refreshed: default = 5.
Definition
DBReplicaSvc.h:46
DBReplicaSvc::m_retrialPeriod
Gaudi::Property< int > m_retrialPeriod
ConnectionRetrialPeriod, retry period for CORAL Connection Service: default = 30 seconds.
Definition
DBReplicaSvc.h:38
DBReplicaSvc::m_usecoolsqlite
Gaudi::Property< bool > m_usecoolsqlite
Definition
DBReplicaSvc.h:32
DBReplicaSvc::m_nofailover
Gaudi::Property< bool > m_nofailover
Definition
DBReplicaSvc.h:35
DBReplicaSvc::m_coolsqlitepattern
Gaudi::Property< std::string > m_coolsqlitepattern
Definition
DBReplicaSvc.h:31
DBReplicaSvc::m_servermap
std::vector< ServerPair > m_servermap
Definition
DBReplicaSvc.h:53
DBReplicaSvc::m_configfile
Gaudi::Property< std::string > m_configfile
Definition
DBReplicaSvc.h:29
DBReplicaSvc::readConfig
StatusCode readConfig()
Definition
DBReplicaSvc.cxx:108
DBReplicaSvc::m_usecoolfrontier
Gaudi::Property< bool > m_usecoolfrontier
Definition
DBReplicaSvc.h:33
PathResolver::find_file
static std::string find_file(const std::string &logical_file_name, const std::string &search_path)
Definition
PathResolver.cxx:220
veto
std::vector< std::string > veto
these patterns are anded
Definition
listroot.cxx:191
msg
MsgStream & msg
Definition
testRead.cxx:32
file
TFile * file
Definition
tile_monitor.h:29
Generated on
for ATLAS Offline Software by
1.17.0