]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/BASE/AliHLTOnlineConfiguration.cxx
bugfix: correct range of DDL for specified detector
[u/mrichter/AliRoot.git] / HLT / BASE / AliHLTOnlineConfiguration.cxx
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 ClassImp(AliHLTOnlineConfiguration)
43
44 AliHLTOnlineConfiguration::AliHLTOnlineConfiguration()
45   : TObject()
46   , fXMLBuffer()
47   , fXMLSize(0)
48   , fConfEntryList()
49   , fDefaultChains()
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
59 AliHLTOnlineConfiguration::~AliHLTOnlineConfiguration()
60 {
61   // destructor
62 }
63
64 int AliHLTOnlineConfiguration::LoadConfiguration(const char* filename)
65 {
66   /// load configuration from file
67
68   if (TestBit(kLoaded))
69     return -EPROTO;
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);
87
88   return filesize;
89 }
90
91 int AliHLTOnlineConfiguration::Compress()
92 {
93   /// compress the xml buffer
94
95   return 0;
96 }
97
98 int AliHLTOnlineConfiguration::Uncompress()
99 {
100   /// compress the xml buffer
101
102   return 0;
103 }
104
105 int AliHLTOnlineConfiguration::Parse()
106 {
107   /// parse the xml buffer
108
109   int iResult = 0;
110   if (TestBit(kLoaded) && !TestBit(kParsed)) {
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()) {
121         AliHLTConfigurationHandler* pHandler = AliHLTConfigurationHandler::Instance();
122         pHandler->Deactivate(true);
123         iResult = ParseConfiguration(doc->GetRootNode());
124         if (iResult == 0)
125           SetBit(kParsed);
126         else {
127           pHandler->ClearScheduledRegistrations();
128           fConfEntryList.Delete();
129           fDefaultChains.Clear();
130         }
131         pHandler->Activate();
132       }
133     }
134     delete domParser;
135   }
136   else
137     iResult = -EPROTO; 
138   return iResult;
139 }
140
141 int AliHLTOnlineConfiguration::ParseConfiguration(TXMLNode* node)
142 {
143   /// parse xml configuration
144
145   int iResult = 0;
146   int nElems = 0;
147   if (node && node->GetChildren()) {
148     node = node->GetChildren();
149     for (; node && iResult == 0; node = node->GetNextNode()) {
150       if (node->GetNodeType() == TXMLNode::kXMLElementNode) {
151         if (strcmp(node->GetNodeName(), "Proc") == 0) {
152           const char* id = 0;
153           const char* type = 0;
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();
161               } else if (strcmp(attr->GetName(), "type") == 0) {
162                 type = attr->GetValue();
163               }
164           }
165           if (id && type && node->GetChildren()) {
166             iResult = ParseEntry(node->GetChildren(), id, type);
167             if (iResult == 0)
168               nElems++;
169           }
170           else {
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             }
181           }
182         }
183       }
184     }
185     if (iResult != 0) {
186       HLTError("An error occurred parsing the configuration. Aborting...");
187     }
188     else if (!nElems) {
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
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   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) {
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         }
227         if (!sources.IsNull()) sources += " "; sources += node->GetText();
228       }
229     }
230   }
231
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     }
253   }
254   
255   return iResult;
256 }
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   if (strcmp(type, "prc") != 0) {
265     iResult = -EINVAL;
266     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     char* cmdcopy = new char[strlen(cmd)+1];
276     if (!cmdcopy) return -ENOMEM;
277     cmdcopy[strlen(cmd)]=0;
278     strncpy(cmdcopy, cmd, strlen(cmd));
279     strtok(cmdcopy, " -"); // Skip "AliRootWrapperSubscriber"
280     char* strtmp = 0;
281     bool CFTransform = false;
282     while (((strtmp = strtok(0, " -")))) {
283       if (strcmp(strtmp, "componentid") == 0) {
284         compid = strtok(0, " -");
285         if (strcmp(compid, "TPCHWClusterTransform") == 0)
286         // FIXME: Ugly hack to replace cluster transformers. Refactor.
287           CFTransform = true;
288       }
289       else if (strcmp(strtmp, "componentargs") == 0)
290         hasArgs = true;
291       else if (strcmp(strtmp, "componentlibrary") == 0)
292         complib = strtok(0, " -");
293     }
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     }
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;
336   }
337   return iResult;
338 }
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   if (strcmp(type, "src") != 0) {
347     iResult = -EINVAL;
348     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     int ddlID;
356     int res;
357     if (strstr(cmd, "-hwcoproc")) {
358       // HW Co-processor has complex argument rules, so skip full validation
359       const char* key=strstr(cmd, "-ddlid");
360       if (key)
361         res = sscanf(key, "-ddlid %d", &ddlID);
362       else
363         res=0;
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     }
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);
379       TString compargs;
380       compargs.Form("-minid %d -datatype 'DDL_RAW ' '%s' -dataspec %s",
381         ddlID, HLTOrigin.c_str(), HLTSpecification.c_str());
382       AliHLTComponentConfiguration* entry = new AliHLTComponentConfiguration(id,
383         compid, sources.Data(), compargs.Data());
384       entry->SetOnlineCommand(cmd);
385       entry->SetComponentLibrary(complib);
386       entry->SetNodeNames(nodes.Data());
387       fConfEntryList.Add(entry);
388     }
389   }
390   return iResult;
391 }
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   if (strcmp(type, "snk") != 0) {
400     iResult = -EINVAL;
401     HLTError("Configuration component %s has invalid type %s (expected snk)",
402       id, type);  
403   }
404   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   if (strcmp(type, "prc") != 0) {
414     iResult = -EINVAL;
415     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     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     }
435   }
436   return iResult;
437 }
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   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   }
454   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   if (strcmp(type, "snk") != 0) {
465     iResult = -EINVAL;
466     HLTError("Configuration component %s has invalid type %s (expected snk)",
467       id, type);  
468   }  
469   return iResult;
470 }
471
472 TString AliHLTOnlineConfiguration::GetComponentLibraries()
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   }
486   return result;
487 }
488
489 void AliHLTOnlineConfiguration::Print(const char* options) const
490 {
491   /// overloaded from TObject, print info
492   const UInt_t defaultSampleSize = 200;
493
494   TObject::Print(options);
495   printf("Configuration loaded: %s\n", (TestBit(kLoaded) ? "YES" : "NO"));
496   TString opt = options;
497   opt.ToLower();
498   Bool_t buffer = opt.Contains("buffer");
499   Bool_t parsed = opt.Contains("parsed");
500
501   if (TestBit(kLoaded)) {
502     if (buffer) {
503       char configuration[fXMLSize + 1];
504       strncpy(configuration, fXMLBuffer.GetArray(), fXMLSize);
505       printf("%s\n\n", configuration);
506     } else if (parsed) {
507         AliHLTComponentConfiguration* pConf;
508         TIter next(&fConfEntryList);
509         while ((pConf=(AliHLTComponentConfiguration*)next())) {
510           pConf->Print("status");
511         }
512     } else {
513       Int_t sampleSize = (defaultSampleSize <= fXMLSize) ?
514               defaultSampleSize : fXMLSize;
515       char sample[sampleSize];
516       for (int i = 0; i < sampleSize - 1; i++)
517               sample[i] = fXMLBuffer.At(i);
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"));
526   printf("Parsed configuration entries: %d\n", fConfEntryList.GetSize());
527   printf("Default chains: %s\n", fDefaultChains.Data());
528 }
529
530 void AliHLTOnlineConfiguration::Dump() const
531 {
532   /// overloaded from TObject, more crude data dump
533
534   TObject::Dump();
535 }
536
537 void AliHLTOnlineConfiguration::Clear(Option_t * option)
538 {
539   /// overloaded from TObject, clear object
540
541   TObject::Clear(option);
542   fConfEntryList.Delete();
543   fDefaultChains.Clear();
544   fXMLBuffer.Reset();
545   fXMLSize = 0;
546   ResetBit(kLoaded);
547   ResetBit(kCompressed);
548   ResetBit(kParsed);
549 }
550
551 TObject * AliHLTOnlineConfiguration::Clone(const char *newname) const
552 {
553   /// overloaded from TObject, clone object
554
555   return TObject::Clone(newname);
556 }
557
558 void AliHLTOnlineConfiguration::Copy(TObject &object) const
559 {
560   /// overloaded from TObject, copy object
561
562   TObject::Copy(object);
563 }
564
565 void AliHLTOnlineConfiguration::Draw(Option_t */*option*/)
566 {
567   /// overloaded from TObject, draw graph of the configuration
568 }