ATLAS Offline Software
DBReplicaSvc.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2017 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 <fstream>
9 #include <cstring>
10 #include "GaudiKernel/MsgStream.h"
12 #include "DBReplicaSvc.h"
13 
14 DBReplicaSvc::DBReplicaSvc(const std::string& name, ISvcLocator* svc) :
16  m_configfile("dbreplica.config"),
17  m_testhost(""),
18  m_coolsqlitepattern(""),
19  m_usecoolsqlite(true),
20  m_usecoolfrontier(true),
21  m_usegeomsqlite(true),
22  m_nofailover(false),
23  m_frontiergen(false)
24 {
25  declareProperty("ConfigFile",m_configfile);
26  declareProperty("TestHost",m_testhost);
27  declareProperty("COOLSQLiteVetoPattern",m_coolsqlitepattern);
28  declareProperty("UseCOOLSQLite",m_usecoolsqlite);
29  declareProperty("UseCOOLFrontier",m_usecoolfrontier);
30  declareProperty("UseGeomSQLite",m_usegeomsqlite);
31  declareProperty("DisableFailover",m_nofailover);
32 }
33 
35 
36 const InterfaceID& DBReplicaSvc::type() const
37 {
39 }
40 
41 StatusCode DBReplicaSvc::queryInterface(const InterfaceID& riid, void** ppvInterface)
42 {
43  if (IDBReplicaSvc::interfaceID().versionMatch(riid)) {
44  *ppvInterface=(IDBReplicaSvc*)this;
45  } else {
46  return AthService::queryInterface(riid,ppvInterface);
47  }
48  return StatusCode::SUCCESS;
49 }
50 
52  // service initialisation
53  if (StatusCode::SUCCESS!=AthService::initialize()) return StatusCode::FAILURE;
54  // determine the hostname (or override if from joboption)
56  // if nothing set on job-options, try environment variable ATLAS_CONDDB
57  if (m_hostname.empty()) {
58  const char* chost=getenv("ATLAS_CONDDB");
59  if (chost) m_hostname=chost;
60  }
61  // if ATLAS_CONDDB not set, try environment variable HOSTNAME
62  if (m_hostname.empty()) {
63  const char* chost=getenv("HOSTNAME");
64  if (chost) m_hostname=chost;
65  // check if the returned host has a .
66  if (m_hostname.find('.')==std::string::npos) {
67  ATH_MSG_DEBUG("HOSTNAME " << m_hostname
68  << " has no domain - try hostname --fqdn");
69  m_hostname="unknown";
70 #ifndef __APPLE__
71  system("hostname --fqdn > hostnamelookup.tmp");
72 #else
73  // Unfortunately Leopard doesn't understand the -f option to hostname, only Snow Leopard does
74  system("hostname > hostnamelookup.tmp");
75 #endif
76  std::ifstream infile;
77  infile.open("hostnamelookup.tmp");
78  if (infile) {
79  infile >> m_hostname;
80  ATH_MSG_DEBUG ("HOSTNAME from fqdn: " << m_hostname);
81  } else {
82  m_hostname="unknown";
83  }
84  }
85  }
86  // check if FRONTIER_SERVER is set, if so, allow generic replicas
87  const char* cfrontier=getenv("FRONTIER_SERVER");
88  if (m_usecoolfrontier && cfrontier && strcmp(cfrontier,"")!=0) {
89  ATH_MSG_INFO ("Frontier server at " << cfrontier
90  << " will be considered for COOL data");
91  m_frontiergen=true;
92  }
94  if (!m_usecoolsqlite) {
95  ATH_MSG_INFO ("COOL SQLite replicas will be excluded");
96  } else if (m_coolsqlitepattern!="") {
97  ATH_MSG_INFO ("COOL SQLite replicas will be excluded if matching pattern "
99  }
100  if (!m_usecoolfrontier)
101  ATH_MSG_INFO ("COOL Frontier replicas will be excluded");
102  if (!m_usegeomsqlite)
103  ATH_MSG_INFO ("Geometry SQLite replicas will be excluded");
104  if (m_nofailover)
105  ATH_MSG_INFO ("Failover to secondary replicas disabled");
106  return sc;
107 }
108 
110  return StatusCode::SUCCESS;
111 }
112 
114 
115 
116  // try to locate the file using pathresolver
117  std::string file=PathResolver::find_file(m_configfile,"DATAPATH");
118  if (file.empty()) {
119  ATH_MSG_ERROR ("Cannot locate configuration file " << m_configfile);
120  return StatusCode::FAILURE;
121  }
122  // open and read the file
123  ATH_MSG_INFO ("Read replica configuration from " << file);
124  FILE* p_inp=fopen(file.c_str(),"r");
125  if (p_inp==0) {
126  ATH_MSG_ERROR ("Cannot open configuration file");
127  return StatusCode::FAILURE;
128  }
129  // buffer for reading line
130  const unsigned int bufsize=999;
131  char p_buf[bufsize];
132  while (!feof(p_inp)) {
133  char* p_line=fgets(p_buf,bufsize,p_inp);
134  if (p_line!=NULL && p_line[0]!='#') {
135  std::string buf=std::string(p_line);
136  std::string::size_type iofs1=0;
137  // analyse based on spaces as seperator
138  bool sequal=false;
139  std::vector<std::string> domains;
140  std::vector<std::string> servers;
141  while (iofs1<buf.size()) {
142  std::string::size_type iofs2=buf.find(' ',iofs1);
143  // allow for trailing linefeed
144  if (iofs2==std::string::npos) iofs2=buf.size()-1;
145  std::string token=buf.substr(iofs1,iofs2-iofs1);
146  // skip empty or space tokens
147  if (token!="" && token!=" ") {
148  if (token=="=") {
149  sequal=true;
150  } else if (!sequal) {
151  // token is a domain name
152  domains.push_back(token);
153  } else {
154  // token is a server name
155  if (!m_nofailover || servers.size()==0 || token=="atlas_dd")
156  servers.push_back(token);
157  }
158  }
159  iofs1=iofs2+1;
160  }
161  // check the list of domains against the hostname to see if this
162  // set of servers is appropriate
163  bool useit=false;
164  unsigned int bestlen=0;
165  for (std::vector<std::string>::const_iterator itr=domains.begin();
166  itr!=domains.end();++itr) {
167  std::string::size_type len=(itr->size());
168  std::string::size_type hlen=m_hostname.size();
169  if (hlen>=len && *itr==m_hostname.substr(hlen-len,len)) {
170  if (len>bestlen) {
171  useit=true;
172  bestlen=len;
173  }
174  }
175  // for 'default' domain name, add the servers as a last resort
176  // if nothing has been found so far
177  if ("default"==*itr && m_servermap.empty()) {
178  ATH_MSG_INFO ("No specific match for domain found - use default fallback");
179  useit=true;
180  bestlen=0;
181  }
182  }
183  if (useit) {
184  // assign these servers, priority based on position in list
185  // and length of match of domain name
186  for (unsigned int i=0;i<servers.size();++i) {
187  int priority=i*5-100*bestlen;
188  // only add ATLF Frontier generic servers if allowed
189  if (servers[i]!="ATLF" || m_frontiergen) {
190  // give generic Frontier server higher (more negative) priority
191  // so it will be preferred over DBRelaese SQLite file
192  if (servers[i]=="ATLF") priority-=2000;
193  m_servermap.push_back(ServerPair(servers[i],priority));
194  ATH_MSG_DEBUG ("Candidate server " << servers[i] <<
195  " (priority " << priority << ")");
196  }
197  }
198  }
199  }
200  }
201  fclose(p_inp);
202  msg() << MSG::INFO << "Total of " << m_servermap.size() <<
203  " servers found for host " << m_hostname << " [";
204  for (ServerMap::const_iterator itr=m_servermap.begin();
205  itr!=m_servermap.end();++itr) msg() << itr->first << " ";
206  msg() << "]" << endmsg;
207  return StatusCode::SUCCESS;
208 }
209 
210 void DBReplicaSvc::sort(std::vector<const
211  coral::IDatabaseServiceDescription*>& replicaSet) {
212  // if only one replica offered, return immediately
213  // this helps for online, where explicit configuration file is given
214  // that does not match any of the standard dbreplica.config entries
215  if (replicaSet.size()<=1) return;
216 
217  // loop through all the offered replicas
218  std::map<int,const coral::IDatabaseServiceDescription*> primap;
219  for (std::vector<const coral::IDatabaseServiceDescription*>::const_iterator
220  itr=replicaSet.begin();itr!=replicaSet.end();++itr) {
221  const std::string conn=(**itr).connectionString();
222  ATH_MSG_DEBUG ("Replica connection string: " << conn);
223  if (conn.find("sqlite_file")!=std::string::npos) {
224  // include SQLite files unless they are vetoed
225  // COOL SQLIte files recognised by ALLP in connection string
226  // vetoed if use-SQlite flag not set, or pattern is found in
227  // SQLite filename
228  // Geometry SQLite files recognised by geomDB in connection string
229  if (!( ((m_usecoolsqlite==false ||
230  (m_coolsqlitepattern!="" &&
231  conn.find(m_coolsqlitepattern)!=std::string::npos))
232  && conn.find("ALLP")!=std::string::npos)
233  || ((m_usegeomsqlite==false ||
234  (m_coolsqlitepattern!="" &&
235  conn.find(m_coolsqlitepattern)!=std::string::npos))
236  && conn.find("geomDB")!=std::string::npos))) {
237  // local sqlite files get -9999, DB release ones
238  // (identified with path starting / or containing DBRelease)
239  // get -999, so local one will be tried first if present
240  if (conn.find("sqlite_file:/")!=std::string::npos ||
241  conn.find("DBRelease")!=std::string::npos) {
242  primap[-999]=*itr;
243  } else {
244  primap[-9999]=*itr;
245  }
246  }
247  } else {
248  // define priority for technologies with this server (lower = better)
249  bool veto=false;
250  int spri=5; // default for Oracle
251  if (conn.find("frontier:")!=std::string::npos) {
252  spri=3; // use frontier before oracle
253  // dont use frontier servers if disabled, or generic Frontier server
254  // is specified (via '()' in server definition) and FRONTIER_SERVER
255  // env variable is not set
256  if (!m_usecoolfrontier ||
257  (conn.find("()")!=std::string::npos && m_frontiergen==false))
258  veto=true;
259  }
260  // extract the server name (assuming URLs "techno://server/schema")
261  std::string::size_type ipos1=conn.find("://");
262  std::string::size_type ipos2=conn.find('/',ipos1+3);
263  // for Frontier, have to remove the (..) part after the server name
264  // e.g. frontier://ATLAS_COOLPROD/(serverurl=http://xyzfrontier.cern.ch:8000/atlr)/schema
265  std::string::size_type ipos3=conn.find('(',ipos1+3);
266  if (ipos3!=std::string::npos && ipos3<ipos2) ipos2=ipos3;
267  if (ipos1!=std::string::npos && ipos2!=std::string::npos && !veto) {
268  const std::string server=conn.substr(ipos1+3,ipos2-ipos1-3);
269  // check if this server is on list of replicas to use for domain
270  // if so, add it with its associated priority
271  for (ServerMap::const_iterator sitr=m_servermap.begin();
272  sitr!=m_servermap.end();++sitr) {
273  if (sitr->first==server)
274  primap[sitr->second+spri]=*itr;
275  }
276  }
277  }
278  }
279  // now create sorted list
280  replicaSet.clear();
281  for (std::map<int,const coral::IDatabaseServiceDescription*>::const_iterator
282  itr=primap.begin();itr!=primap.end();++itr) {
283  replicaSet.push_back(itr->second);
284  ATH_MSG_DEBUG ("Allowed replica to try (priority " << itr->first <<
285  ") : " << (itr->second)->connectionString());
286  }
287  if (replicaSet.empty())
288  ATH_MSG_ERROR ("No matching replicas found");
289  ATH_MSG_DEBUG ("Retained total of " << replicaSet.size() << " replicas");
290 }
DBReplicaSvc::type
virtual const InterfaceID & type() const
Definition: DBReplicaSvc.cxx:36
checkCorrelInHIST.conn
conn
Definition: checkCorrelInHIST.py:25
DBReplicaSvc::m_usecoolfrontier
bool m_usecoolfrontier
Definition: DBReplicaSvc.h:39
run.infile
string infile
Definition: run.py:13
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
PathResolver::find_file
static std::string find_file(const std::string &logical_file_name, const std::string &search_path, SearchType search_type=LocalSearch)
Definition: PathResolver.cxx:251
DBReplicaSvc::m_nofailover
bool m_nofailover
Definition: DBReplicaSvc.h:41
initialize
void initialize()
Definition: run_EoverP.cxx:894
DBReplicaSvc::m_servermap
ServerMap m_servermap
Definition: DBReplicaSvc.h:47
DBReplicaSvc::m_usecoolsqlite
bool m_usecoolsqlite
Definition: DBReplicaSvc.h:38
python.selector.AtlRunQuerySelectorLhcOlc.priority
priority
Definition: AtlRunQuerySelectorLhcOlc.py:611
DBReplicaSvc::initialize
virtual StatusCode initialize()
Definition: DBReplicaSvc.cxx:51
DBReplicaSvc::finalize
virtual StatusCode finalize()
Definition: DBReplicaSvc.cxx:109
AthenaPoolTestRead.sc
sc
Definition: AthenaPoolTestRead.py:27
DBReplicaSvc::ServerPair
std::pair< std::string, int > ServerPair
Definition: DBReplicaSvc.h:45
DBReplicaSvc::m_hostname
std::string m_hostname
Definition: DBReplicaSvc.h:44
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
DBReplicaSvc::readConfig
StatusCode readConfig()
Definition: DBReplicaSvc.cxx:113
lumiFormat.i
int i
Definition: lumiFormat.py:92
DBReplicaSvc::m_usegeomsqlite
bool m_usegeomsqlite
Definition: DBReplicaSvc.h:40
endmsg
#define endmsg
Definition: AnalysisConfig_Ntuple.cxx:63
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
DBReplicaSvc.h
AthService
Definition: AthService.h:32
file
TFile * file
Definition: tile_monitor.h:29
Handler::svc
AthROOTErrorHandlerSvc * svc
Definition: AthROOTErrorHandlerSvc.cxx:10
IDBReplicaSvc::interfaceID
static const InterfaceID & interfaceID()
Definition: IDBReplicaSvc.h:20
DBReplicaSvc::queryInterface
virtual StatusCode queryInterface(const InterfaceID &riid, void **ppvInterface)
Definition: DBReplicaSvc.cxx:41
PathResolver.h
DBReplicaSvc::DBReplicaSvc
DBReplicaSvc(const std::string &name, ISvcLocator *svc)
Definition: DBReplicaSvc.cxx:14
DBReplicaSvc::m_coolsqlitepattern
std::string m_coolsqlitepattern
Definition: DBReplicaSvc.h:37
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:195
DBReplicaSvc::m_frontiergen
bool m_frontiergen
Definition: DBReplicaSvc.h:43
SCT_ConditionsAlgorithms::CoveritySafe::getenv
std::string getenv(const std::string &variableName)
get an environment variable
Definition: SCT_ConditionsUtilities.cxx:17
DBReplicaSvc::m_configfile
std::string m_configfile
Definition: DBReplicaSvc.h:35
AthCommonMsg< Service >::msg
MsgStream & msg() const
Definition: AthCommonMsg.h:24
DBReplicaSvc::m_testhost
std::string m_testhost
Definition: DBReplicaSvc.h:36
DBReplicaSvc::sort
void sort(std::vector< const coral::IDatabaseServiceDescription * > &replicaSet)
Definition: DBReplicaSvc.cxx:210
declareProperty
#define declareProperty(n, p, h)
Definition: BaseFakeBkgTool.cxx:15
DBReplicaSvc::~DBReplicaSvc
virtual ~DBReplicaSvc()
Definition: DBReplicaSvc.cxx:34
veto
std::vector< std::string > veto
these patterns are anded
Definition: listroot.cxx:191
python.html.AtlRunQueryDQSummary.server
server
Definition: AtlRunQueryDQSummary.py:22
IDBReplicaSvc
Definition: IDBReplicaSvc.h:15