Belle II Software  release-08-01-10
AbstractNSMCallback.cc
1 /**************************************************************************
2  * basf2 (Belle II Analysis Software Framework) *
3  * Author: The Belle II Collaboration *
4  * *
5  * See git log for contributors and copyright holders. *
6  * This file is licensed under LGPL-3.0, see LICENSE.md. *
7  **************************************************************************/
8 #include "daq/slc/nsm/AbstractNSMCallback.h"
9 
10 #include "daq/slc/system/Time.h"
11 
12 #include "daq/slc/base/TimeoutException.h"
13 #include "daq/slc/database/DBObject.h"
14 
15 #include "daq/slc/nsm/NSMCommunicator.h"
16 
17 #include <cstdlib>
18 
19 using namespace Belle2;
20 
21 AbstractNSMCallback::AbstractNSMCallback(int timeout)
22 {
23  m_timeout = timeout;
24 }
25 
26 int AbstractNSMCallback::addDB(const DBObject& obj)
27 {
28  DBObject::NameValueList list;
29  obj.search(list, "", true);
30  int id = 0;
31  for (DBObject::NameValueList::iterator it = list.begin();
32  it != list.end(); ++it) {
33  const std::string& name(it->name);
34  if (name.size() == 0 || name.at(0) == '$') continue;
35  switch (it->type) {
36  case DBField::BOOL:
37  id = Callback::add(new NSMVHandlerInt(name, true, true, (int) * ((bool*)it->buf)));
38  set(name, (int) * ((bool*)it->buf));
39  break;
40  case DBField::CHAR:
41  id = Callback::add(new NSMVHandlerInt(name, true, true, (int) * ((char*)it->buf)));
42  set(name, (int) * ((char*)it->buf));
43  break;
44  case DBField::SHORT:
45  id = Callback::add(new NSMVHandlerInt(name, true, true, (int) * ((short*)it->buf)));
46  set(name, (int) * ((short*)it->buf));
47  break;
48  case DBField::INT:
49  id = Callback::add(new NSMVHandlerInt(name, true, true, *((int*)it->buf)));
50  set(name, (int) * ((int*)it->buf));
51  break;
52  case DBField::LONG:
53  id = Callback::add(new NSMVHandlerInt(name, true, true, (int) * ((long long*)it->buf)));
54  set(name, (int) * ((long long*)it->buf));
55  break;
56  case DBField::FLOAT:
57  id = Callback::add(new NSMVHandlerFloat(name, true, true, *((float*)it->buf)));
58  set(name, * ((float*)it->buf));
59  break;
60  case DBField::DOUBLE:
61  id = Callback::add(new NSMVHandlerFloat(name, true, true, (float) * ((double*)it->buf)));
62  set(name, (float) * ((double*)it->buf));
63  break;
64  case DBField::TEXT:
65  id = Callback::add(new NSMVHandlerText(name, true, true, *((std::string*)it->buf)));
66  set(name, *((std::string*)it->buf));
67  break;
68  default:
69  break;
70  }
71  }
72  return id;
73 }
74 
75 NSMCommunicator& AbstractNSMCallback::wait(const NSMNode& node,
76  const NSMCommand& cmd,
77  double timeout)
78 {
79  double t0 = Time().get();
80  double t = t0;
81  while (true) {
82  double t1 = (timeout - (t - t0) > 0 ? timeout - (t - t0) : 0);
83  NSMCommunicator& com(NSMCommunicator::select(t1));
84  NSMMessage msg = com.getMessage();
85  const std::string reqname = msg.getRequestName();
86  if ((cmd == NSMCommand::UNKNOWN || cmd == reqname) &&
87  (node.getName().size() == 0 || msg.getNodeName() == node.getName())) {
88  return com;
89  }
90  com.pushQueue(msg);
91  t = Time().get();
92  }
93 }
94 
95 int AbstractNSMCallback::wait(double timeout)
96 {
97  double t0 = Time().get();
98  double t = t0;
99  int count = 0;
100  try {
101  while (true) {
102  double t1 = (timeout - (t - t0) > 0 ? timeout - (t - t0) : 0);
103  if (t1 == 0) break;
104  NSMCommunicator& com(NSMCommunicator::select(t1));
105  NSMMessage msg = com.getMessage();
106  NSMCommand cmd(msg.getRequestName());
107  if (cmd == NSMCommand::VGET || cmd == NSMCommand::VLISTGET) {
108  perform(com);
109  } else {
110  com.pushQueue(msg);
111  }
112  t = Time().get();
113  }
114  } catch (const TimeoutException& e) {
115  }
116  return count;
117 }
118 
119 bool AbstractNSMCallback::try_wait()
120 {
121  try {
122  perform(wait(NSMNode(), NSMCommand::UNKNOWN, 0));
123  } catch (const std::exception& e) {
124  return false;
125  }
126  return true;
127 }
128 
129 void AbstractNSMCallback::readVar(const NSMMessage& msg, NSMVar& var)
130 {
131  const int* pars = msg.getParams();
132  const char* node = msg.getData();
133  const char* name = (msg.getData() + pars[2] + 1);
134  const char* value = (msg.getData() + pars[2] + 1 + pars[3] + 1);
135  var = NSMVar(name, (NSMVar::Type)pars[0], pars[1], value);
136  var.setNode(node);
137  var.setId(pars[4]);
138  var.setDate(pars[5]);
139 }
140 
141 bool AbstractNSMCallback::get(const NSMNode& node, NSMVHandler* handler,
142  int timeout)
143 {
144  if (handler && node.getName().size() > 0) {
145  NSMVar var(handler->get());
146  add(handler);
147  const std::string name = handler->getName();//var.getName();
148  NSMCommunicator::send(NSMMessage(node, NSMCommand::VGET, name));
149  if (timeout < 0) return true;
150  double t0 = Time().get();
151  double t = t0;
152  double tout = timeout;
153  while (true) {
154  double t1 = (tout - (t - t0) > 0 ? tout - (t - t0) : 0);
155  NSMCommunicator& com(wait(NSMNode(), NSMCommand::UNKNOWN, t1));
156  NSMMessage msg = com.getMessage();
157  NSMCommand cmd(msg.getRequestName());
158  if (cmd == NSMCommand::VSET) {
159  if (node.getName() == msg.getData() &&
160  var.getName() == (msg.getData() + msg.getParam(2) + 1)) {
161  readVar(msg, var);
162  return handler->handleSet(var);
163  }
164  } else if (cmd == NSMCommand::VGET || cmd == NSMCommand::VLISTGET ||
165  cmd == NSMCommand::OK || cmd == NSMCommand::ERROR || cmd == NSMCommand::FATAL) {
166  perform(com);
167  } else {
168  com.pushQueue(msg);
169  }
170  t = Time().get();
171  }
172  }
173  return false;
174 }
175 
176 bool AbstractNSMCallback::get(const NSMNode& node, NSMVar& var,
177  int timeout)
178 {
179  if (node.getName().size() > 0) {
180  const std::string name = var.getName();
181  NSMCommunicator::send(NSMMessage(node, NSMCommand::VGET, name));
182  if (timeout < 0) return true;
183  double t0 = Time().get();
184  double t = t0;
185  double tout = timeout;
186  while (true) {
187  double t1 = (tout - (t - t0) > 0 ? tout - (t - t0) : 0);
188  NSMCommunicator& com(wait(NSMNode(), NSMCommand::UNKNOWN, t1));
189  NSMMessage msg = com.getMessage();
190  NSMCommand cmd(msg.getRequestName());
191  if (cmd == NSMCommand::VSET) {
192  if (msg.getLength() > 0 && msg.getData() != NULL &&
193  node.getName() == msg.getData() &&
194  var.getName() == (msg.getData() + msg.getParam(2) + 1)) {
195  readVar(msg, var);
196  return true;
197  }
198  } else if (cmd == NSMCommand::VGET || cmd == NSMCommand::VLISTGET ||
199  cmd == NSMCommand::OK || cmd == NSMCommand::ERROR || cmd == NSMCommand::FATAL) {
200  perform(com);
201  } else {
202  com.pushQueue(msg);
203  }
204  t = Time().get();
205  }
206  }
207  return false;
208 }
209 
210 bool AbstractNSMCallback::set(const NSMNode& node, const NSMVar& var,
211  int timeout)
212 {
213  if (node.getName().size() > 0) {
214  NSMCommunicator::send(NSMMessage(node, var));
215  if (timeout < 0) return true;
216  double t0 = Time().get();
217  double t = t0;
218  double tout = timeout;
219  while (true) {
220  double t1 = (tout - (t - t0) > 0 ? tout - (t - t0) : 0);
221  NSMCommunicator& com(wait(node, NSMCommand::VREPLY, t1));
222  NSMMessage msg(com.getMessage());
223  NSMCommand cmd(msg.getRequestName());
224  if (cmd == NSMCommand::VREPLY && var.getName() == msg.getData()) {
225  bool ret = msg.getParam(0) > 0;
226  perform(com);
227  return ret;
228  } else if (cmd == NSMCommand::VGET || cmd == NSMCommand::VLISTGET ||
229  cmd == NSMCommand::OK || cmd == NSMCommand::ERROR || cmd == NSMCommand::FATAL) {
230  perform(com);
231  } else {
232  com.pushQueue(msg);
233  }
234  t = Time().get();
235  }
236  }
237  return false;
238 }
239 
240 bool AbstractNSMCallback::get(const NSMNode& node, const std::string& name,
241  int& val, int timeout)
242 {
243  return get_t(node, name, val, timeout, NSMVar::INT, 0);
244 }
245 
246 bool AbstractNSMCallback::get(const NSMNode& node, const std::string& name,
247  float& val, int timeout)
248 {
249  return get_t(node, name, val, timeout, NSMVar::FLOAT, 0);
250 }
251 
252 bool AbstractNSMCallback::get(const NSMNode& node, const std::string& name,
253  std::string& val, int timeout)
254 {
255  return get_t(node, name, val, timeout, NSMVar::TEXT, 1);
256 }
257 
258 bool AbstractNSMCallback::get(const NSMNode& node, const std::string& name,
259  std::vector<int>& val, int timeout)
260 {
261  return get_t(node, name, val, timeout, NSMVar::INT, 1);
262 }
263 
264 bool AbstractNSMCallback::get(const NSMNode& node, const std::string& name,
265  std::vector<float>& val, int timeout)
266 {
267  return get_t(node, name, val, timeout, NSMVar::FLOAT, 1);
268 }
269 
270 bool AbstractNSMCallback::set(const NSMNode& node, const std::string& name,
271  int val, int timeout)
272 {
273  return set(node, NSMVar(name, val), timeout);
274 }
275 
276 bool AbstractNSMCallback::set(const NSMNode& node, const std::string& name,
277  float val, int timeout)
278 {
279  return set(node, NSMVar(name, val), timeout);
280 }
281 
282 bool AbstractNSMCallback::set(const NSMNode& node, const std::string& name,
283  const std::string& val, int timeout)
284 {
285  return set(node, NSMVar(name, val), timeout);
286 }
287 
288 bool AbstractNSMCallback::set(const NSMNode& node, const std::string& name,
289  const std::vector<int>& val, int timeout)
290 {
291  return set(node, NSMVar(name, val), timeout);
292 }
293 
294 bool AbstractNSMCallback::set(const NSMNode& node, const std::string& name,
295  const std::vector<float>& val, int timeout)
296 {
297  return set(node, NSMVar(name, val), timeout);
298 }
299 
300 bool AbstractNSMCallback::get(const DBObject& obj)
301 {
302  DBObject::NameValueList list;
303  obj.search(list);
304  for (DBObject::NameValueList::iterator it = list.begin();
305  it != list.end(); ++it) {
306  const std::string& name(it->name);
307  if (name.size() == 0 || name.at(0) == '$') continue;
308  int vi = 0;
309  float vf = 0;
310  std::string vs;
311  switch (it->type) {
312  case DBField::BOOL:
313  if (get(name, vi)) *((bool*)it->buf) = (bool)vi;
314  break;
315  case DBField::CHAR:
316  if (get(name, vi)) *((char*)it->buf) = (char)vi;
317  break;
318  case DBField::SHORT:
319  if (get(name, vi)) *((short*)it->buf) = (short)vi;
320  break;
321  case DBField::INT:
322  if (get(name, vi)) *((int*)it->buf) = (int)vi;
323  break;
324  case DBField::LONG:
325  if (get(name, vi)) *((long long*)it->buf) = vi;
326  break;
327  case DBField::FLOAT:
328  if (get(name, vf)) *((float*)it->buf) = vf;
329  break;
330  case DBField::DOUBLE:
331  if (get(name, vf)) *((double*)it->buf) = vf;
332  break;
333  case DBField::TEXT:
334  if (get(name, vs)) *((std::string*)it->buf) = vs;
335  break;
336  default:
337  break;
338  }
339  }
340  return true;
341 }
342 
Abstract base class for different kinds of events.