LEMClient_module.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 // \file LEMClient_module.cc
3 // \brief Fetch LEM PID result from remote server
4 // \author Christopher Backhouse - bckhouse@caltech.edu
5 ////////////////////////////////////////////////////////////////////////
6 
7 // NOvASoft includes
8 #include "RecoBase/Cluster.h"
9 #include "Utilities/AssociationUtil.h"
10 
11 // Framework includes
17 #include "fhiclcpp/ParameterSet.h"
18 
19 #include "LEM/LEMInput.h"
20 #include "LEM/PIDDetails.h"
21 
22 #include "LEM/LEMWebSettings.h"
23 #include "LEM/WebUtils.h"
24 
25 #include <cfloat>
26 #include <iostream>
27 
28 #include <curl/curl.h>
29 
30 namespace
31 {
32  struct LEMClientParams
33  {
34  template<class T> using Atom = fhicl::Atom<T>;
35  template<class T> using Table = fhicl::Table<T>;
36  using Comment = fhicl::Comment;
37  using Name = fhicl::Name;
38 
39  Atom<std::string> inputLabel{
40  Name("InputLabel"),
41  Comment("Where to find LEMInput objects")
42  };
43 
44  Atom<std::string> releaseOverride{
45  Name("ReleaseOverride"),
46  Comment("Specify this release to the server. Empty string for current release.")
47  };
48 
49  Table<lem::LEMWebSettings> web{Name("WebSettings")};
50  };
51 }
52 
53 namespace lem
54 {
55  /// Fetch LEM PID result from remote server
56  class LEMClient: public art::EDProducer
57  {
58  public:
59  // Allows 'nova --print-description' to work
61 
62  explicit LEMClient(const Parameters& params);
63  ~LEMClient();
64 
65  virtual void beginJob();
66  virtual void produce(art::Event& evt);
67 
68  protected:
69  LEMClientParams fParams;
70 
72  };
73 
74  //......................................................................
75  LEMClient::LEMClient(const Parameters& params)
76  : fParams(params())
77  {
78  produces<std::vector<lem::PIDDetails>>();
79  produces<art::Assns<lem::PIDDetails, rb::Cluster>>();
80 
81  // Generate a unique ID so that the server can identify us.
82  char host[1024];
83  gethostname(host, 1023);
84  host[1023] = 0;
85  const char* user = getenv("USER");
86  if(!user) user = "(unknown)";
87  fClientID = TString::Format("%s@%s.%d.%ld",
88  user, host, getpid(), time(0)).Data();
89 
90  curl_global_init(CURL_GLOBAL_ALL);
91  }
92 
93  //......................................................................
95  {
96  curl_global_cleanup();
97  }
98 
99  //......................................................................
101  {
102  // Randomize ports and so on properly
103  srand(getpid());
104  }
105 
106  //......................................................................
108  {
109  std::unique_ptr<std::vector<lem::PIDDetails> > pidcol(new std::vector<lem::PIDDetails>);
110  std::unique_ptr<art::Assns<lem::PIDDetails, rb::Cluster>> assns(new art::Assns<lem::PIDDetails, rb::Cluster>);
111 
112  const std::string rel = fParams.releaseOverride().empty() ? get_release() : fParams.releaseOverride();
113 
114  const LEMWebSettings& web = fParams.web();
115 
116  const std::string args = TString::Format("rel=%s&id=%s&timeout=%d",
117  rel.c_str(),
118  fClientID.c_str(),
119  web.queryTimeout()).Data();
120 
122  evt.getByLabel(fParams.inputLabel(), inputs);
123  art::FindManyP<rb::Cluster> fmt(inputs, evt, fParams.inputLabel());
124 
125  const int inputMax = inputs->size();
126  for(int inputIdx = 0; inputIdx < inputMax; ++inputIdx){
127  const LEMInput& input = (*inputs)[inputIdx];
128 
129  // DBL_DIG of precision guarantee the number roundtrips safely
130  std::string postdata = TString::Format("E=%.*g\n",
131  DBL_DIG, input.totalGeV).Data();
132  for(const LiteHit& hit: input.hits){
133  postdata += TString::Format("%d %.*g\n",
134  hit.cellIdx, DBL_DIG, hit.pecorr).Data();
135  }
136 
137  bool ok;
138  const std::string response = post_query(web.host(),
139  "pid?"+args,
140  postdata,
141  web.minPort(),
142  web.maxPort(),
143  web.queryTimeout(),
144  web.retryTimeout(),
145  ok);
146  if(!ok){
147  std::cerr << "No response from server after many retries. Aborting"
148  << std::endl;
149  abort();
150  }
151 
152  pidcol->push_back(PIDDetails::FromString(response));
153 
154  // Get all the slices associated with this match list
155  const std::vector<art::Ptr<rb::Cluster> > slices = fmt.at(inputIdx);
156  assert(slices.size() == 1);
157  util::CreateAssn(*this, evt, *pidcol, slices[0], *assns);
158  }
159 
160  evt.put(std::move(pidcol));
161  evt.put(std::move(assns));
162  }
163 
165 
166 } //namespace lem
167 ////////////////////////////////////////////////////////////////////////
static bool CreateAssn(art::EDProducer const &prod, art::Event &evt, std::vector< T > &a, art::Ptr< U > b, art::Assns< T, U > &assn, size_t indx=UINT_MAX, std::string const &instance=std::string())
Create a 1 to 1 association between a new product and one already in the event.
Atom< std::string > host
Fetch LEM PID result from remote server.
Atom< int > queryTimeout
virtual void beginJob()
OStream cerr
Definition: OStream.cxx:7
float pecorr
Definition: LiteHit.h:24
DEFINE_ART_MODULE(TestTMapFile)
::xsd::cxx::tree::time< char, simple_type > time
Definition: Database.h:194
PID
Definition: FillPIDs.h:13
ProductID put(std::unique_ptr< PROD > &&product)
Definition: Event.h:102
double totalGeV
Definition: LEMInput.h:15
void beginJob()
unsigned short cellIdx
Definition: LiteHit.h:25
std::string getenv(std::string const &name)
std::string post_query(const std::string &host, const std::string &query, const std::string &postdata, int minPort, int maxPort, int queryTimeout, int retryTimeout, bool &ok)
Make an HTTP POST query.
Definition: WebUtils.cxx:162
std::string get_release()
Figure out the current release. TODO: does this belong somewhere else?
Definition: WebUtils.cxx:178
string rel
Definition: shutoffs.py:11
static PIDDetails FromString(const std::string &s)
Definition: PIDDetails.cxx:19
::xsd::cxx::tree::string< char, simple_type > string
Definition: Database.h:154
bool getByLabel(std::string const &label, std::string const &productInstanceName, Handle< PROD > &result) const
Definition: DataViewImpl.h:344
std::string fClientID
std::vector< LiteHit > hits
Definition: LEMInput.h:14
Definition: event.h:1
assert(nhit_max >=nhit_nbins)
void Format(TGraph *gr, int lcol, int lsty, int lwid, int mcol, int msty, double msiz)
Definition: Style.cxx:154
LEMClientParams fParams
Compressed hit info, basic component of LEM events.
Definition: LiteHit.h:18
virtual void produce(art::Event &evt)
Atom< int > retryTimeout