All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DatabaseUtil.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // DatabaseUtil_plugin
4 //
5 ////////////////////////////////////////////////////////////////////////
6 // Framework includes
7 
8 // C++ language includes
9 #include <iostream>
10 #include <fstream>
11 //#include <libpq-fe.h>
12 
13 // LArSoft includes
15 #include "messagefacility/MessageLogger/MessageLogger.h"
16 #include "cetlib_except/exception.h"
17 
18 //-----------------------------------------------
19 util::DatabaseUtil::DatabaseUtil(fhicl::ParameterSet const& pset)
20 {
21  conn = NULL;
22  this->reconfigure(pset);
23  fChannelMap.clear();
24  fChannelReverseMap.clear();
25 }
26 
27 //----------------------------------------------
28 int util::DatabaseUtil::Connect(int conn_wait)
29 {
30  if(!fShouldConnect)
31  return -1;
32 
33  if(conn_wait)
34  sleep(conn_wait);
35 
36  conn = PQconnectdb(connection_str);
37  if (PQstatus(conn) == CONNECTION_BAD) {
38  mf::LogWarning("DatabaseUtil") << "Connection to database failed, "<<PQerrorMessage(conn)<<"\n";
39  if( ( strstr(PQerrorMessage(conn),"remaining connection slots are reserved")!=NULL ||
40  strstr(PQerrorMessage(conn),"sorry, too many clients already")!=NULL )
41  && conn_wait<20 ) {
42  conn_wait+=2;
43  mf::LogWarning("DatabaseUtil") << "retrying connection after " << conn_wait << " seconds \n";
44  return this->Connect(conn_wait);
45  }
46  if(fToughErrorTreatment)
47  throw cet::exception("DataBaseUtil") << " DB connection failed\n";
48 
49  } else {
50  MF_LOG_DEBUG("DatabaseUtil")<<"Connected OK\n";
51  return 1;
52  }
53  return -1;
54 }
55 
56 
58 {
59  if(!fShouldConnect)
60  return -1;
61  //close connection
62  MF_LOG_DEBUG("DatabaseUtil")<<"Closing Connection \n";
63  PQfinish(conn);
64  return 1;
65 }
66 
67 
68 
69 //------------------------------------------------
70 void util::DatabaseUtil::reconfigure(fhicl::ParameterSet const& pset)
71 {
72  fDBHostName = pset.get< std::string >("DBHostName" );
73  fDBName = pset.get< std::string >("DBName" );
74  fDBUser = pset.get< std::string >("DBUser");
75  fTableName = pset.get< std::string >("TableName");
76  fPort = pset.get< int >("Port" );
77  fPassword = "";
78  fToughErrorTreatment = pset.get< bool >("ToughErrorTreatment");
79  fShouldConnect = pset.get< bool >("ShouldConnect");
80 
81  // constructor decides if initialized value is a path or an environment variable
82  std::string passfname;
83  cet::search_path sp("FW_SEARCH_PATH");
84  sp.find_file(pset.get< std::string >("PassFileName"), passfname);
85 
86  if (!passfname.empty()) {
87  std::ifstream in(passfname.c_str());
88  if(!in) {
89  throw art::Exception(art::errors::NotFound)
90  << "Database password file '" << passfname
91  << "' not found in FW_SEARCH_PATH; using an empty password.\n";
92  }
93  std::getline(in, fPassword);
94  in.close();
95  }
96  else if (fShouldConnect){
97  throw art::Exception(art::errors::NotFound)
98  << "Database password file '" << pset.get< std::string >("PassFileName")
99  << "' not found in FW_SEARCH_PATH; using an empty password.\n";
100  }
101 
102  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());
103 
104  return;
105 }
106 
107 
108 
109 
110 int util::DatabaseUtil::SelectSingleFieldByQuery(std::vector<std::string> &value,const char * query)
111 {
112  PGresult *result;
113  char * string_val;
114 
115  if(this->Connect()==-1) {
116  if(fShouldConnect)
117  mf::LogWarning("DatabaseUtil")<< "DB Connection error \n";
118  else
119  mf::LogInfo("DatabaseUtil")<< "Not connecting to DB by choice. \n";
120  return -1;
121  }
122 
123  result = PQexec(conn, query);
124 
125  if (!result) {
126  mf::LogInfo("DatabaseUtil")<< "PQexec command failed, no error code\n";
127  return -1;
128  }
129  else if(PQresultStatus(result)!=PGRES_TUPLES_OK) {
130  if(PQresultStatus(result)==PGRES_COMMAND_OK)
131  MF_LOG_DEBUG("DatabaseUtil")<<"Command executed OK, "<< PQcmdTuples(result) <<" rows affected\n";
132  else
133  mf::LogWarning("DatabaseUtil")<<"Command failed with code "
134  <<PQresStatus(PQresultStatus(result)) <<", error message "
135  <<PQresultErrorMessage(result)<<"\n";
136 
137  PQclear(result);
138  this->DisConnect();
139  return -1;
140  }
141  else {
142  // mf::LogInfo("DatabaseUtil")<<"Query may have returned data\n";
143  // mf::LogInfo("DatabaseUtil")<<"Number of rows returned: "<<PQntuples(result)
144  // <<", fields: "<<PQnfields(result)<<" \n";
145 
146  if(PQntuples(result)>=1){
147  for(int i=0;i<PQntuples(result);i++)
148  {
149  string_val=PQgetvalue(result,i,0);
150  value.push_back(string_val);
151  MF_LOG_DEBUG("DatabaseUtil")<<" extracted value: "<<value[i] << "\n";
152  }
153  PQclear(result);
154  this->DisConnect();
155  return 0;
156  }
157  else {
158  mf::LogWarning("DatabaseUtil")<<"wrong number of rows returned:"<<PQntuples(result)<<"\n";
159  PQclear(result);
160  this->DisConnect();
161  return -1;
162  }
163  }
164 
165 
166 }
167 
168 
169 
170 int util::DatabaseUtil::GetTemperatureFromDB(int run,double &temp_real)
171 {
172  std::vector<std::string> retvalue;
173  char cond[30];
174  sprintf(cond,"run = %d",run);
175  int err=SelectFieldByName(retvalue,"temp",cond,fTableName.c_str());
176 
177  if(err!=-1 && retvalue.size()==1){
178  char * endstr;
179  temp_real=std::strtod(retvalue[0].c_str(),&endstr);
180  return 0;
181  }
182 
183  return -1;
184 
185 
186 }
187 
188 
189 
190 
191 int util::DatabaseUtil::GetEfieldValuesFromDB(int run,std::vector<double> &efield)
192 {
193 
194  std::vector<std::string> retvalue;
195 
196  char query[200];
197  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);
198  int err=SelectSingleFieldByQuery(retvalue,query);
199 
200  if(err!=-1 && retvalue.size()>=1){
201  efield.clear(); //clear value before setting new values
202  for(unsigned int i=0;i<retvalue.size();i++) {
203  char * endstr;
204  efield.push_back(std::strtod(retvalue[i].c_str(),&endstr));
205  }
206  return 0;
207  }
208 
209  return -1;
210 
211 }
212 
213 
214 
215 int util::DatabaseUtil::SelectFieldByName(std::vector<std::string> &value,
216  const char * field,
217  const char * condition,
218  const char * table) {
219 
220  char query[100];
221  sprintf(query,"SELECT %s FROM %s WHERE %s",field, table, condition);
222 
223  return SelectSingleFieldByQuery(value,query);
224 
225 }
226 
227 
228 
229 
230 
231 
232 
233 
234 int util::DatabaseUtil::GetLifetimeFromDB(int run,double &lftime_real) {
235 
236  // char query[100];
237  // sprintf(query,"SELECT tau FROM argoneut_test WHERE run = %d",run);
238 
239  std::vector<std::string> retvalue;
240  char cond[30];
241  sprintf(cond,"run = %d",run);
242  int err=SelectFieldByName(retvalue,"tau",cond,fTableName.c_str());
243 
244  if(err!=-1 && retvalue.size()==1){
245  char * endstr;
246  lftime_real=std::strtod(retvalue[0].c_str(),&endstr);
247  return 0;
248  }
249 
250 
251  return -1;
252 
253 }
254 
255 int util::DatabaseUtil::GetTriggerOffsetFromDB(int run,double &T0_real) {
256 
257  // char query[100];
258  // sprintf(query,"SELECT tau FROM argoneut_test WHERE run = %d",run);
259 
260  std::vector<std::string> retvalue;
261  char cond[30];
262  sprintf(cond,"run = %d",run);
263  int err=SelectFieldByName(retvalue,"T0",cond,fTableName.c_str());
264 
265  if(err!=-1 && retvalue.size()==1){
266  char * endstr;
267  T0_real=std::strtod(retvalue[0].c_str(),&endstr);
268  return 0;
269  }
270 
271 
272  return -1;
273 
274 }
275 
276 
277 int util::DatabaseUtil::GetPOTFromDB(int run,long double &POT) {
278 
279  // char query[100];
280  // sprintf(query,"SELECT tau FROM argoneut_test WHERE run = %d",run);
281 
282  std::vector<std::string> retvalue;
283  char cond[30];
284  sprintf(cond,"run = %d",run);
285  int err=SelectFieldByName(retvalue,"pot",cond,fTableName.c_str());
286 
287  if(err!=-1 && retvalue.size()==1){
288  char * endstr;
289  POT=std::strtold(retvalue[0].c_str(),&endstr);
290  return 0;
291  }
292 
293 
294  return -1;
295 
296 }
297 
298 namespace util {
299 
300  void DatabaseUtil::LoadUBChannelMap( int data_taking_timestamp, int swizzling_timestamp) {
301 
302  if ( fChannelMap.size()>0 ) {
303  // Use prevously grabbed data to avoid repeated call to database.
304  // Also this avoids inglorious segfault.
305  return;
306  }
307  if ( conn==NULL )
308  Connect( 0 );
309 
310  if(PQstatus(conn)!=CONNECTION_OK) {
311  mf::LogError("") << __PRETTY_FUNCTION__ << ": Couldn't open connection to postgresql interface" << PQdb(conn) <<":"<<PQhost(conn);
312  PQfinish(conn);
313  throw art::Exception( art::errors::FileReadError )
314  << "Failed to get channel map from DB."<< std::endl;
315  }
316 
317  fChannelMap.clear();
318  fChannelReverseMap.clear();
319 
320  PGresult *res = PQexec(conn, "BEGIN");
321  if (PQresultStatus(res) != PGRES_COMMAND_OK) {
322  mf::LogError("")<< "postgresql BEGIN failed";
323  PQclear(res);
324  PQfinish(conn);
325  throw art::Exception( art::errors::FileReadError )
326  << "postgresql BEGIN failed." << std::endl;
327  }
328 
329  // Jason St. John's updated call to versioned database.
330  // get_map_double_sec (data_taking_timestamp int DEFAULT now() ,
331  // swizzling_timestamp int DEFAULT now() )
332  // Returns rows of: crate, slot, fem_channel, larsoft_channel
333  // Both arguments are optional, or can be passed their default of now(), or can be passed an explicit timestamp:
334  // Example: "SELECT get_map_double_sec(1438430400);"
335  PQclear(res);
336 
337  char dbquery[200];
338  sprintf(dbquery, "SELECT get_map_double_sec(%i,%i);", data_taking_timestamp, swizzling_timestamp);
339  res = PQexec(conn, dbquery);
340 
341  if ((!res) || (PQresultStatus(res) != PGRES_TUPLES_OK) || (PQntuples(res) < 1))
342  {
343  mf::LogError("")<< "SELECT command did not return tuples properly. \n" << PQresultErrorMessage(res) << "Number rows: "<< PQntuples(res);
344  PQclear(res);
345  PQfinish(conn);
346  throw art::Exception( art::errors::FileReadError )
347  << "postgresql SELECT failed." << std::endl;
348  }
349 
350  int num_records=PQntuples(res); //One record per channel, ideally.
351 
352  for (int i=0;i<num_records;i++) {
353  std::string tup = PQgetvalue(res, i, 0); // (crate,slot,FEMch,larsoft_chan) format
354  tup = tup.substr(1,tup.length()-2); // Strip initial & final parentheses.
355  std::vector<std::string> fields;
356  split(tup, ',', fields); // Explode substrings into vector with comma delimiters.
357 
358  int crate_id = atoi( fields[0].c_str() );
359  int slot = atoi( fields[1].c_str() );
360  int boardChan = atoi( fields[2].c_str() );
361  int larsoft_chan = atoi( fields[3].c_str() );
362 
363  UBDaqID daq_id(crate_id,slot,boardChan);
364  std::pair<UBDaqID, UBLArSoftCh_t> p(daq_id,larsoft_chan);
365 
366  if ( fChannelMap.find(daq_id) != fChannelMap.end() ){
367  std::cout << __PRETTY_FUNCTION__ << ": ";
368  std::cout << "Multiple entries!" << std::endl;
369  mf::LogWarning("")<< "Multiple DB entries for same (crate,card,channel). "<<std::endl
370  << "Redefining (crate,card,channel)=>id link ("
371  << daq_id.crate<<", "<< daq_id.card<<", "<< daq_id.channel<<")=>"
372  << fChannelMap.find(daq_id)->second;
373  }
374 
375  fChannelMap.insert( p );
376  fChannelReverseMap.insert( std::pair< UBLArSoftCh_t, UBDaqID >( larsoft_chan, daq_id ) );
377  }
378  this->DisConnect();
379  }// end of LoadUBChannelMap
380 
381  UBChannelMap_t DatabaseUtil::GetUBChannelMap( int data_taking_timestamp, int swizzling_timestamp ) {
382  LoadUBChannelMap( data_taking_timestamp, swizzling_timestamp );
383  return fChannelMap;
384  }
385 
386  UBChannelReverseMap_t DatabaseUtil::GetUBChannelReverseMap( int data_taking_timestamp, int swizzling_timestamp ) {
387  LoadUBChannelMap( data_taking_timestamp, swizzling_timestamp );
388  return fChannelReverseMap;
389  }
390 
391  // Handy, typical string-splitting-to-vector function.
392  // I hate C++ strong typing and string handling so very, very much.
393  std::vector<std::string> & DatabaseUtil::split(const std::string &s, char delim, std::vector<std::string> &elems) {
394  std::stringstream ss(s);
395  std::string item;
396  while (std::getline(ss, item, delim)) {
397  elems.push_back(item);
398  }
399  return elems;
400  }
401 
402 
403 }
404 
int GetTriggerOffsetFromDB(int run, double &T0_real)
int GetEfieldValuesFromDB(int run, std::vector< double > &efield)
EResult err(const char *call)
double POT
pdgs p
Definition: selectors.fcl:22
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)
int GetPOTFromDB(int run, long double &POT)
then echo echo For and will not be changed by echo further linking echo echo B echo The symbol is in the uninitialized data multiple common symbols may appear with the echo same name If the symbol is defined the common echo symbols are treated as undefined references For more echo details on common see the discussion of warn common echo in *Note Linker see the discussion of warn common echo in *Note Linker such as a global int variable echo as opposed to a large global array echo echo I echo The symbol is an indirect reference to another symbol This echo is a GNU extension to the a out object file format which is echo rarely used echo echo N echo The symbol is a debugging symbol echo echo R echo The symbol is in a read only data section echo echo S echo The symbol is in an uninitialized data section for small echo objects echo echo T echo The symbol is in the the normal defined echo symbol is used with no error When a weak undefined symbol echo is linked and the symbol is not the value of the echo weak symbol becomes zero with no error echo echo W echo The symbol is a weak symbol that has not been specifically echo tagged as a weak object symbol When a weak defined symbol echo is linked with a normal defined the normal defined echo symbol is used with no error When a weak undefined symbol echo is linked and the symbol is not the value of the echo weak symbol becomes zero with no error echo echo echo The symbol is a stabs symbol in an a out object file In echo this the next values printed are the stabs other field
int GetLifetimeFromDB(int run, double &lftime_real)
DatabaseUtil(fhicl::ParameterSet const &pset)
Definition: DatabaseUtil.cc:19
void reconfigure(fhicl::ParameterSet const &pset)
Definition: DatabaseUtil.cc:70
void LoadUBChannelMap(int data_taking_timestamp=-1, int swizzling_timestamp=-1)
int SelectFieldByName(std::vector< std::string > &value, const char *field, const char *condition, const char *table)
if &&[-z"$BASH_VERSION"] then echo Attempting to switch to bash bash shellSwitch exit fi &&["$1"= 'shellSwitch'] shift declare a IncludeDirectives for Dir in
std::map< UBDaqID, UBLArSoftCh_t > UBChannelMap_t
Definition: DatabaseUtil.h:48
then echo File list $list not found else cat $list while read file do echo $file sed s
Definition: file_to_url.sh:60
int Connect(int conn_wait=0)
Definition: DatabaseUtil.cc:28
std::vector< std::string > & split(const std::string &s, char delim, std::vector< std::string > &elems)
temporary value
std::map< UBLArSoftCh_t, UBDaqID > UBChannelReverseMap_t
Definition: DatabaseUtil.h:49
BEGIN_PROLOG could also be cout
UBChannelReverseMap_t fChannelReverseMap
Definition: DatabaseUtil.h:90
int GetTemperatureFromDB(int run, double &temp_real)
UBChannelMap_t fChannelMap
Definition: DatabaseUtil.h:89