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