ALIROOT-5600 - skip non-participating detector modules
[u/mrichter/AliRoot.git] / HLT / BASE / AliHLTOnlineConfiguration.cxx
CommitLineData
ab162f34 1// $Id$
2
3//**************************************************************************
f84fefa5 4//* This file is property of and copyright by the ALICE HLT Project *
ab162f34 5//* ALICE Experiment at CERN, All rights reserved. *
6//* *
7//* Primary Authors: *
8//* for The ALICE HLT Project. *
9//* *
10//* Permission to use, copy, modify and distribute this software and its *
11//* documentation strictly for non-commercial purposes is hereby granted *
12//* without fee, provided that the above copyright notice appears in all *
13//* copies and that both the copyright notice and this permission notice *
14//* appear in the supporting documentation. The authors make no claims *
15//* about the suitability of this software for any purpose. It is *
16//* provided "as is" without express or implied warranty. *
17//**************************************************************************
18
f84fefa5 19/// @file AliHLTOnlineConfiguration.h
20/// @author Matthias Richter
21/// @author Lars Christian Raae
22/// @date
23/// @brief Description of the HLT online configuration
ab162f34 24
d6fd9360 25#include <cerrno>
26#include <fstream>
27#include <iostream>
f84fefa5 28#include <cstdio>
d6fd9360 29
f84fefa5 30#include <TDOMParser.h>
31#include <TXMLAttr.h>
32#include <TXMLNode.h>
33#include <TString.h>
b4a85b5b 34#include <TObjString.h>
d6fd9360 35
c459166a 36#include "AliHLTConfigurationHandler.h"
ff1200fa 37#include "AliHLTDAQ.h"
ab162f34 38#include "AliHLTOnlineConfiguration.h"
f84fefa5 39#include "AliHLTComponentConfiguration.h"
ab162f34 40
41/** ROOT macro for the implementation of ROOT specific class methods */
42ClassImp(AliHLTOnlineConfiguration)
43
44AliHLTOnlineConfiguration::AliHLTOnlineConfiguration()
45 : TObject()
46 , fXMLBuffer()
d6fd9360 47 , fXMLSize(0)
f84fefa5 48 , fConfEntryList()
b4a85b5b 49 , fDefaultChains()
ab162f34 50{
51 // see header file for class documentation
52 // or
53 // refer to README to build package
54 // or
55 // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
56
57}
58
59AliHLTOnlineConfiguration::~AliHLTOnlineConfiguration()
60{
61 // destructor
62}
63
d6fd9360 64int AliHLTOnlineConfiguration::LoadConfiguration(const char* filename)
ab162f34 65{
66 /// load configuration from file
f84fefa5 67
c459166a 68 if (TestBit(kLoaded))
69 return -EPROTO;
d6fd9360 70 ifstream in;
71 in.open(filename);
72 if (!in.is_open())
73 return -EIO;
74
75 size_t filesize = 0;
76 in.seekg(0, std::ios::end );
77 filesize = in.tellg();
78 in.seekg(0, std::ios::beg);
79
80 char * content = new char[filesize];
81 in.read(content, filesize);
82 in.close();
83
84 fXMLBuffer.Adopt(filesize, content);
85 fXMLSize = filesize;
86 SetBit(kLoaded);
ab162f34 87
f84fefa5 88 return filesize;
ab162f34 89}
90
91int AliHLTOnlineConfiguration::Compress()
92{
93 /// compress the xml buffer
94
95 return 0;
96}
97
98int AliHLTOnlineConfiguration::Uncompress()
99{
100 /// compress the xml buffer
101
102 return 0;
103}
104
f84fefa5 105int AliHLTOnlineConfiguration::Parse()
106{
107 /// parse the xml buffer
108
109 int iResult = 0;
c459166a 110 if (TestBit(kLoaded) && !TestBit(kParsed)) {
f84fefa5 111 iResult = -EINVAL;
112 TDOMParser *domParser = new TDOMParser();
113 domParser->SetValidate(false);
114 Int_t parsecode = domParser->ParseBuffer(fXMLBuffer.GetArray(), fXMLSize);
115 if (parsecode < 0) {
116 HLTError("Configuration XML invalid or not well-formed (error code %d)", parsecode);
117 }
118 else {
119 TXMLDocument* doc;
120 if ((doc = domParser->GetXMLDocument()) && doc->GetRootNode()) {
c459166a 121 AliHLTConfigurationHandler* pHandler = AliHLTConfigurationHandler::Instance();
122 pHandler->Deactivate(true);
f84fefa5 123 iResult = ParseConfiguration(doc->GetRootNode());
124 if (iResult == 0)
125 SetBit(kParsed);
c459166a 126 else {
127 pHandler->ClearScheduledRegistrations();
128 fConfEntryList.Delete();
129 fDefaultChains.Clear();
130 }
131 pHandler->Activate();
f84fefa5 132 }
133 }
ff1200fa 134 delete domParser;
f84fefa5 135 }
136 else
137 iResult = -EPROTO;
138 return iResult;
139}
140
141int AliHLTOnlineConfiguration::ParseConfiguration(TXMLNode* node)
142{
b4a85b5b 143 /// parse xml configuration
144
f84fefa5 145 int iResult = 0;
146 int nElems = 0;
147 if (node && node->GetChildren()) {
148 node = node->GetChildren();
c459166a 149 for (; node && iResult == 0; node = node->GetNextNode()) {
f84fefa5 150 if (node->GetNodeType() == TXMLNode::kXMLElementNode) {
151 if (strcmp(node->GetNodeName(), "Proc") == 0) {
152 const char* id = 0;
b4a85b5b 153 const char* type = 0;
f84fefa5 154 if (node->HasAttributes()) {
155 TList* attrList = node->GetAttributes();
156 TXMLAttr* attr = 0;
157 TIter next(attrList);
158 while ((attr=(TXMLAttr*)next()))
159 if (strcmp(attr->GetName(), "ID") == 0) {
160 id = attr->GetValue();
b4a85b5b 161 } else if (strcmp(attr->GetName(), "type") == 0) {
162 type = attr->GetValue();
163 }
f84fefa5 164 }
b4a85b5b 165 if (id && type && node->GetChildren()) {
c459166a 166 iResult = ParseEntry(node->GetChildren(), id, type);
167 if (iResult == 0)
f84fefa5 168 nElems++;
b4a85b5b 169 }
f84fefa5 170 else {
c459166a 171 iResult = -EINVAL;
172 if (!id) {
173 HLTError("Configuration component missing ID attribute");
174 }
175 else if (!type) {
176 HLTError("Configuration component missing type attribute");
177 }
178 else {
179 HLTError("Empty configuration component %s", id);
180 }
f84fefa5 181 }
182 }
183 }
184 }
c459166a 185 if (iResult != 0) {
186 HLTError("An error occurred parsing the configuration. Aborting...");
187 }
188 else if (!nElems) {
f84fefa5 189 iResult = -EINVAL;
190 HLTError("Configuration did not contain any (valid) elements");
191 }
192 }
193 else {
194 iResult = -EINVAL;
195 HLTError("Configuration was empty");
196 }
197 return iResult;
198}
199
b4a85b5b 200int AliHLTOnlineConfiguration::ParseEntry(TXMLNode* node, const char* id,
201 const char* type)
f84fefa5 202{
b4a85b5b 203 /// Parse XML configuration entry.
204
f84fefa5 205 int iResult = 0;
206 const char* cmd = 0;
b4a85b5b 207 const char* source = 0;
f84fefa5 208 TString sources;
209 TString nodes;
210 for (; node; node = node->GetNextNode()) {
211 if (node->GetNodeType() == TXMLNode::kXMLElementNode) {
212 if (strcmp(node->GetNodeName(), "Cmd") == 0) {
213 if (!cmd) // Use only the first (non-empty) <Cmd> element
214 cmd = node->GetText();
215 }
216 else if (strcmp(node->GetNodeName(), "Node") == 0) {
217 if (!nodes.IsNull()) nodes += " "; nodes += node->GetText();
218 }
219 else if (strcmp(node->GetNodeName(), "Parent") == 0) {
b4a85b5b 220 source = node->GetText();
221 if (sources.Contains(source)) {
222 iResult = -EINVAL;
223 HLTError("Configuration component %s has duplicate <Parent> element %s",
224 id, source);
225 break;
226 }
f84fefa5 227 if (!sources.IsNull()) sources += " "; sources += node->GetText();
228 }
229 }
230 }
231
b4a85b5b 232 if (iResult == 0) {
233 if (!cmd) {
234 iResult = -EINVAL;
235 HLTError("Configuration component %s does not contain <Cmd> element", id);
236 }
237 else if (cmd == strstr(cmd, "AliRootWrapperSubscriber"))
238 iResult = ParseStandardComponent(id, type, cmd, sources, nodes);
239 else if (cmd == strstr(cmd, "RORCPublisher"))
240 iResult = ParseRORCPublisher(id, type, cmd, sources, nodes);
241 else if (cmd == strstr(cmd, "TCPDumpSubscriber"))
242 iResult = ParseTCPDumpSubscriber(id, type, cmd, sources, nodes);
243 else if (cmd == strstr(cmd, "Relay"))
244 iResult = ParseRelay(id, type, cmd, sources, nodes);
245 else if (cmd == strstr(cmd, "HLTOutFormatter"))
246 iResult = ParseHLTOutFormatter(id, type, cmd, sources, nodes);
247 else if (cmd == strstr(cmd, "HLTOutWriterSubscriber"))
248 iResult = ParseHLTOutWriterSubscriber(id, type, cmd, sources, nodes);
249 else {
250 iResult = -EINVAL;
251 HLTError("Configuration component %s contains unknown <Cmd> element", id);
252 }
f84fefa5 253 }
254
255 return iResult;
256}
257
b4a85b5b 258int AliHLTOnlineConfiguration::ParseStandardComponent(const char* id,
259 const char* type, const char* cmd, TString& sources, TString& nodes)
f84fefa5 260{
b4a85b5b 261 /// Parse standard component configuration
262
f84fefa5 263 int iResult = 0;
b4a85b5b 264 if (strcmp(type, "prc") != 0) {
f84fefa5 265 iResult = -EINVAL;
b4a85b5b 266 HLTError("Configuration component %s has invalid type %s (expected prc)",
267 id, type);
f84fefa5 268 }
b4a85b5b 269 else {
270 // Parse component command
271 const char* compid="";
272 const char* complib="";
273 char* compargs = 0;
274 bool hasArgs = false;
275 char* cmdcopy = new char[strlen(cmd)+1];
ca69335b 276 if (!cmdcopy) return -ENOMEM;
277 cmdcopy[strlen(cmd)]=0;
278 strncpy(cmdcopy, cmd, strlen(cmd));
b4a85b5b 279 strtok(cmdcopy, " -"); // Skip "AliRootWrapperSubscriber"
280 char* strtmp = 0;
c459166a 281 bool CFTransform = false;
b4a85b5b 282 while (((strtmp = strtok(0, " -")))) {
c459166a 283 if (strcmp(strtmp, "componentid") == 0) {
b4a85b5b 284 compid = strtok(0, " -");
c459166a 285 if (strcmp(compid, "TPCHWClusterTransform") == 0)
286 // FIXME: Ugly hack to replace cluster transformers. Refactor.
287 CFTransform = true;
288 }
b4a85b5b 289 else if (strcmp(strtmp, "componentargs") == 0)
290 hasArgs = true;
291 else if (strcmp(strtmp, "componentlibrary") == 0)
292 complib = strtok(0, " -");
293 }
c459166a 294 if (CFTransform) {
295 compid = "TPCClusterFinder32Bit";
296 // NOTE: Cluster transformer's arguments ignored and cluster finder
297 // component gets no arguments at all...
298 hasArgs = false;
299 }
b4a85b5b 300 if (hasArgs) {
301 // Parse component arguments
302 int start = strstr(cmd, "-componentargs") + strlen("-componentargs") + 2
303 - cmd;
304 int arglen = strcspn(cmd+start, "\"");
305 // Verify that we have the actual limits of the componentargs
306 if ((size_t)(start+arglen) < strlen(cmd) && cmd[start-1] == '\"' &&
307 cmd[start+arglen] == '\"')
308 {
309 compargs = new char[arglen+1];
310 strncpy(compargs, cmd + start, arglen);
311 compargs[arglen] = '\0';
312 }
313 }
314 if (!compid) {
315 iResult = -EINVAL;
316 HLTError("Configuration component %s is missing component id", id);
317 }
318 if (!complib) {
319 iResult = -EINVAL;
320 HLTError("Configuration component %s is missing component library", id);
321 }
322 if (hasArgs && !compargs) {
323 iResult = -EINVAL;
324 HLTError("Configuration component %s is missing component arguments", id);
325 }
326 if (iResult == 0) {
327 AliHLTComponentConfiguration* entry = new AliHLTComponentConfiguration(id,
328 compid, sources.Data(), compargs);
329 entry->SetOnlineCommand(cmd);
330 entry->SetComponentLibrary(complib);
331 entry->SetNodeNames(nodes.Data());
332 fConfEntryList.Add(entry);
333 }
334 delete [] cmdcopy;
335 delete [] compargs;
f84fefa5 336 }
337 return iResult;
338}
339
340int AliHLTOnlineConfiguration::ParseRORCPublisher(const char* id,
b4a85b5b 341 const char* type, const char* cmd, TString& sources, TString& nodes)
f84fefa5 342{
b4a85b5b 343 /// Parse RORCPublisher configuration
344
f84fefa5 345 int iResult = 0;
b4a85b5b 346 if (strcmp(type, "src") != 0) {
f84fefa5 347 iResult = -EINVAL;
b4a85b5b 348 HLTError("Configuration component %s has invalid type %s (expected src)",
349 id, type);
f84fefa5 350 }
351 else {
ca69335b 352 const char compid[] = "AliRawReaderPublisher";
b4a85b5b 353 const char complib[] = "libAliHLTUtil.so";
354 // Parse (and validate) component command
355 int ddlID;
c459166a 356 int res;
357 if (strstr(cmd, "-hwcoproc")) {
358 // HW Co-processor has complex argument rules, so skip full validation
fffa5cc0 359 const char* key=strstr(cmd, "-ddlid");
360 if (key)
361 res = sscanf(key, "-ddlid %d", &ddlID);
362 else
363 res=0;
c459166a 364 } else {
365 res = sscanf(cmd, "RORCPublisher -slot %*d %*d %*d %*d -rorcinterface %*d -sleep "
366 "-sleeptime %*d -maxpendingevents %*d -alicehlt -ddlid %d", &ddlID);
367 }
b4a85b5b 368 if (res != 1) {
369 iResult = -EINVAL;
370 HLTError("Configuration component %s has <Cmd> element of unknown format\n"
371 "Expected format: RORCPublisher -slot %%d %%d %%d %%d -rorcinterface %%d "
372 "-sleep -sleeptime %%d -maxpendingevents %%d -alicehlt -ddlid %%d", id);
373 }
374 else {
375 Int_t ddlIndex;
376 Int_t detectorID = AliHLTDAQ::DetectorIDFromDdlID(ddlID, ddlIndex);
377 string HLTOrigin = AliHLTDAQ::HLTOrigin(detectorID);
378 string HLTSpecification = AliHLTDAQ::HLTSpecificationFromDdlID(ddlID);
ca69335b 379 TString compargs;
380 compargs.Form("-minid %d -datatype 'DDL_RAW ' '%s' -dataspec %s",
b4a85b5b 381 ddlID, HLTOrigin.c_str(), HLTSpecification.c_str());
382 AliHLTComponentConfiguration* entry = new AliHLTComponentConfiguration(id,
ca69335b 383 compid, sources.Data(), compargs.Data());
b4a85b5b 384 entry->SetOnlineCommand(cmd);
385 entry->SetComponentLibrary(complib);
386 entry->SetNodeNames(nodes.Data());
387 fConfEntryList.Add(entry);
388 }
f84fefa5 389 }
390 return iResult;
391}
392
b4a85b5b 393int AliHLTOnlineConfiguration::ParseTCPDumpSubscriber(const char* id,
394 const char* type, const char* /* cmd */, TString& /* sources */,
395 TString& /* nodes */)
f84fefa5 396{
b4a85b5b 397 /// Parse TCPDumpSubscriber configuration
f84fefa5 398 int iResult = 0;
b4a85b5b 399 if (strcmp(type, "snk") != 0) {
400 iResult = -EINVAL;
401 HLTError("Configuration component %s has invalid type %s (expected snk)",
402 id, type);
403 }
f84fefa5 404 return iResult;
405}
406
b4a85b5b 407int AliHLTOnlineConfiguration::ParseRelay(const char* id, const char* type,
408 const char* cmd, TString& sources, TString& nodes)
f84fefa5 409{
b4a85b5b 410 /// Parse Relay configuration
411
f84fefa5 412 int iResult = 0;
b4a85b5b 413 if (strcmp(type, "prc") != 0) {
414 iResult = -EINVAL;
415 HLTError("Configuration component %s has invalid type %s (expected prc)",
416 id, type);
f84fefa5 417 }
418 else {
b4a85b5b 419 const char compid[] = "BlockFilter";
420 const char complib[] = "libAliHLTUtil.so";
421 const char* compargs = "";
422 if (strcmp(cmd, "Relay") == 0) {
423 AliHLTComponentConfiguration* entry = new AliHLTComponentConfiguration(id,
424 compid, sources.Data(), compargs);
425 entry->SetOnlineCommand(cmd);
426 entry->SetComponentLibrary(complib);
427 entry->SetNodeNames(nodes.Data());
428 fConfEntryList.Add(entry);
429 }
430 else {
431 iResult = -EINVAL;
432 HLTError("Configuration component %s has <Cmd> element of unknown type "
433 "\"%s\"", id, cmd);
434 }
f84fefa5 435 }
436 return iResult;
437}
438
b4a85b5b 439int AliHLTOnlineConfiguration::ParseHLTOutFormatter(const char* id,
440 const char* type, const char* /* cmd */, TString& sources,
441 TString& /* nodes */)
f84fefa5 442{
b4a85b5b 443 /// Parse HLTOutFormatter configuration
444
f84fefa5 445 int iResult = 0;
b4a85b5b 446 if (strcmp(type, "prc") != 0) {
447 iResult = -EINVAL;
448 HLTError("Configuration component %s has invalid type %s (expected prc)",
449 id, type);
450 }
451 else {
452 fDefaultChains = sources;
453 }
f84fefa5 454 return iResult;
455}
456
b4a85b5b 457int AliHLTOnlineConfiguration::ParseHLTOutWriterSubscriber(const char* id,
458 const char* type, const char* /* cmd */, TString& /* sources */,
459 TString& /* nodes */)
f84fefa5 460{
b4a85b5b 461 /// Parse HLTOutWriterSubscriber configuration
462
f84fefa5 463 int iResult = 0;
b4a85b5b 464 if (strcmp(type, "snk") != 0) {
465 iResult = -EINVAL;
466 HLTError("Configuration component %s has invalid type %s (expected snk)",
467 id, type);
468 }
f84fefa5 469 return iResult;
470}
471
fc79e537 472TString AliHLTOnlineConfiguration::GetComponentLibraries()
b4a85b5b 473{
474 /// get component libraries
475
476 TString result;
477 AliHLTComponentConfiguration* pConf;
478 const char* complib;
479 TIter next(&fConfEntryList);
480 while ((pConf=(AliHLTComponentConfiguration*)next())) {
481 complib = pConf->GetComponentLibrary();
482 if (!result.Contains(complib)) {
483 if (!result.IsNull()) result+=" "; result+=complib;
484 }
485 }
fc79e537 486 return result;
b4a85b5b 487}
488
ab162f34 489void AliHLTOnlineConfiguration::Print(const char* options) const
490{
491 /// overloaded from TObject, print info
d6fd9360 492 const UInt_t defaultSampleSize = 200;
ab162f34 493
494 TObject::Print(options);
d6fd9360 495 printf("Configuration loaded: %s\n", (TestBit(kLoaded) ? "YES" : "NO"));
496 TString opt = options;
497 opt.ToLower();
b4a85b5b 498 Bool_t buffer = opt.Contains("buffer");
499 Bool_t parsed = opt.Contains("parsed");
d6fd9360 500
501 if (TestBit(kLoaded)) {
b4a85b5b 502 if (buffer) {
d6fd9360 503 char configuration[fXMLSize + 1];
504 strncpy(configuration, fXMLBuffer.GetArray(), fXMLSize);
505 printf("%s\n\n", configuration);
b4a85b5b 506 } else if (parsed) {
507 AliHLTComponentConfiguration* pConf;
508 TIter next(&fConfEntryList);
509 while ((pConf=(AliHLTComponentConfiguration*)next())) {
510 pConf->Print("status");
511 }
d6fd9360 512 } else {
513 Int_t sampleSize = (defaultSampleSize <= fXMLSize) ?
f84fefa5 514 defaultSampleSize : fXMLSize;
d6fd9360 515 char sample[sampleSize];
516 for (int i = 0; i < sampleSize - 1; i++)
f84fefa5 517 sample[i] = fXMLBuffer.At(i);
d6fd9360 518 sample[sampleSize - 1] = '\0';
519 printf("%s...\n\n", sample);
520 }
521 }
522
523 printf("XML size (uncompressed): %d\n", fXMLSize);
524 printf("Configuration compressed: %s\n", (TestBit(kCompressed) ? "YES" : "NO"));
525 printf("Configuration parsed: %s\n", (TestBit(kParsed) ? "YES" : "NO"));
f84fefa5 526 printf("Parsed configuration entries: %d\n", fConfEntryList.GetSize());
b4a85b5b 527 printf("Default chains: %s\n", fDefaultChains.Data());
ab162f34 528}
529
530void AliHLTOnlineConfiguration::Dump() const
531{
532 /// overloaded from TObject, more crude data dump
533
534 TObject::Dump();
535}
536
537void AliHLTOnlineConfiguration::Clear(Option_t * option)
538{
539 /// overloaded from TObject, clear object
f84fefa5 540
ab162f34 541 TObject::Clear(option);
ff1200fa 542 fConfEntryList.Delete();
b4a85b5b 543 fDefaultChains.Clear();
d6fd9360 544 fXMLBuffer.Reset();
545 fXMLSize = 0;
546 ResetBit(kLoaded);
547 ResetBit(kCompressed);
548 ResetBit(kParsed);
ab162f34 549}
550
551TObject * AliHLTOnlineConfiguration::Clone(const char *newname) const
552{
553 /// overloaded from TObject, clone object
554
555 return TObject::Clone(newname);
556}
557
558void AliHLTOnlineConfiguration::Copy(TObject &object) const
559{
560 /// overloaded from TObject, copy object
561
562 TObject::Copy(object);
563}
564
565void AliHLTOnlineConfiguration::Draw(Option_t */*option*/)
566{
567 /// overloaded from TObject, draw graph of the configuration
568}