DABC (Data Acquisition Backbone Core)  2.9.9
Monitor.cxx
Go to the documentation of this file.
1 // $Id: Monitor.cxx 4473 2020-04-15 13:35:08Z linev $
2 
3 /************************************************************
4  * The Data Acquisition Backbone Core (DABC) *
5  ************************************************************
6  * Copyright (C) 2009 - *
7  * GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
8  * Planckstr. 1, 64291 Darmstadt, Germany *
9  * Contact: http://dabc.gsi.de *
10  ************************************************************
11  * This software can be used under the GPL license *
12  * agreements as stated in LICENSE.txt file *
13  * which is part of the distribution. *
14  ************************************************************/
15 
16 #include "dim/Monitor.h"
17 
18 #include <ctime>
19 
20 #include "dabc/Publisher.h"
21 #include "dabc/Url.h"
22 
23 #include "mbs/SlowControlData.h"
24 
25 
26 dim::Monitor::Monitor(const std::string &name, dabc::Command cmd) :
27  mbs::MonitorSlowControl(name, "Dim", cmd),
28  DimInfoHandler(),
29  fDimDns(),
30  fDimMask(),
31  fDimPeriod(1.),
32  fDimBr(0),
33  fDimInfos(),
34  fLastScan(),
35  fNeedDnsUpdate(true)
36 {
37  strncpy(fNoLink, "no_link", sizeof(fNoLink));
38 
39  fDimDns = Cfg("DimDns", cmd).AsStr();
40  fDimMask = Cfg("DimMask", cmd).AsStr("*");
41  if (fDimMask.empty()) fDimMask = "*";
42 
43  fWorkerHierarchy.Create("DIMC", true);
44  // fWorkerHierarchy.EnableHistory(100, true); // TODO: make it configurable
45 
46  fDimPeriod = Cfg("DimPeriod", cmd).AsDouble(1);
47 
48  CreateTimer("DimTimer", (fDimPeriod>0.01) ? fDimPeriod : 0.01);
49 
50 
51  Publish(fWorkerHierarchy, "DIMC");
52 }
53 
55 {
56  for (DimServicesMap::iterator iter = fDimInfos.begin(); iter!=fDimInfos.end();iter++) {
57  delete iter->second.info;
58  iter->second.info = 0;
59  }
60  fDimInfos.clear();
61 
62  delete fDimBr; fDimBr = 0;
63 }
64 
65 
67 {
69 
70  if (!fDimDns.empty()) {
71  dabc::Url url(fDimDns);
72  if (url.IsValid()) {
73  if (url.GetPort()>0)
74  ::DimClient::setDnsNode(url.GetHostName().c_str(), url.GetPort());
75  else
76  ::DimClient::setDnsNode(url.GetHostName().c_str());
77  }
78  }
79 
80  fDimBr = new ::DimBrowser();
81 }
82 
84 {
85  char *service_name, *service_descr;
86  int type;
87 
88 // DimClient::addErrorHandler(errHandler);
89 
90  {
91  dabc::LockGuard lock(fWorkerHierarchy.GetHMutex());
92 
93  for (DimServicesMap::iterator iter = fDimInfos.begin(); iter!=fDimInfos.end();iter++) {
94  iter->second.flag = 0;
95  }
96  }
97 
98  int nservices = fDimBr->getServices(fDimMask.c_str());
99  DOUT3("found %d DIM services", nservices);
100 
101  while((type = fDimBr->getNextService(service_name, service_descr))!= 0)
102  {
103  nservices--;
104 
105  dabc::LockGuard lock(fWorkerHierarchy.GetHMutex());
106 
107  DOUT3("DIM type %d name %s descr %s", type, service_name, service_descr);
108 
109  if ((service_descr==0) || ((type!=1) && (type!=2))) continue;
110 
111  DimServicesMap::iterator iter = fDimInfos.find(service_name);
112  if (iter!=fDimInfos.end()) {
113  iter->second.flag = type; // mark entry as found
114  continue;
115  }
116 
117  MyEntry entry;
118  entry.flag = type;
119 
120  // we processing call-back only for normal records
121  if (type==1)
122  entry.info = new DimInfo(service_name, (void*) fNoLink, (int) sizeof(fNoLink), (DimInfoHandler*) this);
123 
124  fDimInfos[service_name] = entry;
125 
126  DOUT3("Create entry %p type %d name %s descr %s", entry.info, type, service_name, service_descr);
127 
128  dabc::Hierarchy item = fWorkerHierarchy.CreateHChild(service_name);
129 
130  if (type==1) {
131  item.EnableHistory(100);
132  } else
133  if (type==2) {
134  item.SetField(dabc::prop_kind, "DABC.Command");
135  item.SetField("dimcmd", service_name);
136  item.SetField("numargs", 1);
137  item.SetField("arg0", "PAR");
138  item.SetField("arg0_dflt", "");
139  item.SetField("arg0_kind", "string");
140  }
141  }
142 
143  {
144  dabc::LockGuard lock(fWorkerHierarchy.GetHMutex());
145 
146  DimServicesMap::iterator iter = fDimInfos.begin();
147  while (iter!=fDimInfos.end()) {
148  if (iter->second.flag != 0) { iter++; continue; }
149 
150  delete iter->second.info;
151  iter->second.info = 0;
152 
153  DOUT3("Destroy entry %s", iter->first.c_str());
154 
155  fWorkerHierarchy.RemoveHChild(iter->first);
156 
157  fDimInfos.erase(iter++);
158  }
159  }
160 
161  fLastScan.GetNow();
162  fNeedDnsUpdate = false;
163 }
164 
165 void dim::Monitor::ProcessTimerEvent(unsigned timer)
166 {
167  if (fDimBr==0) return;
168 
169  if (TimerName(timer) == "DimTimer")
170  if (fLastScan.Expired(10.) || (fDimInfos.size()==0) || fNeedDnsUpdate)
171  ScanDimServices();
172 
174 }
175 
177 {
178  if (cmd.IsName(dabc::CmdHierarchyExec::CmdName())) {
179  std::string path = cmd.GetStr("Item");
180  std::string arg = cmd.GetStr("PAR");
181  std::string dimcmd;
182 
183  {
184  dabc::LockGuard lock(fWorkerHierarchy.GetHMutex());
185  dabc::Hierarchy item = fWorkerHierarchy.FindChild(path.c_str());
186  if (item.null()) {
187  EOUT("Did not found command item %s in DIM hierarchy", path.c_str());
188  return dabc::cmd_false;
189  }
190  dimcmd = item.GetField("dimcmd").AsStr();
191  }
192 
193  if (dimcmd.empty()) return dabc::cmd_false;
194 
195  DOUT2("Execute DIM command %s arg %s", dimcmd.c_str(), arg.c_str());
196 
197  DimClient::sendCommand(dimcmd.c_str(), arg.c_str());
198 
199  return dabc::cmd_true;
200  }
201 
203 }
204 
206 {
207  // DIM method, called when service is updated
208 
209  DimInfo *info = getInfo();
210  if (info==0) return;
211 
212  if (info->getData() == fNoLink) {
213  DOUT3("Get nolink for %s", info->getName());
214  return;
215  }
216 
217  if (info->getFormat() == 0) {
218  EOUT("Get null format for %s", info->getName());
219  return;
220  }
221 
222  dabc::LockGuard lock(fWorkerHierarchy.GetHMutex());
223  dabc::Hierarchy item = fWorkerHierarchy.GetHChild(info->getName());
224 
225  if (item.null()) {
226  EOUT("Fail to find item for %s", info->getName());
227  return;
228  }
229 
230  DimServicesMap::iterator iter = fDimInfos.find(info->getName());
231  if ((iter==fDimInfos.end()) || (iter->second.info!=info)) {
232  EOUT("Did not found service %s in infos map", info->getName());
233  return;
234  }
235 
236  if (strcmp(info->getName(),"DIS_DNS/SERVER_LIST")==0) {
237  DOUT3("Get DIS_DNS/SERVER_LIST");
238  fNeedDnsUpdate = true;
239  }
240  // DOUT0("Get change for info %p name :%s: format %s", info, info->getName(), info->getFormat());
241 
242  bool changed = true;
243 
244  iter->second.fKind = 0;
245  if (strcmp(info->getFormat(),"I")==0) {
246  item.SetField("value", info->getInt());
247  item.SetField(dabc::prop_kind,"rate");
248  iter->second.fKind = 1;
249  iter->second.fLong = info->getInt();
250  } else
251  if (strcmp(info->getFormat(),"F")==0) {
252  item.SetField("value", info->getFloat());
253  item.SetField(dabc::prop_kind,"rate");
254  iter->second.fKind = 2;
255  iter->second.fDouble = info->getFloat();
256  } else
257  if (strcmp(info->getFormat(),"D")==0) {
258  item.SetField("value", info->getDouble());
259  item.SetField(dabc::prop_kind,"rate");
260  iter->second.fKind = 2;
261  iter->second.fDouble = info->getDouble();
262  } else
263  if (strcmp(info->getFormat(),"C")==0) {
264  item.SetField("value", info->getString());
265  item.SetField(dabc::prop_kind,"log");
266  } else
267  if ((strcmp(info->getFormat(),"F:1;I:1;F:1;F:1;F:1;F:1;C:16;C:16;C:16")==0) && (strncmp(info->getName(),"DABC/",5)==0)) {
268  // old DABC rate record
269  item.SetField("value", info->getFloat());
270  item.SetField(dabc::prop_kind,"rate");
271  iter->second.fKind = 2;
272  iter->second.fDouble = info->getFloat();
273  } else
274  if ((strcmp(info->getFormat(),"I:1;C:16;C:128")==0) && (strncmp(info->getName(),"DABC/",5)==0)) {
275  // old DABC info record
276  item.SetField("value", (const char*) info->getData() + sizeof(int) + 16);
277  item.SetField(dabc::prop_kind,"log");
278  } else
279  if (strlen(info->getFormat()) > 2) {
280  const char* fmt = info->getFormat();
281 
282  // DOUT0("Process FORMAT %s", fmt);
283  int fldcnt = 0;
284  char* ptr = (char*) info->getData();
285  while (*fmt != 0) {
286  char kind = *fmt++;
287  if (*fmt++!=':') break;
288  int size = 0;
289  while ((*fmt>='0') && (*fmt<='9')) {
290  size = size*10 + (*fmt - '0');
291  fmt++;
292  }
293  if (*fmt==';') fmt++;
294 
295  if (size<=0) break;
296 
297  // DOUT0("Process item %c size %d", kind, size);
298 
299  dabc::RecordField fld;
300  switch(kind) {
301  case 'I' :
302  if (size==1) {
303  fld.SetInt(*((int*)ptr));
304  } else {
305  std::vector<int64_t> vect;
306  for (int n=0;n<size;n++) vect.push_back(((int*)ptr)[n]);
307  fld.SetVectInt(vect);
308  }
309  ptr += sizeof(int) * size;
310  break;
311  case 'F' :
312  if (size==1) {
313  fld.SetDouble(*((float*)ptr));
314  } else {
315  std::vector<double> vect;
316  for (int n=0;n<size;n++) vect.push_back(((float*)ptr)[n]);
317  fld.SetVectDouble(vect);
318  }
319  ptr += sizeof(float) * size;
320  break;
321  case 'D' :
322  if (size==1) {
323  fld.SetDouble(*((double*)ptr));
324  } else {
325  std::vector<double> vect;
326  for (int n=0;n<size;n++) vect.push_back(((double*)ptr)[n]);
327  fld.SetVectDouble(vect);
328  }
329  ptr += sizeof(double) * size;
330  break;
331  case 'C' : {
332  int slen(0);
333  while ((slen<size) && (ptr[slen]!=0)) slen++;
334  if (slen<size)
335  fld.SetStr(ptr);
336  else
337  fld.SetStr(std::string(ptr,size));
338  ptr += size;
339  break;
340  }
341  default:
342  EOUT("Unknown data format %c", kind);
343  break;
344  }
345  // unrecognized field
346  if (fld.null()) break;
347 
348  item.SetField(dabc::format("fld%d", fldcnt++), fld);
349  }
350  } else {
351  if (strlen(info->getFormat())>0)
352  EOUT("Not processed DIM format %s for record %s", info->getFormat(), info->getName());
353  changed = false;
354  }
355 
356  if (changed) item.MarkChangedItems();
357 
358 }
359 
361 {
362  fRec.Clear();
363 
364  {
365  dabc::LockGuard lock(fWorkerHierarchy.GetHMutex());
366 
367  for (DimServicesMap::iterator iter = fDimInfos.begin(); iter!=fDimInfos.end(); iter++) {
368  switch (iter->second.fKind) {
369  case 1: fRec.AddLong(iter->first, iter->second.fLong); break;
370  case 2: fRec.AddDouble(iter->first, iter->second.fDouble); break;
371  default: break;
372  }
373  }
374  }
375 
376  return fRec.GetRawSize();
377 }
Represents command with its arguments.
Definition: Command.h:99
std::string GetStr(const std::string &name, const std::string &dflt="") const
Definition: Command.h:136
Represents objects hierarchy of remote (or local) DABC process.
Definition: Hierarchy.h:285
void MarkChangedItems(uint64_t tm=0)
If any field was modified, item will be marked with new version.
Definition: Hierarchy.h:330
Hierarchy FindChild(const char *name)
Return child element from hierarchy.
Definition: Hierarchy.h:362
Hierarchy CreateHChild(const std::string &name, bool allowslahes=false, bool sortorder=false)
Create child item in hierarchy with specified name If allowslahes enabled, instead of subfolders item...
Definition: Hierarchy.h:392
Hierarchy GetHChild(const std::string &name, bool allowslahes=false, bool force=false, bool sortorder=false)
Return child, if necessary creates with full subfolder If force specified, missing childs and folders...
Definition: Hierarchy.cxx:944
void EnableHistory(unsigned length=100, bool withchilds=false)
Activate history production for selected element and its childs.
Definition: Hierarchy.cxx:837
Lock guard for posix mutex.
Definition: threads.h:127
virtual void OnThreadAssigned()
Definition: Module.cxx:79
virtual int ExecuteCommand(Command cmd)
Main method where commands are executed.
Definition: Module.h:232
bool SetVectInt(const std::vector< int64_t > &v)
Definition: Record.cxx:1251
bool SetStr(const std::string &v)
Definition: Record.cxx:1127
bool SetDouble(double v)
Definition: Record.cxx:1114
std::string AsStr(const std::string &dflt="") const
Definition: Record.cxx:749
bool SetVectDouble(const std::vector< double > &v)
Definition: Record.cxx:1299
bool SetInt(int64_t v)
Definition: Record.cxx:1073
bool null() const
Definition: Record.h:302
RecordField GetField(const std::string &name) const
Definition: Record.h:510
bool SetField(const std::string &name, const RecordField &v)
Definition: Record.h:516
bool IsName(const char *name) const
Returns true if object name is the same as specified one.
Definition: Reference.cxx:177
bool null() const
Returns true if reference contains nullptr.
Definition: Reference.h:151
Uniform Resource Locator interpreter.
Definition: Url.h:33
virtual int ExecuteCommand(dabc::Command cmd)
Main method where commands are executed.
Definition: Monitor.cxx:176
virtual void ProcessTimerEvent(unsigned timer)
Method called by framework when timer event is produced.
Definition: Monitor.cxx:165
virtual void infoHandler()
Definition: Monitor.cxx:205
Monitor(const std::string &name, dabc::Command cmd=nullptr)
Definition: Monitor.cxx:26
void ScanDimServices()
Definition: Monitor.cxx:83
virtual ~Monitor()
Definition: Monitor.cxx:54
virtual unsigned GetRecRawSize()
Definition: Monitor.cxx:360
virtual void OnThreadAssigned()
Definition: Monitor.cxx:66
::DimBrowser * fDimBr
dim browser
Definition: Monitor.h:58
DimServicesMap fDimInfos
all subscribed DIM services
Definition: Monitor.h:59
virtual void ProcessTimerEvent(unsigned timer)
Method called by framework when timer event is produced.
#define DOUT2(args ...)
Definition: logging.h:170
#define DOUT3(args ...)
Definition: logging.h:176
#define EOUT(args ...)
Definition: logging.h:150
std::string format(const char *fmt,...)
Definition: string.cxx:49
const char * prop_kind
Definition: Hierarchy.cxx:29
@ cmd_false
Definition: Command.h:37
@ cmd_true
Definition: Command.h:38
Support for MBS - standard GSI DAQ.
Definition: api.h:36