LArSoft  v06_85_00
Liquid Argon Software toolkit - http://larsoft.org/
DatabaseUtil_service.cc
Go to the documentation of this file.
1 //
3 // DatabaseUtil_plugin
4 //
6 // Framework includes
7 
8 // C++ language includes
9 #include <iostream>
10 #include <fstream>
11 //#include <libpq-fe.h>
12 
13 // LArSoft includes
16 #include "cetlib_except/exception.h"
17 
18 //-----------------------------------------------
20 {
21  conn = NULL;
22  this->reconfigure(pset);
23  fChannelMap.clear();
24  fChannelReverseMap.clear();
25 }
26 
27 //------------------------------------------------
29 {
30 
31 }
32 
33 //----------------------------------------------
34 int util::DatabaseUtil::Connect(int conn_wait)
35 {
36  if(!fShouldConnect)
37  return -1;
38 
39  if(conn_wait)
40  sleep(conn_wait);
41 
42  conn = PQconnectdb(connection_str);
43  if (PQstatus(conn) == CONNECTION_BAD) {
44  mf::LogWarning("DatabaseUtil") << "Connection to database failed, "<<PQerrorMessage(conn)<<"\n";
45  if( ( strstr(PQerrorMessage(conn),"remaining connection slots are reserved")!=NULL ||
46  strstr(PQerrorMessage(conn),"sorry, too many clients already")!=NULL )
47  && conn_wait<20 ) {
48  conn_wait+=2;
49  mf::LogWarning("DatabaseUtil") << "retrying connection after " << conn_wait << " seconds \n";
50  return this->Connect(conn_wait);
51  }
53  throw cet::exception("DataBaseUtil") << " DB connection failed\n";
54 
55  } else {
56  LOG_DEBUG("DatabaseUtil")<<"Connected OK\n";
57  return 1;
58  }
59  return -1;
60 }
61 
62 
64 {
65  if(!fShouldConnect)
66  return -1;
67  //close connection
68  LOG_DEBUG("DatabaseUtil")<<"Closing Connection \n";
69  PQfinish(conn);
70  return 1;
71 }
72 
73 
74 
75 //------------------------------------------------
77 {
78  fDBHostName = pset.get< std::string >("DBHostName" );
79  fDBName = pset.get< std::string >("DBName" );
80  fDBUser = pset.get< std::string >("DBUser");
81  fTableName = pset.get< std::string >("TableName");
82  fPort = pset.get< int >("Port" );
83  fPassword = "";
84  fToughErrorTreatment = pset.get< bool >("ToughErrorTreatment");
85  fShouldConnect = pset.get< bool >("ShouldConnect");
86 
87  // constructor decides if initialized value is a path or an environment variable
88  std::string passfname;
89  cet::search_path sp("FW_SEARCH_PATH");
90  sp.find_file(pset.get< std::string >("PassFileName"), passfname);
91 
92  if (!passfname.empty()) {
93  std::ifstream in(passfname.c_str());
94  if(!in) {
96  << "Database password file '" << passfname
97  << "' not found in FW_SEARCH_PATH; using an empty password.\n";
98  }
99  std::getline(in, fPassword);
100  in.close();
101  }
102  else if (fShouldConnect){
104  << "Database password file '" << pset.get< std::string >("PassFileName")
105  << "' not found in FW_SEARCH_PATH; using an empty password.\n";
106  }
107 
108  sprintf(connection_str,"host=%s dbname=%s user=%s port=%d password=%s ",fDBHostName.c_str(),fDBName.c_str(),fDBUser.c_str(),fPort,fPassword.c_str());
109 
110  return;
111 }
112 
113 
114 
115 
116 int util::DatabaseUtil::SelectSingleFieldByQuery(std::vector<std::string> &value,const char * query)
117 {
118  PGresult *result;
119  char * string_val;
120 
121  if(this->Connect()==-1) {
122  if(fShouldConnect)
123  mf::LogWarning("DatabaseUtil")<< "DB Connection error \n";
124  else
125  mf::LogInfo("DatabaseUtil")<< "Not connecting to DB by choice. \n";
126  return -1;
127  }
128 
129  result = PQexec(conn, query);
130 
131  if (!result) {
132  mf::LogInfo("DatabaseUtil")<< "PQexec command failed, no error code\n";
133  return -1;
134  }
135  else if(PQresultStatus(result)!=PGRES_TUPLES_OK) {
136  if(PQresultStatus(result)==PGRES_COMMAND_OK)
137  LOG_DEBUG("DatabaseUtil")<<"Command executed OK, "<< PQcmdTuples(result) <<" rows affected\n";
138  else
139  mf::LogWarning("DatabaseUtil")<<"Command failed with code "
140  <<PQresStatus(PQresultStatus(result)) <<", error message "
141  <<PQresultErrorMessage(result)<<"\n";
142 
143  PQclear(result);
144  this->DisConnect();
145  return -1;
146  }
147  else {
148  // mf::LogInfo("DatabaseUtil")<<"Query may have returned data\n";
149  // mf::LogInfo("DatabaseUtil")<<"Number of rows returned: "<<PQntuples(result)
150  // <<", fields: "<<PQnfields(result)<<" \n";
151 
152  if(PQntuples(result)>=1){
153  for(int i=0;i<PQntuples(result);i++)
154  {
155  string_val=PQgetvalue(result,i,0);
156  value.push_back(string_val);
157  LOG_DEBUG("DatabaseUtil")<<" extracted value: "<<value[i] << "\n";
158  }
159  PQclear(result);
160  this->DisConnect();
161  return 0;
162  }
163  else {
164  mf::LogWarning("DatabaseUtil")<<"wrong number of rows returned:"<<PQntuples(result)<<"\n";
165  PQclear(result);
166  this->DisConnect();
167  return -1;
168  }
169  }
170 
171 
172 }
173 
174 
175 
176 int util::DatabaseUtil::GetTemperatureFromDB(int run,double &temp_real)
177 {
178  std::vector<std::string> retvalue;
179  char cond[30];
180  sprintf(cond,"run = %d",run);
181  int err=SelectFieldByName(retvalue,"temp",cond,fTableName.c_str());
182 
183  if(err!=-1 && retvalue.size()==1){
184  char * endstr;
185  temp_real=std::strtod(retvalue[0].c_str(),&endstr);
186  return 0;
187  }
188 
189  return -1;
190 
191 
192 }
193 
194 
195 
196 
197 int util::DatabaseUtil::GetEfieldValuesFromDB(int run,std::vector<double> &efield)
198 {
199 
200  std::vector<std::string> retvalue;
201 
202  char query[200];
203  sprintf(query,"SELECT EFbet FROM EField,%s WHERE Efield.FID = %s.FID AND run = %d ORDER BY planegap",fTableName.c_str(),fTableName.c_str(),run);
204  int err=SelectSingleFieldByQuery(retvalue,query);
205 
206  if(err!=-1 && retvalue.size()>=1){
207  efield.clear(); //clear value before setting new values
208  for(unsigned int i=0;i<retvalue.size();i++) {
209  char * endstr;
210  efield.push_back(std::strtod(retvalue[i].c_str(),&endstr));
211  }
212  return 0;
213  }
214 
215  return -1;
216 
217 }
218 
219 
220 
221 int util::DatabaseUtil::SelectFieldByName(std::vector<std::string> &value,
222  const char * field,
223  const char * condition,
224  const char * table) {
225 
226  char query[100];
227  sprintf(query,"SELECT %s FROM %s WHERE %s",field, table, condition);
228 
229  return SelectSingleFieldByQuery(value,query);
230 
231 }
232 
233 
234 
235 
236 
237 
238 
239 
240 int util::DatabaseUtil::GetLifetimeFromDB(int run,double &lftime_real) {
241 
242  // char query[100];
243  // sprintf(query,"SELECT tau FROM argoneut_test WHERE run = %d",run);
244 
245  std::vector<std::string> retvalue;
246  char cond[30];
247  sprintf(cond,"run = %d",run);
248  int err=SelectFieldByName(retvalue,"tau",cond,fTableName.c_str());
249 
250  if(err!=-1 && retvalue.size()==1){
251  char * endstr;
252  lftime_real=std::strtod(retvalue[0].c_str(),&endstr);
253  return 0;
254  }
255 
256 
257  return -1;
258 
259 }
260 
261 int util::DatabaseUtil::GetTriggerOffsetFromDB(int run,double &T0_real) {
262 
263  // char query[100];
264  // sprintf(query,"SELECT tau FROM argoneut_test WHERE run = %d",run);
265 
266  std::vector<std::string> retvalue;
267  char cond[30];
268  sprintf(cond,"run = %d",run);
269  int err=SelectFieldByName(retvalue,"T0",cond,fTableName.c_str());
270 
271  if(err!=-1 && retvalue.size()==1){
272  char * endstr;
273  T0_real=std::strtod(retvalue[0].c_str(),&endstr);
274  return 0;
275  }
276 
277 
278  return -1;
279 
280 }
281 
282 
283 int util::DatabaseUtil::GetPOTFromDB(int run,long double &POT) {
284 
285  // char query[100];
286  // sprintf(query,"SELECT tau FROM argoneut_test WHERE run = %d",run);
287 
288  std::vector<std::string> retvalue;
289  char cond[30];
290  sprintf(cond,"run = %d",run);
291  int err=SelectFieldByName(retvalue,"pot",cond,fTableName.c_str());
292 
293  if(err!=-1 && retvalue.size()==1){
294  char * endstr;
295  POT=std::strtold(retvalue[0].c_str(),&endstr);
296  return 0;
297  }
298 
299 
300  return -1;
301 
302 }
303 
304 namespace util {
305 
306  void DatabaseUtil::LoadUBChannelMap( int data_taking_timestamp, int swizzling_timestamp) {
307 
308  if ( fChannelMap.size()>0 ) {
309  // Use prevously grabbed data to avoid repeated call to database.
310  // Also this avoids inglorious segfault.
311  return;
312  }
313  if ( conn==NULL )
314  Connect( 0 );
315 
316  if(PQstatus(conn)!=CONNECTION_OK) {
317  mf::LogError("") << __PRETTY_FUNCTION__ << ": Couldn't open connection to postgresql interface" << PQdb(conn) <<":"<<PQhost(conn);
318  PQfinish(conn);
320  << "Failed to get channel map from DB."<< std::endl;
321  }
322 
323  fChannelMap.clear();
324  fChannelReverseMap.clear();
325 
326  PGresult *res = PQexec(conn, "BEGIN");
327  if (PQresultStatus(res) != PGRES_COMMAND_OK) {
328  mf::LogError("")<< "postgresql BEGIN failed";
329  PQclear(res);
330  PQfinish(conn);
332  << "postgresql BEGIN failed." << std::endl;
333  }
334 
335  // Jason St. John's updated call to versioned database.
336  // get_map_double_sec (data_taking_timestamp int DEFAULT now() ,
337  // swizzling_timestamp int DEFAULT now() )
338  // Returns rows of: crate, slot, fem_channel, larsoft_channel
339  // Both arguments are optional, or can be passed their default of now(), or can be passed an explicit timestamp:
340  // Example: "SELECT get_map_double_sec(1438430400);"
341  PQclear(res);
342 
343  char dbquery[200];
344  sprintf(dbquery, "SELECT get_map_double_sec(%i,%i);", data_taking_timestamp, swizzling_timestamp);
345  res = PQexec(conn, dbquery);
346 
347  if ((!res) || (PQresultStatus(res) != PGRES_TUPLES_OK) || (PQntuples(res) < 1))
348  {
349  mf::LogError("")<< "SELECT command did not return tuples properly. \n" << PQresultErrorMessage(res) << "Number rows: "<< PQntuples(res);
350  PQclear(res);
351  PQfinish(conn);
353  << "postgresql SELECT failed." << std::endl;
354  }
355 
356  int num_records=PQntuples(res); //One record per channel, ideally.
357 
358  for (int i=0;i<num_records;i++) {
359  std::string tup = PQgetvalue(res, i, 0); // (crate,slot,FEMch,larsoft_chan) format
360  tup = tup.substr(1,tup.length()-2); // Strip initial & final parentheses.
361  std::vector<std::string> fields;
362  split(tup, ',', fields); // Explode substrings into vector with comma delimiters.
363 
364  int crate_id = atoi( fields[0].c_str() );
365  int slot = atoi( fields[1].c_str() );
366  int boardChan = atoi( fields[2].c_str() );
367  int larsoft_chan = atoi( fields[3].c_str() );
368 
369  UBDaqID daq_id(crate_id,slot,boardChan);
370  std::pair<UBDaqID, UBLArSoftCh_t> p(daq_id,larsoft_chan);
371 
372  if ( fChannelMap.find(daq_id) != fChannelMap.end() ){
373  std::cout << __PRETTY_FUNCTION__ << ": ";
374  std::cout << "Multiple entries!" << std::endl;
375  mf::LogWarning("")<< "Multiple DB entries for same (crate,card,channel). "<<std::endl
376  << "Redefining (crate,card,channel)=>id link ("
377  << daq_id.crate<<", "<< daq_id.card<<", "<< daq_id.channel<<")=>"
378  << fChannelMap.find(daq_id)->second;
379  }
380 
381  fChannelMap.insert( p );
382  fChannelReverseMap.insert( std::pair< UBLArSoftCh_t, UBDaqID >( larsoft_chan, daq_id ) );
383  }
384  this->DisConnect();
385  }// end of LoadUBChannelMap
386 
387  UBChannelMap_t DatabaseUtil::GetUBChannelMap( int data_taking_timestamp, int swizzling_timestamp ) {
388  LoadUBChannelMap( data_taking_timestamp, swizzling_timestamp );
389  return fChannelMap;
390  }
391 
392  UBChannelReverseMap_t DatabaseUtil::GetUBChannelReverseMap( int data_taking_timestamp, int swizzling_timestamp ) {
393  LoadUBChannelMap( data_taking_timestamp, swizzling_timestamp );
394  return fChannelReverseMap;
395  }
396 
397  // Handy, typical string-splitting-to-vector function.
398  // I hate C++ strong typing and string handling so very, very much.
399  std::vector<std::string> & DatabaseUtil::split(const std::string &s, char delim, std::vector<std::string> &elems) {
400  std::stringstream ss(s);
401  std::string item;
402  while (std::getline(ss, item, delim)) {
403  elems.push_back(item);
404  }
405  return elems;
406  }
407 
408 
409 }
410 
411 
412 
413 namespace util{
414 
416 
417 } // namespace util
418 
419 
int GetTriggerOffsetFromDB(int run, double &T0_real)
Float_t s
Definition: plot.C:23
Namespace for general, non-LArSoft-specific utilities.
Definition: PIDAAlg.h:17
std::string fPassword
Definition: DatabaseUtil.h:86
int GetEfieldValuesFromDB(int run, std::vector< double > &efield)
std::string fDBName
Definition: DatabaseUtil.h:82
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
#define DEFINE_ART_SERVICE(svc)
Definition: ServiceMacros.h:93
Float_t ss
Definition: plot.C:23
MaybeLogger_< ELseverityLevel::ELsev_error, false > LogError
UBChannelMap_t GetUBChannelMap(int data_taking_timestamp=-1, int swizzling_timestamp=-1)
UBChannelReverseMap_t GetUBChannelReverseMap(int data_taking_timestamp=-1, int swizzling_timestamp=-1)
int SelectSingleFieldByQuery(std::vector< std::string > &value, const char *query)
std::string fDBHostName
Definition: DatabaseUtil.h:81
int GetPOTFromDB(int run, long double &POT)
T get(std::string const &key) const
Definition: ParameterSet.h:231
char connection_str[200]
Definition: DatabaseUtil.h:78
int GetLifetimeFromDB(int run, double &lftime_real)
void reconfigure(fhicl::ParameterSet const &pset)
std::string fTableName
Definition: DatabaseUtil.h:84
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
DatabaseUtil(fhicl::ParameterSet const &pset, art::ActivityRegistry &reg)
void LoadUBChannelMap(int data_taking_timestamp=-1, int swizzling_timestamp=-1)
ifstream in
Definition: comparison.C:7
std::string value(boost::any const &)
pg_result PGresult
Definition: Table.h:19
int SelectFieldByName(std::vector< std::string > &value, const char *field, const char *condition, const char *table)
std::map< UBDaqID, UBLArSoftCh_t > UBChannelMap_t
Definition: DatabaseUtil.h:48
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
int Connect(int conn_wait=0)
std::vector< std::string > & split(const std::string &s, char delim, std::vector< std::string > &elems)
#define LOG_DEBUG(id)
std::map< UBLArSoftCh_t, UBDaqID > UBChannelReverseMap_t
Definition: DatabaseUtil.h:49
std::string fDBUser
Definition: DatabaseUtil.h:83
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
UBChannelReverseMap_t fChannelReverseMap
Definition: DatabaseUtil.h:91
int GetTemperatureFromDB(int run, double &temp_real)
UBChannelMap_t fChannelMap
Definition: DatabaseUtil.h:90