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