Belle II Software development
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
19using namespace Belle2;
20
21AbstractNSMCallback::AbstractNSMCallback(int timeout)
22{
23 m_timeout = timeout;
24}
25
26int 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
75NSMCommunicator& 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
95int 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
119bool 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
129void 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
141bool 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
176bool 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
210bool 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
240bool 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
246bool 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
252bool 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
258bool 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
264bool 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
270bool 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
276bool 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
282bool 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
288bool 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
294bool 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
300bool 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.